Compare commits

..

221 Commits

Author SHA1 Message Date
Harald Kuhr 666e0ef94a [maven-release-plugin] prepare for next development iteration 2023-11-07 20:24:45 +01:00
Harald Kuhr b58c4ba5dd [maven-release-plugin] prepare release twelvemonkeys-3.10.1 2023-11-07 20:24:40 +01:00
Harald Kuhr 6328862e4f Set versions to 3.10.1-SNAPSHOT 2023-11-07 20:17:30 +01:00
Harald Kuhr a95235b422 #860: Fix regression in reading broken PackBits stream. 2023-11-07 14:04:28 +01:00
dependabot[bot] 9f4b09fc7d Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.0 to 3.6.2
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.0 to 3.6.2.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.0...maven-javadoc-plugin-3.6.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 10:08:53 +01:00
dependabot[bot] 03455f0132 Bump org.apache.maven.plugins:maven-surefire-report-plugin
Bumps [org.apache.maven.plugins:maven-surefire-report-plugin](https://github.com/apache/maven-surefire) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.1...surefire-3.2.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-report-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 10:08:40 +01:00
dependabot[bot] ac5779d8d6 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.1 to 3.2.2
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.1...surefire-3.2.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 09:59:54 +01:00
dependabot[bot] fef8ff3aab Bump org.apache.maven.plugins:maven-pmd-plugin from 3.21.0 to 3.21.2
Bumps [org.apache.maven.plugins:maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.21.0 to 3.21.2.
- [Release notes](https://github.com/apache/maven-pmd-plugin/releases)
- [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.21.0...maven-pmd-plugin-3.21.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-pmd-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-03 10:07:49 +01:00
Steinar Bang a9e4b2e262 Change maven-bundle-plugin config to correctly export ImageWriterSpi services 2023-11-02 09:48:01 +01:00
dependabot[bot] 7147e2dfb1 Bump github/codeql-action from 2.22.4 to 2.22.5 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.4 to 2.22.5.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/49abf0ba24d0b7953cb586944e918a0b92074c80...74483a38d39275f33fcff5f35b679b5ca4a26a99)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 10:09:56 +01:00
dependabot[bot] 1680fadf83 Bump commons-io:commons-io from 2.14.0 to 2.15.0
Bumps commons-io:commons-io from 2.14.0 to 2.15.0.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-26 11:04:08 +02:00
Harald Kuhr d1df8c13ed Remove outdated TODO 2023-10-25 22:14:54 +02:00
Harald Kuhr 031937fe99 #852 JPEG: Preserve existing metadata when writing CMYK data 2023-10-25 22:14:05 +02:00
dependabot[bot] 24c473ae45 Bump org.apache.maven.plugins:maven-surefire-report-plugin
Bumps [org.apache.maven.plugins:maven-surefire-report-plugin](https://github.com/apache/maven-surefire) from 3.1.2 to 3.2.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-report-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 11:26:45 +02:00
dependabot[bot] 57941cb638 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.1.2 to 3.2.1
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.2 to 3.2.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 11:26:24 +02:00
dependabot[bot] d325b6deec Bump org.apache.maven.plugins:maven-checkstyle-plugin
Bumps [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.3.0 to 3.3.1.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.0...maven-checkstyle-plugin-3.3.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 11:25:52 +02:00
dependabot[bot] 3f67430b2d Bump ossf/scorecard-action from 2.3.0 to 2.3.1 in /.github/workflows
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.3.0 to 2.3.1.
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](https://github.com/ossf/scorecard-action/compare/483ef80eb98fb506c348f7d62e28055e49fe2398...0864cf19026789058feabb7e87baa5f140aac736)

---
updated-dependencies:
- dependency-name: ossf/scorecard-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 11:25:19 +02:00
dependabot[bot] 314071dde8 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.0.2 to 4.0.3.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/7e43ff95fc4d43209637c265c8fca9c8f1c157b5...0831a82caad2465c31c6dd929978f640cb42556c)

---
updated-dependencies:
- dependency-name: mikepenz/action-junit-report
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 11:19:36 +02:00
dependabot[bot] 83ad25c2dd Bump github/codeql-action from 2.22.3 to 2.22.4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.3 to 2.22.4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/0116bc2df50751f9724a2e35ef1f24d22f90e4e1...49abf0ba24d0b7953cb586944e918a0b92074c80)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 11:19:12 +02:00
KoenDG d7dae90e2e The original condition of i bigger than mapsize will never be true, since i starts at 0.
The condition should be: i smaller than mapsize, if we want to loop over the mapsize.
2023-10-21 11:06:54 +02:00
Harald Kuhr ad437c2470 Better comment 2023-10-20 22:12:23 +02:00
Harald Kuhr dabc26bdb5 [maven-release-plugin] prepare for next development iteration 2023-10-20 21:25:12 +02:00
Harald Kuhr b441298a9a [maven-release-plugin] prepare release twelvemonkeys-3.10.0 2023-10-20 21:25:06 +02:00
Harald Kuhr 345ca0ac13 POM fixes 2023-10-20 16:53:25 +02:00
Harald Kuhr 9720a931c5 #843: Correctly handle empty image resources section. 2023-10-20 12:27:17 +02:00
dependabot[bot] 4d3f691e6a Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/0a8a5ba57593d67b2e45de2c543b438412382b7b...7e43ff95fc4d43209637c265c8fca9c8f1c157b5)

---
updated-dependencies:
- dependency-name: mikepenz/action-junit-report
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-20 12:08:47 +02:00
Harald Kuhr 2e0e575183 #841: Filter out incompatible ICC profiles 2023-10-19 11:10:47 +02:00
Harald Kuhr 2c7c47b158 #837: Now uses last app segment for color space detection. 2023-10-18 16:52:47 +02:00
Harald Kuhr 57680f1bec Change from java 21-ea to 21 (official temurin build is out) 2023-10-18 16:33:11 +02:00
Harald Kuhr 8dc83c4e9e Remove JDK 20 now that we have 21. 2023-10-18 16:20:31 +02:00
dependabot[bot] 929bea6b6b Bump actions/checkout from 4.1.0 to 4.1.1 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/8ade135a41bc03ea155e62e844d188df1ea18608...b4ffde65f46336ab88eb53be808477a3936bae11)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-18 11:58:04 +02:00
dependabot[bot] 699662d054 Bump github/codeql-action from 2.22.2 to 2.22.3 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.2 to 2.22.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/d90b8d79de6dc1f58e83a1499aa58d6c93dc28de...0116bc2df50751f9724a2e35ef1f24d22f90e4e1)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 11:58:00 +02:00
dependabot[bot] 1bebee1851 Bump github/codeql-action from 2.22.1 to 2.22.2 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.1 to 2.22.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/fdcae64e1484d349b3366718cdfef3d404390e85...d90b8d79de6dc1f58e83a1499aa58d6c93dc28de)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-13 10:53:29 +02:00
dependabot[bot] b0e8dd86bb Bump github/codeql-action from 2.22.0 to 2.22.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.0 to 2.22.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/2cb752a87e96af96708ab57187ab6372ee1973ab...fdcae64e1484d349b3366718cdfef3d404390e85)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-10 11:06:58 +02:00
dependabot[bot] 5bdb0b5502 Bump ossf/scorecard-action from 2.2.0 to 2.3.0 in /.github/workflows
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](https://github.com/ossf/scorecard-action/compare/08b4669551908b1024bb425080c797723083c031...483ef80eb98fb506c348f7d62e28055e49fe2398)

---
updated-dependencies:
- dependency-name: ossf/scorecard-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-09 11:41:44 +02:00
dependabot[bot] 85d47528a3 Bump github/codeql-action from 2.21.9 to 2.22.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.9 to 2.22.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ddccb873888234080b77e9bc2d4764d5ccaaccf9...2cb752a87e96af96708ab57187ab6372ee1973ab)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-09 11:41:25 +02:00
Steinar Bang a7ebd66149 Export all TwelveMonkeys imageio SPI plugins using the osgi.serviceloader capability 2023-10-05 21:52:33 +02:00
Steinar Bang f0a032a7b9 Add Require-Capability header requiring osgi.serviceloader.registrar to all imageio OSGi bundle MANIFEST.MF files 2023-10-05 21:52:33 +02:00
Steinar Bang 690cb064e7 Ignore eclipse .metadata directory 2023-10-05 21:52:33 +02:00
Steinar Bang e65f471a8f Provide Require-Capability and Add-Capability headers for osgi.serviceloader to the imageio-jpeg MANIFEST.MF
This is to make it possible to load the SPI plugin in OSGi.
2023-10-05 21:52:33 +02:00
Steinar Bang f2cc9faaf8 Add maven-bundle-plugin to build to give jar files OSGi manifest headers and make the jar files OSGi bundles, fixes #794 2023-10-05 21:52:33 +02:00
Harald Kuhr 8bd3f4f34a Badge reorganization. 2023-10-05 21:51:01 +02:00
Harald Kuhr be348543d8 Fix possibly flaky test. 2023-10-05 20:30:22 +02:00
Harald Kuhr 80229b8c3c Minor code clean-up. 2023-10-05 20:27:18 +02:00
Harald Kuhr a5ee53569d Added OpenSSF Best Practices badge. 2023-10-05 20:20:11 +02:00
Harald Kuhr c22ada03cd Replace some usages of ImageTypeSpecifier.createFromRenderedImage. 2023-10-05 20:09:37 +02:00
Harald Kuhr b61341ce3b Testing JDK 21-ea 2023-10-05 15:05:30 +02:00
Harald Kuhr e73b0a7bcf Update ci.yml 2023-10-05 15:05:30 +02:00
dependabot[bot] ea9d1c0dc5 Bump github/codeql-action from 2.21.8 to 2.21.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.8 to 2.21.9.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2.21.8...ddccb873888234080b77e9bc2d4764d5ccaaccf9)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-04 10:19:14 +02:00
Harald Kuhr e0563ee7dd Fix some easy to fix CodeQL issues 2023-10-03 13:44:51 +02:00
Joyce 44bcd202e8 Update codeql.yml
Signed-off-by: Joyce <joycebrum@google.com>
2023-10-03 12:23:13 +02:00
Joyce 5b57b51ff1 set top level permission to codeql.yml
Signed-off-by: Joyce <joycebrum@google.com>
2023-10-03 12:23:13 +02:00
Joyce 0b5f8a071e Create codeql.yml
Signed-off-by: Joyce <joycebrum@google.com>
2023-10-03 12:23:13 +02:00
dependabot[bot] d3dc578936 Bump commons-io:commons-io from 2.13.0 to 2.14.0
Bumps commons-io:commons-io from 2.13.0 to 2.14.0.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 11:51:46 +02:00
dependabot[bot] 2ae937b870 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/75b84e78b3f0aaea7ed7cf8d1d100d7f97f963ec...0a8a5ba57593d67b2e45de2c543b438412382b7b)

---
updated-dependencies:
- dependency-name: mikepenz/action-junit-report
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-02 11:51:17 +02:00
dependabot[bot] 2a7763299a Bump github/codeql-action from 2.21.8 to 2.21.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.8 to 2.21.9.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/6a28655e3dcb49cb0840ea372fd6d17733edd8a4...ddccb873888234080b77e9bc2d4764d5ccaaccf9)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-28 13:36:41 +02:00
dependabot[bot] a57a1d35f9 Bump actions/checkout from 4.0.0 to 4.1.0 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/3df4ab11eba7bda6032a0b82a6bb43b11571feac...8ade135a41bc03ea155e62e844d188df1ea18608)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-25 11:15:14 +02:00
dependabot[bot] e618805786 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.0 to 3.5.1
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.5.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-25 11:05:30 +02:00
Harald Kuhr e3cb923d37 #815: Filter metadata and thumbnails before passing to JPEG delegate. 2023-09-23 16:14:23 +02:00
Harald Kuhr 4513b0c166 Better support for ImageTypeSpecifiers with IndexColorModel. 2023-09-22 11:52:11 +02:00
dependabot[bot] b55d4e8c1b Bump actions/setup-java from 3.12.0 to 3.13.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.12.0 to 3.13.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/cd89f46ac9d01407894225f350157564c9c7cee2...0ab4596768b603586c0de567f2430c30f5b0d2b0)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-21 10:52:58 +02:00
dependabot[bot] 399c75f59e Bump github/codeql-action from 2.21.7 to 2.21.8 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.7 to 2.21.8.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/04daf014b50eaf774287bf3f0f1869d4b4c4b913...6a28655e3dcb49cb0840ea372fd6d17733edd8a4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-20 10:46:35 +02:00
dependabot[bot] a7f7d73e2d Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.5.0 to 3.6.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.5.0 to 3.6.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.5.0...maven-javadoc-plugin-3.6.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-18 11:51:50 +02:00
dependabot[bot] 41a83191b7 Bump github/codeql-action from 2.21.6 to 2.21.7 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.6 to 2.21.7.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/701f152f28d4350ad289a5e31435e9ab6169a7ca...04daf014b50eaf774287bf3f0f1869d4b4c4b913)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-15 11:48:36 +02:00
dependabot[bot] 49e805eeb7 Bump github/codeql-action from 2.21.5 to 2.21.6 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.5 to 2.21.6.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/00e563ead9f72a8461b24876bee2d0c2e8bd2ee8...701f152f28d4350ad289a5e31435e9ab6169a7ca)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-14 10:37:08 +02:00
dependabot[bot] f426637fdd Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 3.8.0 to 4.0.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/150e2f992e4fad1379da2056d1d1c279f520e058...75b84e78b3f0aaea7ed7cf8d1d100d7f97f963ec)

---
updated-dependencies:
- dependency-name: mikepenz/action-junit-report
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-07 11:04:31 +02:00
dependabot[bot] 4081ff1545 Bump actions/upload-artifact from 3.1.2 to 3.1.3 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/0b7f8abb1508181956e8e162db84b466c27e18ce...a8a3f3ad30e3422c9c7b888a15615d19a852ae32)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-07 11:03:42 +02:00
Harald Kuhr ae4fbcc726 Merge pull request #806 from haraldk/dependabot/github_actions/dot-github/workflows/actions/checkout-4.0.0
Bump actions/checkout from 3.6.0 to 4.0.0 in /.github/workflows
2023-09-05 13:54:23 +02:00
dependabot[bot] 66208bfa03 Bump actions/checkout from 3.6.0 to 4.0.0 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/f43a0e5ff2bd294095638e18286ca9a3d1956744...3df4ab11eba7bda6032a0b82a6bb43b11571feac)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-05 09:06:47 +00:00
Harald Kuhr e72255805e Merge pull request #805 from haraldk/dependabot/github_actions/dot-github/workflows/github/codeql-action-2.21.5
Bump github/codeql-action from 2.21.4 to 2.21.5 in /.github/workflows
2023-08-29 10:50:48 +02:00
dependabot[bot] 780ccd7916 Bump github/codeql-action from 2.21.4 to 2.21.5 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.21.4 to 2.21.5.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/a09933a12a80f87b87005513f0abb1494c27a716...00e563ead9f72a8461b24876bee2d0c2e8bd2ee8)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-29 08:20:59 +00:00
Harald Kuhr 957e917281 Merge pull request #803 from haraldk/dependabot/github_actions/dot-github/workflows/actions/checkout-3.6.0
Bump actions/checkout from 3.5.3 to 3.6.0 in /.github/workflows
2023-08-25 10:31:16 +02:00
dependabot[bot] 9daf8337ee Bump actions/checkout from 3.5.3 to 3.6.0 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/c85c95e3d7251135ab7dc9ce3241c5835cc595a9...f43a0e5ff2bd294095638e18286ca9a3d1956744)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 08:13:57 +00:00
Harald Kuhr 89c104d59f Merge pull request #802 from haraldk/dependabot/maven/batik.version-1.17
Bump batik.version from 1.16 to 1.17
2023-08-23 12:52:34 +02:00
dependabot[bot] 8608ee76c5 Bump batik.version from 1.16 to 1.17
Bumps `batik.version` from 1.16 to 1.17.

Updates `org.apache.xmlgraphics:batik-rasterizer-ext` from 1.16 to 1.17

Updates `org.apache.xmlgraphics:batik-extension` from 1.16 to 1.17

Updates `org.apache.xmlgraphics:batik-anim` from 1.16 to 1.17

Updates `org.apache.xmlgraphics:batik-svggen` from 1.16 to 1.17

Updates `org.apache.xmlgraphics:batik-transcoder` from 1.16 to 1.17

---
updated-dependencies:
- dependency-name: org.apache.xmlgraphics:batik-rasterizer-ext
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.xmlgraphics:batik-extension
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.xmlgraphics:batik-anim
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.xmlgraphics:batik-svggen
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.xmlgraphics:batik-transcoder
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-23 10:46:41 +00:00
Harald Kuhr aab2d36e92 Prepare for new Batik version 2023-08-23 12:41:54 +02:00
Harald Kuhr 608b37232d #792: Guard against incorrect JPEG Huffman Table class 2023-08-21 13:10:45 +02:00
Harald Kuhr e3ebf8e0fa Merge pull request #800 from haraldk/dependabot/github_actions/dot-github/workflows/ossf/scorecard-action-2.2.0
Bump ossf/scorecard-action from 2.1.2 to 2.2.0 in /.github/workflows
2023-08-21 11:56:14 +02:00
Harald Kuhr 9af10625a2 Merge pull request #799 from haraldk/dependabot/github_actions/dot-github/workflows/actions/upload-artifact-3.1.2
Bump actions/upload-artifact from 3.1.0 to 3.1.2 in /.github/workflows
2023-08-21 11:56:05 +02:00
Harald Kuhr ccc4e7b411 Merge pull request #798 from haraldk/dependabot/github_actions/dot-github/workflows/actions/checkout-3.5.3
Bump actions/checkout from 3.1.0 to 3.5.3 in /.github/workflows
2023-08-21 11:51:32 +02:00
dependabot[bot] 439323c5e5 Bump actions/checkout from 3.1.0 to 3.5.3 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.5.3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3.1.0...c85c95e3d7251135ab7dc9ce3241c5835cc595a9)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 09:50:52 +00:00
Harald Kuhr 332e191d0d Merge pull request #797 from haraldk/dependabot/github_actions/dot-github/workflows/github/codeql-action-2.21.4
Bump github/codeql-action from 2.2.4 to 2.21.4 in /.github/workflows
2023-08-21 11:50:12 +02:00
Harald Kuhr 58d1a89028 Merge pull request #790 from haraldk/dependabot/github_actions/dot-github/workflows/actions/setup-java-3.12.0
Bump actions/setup-java from 3.11.0 to 3.12.0 in /.github/workflows
2023-08-21 11:49:57 +02:00
dependabot[bot] 72fe799cc8 Bump ossf/scorecard-action from 2.1.2 to 2.2.0 in /.github/workflows
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.1.2 to 2.2.0.
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](https://github.com/ossf/scorecard-action/compare/e38b1902ae4f44df626f11ba0734b14fb91f8f86...08b4669551908b1024bb425080c797723083c031)

---
updated-dependencies:
- dependency-name: ossf/scorecard-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 08:59:55 +00:00
dependabot[bot] 18af213e27 Bump actions/upload-artifact from 3.1.0 to 3.1.2 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.0 to 3.1.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/3cea5372237819ed00197afe530f5a7ea3e805c8...0b7f8abb1508181956e8e162db84b466c27e18ce)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 08:59:52 +00:00
dependabot[bot] 9d267f352f Bump github/codeql-action from 2.2.4 to 2.21.4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.2.4 to 2.21.4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/17573ee1cc1b9d061760f3a006fc4aac4f944fd5...a09933a12a80f87b87005513f0abb1494c27a716)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-21 08:59:46 +00:00
Harald Kuhr f8f6f9f1e4 Merge pull request #796 from joycebrum/master
Add OpenSSF Scorecard Workflow
2023-08-18 16:00:02 +02:00
Joyce 2841d26785 Add scorecard badge to README.md
Signed-off-by: Joyce <joycebrum@google.com>
2023-08-07 15:28:33 -03:00
Joyce 98ae5967ca Create scorecard.yml
Signed-off-by: Joyce <joycebrum@google.com>
2023-08-07 15:26:28 -03:00
dependabot[bot] da9d87a561 Bump actions/setup-java from 3.11.0 to 3.12.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.11.0 to 3.12.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2...cd89f46ac9d01407894225f350157564c9c7cee2)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-25 08:32:19 +00:00
Harald Kuhr d472191926 BMP cleanup 2023-07-19 14:04:27 +02:00
Harald Kuhr a8472170c4 HDR clean-up 2023-07-19 13:24:40 +02:00
Harald Kuhr b2f7cada21 #784 TIFF: No longer return incorrect standard image type for RGB with custom ICC profile 2023-07-17 12:08:43 +02:00
Harald Kuhr 2a4c152c3d #786 TIFF: No longer create custom Inflater, to avoid resource leak 2023-07-17 12:04:45 +02:00
Harald Kuhr 660932b7e7 Merge pull request #787 from haraldk/dependabot/github_actions/dot-github/workflows/mikepenz/action-junit-report-3.8.0
Bump mikepenz/action-junit-report from 3.7.8 to 3.8.0 in /.github/workflows
2023-07-17 10:31:12 +02:00
dependabot[bot] d0a17ff3b3 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 3.7.8 to 3.8.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/baaeba622e27b396105f35ec9ec4ee89ffcbd306...150e2f992e4fad1379da2056d1d1c279f520e058)

---
updated-dependencies:
- dependency-name: mikepenz/action-junit-report
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-17 08:25:39 +00:00
Harald Kuhr 4259903bdd Merge pull request #781 from haraldk/dependabot/github_actions/dot-github/workflows/mikepenz/action-junit-report-3.7.8
Bump mikepenz/action-junit-report from 3.7.7 to 3.7.8 in /.github/workflows
2023-06-22 11:31:12 +02:00
dependabot[bot] 3018d2a342 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 3.7.7 to 3.7.8.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/c0e4b81aaa0067314a2d0d06e19b512c9d8af4f5...baaeba622e27b396105f35ec9ec4ee89ffcbd306)

---
updated-dependencies:
- dependency-name: mikepenz/action-junit-report
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-22 09:08:28 +00:00
Harald Kuhr 8f94318f28 Merge pull request #780 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.5.0
Bump maven-shade-plugin from 3.4.1 to 3.5.0
2023-06-19 12:08:24 +02:00
dependabot[bot] 60b7151eb6 Bump maven-shade-plugin from 3.4.1 to 3.5.0
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.4.1 to 3.5.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.4.1...maven-shade-plugin-3.5.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 09:11:11 +00:00
Harald Kuhr 8ad21307e8 Merge pull request #779 from haraldk/dependabot/github_actions/dot-github/workflows/actions/checkout-3.5.3
Bump actions/checkout from 3.5.2 to 3.5.3 in /.github/workflows
2023-06-12 12:03:24 +02:00
dependabot[bot] 8c854f1e20 Bump actions/checkout from 3.5.2 to 3.5.3 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/8e5e7e5ab8b370d6c329ec480221332ada57f0ab...c85c95e3d7251135ab7dc9ce3241c5835cc595a9)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 09:09:29 +00:00
Harald Kuhr 1445ff2533 Merge pull request #778 from haraldk/dependabot/maven/commons-io-commons-io-2.13.0
Bump commons-io from 2.12.0 to 2.13.0
2023-06-08 12:13:03 +02:00
dependabot[bot] e8f1e80d4e Bump commons-io from 2.12.0 to 2.13.0
Bumps commons-io from 2.12.0 to 2.13.0.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-08 09:17:37 +00:00
Harald Kuhr 18e29e9ed5 Merge pull request #777 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-surefire-report-plugin-3.1.2
Bump maven-surefire-report-plugin from 3.1.0 to 3.1.2
2023-06-07 11:59:39 +02:00
Harald Kuhr ec4003b1c1 Merge pull request #776 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-surefire-plugin-3.1.2
Bump maven-surefire-plugin from 3.1.0 to 3.1.2
2023-06-07 11:59:27 +02:00
dependabot[bot] 164b8db988 Bump maven-surefire-report-plugin from 3.1.0 to 3.1.2
Bumps [maven-surefire-report-plugin](https://github.com/apache/maven-surefire) from 3.1.0 to 3.1.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.0...surefire-3.1.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-report-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-07 09:09:31 +00:00
dependabot[bot] 21feace385 Bump maven-surefire-plugin from 3.1.0 to 3.1.2
Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.0 to 3.1.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.0...surefire-3.1.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-07 09:09:19 +00:00
Harald Kuhr ba1f754611 #722 Fix WebP animation transparent frame issue 2023-06-05 12:36:38 +02:00
Harald Kuhr 822b5da631 #772 Fix WebP animation transparent frame issue 2023-06-05 11:41:03 +02:00
Harald Kuhr c785f6932f Merge remote-tracking branch 'origin/master' 2023-06-05 11:38:06 +02:00
Harald Kuhr 43e2a27c7f Merge pull request #774 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-release-plugin-3.0.1
Bump maven-release-plugin from 3.0.0 to 3.0.1
2023-06-05 11:23:23 +02:00
dependabot[bot] 9d50acd2fe Bump maven-release-plugin from 3.0.0 to 3.0.1
Bumps [maven-release-plugin](https://github.com/apache/maven-release) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.0...maven-release-3.0.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-release-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-05 09:10:54 +00:00
Harald Kuhr ba73a308d6 Merge pull request #771 from daaaaa/master
PSD: Adding parsing for 'lsdk' (undocumented) additional layer information
2023-05-30 09:32:31 +02:00
Davide Tantillo 20cd259abd PSD: Adding parsing for 'lsdk' (undocumented) additional layer information key that represents a 'nested section diverder setting' 2023-05-30 09:18:47 +02:00
Harald Kuhr 033a1423ff Merge pull request #770 from haraldk/dependabot/maven/org.sonatype.plugins-nexus-staging-maven-plugin-1.6.13
Bump nexus-staging-maven-plugin from 1.6.8 to 1.6.13
2023-05-25 14:54:16 +02:00
Harald Kuhr 7c8c520006 Merge pull request #769 from haraldk/dependabot/maven/org.apache.maven.scm-maven-scm-provider-gitexe-2.0.1
Bump maven-scm-provider-gitexe from 1.11.2 to 2.0.1
2023-05-25 14:54:07 +02:00
Harald Kuhr 9162458e36 Merge pull request #765 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-deploy-plugin-3.1.1
Bump maven-deploy-plugin from 3.0.0-M1 to 3.1.1
2023-05-25 14:53:56 +02:00
Harald Kuhr d38af3cb16 Merge pull request #761 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-gpg-plugin-3.1.0
Bump maven-gpg-plugin from 1.6 to 3.1.0
2023-05-25 14:53:41 +02:00
Harald Kuhr c57e8f80fa Merge pull request #763 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.4.1
Bump maven-shade-plugin from 3.2.2 to 3.4.1
2023-05-25 14:39:24 +02:00
Harald Kuhr 4750359ada Merge pull request #766 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.5.0
Bump maven-javadoc-plugin from 3.2.0 to 3.5.0
2023-05-25 14:35:45 +02:00
Harald Kuhr cbe8038619 Merge pull request #767 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-jar-plugin-3.3.0
Bump maven-jar-plugin from 2.4 to 3.3.0
2023-05-25 14:33:30 +02:00
Harald Kuhr 2d8125e69c Manual mockito bump 2023-05-25 14:29:32 +02:00
Harald Kuhr 57a664c093 Merge pull request #764 from haraldk/dependabot/maven/commons-io-commons-io-2.12.0
Bump commons-io from 2.11.0 to 2.12.0
2023-05-25 14:00:06 +02:00
Harald Kuhr 7f82377fd7 Merge pull request #762 from haraldk/dependabot/maven/javax.servlet-servlet-api-2.5
Bump servlet-api from 2.4 to 2.5
2023-05-25 13:59:05 +02:00
dependabot[bot] 72b9f19a51 Bump nexus-staging-maven-plugin from 1.6.8 to 1.6.13
Bumps nexus-staging-maven-plugin from 1.6.8 to 1.6.13.

---
updated-dependencies:
- dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:55:57 +00:00
dependabot[bot] 0083b8e77e Bump maven-scm-provider-gitexe from 1.11.2 to 2.0.1
Bumps maven-scm-provider-gitexe from 1.11.2 to 2.0.1.

---
updated-dependencies:
- dependency-name: org.apache.maven.scm:maven-scm-provider-gitexe
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:55:55 +00:00
dependabot[bot] 79982cd493 Bump maven-jar-plugin from 2.4 to 3.3.0
Bumps [maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 2.4 to 3.3.0.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-2.4...maven-jar-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-jar-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:55:46 +00:00
dependabot[bot] f0db338f3b Bump maven-javadoc-plugin from 3.2.0 to 3.5.0
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.2.0 to 3.5.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.2.0...maven-javadoc-plugin-3.5.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:55:41 +00:00
Harald Kuhr 9db4e0b3ed More Dependabot PRs, please 2023-05-25 13:55:14 +02:00
Harald Kuhr cd4cbdcb82 Merge pull request #760 from haraldk/dependabot/github_actions/dot-github/workflows/mikepenz/action-junit-report-3.7.7
Bump mikepenz/action-junit-report from 3.7.6 to 3.7.7 in /.github/workflows
2023-05-25 13:45:06 +02:00
dependabot[bot] 15dc4b3852 Bump maven-deploy-plugin from 3.0.0-M1 to 3.1.1
Bumps [maven-deploy-plugin](https://github.com/apache/maven-deploy-plugin) from 3.0.0-M1 to 3.1.1.
- [Release notes](https://github.com/apache/maven-deploy-plugin/releases)
- [Commits](https://github.com/apache/maven-deploy-plugin/compare/maven-deploy-plugin-3.0.0-M1...maven-deploy-plugin-3.1.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-deploy-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:43:04 +00:00
dependabot[bot] a3534ecd59 Bump commons-io from 2.11.0 to 2.12.0
Bumps commons-io from 2.11.0 to 2.12.0.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:43:00 +00:00
dependabot[bot] 7bb5fee23b Bump maven-shade-plugin from 3.2.2 to 3.4.1
Bumps [maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.2.2 to 3.4.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.2.2...maven-shade-plugin-3.4.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-shade-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:42:57 +00:00
dependabot[bot] 6cb7424bd0 Bump servlet-api from 2.4 to 2.5
Bumps servlet-api from 2.4 to 2.5.

---
updated-dependencies:
- dependency-name: javax.servlet:servlet-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:42:53 +00:00
dependabot[bot] 9aa04d311e Bump maven-gpg-plugin from 1.6 to 3.1.0
Bumps [maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 1.6 to 3.1.0.
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-1.6...maven-gpg-plugin-3.1.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:42:51 +00:00
dependabot[bot] 967e71dc92 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 3.7.6 to 3.7.7.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/959aefb7f095e717eb407fe917238d61ca323ff3...c0e4b81aaa0067314a2d0d06e19b512c9d8af4f5)

---
updated-dependencies:
- dependency-name: mikepenz/action-junit-report
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 11:42:47 +00:00
Harald Kuhr 628523ddc8 Dependabot workflow updates 2023-05-25 13:42:21 +02:00
Harald Kuhr 783c28ae0e More lenient test, using dynamic local port. 2023-05-25 12:16:38 +02:00
Harald Kuhr d35d67651f Merge pull request #759 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-resources-plugin-3.3.1
Bump maven-resources-plugin from 3.2.0 to 3.3.1
2023-05-25 12:15:21 +02:00
Harald Kuhr 816d48efef Merge pull request #758 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-pmd-plugin-3.21.0
Bump maven-pmd-plugin from 3.14.0 to 3.21.0
2023-05-25 12:15:07 +02:00
Harald Kuhr 25ee21d090 Merge pull request #757 from haraldk/dependabot/maven/junit-junit-4.13.2
Bump junit from 4.13.1 to 4.13.2
2023-05-25 12:02:51 +02:00
Harald Kuhr 536ea7ba88 Merge pull request #756 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-checkstyle-plugin-3.3.0
Bump maven-checkstyle-plugin from 3.1.2 to 3.3.0
2023-05-25 12:02:36 +02:00
Harald Kuhr d2687383f5 Merge pull request #755 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-help-plugin-3.4.0
Bump maven-help-plugin from 3.2.0 to 3.4.0
2023-05-25 11:39:05 +02:00
dependabot[bot] 3ce35e059c Bump maven-resources-plugin from 3.2.0 to 3.3.1
Bumps [maven-resources-plugin](https://github.com/apache/maven-resources-plugin) from 3.2.0 to 3.3.1.
- [Release notes](https://github.com/apache/maven-resources-plugin/releases)
- [Commits](https://github.com/apache/maven-resources-plugin/compare/maven-resources-plugin-3.2.0...maven-resources-plugin-3.3.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-resources-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 09:08:40 +00:00
dependabot[bot] 1d5359dd35 Bump maven-pmd-plugin from 3.14.0 to 3.21.0
Bumps [maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.14.0 to 3.21.0.
- [Release notes](https://github.com/apache/maven-pmd-plugin/releases)
- [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.14.0...maven-pmd-plugin-3.21.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-pmd-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 09:08:34 +00:00
dependabot[bot] 2699b75b79 Bump junit from 4.13.1 to 4.13.2
Bumps [junit](https://github.com/junit-team/junit4) from 4.13.1 to 4.13.2.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.13.1...r4.13.2)

---
updated-dependencies:
- dependency-name: junit:junit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 09:08:30 +00:00
dependabot[bot] 4e614dfc7e Bump maven-checkstyle-plugin from 3.1.2 to 3.3.0
Bumps [maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.1.2 to 3.3.0.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.1.2...maven-checkstyle-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 09:08:23 +00:00
dependabot[bot] 3a2efd9491 Bump maven-help-plugin from 3.2.0 to 3.4.0
Bumps [maven-help-plugin](https://github.com/apache/maven-help-plugin) from 3.2.0 to 3.4.0.
- [Commits](https://github.com/apache/maven-help-plugin/compare/maven-help-plugin-3.2.0...maven-help-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-help-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 09:08:18 +00:00
Harald Kuhr c5dc2e4e53 Update README.md 2023-05-25 10:29:09 +02:00
Harald Kuhr 41460bd32a JDK 20 compliance 2023-05-24 21:43:33 +02:00
Harald Kuhr 13b37b3839 Use Maven in batch mode! 2023-05-24 20:34:21 +02:00
Harald Kuhr 6dd74070f4 Remove transfer progress from Maven deploy output 2023-05-24 20:27:26 +02:00
Harald Kuhr 81b358b377 Attempt to fix problem with upgraded maven source plugin, take 2 2023-05-24 20:14:28 +02:00
Harald Kuhr 9715f4e74c Attempt to fix problem with upgraded maven source plugin. 2023-05-24 20:04:16 +02:00
Harald Kuhr 38256c8be0 Merge pull request #754 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-surefire-report-plugin-3.1.0
Bump maven-surefire-report-plugin from 3.0.0-M5 to 3.1.0
2023-05-24 19:21:44 +02:00
Harald Kuhr bf3c1fad17 Merge pull request #753 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-release-plugin-3.0.0
Bump maven-release-plugin from 3.0.0-M4 to 3.0.0
2023-05-24 19:21:16 +02:00
Harald Kuhr b8488ae39b Merge pull request #751 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-source-plugin-3.3.0
Bump maven-source-plugin from 3.2.1 to 3.3.0
2023-05-24 19:19:54 +02:00
Harald Kuhr d3bea0ae38 Merge pull request #752 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-compiler-plugin-3.11.0
Bump maven-compiler-plugin from 3.8.1 to 3.11.0
2023-05-24 19:19:15 +02:00
Harald Kuhr 9435410b1e Merge pull request #750 from haraldk/dependabot/maven/org.apache.maven.plugins-maven-surefire-plugin-3.1.0
Bump maven-surefire-plugin from 3.0.0-M5 to 3.1.0
2023-05-24 19:18:44 +02:00
Harald Kuhr f74e8c8ba1 Stop dependabot causing double workflow runs. 2023-05-24 18:48:32 +02:00
dependabot[bot] 0ae2c2f01d Bump maven-surefire-report-plugin from 3.0.0-M5 to 3.1.0
Bumps [maven-surefire-report-plugin](https://github.com/apache/maven-surefire) from 3.0.0-M5 to 3.1.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0-M5...surefire-3.1.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-report-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-24 16:23:01 +00:00
dependabot[bot] 77c81a06bc Bump maven-release-plugin from 3.0.0-M4 to 3.0.0
Bumps [maven-release-plugin](https://github.com/apache/maven-release) from 3.0.0-M4 to 3.0.0.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.0-M4...maven-release-3.0.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-release-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-24 16:22:56 +00:00
dependabot[bot] 2bbcd88798 Bump maven-compiler-plugin from 3.8.1 to 3.11.0
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.8.1 to 3.11.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.8.1...maven-compiler-plugin-3.11.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-24 16:22:53 +00:00
dependabot[bot] 829fbe7547 Bump maven-source-plugin from 3.2.1 to 3.3.0
Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.2.1 to 3.3.0.
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.1...maven-source-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-source-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-24 16:22:49 +00:00
dependabot[bot] 078425eed9 Bump maven-surefire-plugin from 3.0.0-M5 to 3.1.0
Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.0.0-M5 to 3.1.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0-M5...surefire-3.1.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-24 16:22:44 +00:00
Harald Kuhr 8ddcbbd2b2 Create dependabot.yml 2023-05-24 18:22:20 +02:00
Harald Kuhr 507cca5fd7 Merge pull request #749 from joycebrum/master
Hash pin ci.yml
2023-05-24 18:12:15 +02:00
Joyce a4caac0c82 Hash pin ci.yml 2023-05-22 17:46:55 -03:00
Harald Kuhr 54c07b849c Added logo to README.md 2023-04-17 20:11:16 +02:00
Harald Kuhr c531d4f5d3 Reverted test, glossed over flakyness in library instead. 2023-04-04 16:30:45 +02:00
Harald Kuhr aa2e8e5d7e Fix flaky old test. 2023-04-04 16:06:42 +02:00
Harald Kuhr 76a35331b0 #744 TIFF: Re-complicated TIFF writing for the sake of performance... 2023-04-04 15:41:42 +02:00
Harald Kuhr 6b3f1c6ee3 #740 TIFF: Floating point predictor support. 2023-03-24 08:54:31 +01:00
Harald Kuhr c731e10e8f Merge pull request #742 from joycebrum/master
Create a Security Policy
2023-03-21 20:29:00 +01:00
Joyce 4a8c3530f7 Update SECURITY.md 2023-03-21 10:10:34 -03:00
Joyce e8996daa12 Update SECURITY.md to best effort 2023-03-21 10:03:27 -03:00
Joyce 9196e60c74 Create SECURITY.md 2023-03-20 14:49:44 -03:00
Harald Kuhr eabb8fd02b WebP cleanup. 2023-03-18 11:40:47 +01:00
Harald Kuhr 1794e336de WebP minor bugfix and optimization. 2023-03-18 11:34:24 +01:00
Harald Kuhr ac7612b3df WebP cleanup 2023-03-18 11:33:29 +01:00
Harald Kuhr 606fd53823 #738 PSD: No longer decompress PackBits across boundaries 2023-03-18 10:33:34 +01:00
Harald Kuhr 614a07e040 Merge pull request #737 from tc-wleite/WebP_FixAlphaSubsampling
WebP: Fix alpha decoding when source subsampling is used
2023-03-16 11:59:27 +01:00
tc-wleite 34e8d88007 Avoid creating another temporary raster, filtering on the tempRaster. 2023-03-15 17:23:53 -03:00
tc-wleite 9b727df901 Remove the TODO comment. 2023-03-15 16:56:46 -03:00
tc-wleite f1f98bb4a4 Use a static import. 2023-03-15 16:56:08 -03:00
tc-wleite b34b26e08c Let copyIntoRasterWithParams() handle null param. 2023-03-15 16:53:27 -03:00
Wladimir Leite 993e07ee34 Accept and handle null param in copyIntoRasterWithParams().
Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2023-03-15 16:47:53 -03:00
tc-wleite a377712bdb Replace the WebP to test alpha subsampling by a slightly smaller image. 2023-03-15 16:39:50 -03:00
tc-wleite e5dc6aa878 Add the new image to the basic reading test. 2023-03-15 11:44:35 -03:00
tc-wleite 46b1c1cf96 Test if a WebP with alpha was read correctly using subsampling. 2023-03-15 11:43:51 -03:00
tc-wleite d9300b1c90 Add to resources a test WebP with alpha and filters. 2023-03-15 11:39:10 -03:00
tc-wleite 0a2efb9eac Param can be null in readAlpha(). Copy alphaRaster to dst in this case. 2023-03-15 11:15:17 -03:00
tc-wleite 3eabc591d8 Fix: use raster instead of decodedRaster to keep previous behavior. 2023-03-15 09:39:10 -03:00
tc-wleite 5cefce2dbf Minor fix in code formatting. 2023-03-14 21:21:28 -03:00
tc-wleite 4c645c0220 Fix TODO comment message. 2023-03-14 21:04:59 -03:00
tc-wleite 703848ca45 Decode alpha using source dimensions and copy to destination later. 2023-03-14 21:01:29 -03:00
tc-wleite 0ebd18fcb6 Move to a static method the code that copies into a raster with params. 2023-03-14 20:59:54 -03:00
Harald Kuhr 29f7547a99 CI: Suppress download progress messages 2023-03-09 13:05:32 +01:00
Harald Kuhr 25cd351eee Servlet: Now logs a message on context startup to aid debugging.
+ bonus generic refactorings
2023-03-09 12:17:20 +01:00
Harald Kuhr 77c98c917e #733: Stricter permissions 2023-03-01 09:54:36 +01:00
Harald Kuhr 4bbe946f46 Merge pull request #731 from daaaaa/master
PSD: Add missing guide info in metadata
2023-02-01 10:17:39 +01:00
Davide Tantillo 78832ed923 PSD: Add missing guide info in metadata 2023-01-31 23:49:44 +01:00
Harald Kuhr 164cc11592 New versions, FAQ additions ++ 2022-11-23 15:41:57 +01:00
Harald Kuhr 8f5c1b409f #712 Core: Fix possible OOM situation in new stream implementation 2022-11-21 16:15:21 +01:00
Harald Kuhr 26981513d8 #714 PNM: Add support for writing TYPE_INT_* images + implementation of WriterSpi.canEncode 2022-11-21 16:13:54 +01:00
Harald Kuhr a3a30d54d4 Merge pull request #715 from KoenDG/batik_new
Batik upgraded to 1.16
2022-11-15 13:39:31 +01:00
Koen De Groote 102e9cff51 Batik upgraded to 1.16 2022-11-14 17:27:32 +01:00
Harald Kuhr da800be8c8 #713 PSD: Broken uncompressed reading from stream w/unknown length 2022-11-10 16:11:45 +01:00
Harald Kuhr 70493bd323 Merge pull request #710 from haraldk/snyk-fix-1db7a7baf4764ce7cab80fb2bc152b73
[Snyk] Fix for 2 vulnerabilities
2022-11-01 11:59:49 +01:00
snyk-bot 304d050bc3 fix: imageio/imageio-batik/pom.xml to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JAVA-ORGAPACHEXMLGRAPHICS-3063442
- https://snyk.io/vuln/SNYK-JAVA-ORGAPACHEXMLGRAPHICS-3063691
2022-10-27 04:06:55 +00:00
Harald Kuhr 0443172666 #708 PSD: No longer emit warning for '8B64' (64 bit/long) resources. 2022-10-20 17:06:52 +02:00
Harald Kuhr cee2663f06 #707 WebP: Fix Alpha support the correct way... 2022-10-20 16:09:02 +02:00
Harald Kuhr 8f44cfc43c #707 WebP: Fix Alpha support 2022-10-20 16:00:12 +02:00
Harald Kuhr 8a240aac68 #704 Fix LSBBitReader to avoid back/forth seeking that invalidates buffer 2022-10-20 13:57:11 +02:00
Harald Kuhr 61424f33b6 #704 Tiny performance improvement + code clean-up 2022-10-19 20:46:24 +02:00
Harald Kuhr c7b9b1fadd Code clean-up. 2022-10-19 20:45:41 +02:00
Harald Kuhr ab08ec1e0d #705 No longer closes streams we didn't open 2022-10-18 20:25:31 +02:00
Harald Kuhr cbe78dc67f ...and removed System.out.. Ouch... 2022-10-18 16:08:03 +02:00
Harald Kuhr c9e11f171f Fixed typo... 2022-10-18 16:05:54 +02:00
Harald Kuhr bc2c0c2301 [maven-release-plugin] prepare for next development iteration 2022-10-15 12:12:53 +02:00
113 changed files with 2325 additions and 1044 deletions
+13
View File
@@ -0,0 +1,13 @@
version: 2
updates:
# Maven/Java library updates
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 10
# GitHub actions updates
- package-ecosystem: "github-actions"
directory: "/.github/workflows"
schedule:
interval: "daily"
+27 -15
View File
@@ -1,6 +1,14 @@
name: CI
on: [ push, pull_request ]
on:
push:
branches:
- '**'
- '!dependabot/**'
pull_request:
branches: [ 'master' ]
permissions: read-all
jobs:
test:
@@ -9,20 +17,22 @@ jobs:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
java: [ 8, 11, 17, 18 ]
java: [ 8, 11, 17, 21 ]
runs-on: ${{ matrix.os }}
permissions:
checks: write
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
java-package: jdk
cache: 'maven'
- name: Run Tests
run: mvn test
run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report
uses: mikepenz/action-junit-report@v3
uses: mikepenz/action-junit-report@0831a82caad2465c31c6dd929978f640cb42556c # v4.0.3
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
@@ -31,15 +41,17 @@ jobs:
test_oracle:
name: Test Oracle JDK 8 with KCMS=${{ matrix.kcms }}
runs-on: ubuntu-latest
permissions:
checks: write
strategy:
matrix:
kcms: [ true, false ]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- 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@v3
- uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0
with:
distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz
@@ -52,9 +64,9 @@ jobs:
- name: Display Java version
run: java -version
- name: Run Tests
run: mvn test
run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report
uses: mikepenz/action-junit-report@v3
uses: mikepenz/action-junit-report@0831a82caad2465c31c6dd929978f640cb42556c # v4.0.3
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
@@ -66,9 +78,9 @@ jobs:
if: github.ref == 'refs/heads/master' # only perform on latest master
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Set up Maven Central
uses: actions/setup-java@v3
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0
with: # running setup-java again overwrites the settings.xml
distribution: 'temurin'
java-version: '8'
@@ -80,11 +92,11 @@ jobs:
gpg-passphrase: MAVEN_CENTRAL_GPG_PASSPHRASE # env variable for GPG private key passphrase (3)
- name: Get Project Version
run: |
echo "PROJECT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
echo "PROJECT_VERSION=$(mvn --batch-mode help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
- name: Publish to Maven Central
if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }}
run: mvn deploy -P release -DskipTests
run: mvn --batch-mode --no-transfer-progress deploy -P release -DskipTests
env:
MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} # must be the same env variable name as (1)
MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # must be the same env variable name as (2)
MAVEN_CENTRAL_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} # must be the same env variable name as (3)
MAVEN_CENTRAL_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} # must be the same env variable name as (3)
+69
View File
@@ -0,0 +1,69 @@
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
schedule:
- cron: '26 13 * * 6'
permissions: {}
jobs:
analyze:
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
with:
category: "/language:${{matrix.language}}"
+62
View File
@@ -0,0 +1,62 @@
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '38 8 * * 2'
push:
branches: [ "master" ]
permissions: read-all # Declare default permissions as read only.
jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
security-events: write # to upload the results to code-scanning dashboard.
id-token: write # to publish results and get a badge
steps:
- name: "Checkout code"
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# you want to enable the Branch-Protection check on the repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-fine-grained-pat-optional.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
# Publish Results:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@74483a38d39275f33fcff5f35b679b5ca4a26a99 # v2.22.5
with:
sarif_file: results.sarif
+1
View File
@@ -15,3 +15,4 @@ private
profiles.xml
Thumbs.db
.DS_Store
/.metadata/
+63 -73
View File
@@ -1,9 +1,15 @@
[![CI](https://github.com/haraldk/TwelveMonkeys/actions/workflows/ci.yml/badge.svg)](https://github.com/haraldk/TwelveMonkeys/actions/workflows/ci.yml)
[![CodeQL](https://github.com/haraldk/TwelveMonkeys/actions/workflows/codeql.yml/badge.svg)](https://github.com/haraldk/TwelveMonkeys/actions/workflows/codeql.yml)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/haraldk/TwelveMonkeys/badge)](https://securityscorecards.dev/viewer/?uri=github.com/haraldk/TwelveMonkeys)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7900/badge)](https://www.bestpractices.dev/projects/7900)
[![Maven Central](https://img.shields.io/maven-central/v/com.twelvemonkeys.imageio/imageio?color=slateblue)](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio)
[![Maven Snapshot](https://img.shields.io/nexus/s/com.twelvemonkeys.imageio/imageio?label=development&server=https%3A%2F%2Foss.sonatype.org&color=slateblue)](https://oss.sonatype.org/content/repositories/snapshots/com/twelvemonkeys/)
[![StackOverflow](https://img.shields.io/badge/stack_overflow-twelvemonkeys-orange.svg)](https://stackoverflow.com/questions/tagged/twelvemonkeys)
[![Donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/haraldk76/100)
![Logo](logo.png)
## About
TwelveMonkeys ImageIO provides extended image file format support for the Java platform, through plugins for the `javax.imageio.*` package.
@@ -272,12 +278,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.8.1</version>
<version>3.9.4</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.8.1</version>
<version>3.9.4</version>
</dependency>
<!--
@@ -287,7 +293,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.8.1</version>
<version>3.9.4</version>
</dependency>
<!--
@@ -296,7 +302,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.8.1</version>
<version>3.9.4</version>
<classifier>jakarta</classifier>
</dependency>
</dependencies>
@@ -306,13 +312,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.8.1.jar
twelvemonkeys-common-io-3.8.1.jar
twelvemonkeys-common-image-3.8.1.jar
twelvemonkeys-imageio-core-3.8.1.jar
twelvemonkeys-imageio-metadata-3.8.1.jar
twelvemonkeys-imageio-jpeg-3.8.1.jar
twelvemonkeys-imageio-tiff-3.8.1.jar
twelvemonkeys-common-lang-3.9.4.jar
twelvemonkeys-common-io-3.9.4.jar
twelvemonkeys-common-image-3.9.4.jar
twelvemonkeys-imageio-core-3.9.4.jar
twelvemonkeys-imageio-metadata-3.9.4.jar
twelvemonkeys-imageio-jpeg-3.9.4.jar
twelvemonkeys-imageio-tiff-3.9.4.jar
#### Deploying the plugins in a web app
@@ -378,81 +384,50 @@ Other "fat" JAR bundlers will probably have similar mechanisms to merge entries
### Links to prebuilt binaries
##### Latest version (3.8.1)
##### Latest version (3.9.4)
Requires Java 7 or later.
The latest version that will run on Java 7 is 3.9.4. Later versions will require Java 8 or later.
Common dependencies
* [common-lang-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.8.1/common-lang-3.8.1.jar)
* [common-io-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.8.1/common-io-3.8.1.jar)
* [common-image-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.8.1/common-image-3.8.1.jar)
* [common-lang-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.9.4/common-lang-3.9.4.jar)
* [common-io-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.9.4/common-io-3.9.4.jar)
* [common-image-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.9.4/common-image-3.9.4.jar)
ImageIO dependencies
* [imageio-core-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.8.1/imageio-core-3.8.1.jar)
* [imageio-metadata-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.8.1/imageio-metadata-3.8.1.jar)
* [imageio-core-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.9.4/imageio-core-3.9.4.jar)
* [imageio-metadata-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.9.4/imageio-metadata-3.9.4.jar)
ImageIO plugins
* [imageio-bmp-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.8.1/imageio-bmp-3.8.1.jar)
* [imageio-hdr-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.8.1/imageio-hdr-3.8.1.jar)
* [imageio-icns-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.8.1/imageio-icns-3.8.1.jar)
* [imageio-iff-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.8.1/imageio-iff-3.8.1.jar)
* [imageio-jpeg-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.8.1/imageio-jpeg-3.8.1.jar)
* [imageio-pcx-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.8.1/imageio-pcx-3.8.1.jar)
* [imageio-pict-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.8.1/imageio-pict-3.8.1.jar)
* [imageio-pnm-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.8.1/imageio-pnm-3.8.1.jar)
* [imageio-psd-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.8.1/imageio-psd-3.8.1.jar)
* [imageio-sgi-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.8.1/imageio-sgi-3.8.1.jar)
* [imageio-tga-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.8.1/imageio-tga-3.8.1.jar)
* [imageio-thumbsdb-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.8.1/imageio-thumbsdb-3.8.1.jar)
* [imageio-tiff-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.8.1/imageio-tiff-3.8.1.jar)
* [imageio-webp-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.8.1/imageio-webp-3.8.1.jar)
* [imageio-xwd-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.8.1/imageio-xwd-3.8.1.jar)
* [imageio-bmp-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.9.4/imageio-bmp-3.9.4.jar)
* [imageio-hdr-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.9.4/imageio-hdr-3.9.4.jar)
* [imageio-icns-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.9.4/imageio-icns-3.9.4.jar)
* [imageio-iff-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.9.4/imageio-iff-3.9.4.jar)
* [imageio-jpeg-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.9.4/imageio-jpeg-3.9.4.jar)
* [imageio-pcx-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.9.4/imageio-pcx-3.9.4.jar)
* [imageio-pict-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.9.4/imageio-pict-3.9.4.jar)
* [imageio-pnm-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.9.4/imageio-pnm-3.9.4.jar)
* [imageio-psd-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.9.4/imageio-psd-3.9.4.jar)
* [imageio-sgi-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.9.4/imageio-sgi-3.9.4.jar)
* [imageio-tga-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.9.4/imageio-tga-3.9.4.jar)
* [imageio-thumbsdb-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.9.4/imageio-thumbsdb-3.9.4.jar)
* [imageio-tiff-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.9.4/imageio-tiff-3.9.4.jar)
* [imageio-webp-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.9.4/imageio-webp-3.9.4.jar)
* [imageio-xwd-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.9.4/imageio-xwd-3.9.4.jar)
ImageIO plugins requiring 3rd party libs
* [imageio-batik-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.8.1/imageio-batik-3.8.1.jar)
* [imageio-batik-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.9.4/imageio-batik-3.9.4.jar)
Photoshop Path support for ImageIO
* [imageio-clippath-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.8.1/imageio-clippath-3.8.1.jar)
* [imageio-clippath-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.9.4/imageio-clippath-3.9.4.jar)
Servlet support
* [servlet-3.8.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.8.1/servlet-3.8.1.jar)
##### Old version (3.0.x)
Use this version for projects that requires Java 6 or need the JMagick support. *Does not support Java 8 or later*.
Common dependencies
* [common-lang-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.0.2/common-lang-3.0.2.jar)
* [common-io-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.0.2/common-io-3.0.2.jar)
* [common-image-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.0.2/common-image-3.0.2.jar)
ImageIO dependencies
* [imageio-core-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.0.2/imageio-core-3.0.2.jar)
* [imageio-metadata-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.0.2/imageio-metadata-3.0.2.jar)
ImageIO plugins
* [imageio-jpeg-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.0.2/imageio-jpeg-3.0.2.jar)
* [imageio-tiff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.0.2/imageio-tiff-3.0.2.jar)
* [imageio-psd-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.0.2/imageio-psd-3.0.2.jar)
* [imageio-pict-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.0.2/imageio-pict-3.0.2.jar)
* [imageio-iff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.0.2/imageio-iff-3.0.2.jar)
* [imageio-icns-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.0.2/imageio-icns-3.0.2.jar)
* [imageio-ico-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-ico/3.0.2/imageio-ico-3.0.2.jar)
* [imageio-thumbsdb-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.0.2/imageio-thumbsdb-3.0.2.jar)
ImageIO plugins requiring 3rd party libs
* [imageio-batik-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.0.2/imageio-batik-3.0.2.jar)
* [imageio-jmagick-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jmagick/3.0.2/imageio-jmagick-3.0.2.jar)
Servlet support
* [servlet-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.0.2/servlet-3.0.2.jar)
* [servlet-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.9.4/servlet-3.9.4.jar)
## License
This project is provided under the OSI approved [BSD license](https://opensource.org/licenses/BSD-3-Clause):
Copyright (c) 2008-2020, Harald Kuhr
Copyright (c) 2008-2022, Harald Kuhr
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -484,8 +459,9 @@ This project is provided under the OSI approved [BSD license](https://opensource
q: How do I use it?
a: The easiest way is to build your own project using Maven, and just add dependencies to the specific plug-ins you need.
If you don't use Maven, make sure you have all the necessary JARs in classpath. See the Install section above.
a: The easiest way is to build your own project using Maven, Gradle or other build tool with dependency management,
and just add dependencies to the specific plug-ins you need.
If you don't use such a build tool, make sure you have all the necessary JARs in classpath. See the Install section above.
q: What changes do I have to make to my code in order to use the plug-ins?
@@ -503,22 +479,36 @@ q: How does it work?
a: The TwelveMonkeys ImageIO project contains plug-ins for ImageIO. ImageIO uses a service lookup mechanism, to discover plug-ins at runtime.
All you have have to do, is to make sure you have the TwelveMonkeys JARs in your classpath.
All you have to do, is to make sure you have the TwelveMonkeys ImageIO JARs in your classpath.
You can read more about the registry and the lookup mechanism in the [IIORegistry API doc](https://docs.oracle.com/javase/7/docs/api/javax/imageio/spi/IIORegistry.html).
The fine print: The TwelveMonkeys service providers for JPEG, BMP and TIFF, overrides the onRegistration method, and
utilizes the pairwise partial ordering mechanism of the `IIOServiceRegistry` to make sure it is installed before
the Sun/Oracle provided `JPEGImageReader` and `BMPImageReader`, and the Apple provided `TIFFImageReader` on OS X,
the Sun/Oracle provided `JPEGImageReader`, `BMPImageReader` `TIFFImageReader`, and the Apple provided `TIFFImageReader` on OS X,
respectively. Using the pairwise ordering will not remove any functionality form these implementations, but in most
cases you'll end up using the TwelveMonkeys plug-ins instead.
q: Why is there no support for common formats like GIF or PNG?
a: The short answer is simply that the built-in support in ImageIO for these formats are good enough as-is.
a: The short answer is simply that the built-in support in ImageIO for these formats are considered good enough as-is.
If you are looking for better PNG write performance on Java 7 and 8, see [JDK9 PNG Writer Backport](https://github.com/gredler/jdk9-png-writer-backport).
q: When is the next release? What is the current release schedule?
a: The goal is to make monthly releases, containing bug fixes and minor new features.
And quarterly releases with more "major" features.
q: I love this project! How can I help?
a: Have a look at the open issues, and see if there are any issues you can help fix, or provide sample file or create test cases for.
It is also possible for you or your organization to become a sponsor, through GitHub Sponsors.
Providing funding will allow us to spend more time on fixing bugs and implementing new features.
q: What about JAI? Several of the formats are already supported by JAI.
a: While JAI (and jai-imageio in particular) have support for some of the same formats, JAI has some major issues.
+5
View File
@@ -0,0 +1,5 @@
# Security Policy
To report a security issue, please disclose it at [security advisory](https://github.com/haraldk/TwelveMonkeys/security/advisories/new).
Vulnerabilities will be disclosed in a best effort base.
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.bom</groupId>
+11 -2
View File
@@ -4,13 +4,13 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>common-image</artifactId>
<packaging>jar</packaging>
<name>TwelveMonkeys :: Common :: Image</name>
<description>
The TwelveMonkeys Common Image support
TwelveMonkeys Common image support classes.
</description>
<properties>
@@ -36,4 +36,13 @@
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -79,7 +79,7 @@ public final class BufferedImageFactory {
private int scanSize;
private ColorModel sourceColorModel;
private Hashtable sourceProperties; // ImageConsumer API dictates Hashtable
private Hashtable<?, ?> sourceProperties; // ImageConsumer API dictates Hashtable
private Object sourcePixels;
@@ -91,21 +91,21 @@ public final class BufferedImageFactory {
/**
* Creates a {@code BufferedImageFactory}.
* @param pSource the source image
* @throws IllegalArgumentException if {@code pSource == null}
* @param source the source image
* @throws IllegalArgumentException if {@code source == null}
*/
public BufferedImageFactory(final Image pSource) {
this(pSource != null ? pSource.getSource() : null);
public BufferedImageFactory(final Image source) {
this(source != null ? source.getSource() : null);
}
/**
* Creates a {@code BufferedImageFactory}.
* @param pSource the source image producer
* @throws IllegalArgumentException if {@code pSource == null}
* @param source the source image producer
* @throws IllegalArgumentException if {@code source == null}
*/
public BufferedImageFactory(final ImageProducer pSource) {
Validate.notNull(pSource, "source");
producer = pSource;
public BufferedImageFactory(final ImageProducer source) {
Validate.notNull(source, "source");
producer = source;
}
/**
@@ -155,44 +155,44 @@ public final class BufferedImageFactory {
/**
* Sets the source region (AOI) for the new image.
*
* @param pRegion the source region
* @param region the source region
*/
public void setSourceRegion(final Rectangle pRegion) {
public void setSourceRegion(final Rectangle region) {
// Re-fetch everything, if region changed
if (x != pRegion.x || y != pRegion.y || width != pRegion.width || height != pRegion.height) {
if (x != region.x || y != region.y || width != region.width || height != region.height) {
dispose();
}
x = pRegion.x;
y = pRegion.y;
width = pRegion.width;
height = pRegion.height;
x = region.x;
y = region.y;
width = region.width;
height = region.height;
}
/**
* Sets the source subsampling for the new image.
*
* @param pXSub horizontal subsampling factor
* @param pYSub vertical subsampling factor
* @param xSubsampling horizontal subsampling factor
* @param ySubsampling vertical subsampling factor
*/
public void setSourceSubsampling(int pXSub, int pYSub) {
public void setSourceSubsampling(int xSubsampling, int ySubsampling) {
// Re-fetch everything, if subsampling changed
if (xSub != pXSub || ySub != pYSub) {
if (xSub != xSubsampling || ySub != ySubsampling) {
dispose();
}
if (pXSub > 1) {
xSub = pXSub;
if (xSubsampling > 1) {
xSub = xSubsampling;
}
if (pYSub > 1) {
ySub = pYSub;
if (ySubsampling > 1) {
ySub = ySubsampling;
}
}
private synchronized void doFetch(boolean pColorModelOnly) throws ImageConversionException {
if (!fetching && (!pColorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
private synchronized void doFetch(final boolean colorModelOnly) throws ImageConversionException {
if (!fetching && (!colorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
// NOTE: Subsampling is only applied if extracting full image
if (!pColorModelOnly && (xSub > 1 || ySub > 1)) {
if (!colorModelOnly && (xSub > 1 || ySub > 1)) {
// If only sampling a region, the region must be scaled too
if (width > 0 && height > 0) {
width = (width + xSub - 1) / xSub;
@@ -207,38 +207,41 @@ public final class BufferedImageFactory {
// Start fetching
fetching = true;
readColorModelOnly = pColorModelOnly;
readColorModelOnly = colorModelOnly;
producer.startProduction(consumer); // Note: If single-thread (synchronous), this call will block
// Wait until the producer wakes us up, by calling imageComplete
while (fetching) {
try {
wait(200l);
wait(200L);
}
catch (InterruptedException e) {
throw new ImageConversionException("Image conversion aborted: " + e.getMessage(), e);
}
}
if (consumerException != null) {
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
}
try {
if (consumerException != null) {
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
}
if (pColorModelOnly) {
createColorModel();
if (colorModelOnly) {
createColorModel();
}
else {
createBuffered();
}
}
else {
createBuffered();
finally {
// Clean up, in case any objects are copied/cloned, so we can free resources
freeResources();
}
}
}
private void createColorModel() {
colorModel = sourceColorModel;
// Clean up, in case any objects are copied/cloned, so we can free resources
freeResources();
}
private void createBuffered() {
@@ -253,8 +256,9 @@ public final class BufferedImageFactory {
}
}
// Clean up, in case any objects are copied/cloned, so we can free resources
freeResources();
if (buffered == null) {
throw new ImageConversionException("Could not create BufferedImage");
}
}
private void freeResources() {
@@ -280,27 +284,27 @@ public final class BufferedImageFactory {
/**
* Adds a progress listener to this factory.
*
* @param pListener the progress listener
* @param listener the progress listener
*/
public void addProgressListener(ProgressListener pListener) {
if (pListener == null) {
public void addProgressListener(ProgressListener listener) {
if (listener == null) {
return;
}
if (listeners == null) {
listeners = new CopyOnWriteArrayList<ProgressListener>();
listeners = new CopyOnWriteArrayList<>();
}
listeners.add(pListener);
listeners.add(listener);
}
/**
* Removes a progress listener from this factory.
*
* @param pListener the progress listener
* @param listener the progress listener
*/
public void removeProgressListener(ProgressListener pListener) {
if (pListener == null) {
public void removeProgressListener(ProgressListener listener) {
if (listener == null) {
return;
}
@@ -308,7 +312,7 @@ public final class BufferedImageFactory {
return;
}
listeners.remove(pListener);
listeners.remove(listener);
}
/**
@@ -324,21 +328,22 @@ public final class BufferedImageFactory {
* Converts an array of {@code int} pixels to an array of {@code short}
* pixels. The conversion is done, by masking out the
* <em>higher 16 bits</em> of the {@code int}.
*
* <p>
* For any given {@code int}, the {@code short} value is computed as
* follows:
* <blockquote>{@code
* short value = (short) (intValue & 0x0000ffff);
* }</blockquote>
* </p>
*
* @param pPixels the pixel data to convert
* @return an array of {@code short}s, same lenght as {@code pPixels}
* @param inputPixels the pixel data to convert
* @return an array of {@code short}s, same length as {@code inputPixels}
*/
private static short[] toShortPixels(int[] pPixels) {
short[] pixels = new short[pPixels.length];
private static short[] toShortPixels(int[] inputPixels) {
short[] pixels = new short[inputPixels.length];
for (int i = 0; i < pixels.length; i++) {
pixels[i] = (short) (pPixels[i] & 0xffff);
pixels[i] = (short) (inputPixels[i] & 0xffff);
}
return pixels;
@@ -351,17 +356,17 @@ public final class BufferedImageFactory {
* @see BufferedImageFactory#addProgressListener
* @see BufferedImageFactory#removeProgressListener
*/
public static interface ProgressListener extends EventListener {
public interface ProgressListener extends EventListener {
/**
* Reports progress to this listener.
* Invoked by the {@code BufferedImageFactory} to report progress in
* the image decoding.
*
* @param pFactory the factory reporting the progress
* @param pPercentage the percentage of progress
* @param factory the factory reporting the progress
* @param percentage the percentage of progress
*/
void progress(BufferedImageFactory pFactory, float pPercentage);
void progress(BufferedImageFactory factory, float percentage);
}
private class Consumer implements ImageConsumer {
@@ -446,18 +451,18 @@ public final class BufferedImageFactory {
processProgress(pY + pHeight);
}
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, short[] pPixels, int pOffset, int pScanSize) {
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, short[] pixels, int offset, int scanSize) {
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
}
private void setColorModelOnce(final ColorModel pModel) {
private void setColorModelOnce(final ColorModel colorModel) {
// NOTE: There seems to be a "bug" in AreaAveragingScaleFilter, as it
// first passes the original color model through in setColorModel, then
// later replaces it with the default RGB in the first setPixels call
// (this is probably allowed according to the spec, but it's a waste of time and space).
if (sourceColorModel != pModel) {
if (/*sourceColorModel == null ||*/ sourcePixels == null) {
sourceColorModel = pModel;
if (sourceColorModel != colorModel) {
if (sourcePixels == null) {
sourceColorModel = colorModel;
}
else {
throw new IllegalStateException("Change of ColorModel after pixel delivery not supported");
@@ -470,17 +475,16 @@ public final class BufferedImageFactory {
}
}
public void imageComplete(int pStatus) {
@Override
public void imageComplete(int status) {
fetching = false;
if (producer != null) {
producer.removeConsumer(this);
}
switch (pStatus) {
case ImageConsumer.IMAGEERROR:
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
break;
if (status == ImageConsumer.IMAGEERROR) {
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
}
synchronized (BufferedImageFactory.this) {
@@ -488,16 +492,18 @@ public final class BufferedImageFactory {
}
}
public void setColorModel(ColorModel pModel) {
setColorModelOnce(pModel);
@Override
public void setColorModel(ColorModel colorModel) {
setColorModelOnce(colorModel);
}
public void setDimensions(int pWidth, int pHeight) {
@Override
public void setDimensions(int w, int h) {
if (width < 0) {
width = pWidth - x;
width = w - x;
}
if (height < 0) {
height = pHeight - y;
height = h - y;
}
// Hmm.. Special case, but is it a good idea?
@@ -506,27 +512,31 @@ public final class BufferedImageFactory {
}
}
public void setHints(int pHintflags) {
@Override
public void setHints(int hintFlags) {
// ignore
}
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, byte[] pPixels, int pOffset, int pScanSize) {
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
@Override
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, byte[] pixels, int offset, int scanSize) {
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
}
public void setPixels(int pX, int pY, int pWeigth, int pHeight, ColorModel pModel, int[] pPixels, int pOffset, int pScanSize) {
if (pModel.getTransferType() == DataBuffer.TYPE_USHORT) {
@Override
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, int[] pixels, int offset, int scanSize) {
if (colorModel.getTransferType() == DataBuffer.TYPE_USHORT) {
// NOTE: Workaround for limitation in ImageConsumer API
// Convert int[] to short[], to be compatible with the ColorModel
setPixelsImpl(pX, pY, pWeigth, pHeight, pModel, toShortPixels(pPixels), pOffset, pScanSize);
setPixelsImpl(x, y, width, height, colorModel, toShortPixels(pixels), offset, scanSize);
}
else {
setPixelsImpl(pX, pY, pWeigth, pHeight, pModel, pPixels, pOffset, pScanSize);
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
}
}
public void setProperties(Hashtable pProperties) {
sourceProperties = pProperties;
@Override
public void setProperties(Hashtable properties) {
sourceProperties = properties;
}
}
@@ -844,7 +844,7 @@ public final class ImageUtil {
return false;
}
for (int i = 0; i > mapSize1; i++) {
for (int i = 0; i < mapSize1; i++) {
if (icm1.getRGB(i) != icm2.getRGB(i)) {
return false;
}
@@ -34,14 +34,13 @@ import org.junit.Ignore;
import org.junit.Test;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ImageProducer;
import java.awt.image.IndexColorModel;
import java.awt.color.*;
import java.awt.image.*;
import java.net.URL;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* BufferedImageFactoryTestCase
@@ -260,9 +259,9 @@ public class BufferedImageFactoryTest {
// Listener should abort ASAP
factory.addProgressListener(new BufferedImageFactory.ProgressListener() {
public void progress(BufferedImageFactory pFactory, float pPercentage) {
if (pPercentage > 5) {
pFactory.abort();
public void progress(BufferedImageFactory factory, float percentage) {
if (percentage > 5) {
factory.abort();
}
}
});
@@ -343,7 +342,7 @@ public class BufferedImageFactoryTest {
VerifyingListener listener = new VerifyingListener(factory);
factory.addProgressListener(listener);
factory.removeProgressListener(new BufferedImageFactory.ProgressListener() {
public void progress(BufferedImageFactory pFactory, float pPercentage) {
public void progress(BufferedImageFactory factory, float percentage) {
}
});
factory.getBufferedImage();
@@ -380,11 +379,11 @@ public class BufferedImageFactoryTest {
this.factory = factory;
}
public void progress(BufferedImageFactory pFactory, float pPercentage) {
assertEquals(factory, pFactory);
assertTrue(pPercentage >= progress && pPercentage <= 100f);
public void progress(BufferedImageFactory factory, float percentage) {
assertEquals(this.factory, factory);
assertTrue(percentage >= progress && percentage <= 100f);
progress = pPercentage;
progress = percentage;
}
+10 -2
View File
@@ -4,13 +4,13 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>common-io</artifactId>
<packaging>jar</packaging>
<name>TwelveMonkeys :: Common :: IO</name>
<description>
The TwelveMonkeys Common IO support
TwelveMonkeys Common I/O support classes.
</description>
<properties>
@@ -31,4 +31,12 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -56,8 +56,8 @@ public class CompoundReader extends Reader {
private int currentReader;
private int markedReader;
private int mark;
private int mNext;
private long mark;
private long next;
/**
* Create a new compound reader.
@@ -76,7 +76,7 @@ public class CompoundReader extends Reader {
finalLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
// reference can't change, only it's elements
readers = new ArrayList<Reader>();
readers = new ArrayList<>();
boolean markSupported = true;
while (pReaders.hasNext()) {
@@ -101,7 +101,7 @@ public class CompoundReader extends Reader {
}
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
mNext = 0;
next = 0;
return current;
}
@@ -135,7 +135,7 @@ public class CompoundReader extends Reader {
synchronized (finalLock) {
ensureOpen();
mark = mNext;
mark = next;
markedReader = currentReader;
current.mark(pReadLimit);
@@ -158,7 +158,7 @@ public class CompoundReader extends Reader {
}
current.reset();
mNext = mark;
next = mark;
}
}
@@ -177,13 +177,13 @@ public class CompoundReader extends Reader {
return read(); // In case of 0-length readers
}
mNext++;
next++;
return read;
}
}
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
@@ -192,7 +192,7 @@ public class CompoundReader extends Reader {
return read(pBuffer, pOffset, pLength); // In case of 0-length readers
}
mNext += read;
next += read;
return read;
}
@@ -213,7 +213,7 @@ public class CompoundReader extends Reader {
return skip(pChars); // In case of 0-length readers
}
mNext += skipped;
next += skipped;
return skipped;
}
@@ -50,8 +50,8 @@ public class StringArrayReader extends StringReader {
protected final Object finalLock;
private int currentSting;
private int markedString;
private int mark;
private int next;
private long mark;
private long next;
/**
* Create a new string array reader.
@@ -151,7 +151,7 @@ public class StringArrayReader extends StringReader {
}
}
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
@@ -41,21 +41,20 @@ import java.io.InputStream;
* underlying stream.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/SubStream.java#2 $
*/
public final class SubStream extends FilterInputStream {
private long bytesLeft;
private int markLimit;
/**
* Creates a {@code SubStream} of the given {@code pStream}.
* Creates a {@code SubStream} of the given {@code stream}.
*
* @param pStream the underlying input stream
* @param pLength maximum number of bytes to read drom this stream
* @param stream the underlying input stream
* @param length maximum number of bytes to read from this stream
*/
public SubStream(final InputStream pStream, final long pLength) {
super(Validate.notNull(pStream, "stream"));
bytesLeft = pLength;
public SubStream(final InputStream stream, final long length) {
super(Validate.notNull(stream, "stream"));
bytesLeft = Validate.isTrue(length >= 0, length, "length < 0: %s");
}
/**
@@ -64,22 +63,23 @@ public final class SubStream extends FilterInputStream {
*/
@Override
public void close() throws IOException {
// NOTE: Do not close the underlying stream
// NOTE: Do not close the underlying stream, but consume it
while (bytesLeft > 0) {
//noinspection ResultOfMethodCallIgnored
skip(bytesLeft);
if (skip(bytesLeft) <= 0 && read() < 0) {
break;
}
}
}
@Override
public int available() throws IOException {
return (int) Math.min(super.available(), bytesLeft);
return (int) findMaxLen(super.available());
}
@Override
public void mark(int pReadLimit) {
super.mark(pReadLimit);// This either succeeds or does nothing...
markLimit = pReadLimit;
public void mark(int readLimit) {
super.mark(readLimit);// This either succeeds or does nothing...
markLimit = readLimit;
}
@Override
@@ -93,44 +93,42 @@ public final class SubStream extends FilterInputStream {
if (bytesLeft-- <= 0) {
return -1;
}
return super.read();
}
@Override
public final int read(byte[] pBytes) throws IOException {
return read(pBytes, 0, pBytes.length);
public int read(byte[] bytes) throws IOException {
return read(bytes, 0, bytes.length);
}
@Override
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
public int read(final byte[] bytes, final int off, final int len) throws IOException {
if (bytesLeft <= 0) {
return -1;
}
int read = super.read(pBytes, pOffset, (int) findMaxLen(pLength));
int read = super.read(bytes, off, (int) findMaxLen(len));
bytesLeft = read < 0 ? 0 : bytesLeft - read;
return read;
}
@Override
public long skip(long length) throws IOException {
long skipped = super.skip(findMaxLen(length)); // Skips 0 or more, never -1
bytesLeft -= skipped;
return skipped;
}
/**
* Finds the maximum number of bytes we can read or skip, from this stream.
*
* @param pLength the requested length
* @param length the requested length
* @return the maximum number of bytes to read
*/
private long findMaxLen(long pLength) {
if (bytesLeft < pLength) {
return (int) Math.max(bytesLeft, 0);
}
else {
return pLength;
}
}
@Override
public long skip(long pLength) throws IOException {
long skipped = super.skip(findMaxLen(pLength));// Skips 0 or more, never -1
bytesLeft -= skipped;
return skipped;
private long findMaxLen(long length) {
return bytesLeft < length ? Math.max(bytesLeft, 0) : length;
}
}
@@ -0,0 +1,114 @@
package com.twelvemonkeys.io;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Random;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
/**
* SubStreamTest.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haraldk$
* @version $Id: SubStreamTest.java,v 1.0 07/11/2023 haraldk Exp$
*/
public class SubStreamTest {
private final Random rng = new Random(2918475687L);
@SuppressWarnings("resource")
@Test(expected = IllegalArgumentException.class)
public void testCreateNullStream() {
new SubStream(null, 42);
}
@Test(expected = IllegalArgumentException.class)
public void testCreateNegativeLength() {
new SubStream(new ByteArrayInputStream(new byte[1]), -1);
}
@Test
public void testReadAll() throws IOException {
byte[] buf = new byte[128];
rng.nextBytes(buf);
try (InputStream stream = new SubStream(new ByteArrayInputStream(buf), buf.length)) {
for (byte b : buf) {
assertEquals(b, (byte) stream.read());
}
assertEquals(-1, stream.read());
}
}
@Test
public void testReadAllArray() throws IOException {
byte[] buf = new byte[128];
rng.nextBytes(buf);
try (InputStream stream = new SubStream(new ByteArrayInputStream(buf), buf.length)) {
byte[] temp = new byte[buf.length / 4];
for (int i = 0; i < 4; i++) {
assertEquals(temp.length, stream.read(temp)); // Depends on ByteArrayInputStream specifics...
assertArrayEquals(Arrays.copyOfRange(buf, i * temp.length, (i + 1) * temp.length), temp);
}
assertEquals(-1, stream.read());
}
}
@Test
public void testSkipAll() throws IOException {
byte[] buf = new byte[128];
try (InputStream stream = new SubStream(new ByteArrayInputStream(buf), buf.length)) {
assertEquals(128, stream.skip(buf.length)); // Depends on ByteArrayInputStream specifics...
assertEquals(-1, stream.read());
}
}
@SuppressWarnings("EmptyTryBlock")
@Test
public void testCloseConsumesAll() throws IOException {
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[128]);
try (InputStream ignore = new SubStream(stream, 128)) {
// Nothing here...
}
assertEquals(0, stream.available());
assertEquals(-1, stream.read());
}
@SuppressWarnings("EmptyTryBlock")
@Test
public void testCloseConsumesAllLongStream() throws IOException {
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[256]);
try (InputStream ignore = new SubStream(stream, 128)) {
// Nothing here...
}
assertEquals(128, stream.available());
assertEquals(0, stream.read());
}
@SuppressWarnings("EmptyTryBlock")
@Test(timeout = 500L)
public void testCloseConsumesAllShortStream() throws IOException {
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[13]);
try (InputStream ignore = new SubStream(stream, 42)) {
// Nothing here...
}
assertEquals(0, stream.available());
assertEquals(-1, stream.read());
}
}
+10 -2
View File
@@ -4,17 +4,25 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>common-lang</artifactId>
<packaging>jar</packaging>
<name>TwelveMonkeys :: Common :: Language support</name>
<description>
The TwelveMonkeys Common Language support
TwelveMonkeys Common language support classes.
</description>
<properties>
<project.jpms.module.name>com.twelvemonkeys.common.lang</project.jpms.module.name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -904,7 +904,7 @@ public final class StringUtil {
}
catch (ParseException pe) {
// Wrap in RuntimeException
throw new IllegalArgumentException(pe.getMessage());
throw new IllegalArgumentException(pe.getMessage() + " at pos " + pe.getErrorOffset());
}
}
@@ -593,8 +593,8 @@ public class StringUtilTest {
cal.clear();
cal.set(Calendar.HOUR, 1);
cal.set(Calendar.MINUTE, 2);
date = StringUtil.toDate("1:02 am",
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US));
format = new SimpleDateFormat("HH:mm");
date = StringUtil.toDate("1:02", format);
assertNotNull(date);
assertEquals(cal.getTime(), date);
}
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
@@ -47,7 +47,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
+12 -3
View File
@@ -4,13 +4,13 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.contrib</groupId>
<artifactId>contrib</artifactId>
<name>TwelveMonkeys :: Contrib</name>
<description>
Contributions to TwelveMonkeys which are not matching into the ImageIO plug-ins.
Contributions to TwelveMonkeys and code that doesn't fit anywhere else.
</description>
<dependencies>
@@ -65,8 +65,17 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
+15 -3
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-batik</artifactId>
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
@@ -17,7 +17,7 @@
<properties>
<project.jpms.module.name>com.twelvemonkeys.imageio.batik</project.jpms.module.name>
<batik.version>1.16</batik.version>
<batik.version>1.17</batik.version>
</properties>
<build>
@@ -33,6 +33,18 @@
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
@@ -51,7 +63,7 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
<version>2.15.0</version>
<scope>provided</scope>
</dependency>
@@ -33,6 +33,7 @@ package com.twelvemonkeys.imageio.plugins.svg;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.ImageReaderBase;
import com.twelvemonkeys.imageio.util.IIOUtil;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.lang.StringUtil;
import org.apache.batik.anim.dom.SVGDOMImplementation;
@@ -91,10 +92,10 @@ public class SVGImageReader extends ImageReaderBase {
/**
* Creates an {@code SVGImageReader}.
*
* @param pProvider the provider
* @param provider the provider
*/
public SVGImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
public SVGImageReader(final ImageReaderSpi provider) {
super(provider);
}
protected void resetMembers() {
@@ -108,20 +109,20 @@ public class SVGImageReader extends ImageReaderBase {
}
@Override
public void setInput(Object pInput, boolean seekForwardOnly, boolean ignoreMetadata) {
super.setInput(pInput, seekForwardOnly, ignoreMetadata);
public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) {
super.setInput(input, seekForwardOnly, ignoreMetadata);
if (imageInput != null) {
TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
rasterizer.setInput(input);
TranscoderInput transcoderInput = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
rasterizer.setInput(transcoderInput);
}
}
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
checkBounds(pIndex);
public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
checkBounds(imageIndex);
if (pParam instanceof SVGReadParam) {
SVGReadParam svgParam = (SVGReadParam) pParam;
if (param instanceof SVGReadParam) {
SVGReadParam svgParam = (SVGReadParam) param;
// set the external-resource-resolution preference
allowExternalResources = svgParam.isAllowExternalResources();
@@ -139,17 +140,17 @@ public class SVGImageReader extends ImageReaderBase {
}
Dimension size = null;
if (pParam != null) {
size = pParam.getSourceRenderSize();
if (param != null) {
size = param.getSourceRenderSize();
}
if (size == null) {
size = new Dimension(getWidth(pIndex), getHeight(pIndex));
size = new Dimension(getWidth(imageIndex), getHeight(imageIndex));
}
BufferedImage destination = getDestination(pParam, getImageTypes(pIndex), size.width, size.height);
BufferedImage destination = getDestination(param, getImageTypes(imageIndex), size.width, size.height);
// Read in the image, using the Batik Transcoder
processImageStarted(pIndex);
processImageStarted(imageIndex);
BufferedImage image = rasterizer.getImage();
@@ -173,18 +174,18 @@ public class SVGImageReader extends ImageReaderBase {
return ex.getException() != null ? ex.getException() : ex;
}
private TranscodingHints paramsToHints(SVGReadParam pParam) throws IOException {
private TranscodingHints paramsToHints(SVGReadParam param) throws IOException {
TranscodingHints hints = new TranscodingHints();
// Note: We must allow generic ImageReadParams, so converting to
// TanscodingHints should be done outside the SVGReadParam class.
// Set dimensions
Dimension size = pParam.getSourceRenderSize();
Dimension size = param.getSourceRenderSize();
Rectangle viewBox = rasterizer.getViewBox();
if (size == null) {
// SVG is not a pixel based format, but we'll scale it, according to
// the subsampling for compatibility
size = getSourceRenderSizeFromSubsamping(pParam, viewBox.getSize());
size = getSourceRenderSizeFromSubsamping(param, viewBox.getSize());
}
if (size != null) {
@@ -193,7 +194,7 @@ public class SVGImageReader extends ImageReaderBase {
}
// Set area of interest
Rectangle region = pParam.getSourceRegion();
Rectangle region = param.getSourceRegion();
if (region != null) {
hints.put(ImageTranscoder.KEY_AOI, region);
@@ -217,7 +218,7 @@ public class SVGImageReader extends ImageReaderBase {
}
// Background color
Paint bg = pParam.getBackgroundColor();
Paint bg = param.getBackgroundColor();
if (bg != null) {
hints.put(ImageTranscoder.KEY_BACKGROUND_COLOR, bg);
}
@@ -225,10 +226,10 @@ public class SVGImageReader extends ImageReaderBase {
return hints;
}
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam pParam, Dimension pOrigSize) {
if (pParam.getSourceXSubsampling() > 1 || pParam.getSourceYSubsampling() > 1) {
return new Dimension((int) (pOrigSize.width / (float) pParam.getSourceXSubsampling()),
(int) (pOrigSize.height / (float) pParam.getSourceYSubsampling()));
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam param, Dimension origSize) {
if (param.getSourceXSubsampling() > 1 || param.getSourceYSubsampling() > 1) {
return new Dimension((int) (origSize.width / (float) param.getSourceXSubsampling()),
(int) (origSize.height / (float) param.getSourceYSubsampling()));
}
return null;
}
@@ -237,19 +238,19 @@ public class SVGImageReader extends ImageReaderBase {
return new SVGReadParam();
}
public int getWidth(int pIndex) throws IOException {
checkBounds(pIndex);
public int getWidth(int imageIndex) throws IOException {
checkBounds(imageIndex);
return rasterizer.getDefaultWidth();
}
public int getHeight(int pIndex) throws IOException {
checkBounds(pIndex);
public int getHeight(int imageIndex) throws IOException {
checkBounds(imageIndex);
return rasterizer.getDefaultHeight();
}
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) {
return Collections.singleton(ImageTypeSpecifier.createFromRenderedImage(rasterizer.createImage(1, 1))).iterator();
return Collections.singleton(ImageTypeSpecifiers.createFromRenderedImage(rasterizer.createImage(1, 1))).iterator();
}
/**
@@ -601,6 +602,7 @@ public class SVGImageReader extends ImageReaderBase {
initialized = true;
try {
super.addTranscodingHint(SVGAbstractTranscoder.KEY_ALLOW_EXTERNAL_RESOURCES, allowExternalResources);
super.transcode(transcoderInput, null);
}
catch (TranscoderException e) {
@@ -633,8 +635,8 @@ public class SVGImageReader extends ImageReaderBase {
return viewBox.getBounds();
}
void setInput(final TranscoderInput pInput) {
transcoderInput = pInput;
void setInput(final TranscoderInput input) {
transcoderInput = input;
}
@Override
@@ -60,22 +60,22 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
super(new SVGProviderInfo());
}
public boolean canDecodeInput(final Object pSource) throws IOException {
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
public boolean canDecodeInput(final Object source) throws IOException {
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
}
@SuppressWarnings("StatementWithEmptyBody")
private static boolean canDecode(final ImageInputStream pInput) throws IOException {
private static boolean canDecode(final ImageInputStream input) throws IOException {
// NOTE: This test is quite quick as it does not involve any parsing,
// however it may not recognize all kinds of SVG documents.
try {
pInput.mark();
input.mark();
// TODO: This is not ok for UTF-16 and other wide encodings
// TODO: Use an XML (encoding) aware Reader instance instead
// Need to figure out pretty fast if this is XML or not
int b;
while (Character.isWhitespace((char) (b = pInput.read()))) {
while (Character.isWhitespace((char) (b = input.read()))) {
// Skip over leading WS
}
@@ -95,30 +95,30 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
byte[] buffer = new byte[4];
while (true) {
pInput.readFully(buffer);
input.readFully(buffer);
if (buffer[0] == '?') {
// This is the XML declaration or a processing instruction
while (!((pInput.readByte() & 0xFF) == '?' && pInput.read() == '>')) {
while (!((input.readByte() & 0xFF) == '?' && input.read() == '>')) {
// Skip until end of XML declaration or processing instruction or EOF
}
}
else if (buffer[0] == '!') {
if (buffer[1] == '-' && buffer[2] == '-') {
// This is a comment
while (!((pInput.readByte() & 0xFF) == '-' && pInput.read() == '-' && pInput.read() == '>')) {
while (!((input.readByte() & 0xFF) == '-' && input.read() == '-' && input.read() == '>')) {
// Skip until end of comment or EOF
}
}
else if (buffer[1] == 'D' && buffer[2] == 'O' && buffer[3] == 'C'
&& pInput.read() == 'T' && pInput.read() == 'Y'
&& pInput.read() == 'P' && pInput.read() == 'E') {
&& input.read() == 'T' && input.read() == 'Y'
&& input.read() == 'P' && input.read() == 'E') {
// This is the DOCTYPE declaration
while (Character.isWhitespace((char) (b = pInput.read()))) {
while (Character.isWhitespace((char) (b = input.read()))) {
// Skip over WS
}
if (b == 's' && pInput.read() == 'v' && pInput.read() == 'g') {
if (b == 's' && input.read() == 'v' && input.read() == 'g') {
// It's SVG, identified by DOCTYPE
return true;
}
@@ -142,7 +142,7 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
return false;
}
while ((pInput.readByte() & 0xFF) != '<') {
while ((input.readByte() & 0xFF) != '<') {
// Skip over, until next begin tag or EOF
}
}
@@ -153,7 +153,7 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
}
finally {
//noinspection ThrowFromFinallyBlock
pInput.reset();
input.reset();
}
}
@@ -51,16 +51,16 @@ public class SVGReadParam extends ImageReadParam {
return background;
}
public void setBackgroundColor(Paint pColor) {
background = pColor;
public void setBackgroundColor(Paint color) {
background = color;
}
public String getBaseURI() {
return baseURI;
}
public void setBaseURI(String pBaseURI) {
baseURI = pBaseURI;
public void setBaseURI(String baseURI) {
this.baseURI = baseURI;
}
public void setAllowExternalResources(boolean allow) {
+20 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-bmp</artifactId>
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
@@ -26,4 +26,23 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -81,8 +81,8 @@ public final class BMPImageReader extends ImageReaderBase {
super(new BMPImageReaderSpi());
}
BMPImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
BMPImageReader(final ImageReaderSpi provider) {
super(provider);
}
@Override
@@ -129,6 +129,7 @@ public final class BMPImageReader extends ImageReaderBase {
// Read DIB header
header = DIBHeader.read(imageInput);
// System.out.println("header = " + header);
if (pixelOffset < header.size + DIB.BMP_FILE_HEADER_SIZE) {
throw new IIOException("Invalid pixel offset: " + pixelOffset);
@@ -186,30 +187,30 @@ public final class BMPImageReader extends ImageReaderBase {
}
@Override
public int getWidth(int pImageIndex) throws IOException {
checkBounds(pImageIndex);
public int getWidth(int imageIndex) throws IOException {
checkBounds(imageIndex);
return header.getWidth();
}
@Override
public int getHeight(int pImageIndex) throws IOException {
checkBounds(pImageIndex);
public int getHeight(int imageIndex) throws IOException {
checkBounds(imageIndex);
return header.getHeight();
}
@Override
public Iterator<ImageTypeSpecifier> getImageTypes(int pImageIndex) throws IOException {
checkBounds(pImageIndex);
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
checkBounds(imageIndex);
// TODO: Better implementation, include INT_RGB types for 3BYTE_BGR and 4BYTE_ABGR for INT_ARGB
return Collections.singletonList(getRawImageType(pImageIndex)).iterator();
return Collections.singletonList(getRawImageType(imageIndex)).iterator();
}
@Override
public ImageTypeSpecifier getRawImageType(int pImageIndex) throws IOException {
checkBounds(pImageIndex);
public ImageTypeSpecifier getRawImageType(int imageIndex) throws IOException {
checkBounds(imageIndex);
if (header.getPlanes() != 1) {
throw new IIOException("Multiple planes not supported");
@@ -685,8 +686,8 @@ public final class BMPImageReader extends ImageReaderBase {
}
@SuppressWarnings({ "unchecked", "UnusedDeclaration", "SameParameterValue" })
static <T extends Throwable> void throwAs(final Class<T> pType, final Throwable pThrowable) throws T {
throw (T) pThrowable;
static <T extends Throwable> void throwAs(final Class<T> type, final Throwable throwable) throws T {
throw (T) throwable;
}
private class ListenerDelegator extends ProgressListenerBase implements IIOReadUpdateListener, IIOReadWarningListener {
@@ -65,16 +65,16 @@ public final class BMPImageReaderSpi extends ImageReaderSpiBase {
}
}
public boolean canDecodeInput(final Object pSource) throws IOException {
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
public boolean canDecodeInput(final Object source) throws IOException {
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
}
private static boolean canDecode(final ImageInputStream pInput) throws IOException {
private static boolean canDecode(final ImageInputStream input) throws IOException {
byte[] fileHeader = new byte[18]; // Strictly: file header (14 bytes) + BMP header size field (4 bytes)
try {
pInput.mark();
pInput.readFully(fileHeader);
input.mark();
input.readFully(fileHeader);
// Magic: BM
if (fileHeader[0] != 'B' || fileHeader[1] != 'M') {
@@ -112,15 +112,15 @@ public final class BMPImageReaderSpi extends ImageReaderSpiBase {
}
}
finally {
pInput.reset();
input.reset();
}
}
public ImageReader createReaderInstance(final Object pExtension) {
public ImageReader createReaderInstance(final Object extension) {
return new BMPImageReader(this);
}
public String getDescription(final Locale pLocale) {
public String getDescription(final Locale locale) {
return "Windows Device Independent Bitmap Format (BMP) Reader";
}
}
@@ -47,7 +47,7 @@ import java.nio.ByteOrder;
* BMPImageWriter
*/
public final class BMPImageWriter extends DIBImageWriter {
protected BMPImageWriter(ImageWriterSpi provider) {
BMPImageWriter(ImageWriterSpi provider) {
super(provider);
}
@@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.AbstractMetadata;
import com.twelvemonkeys.lang.Validate;
import org.w3c.dom.Node;
import javax.imageio.metadata.IIOMetadataNode;
@@ -141,7 +142,7 @@ final class BMPMetadata extends AbstractMetadata {
@Override
protected IIOMetadataNode getStandardChromaNode() {
// NOTE: BMP files may contain a color map, even if true color...
// Not sure if this is a good idea to expose to the meta data,
// Not sure if this is a good idea to expose to the metadata,
// as it might be unexpected... Then again...
if (colorMap != null) {
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
@@ -29,11 +29,11 @@
*/
package com.twelvemonkeys.imageio.plugins.bmp;
import static com.twelvemonkeys.lang.Validate.notNull;
import java.awt.image.BufferedImage;
import java.awt.image.*;
import java.io.IOException;
import static com.twelvemonkeys.lang.Validate.notNull;
/**
* Describes a bitmap structure.
*
@@ -47,9 +47,9 @@ abstract class BitmapDescriptor {
protected BufferedImage image;
protected BitmapMask mask;
public BitmapDescriptor(final DirectoryEntry pEntry, final DIBHeader pHeader) {
entry = notNull(pEntry, "entry");;
header = notNull(pHeader, "header");
public BitmapDescriptor(final DirectoryEntry entry, final DIBHeader header) {
this.entry = notNull(entry, "entry");
this.header = notNull(header, "header");
}
abstract public BufferedImage getImage() throws IOException;
@@ -75,7 +75,7 @@ abstract class BitmapDescriptor {
return getClass().getSimpleName() + "[" + entry + ", " + header + "]";
}
public final void setMask(final BitmapMask mask) {
final void setMask(final BitmapMask mask) {
this.mask = mask;
}
@@ -29,10 +29,7 @@
*/
package com.twelvemonkeys.imageio.plugins.bmp;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.awt.image.*;
import java.util.Hashtable;
/**
@@ -41,12 +38,13 @@ import java.util.Hashtable;
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: BitmapIndexed.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/
class BitmapIndexed extends BitmapDescriptor {
protected final int[] bits;
protected final int[] colors;
final class BitmapIndexed extends BitmapDescriptor {
final int[] bits;
final int[] colors;
public BitmapIndexed(final DirectoryEntry entry, final DIBHeader header) {
super(entry, header);
public BitmapIndexed(final DirectoryEntry pEntry, final DIBHeader pHeader) {
super(pEntry, pHeader);
bits = new int[getWidth() * getHeight()];
// NOTE: We're adding space for one extra color, for transparency
@@ -59,20 +57,16 @@ class BitmapIndexed extends BitmapDescriptor {
IndexColorModel icm = createColorModel();
// This is slightly obscure, and should probably be moved..
// We add cursor hotspot as a property to images created from CUR format.
// This is slightly obscure, and should probably be moved...
Hashtable<String, Object> properties = null;
if (entry instanceof DirectoryEntry.CUREntry) {
properties = new Hashtable<>(1);
properties.put("cursor_hotspot", ((DirectoryEntry.CUREntry) this.entry).getHotspot());
}
BufferedImage image = new BufferedImage(
icm,
icm.createCompatibleWritableRaster(getWidth(), getHeight()),
icm.isAlphaPremultiplied(), properties
);
WritableRaster raster = image.getRaster();
WritableRaster raster = icm.createCompatibleWritableRaster(getWidth(), getHeight());
BufferedImage image = new BufferedImage(icm, raster, icm.isAlphaPremultiplied(), properties);
// Make pixels transparent according to mask
final int trans = icm.getTransparentPixel();
@@ -105,7 +99,7 @@ class BitmapIndexed extends BitmapDescriptor {
int index = findTransparentIndexMaybeRemap(this.colors, this.bits);
if (index == -1) {
// No duplicate found, increase bitcount
// No duplicate found, increase bit count
bits++;
transparent = this.colors.length - 1;
}
@@ -117,10 +111,8 @@ class BitmapIndexed extends BitmapDescriptor {
}
// NOTE: Setting hasAlpha to true, makes things work on 1.2
return new IndexColorModel(
bits, colors, this.colors, 0, true, transparent,
bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT
);
return new IndexColorModel(bits, colors, this.colors, 0, true, transparent,
bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT);
}
private static int findTransparentIndexMaybeRemap(final int[] colors, final int[] bits) {
@@ -30,7 +30,7 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import java.awt.image.BufferedImage;
import java.awt.image.*;
/**
@@ -39,17 +39,17 @@ import java.awt.image.BufferedImage;
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: BitmapMask.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/
class BitmapMask extends BitmapDescriptor {
protected final BitmapIndexed bitMask;
final class BitmapMask extends BitmapDescriptor {
final BitmapIndexed bitMask;
public BitmapMask(final DirectoryEntry pParent, final DIBHeader pHeader) {
super(pParent, pHeader);
bitMask = new BitmapIndexed(pParent, pHeader);
public BitmapMask(final DirectoryEntry parent, final DIBHeader header) {
super(parent, header);
bitMask = new BitmapIndexed(parent, header);
}
boolean isTransparent(final int pX, final int pY) {
boolean isTransparent(final int x, final int y) {
// NOTE: 1: Fully transparent, 0: Opaque...
return bitMask.bits[pX + pY * getWidth()] != 0;
return bitMask.bits[x + y * getWidth()] != 0;
}
public BufferedImage getImage() {
@@ -31,8 +31,7 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.awt.image.*;
/**
* Describes an RGB/true color bitmap structure (16, 24 and 32 bits per pixel).
@@ -40,10 +39,10 @@ import java.awt.image.WritableRaster;
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: BitmapRGB.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/
class BitmapRGB extends BitmapDescriptor {
final class BitmapRGB extends BitmapDescriptor {
public BitmapRGB(final DirectoryEntry pEntry, final DIBHeader pHeader) {
super(pEntry, pHeader);
public BitmapRGB(final DirectoryEntry entry, final DIBHeader header) {
super(entry, header);
}
@Override
@@ -71,7 +70,7 @@ class BitmapRGB extends BitmapDescriptor {
WritableRaster alphaRaster = masked.getAlphaRaster();
byte[] trans = {0x0};
byte[] trans = {0x00};
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
if (mask.isTransparent(x, y)) {
@@ -30,10 +30,9 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.IIOException;
import java.awt.image.*;
import java.io.IOException;
/**
* Represents bitmap structures we can't read.
@@ -42,13 +41,13 @@ import javax.imageio.IIOException;
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: BitmapUnsupported.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
*/
class BitmapUnsupported extends BitmapDescriptor {
private String message;
final class BitmapUnsupported extends BitmapDescriptor {
private final String message;
public BitmapUnsupported(final DirectoryEntry pEntry, DIBHeader header, final String pMessage) {
super(pEntry, header);
public BitmapUnsupported(final DirectoryEntry entry, DIBHeader header, final String message) {
super(entry, header);
message = pMessage;
this.message = message;
}
@Override
@@ -48,22 +48,22 @@ public final class CURImageReader extends DIBImageReader {
super(new CURImageReaderSpi());
}
protected CURImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
CURImageReader(final ImageReaderSpi provider) {
super(provider);
}
/**
* Returns the hot spot location for the cursor.
*
* @param pImageIndex the index of the cursor in the current input.
* @param imageIndex the index of the cursor in the current input.
* @return the hot spot location for the cursor
*
* @throws java.io.IOException if an I/O exception occurs during reading of image meta data
* @throws IndexOutOfBoundsException if {@code pImageIndex} is less than {@code 0} or greater than/equal to
* the number of cursors in the file
*/
public final Point getHotSpot(final int pImageIndex) throws IOException {
DirectoryEntry.CUREntry entry = (DirectoryEntry.CUREntry) getEntry(pImageIndex);
public Point getHotSpot(final int imageIndex) throws IOException {
DirectoryEntry.CUREntry entry = (DirectoryEntry.CUREntry) getEntry(imageIndex);
return entry.getHotspot();
}
}
@@ -32,7 +32,6 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;
import java.util.Locale;
@@ -49,15 +48,15 @@ public final class CURImageReaderSpi extends ImageReaderSpiBase {
super(new CURProviderInfo());
}
public boolean canDecodeInput(final Object pSource) throws IOException {
return pSource instanceof ImageInputStream && ICOImageReaderSpi.canDecode((ImageInputStream) pSource, DIB.TYPE_CUR);
public boolean canDecodeInput(final Object source) throws IOException {
return source instanceof ImageInputStream && ICOImageReaderSpi.canDecode((ImageInputStream) source, DIB.TYPE_CUR);
}
public ImageReader createReaderInstance(final Object pExtension) throws IOException {
public CURImageReader createReaderInstance(final Object extension) {
return new CURImageReader(this);
}
public String getDescription(final Locale pLocale) {
public String getDescription(final Locale locale) {
return "Windows Cursor Format (CUR) Reader";
}
}
@@ -30,12 +30,11 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import javax.imageio.IIOException;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import javax.imageio.IIOException;
/**
* Represents the DIB (Device Independent Bitmap) Information header structure.
*
@@ -91,17 +90,17 @@ abstract class DIBHeader {
protected DIBHeader() {
}
public static DIBHeader read(final DataInput pStream) throws IOException {
int size = pStream.readInt();
public static DIBHeader read(final DataInput stream) throws IOException {
int size = stream.readInt();
DIBHeader header = createHeader(size);
header.read(size, pStream);
header.read(size, stream);
return header;
}
private static DIBHeader createHeader(final int pSize) throws IOException {
switch (pSize) {
private static DIBHeader createHeader(final int size) throws IOException {
switch (size) {
case DIB.BITMAP_CORE_HEADER_SIZE:
return new BitmapCoreHeader();
case DIB.OS2_V2_HEADER_16_SIZE:
@@ -118,11 +117,12 @@ abstract class DIBHeader {
case DIB.BITMAP_V5_INFO_HEADER_SIZE:
return new BitmapV5InfoHeader();
default:
throw new IIOException(String.format("Unknown Bitmap Information Header (size: %s)", pSize));
throw new IIOException(String.format("Unknown Bitmap Information Header (size: %s)", size));
}
}
protected abstract void read(int pSize, DataInput pStream) throws IOException;
protected abstract void read(int size, DataInput stream) throws IOException;
protected abstract void write(final DataOutput stream) throws IOException;
public final int getSize() {
return size;
@@ -189,12 +189,12 @@ abstract class DIBHeader {
);
}
private static int[] readMasks(final DataInput pStream, final boolean hasAlphaMask) throws IOException {
private static int[] readMasks(final DataInput stream, final boolean hasAlphaMask) throws IOException {
int maskCount = hasAlphaMask ? 4 : 3;
int[] masks = new int[4];
for (int i = 0; i < maskCount; i++) {
masks[i] = pStream.readInt();
masks[i] = stream.readInt();
}
return masks;
@@ -205,24 +205,30 @@ abstract class DIBHeader {
// TODO: Get rid of code duplication below...
static final class BitmapCoreHeader extends DIBHeader {
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (pSize != DIB.BITMAP_CORE_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_CORE_HEADER_SIZE));
@Override
protected void read(final int size, final DataInput stream) throws IOException {
if (size != DIB.BITMAP_CORE_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_CORE_HEADER_SIZE));
}
size = pSize;
this.size = size;
// NOTE: Unlike all other headers, width and height are unsigned SHORT values (16 bit)!
width = pStream.readUnsignedShort();
height = pStream.readShort();
width = stream.readUnsignedShort();
height = stream.readShort();
if (height < 0) {
height = -height;
topDown = true;
}
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
}
@Override
protected void write(DataOutput stream) {
throw new UnsupportedOperationException();
}
public String getBMPVersion() {
@@ -242,45 +248,51 @@ abstract class DIBHeader {
*/
static final class BitmapCoreHeaderV2 extends DIBHeader {
@SuppressWarnings("unused")
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (pSize != DIB.OS2_V2_HEADER_SIZE && pSize != DIB.OS2_V2_HEADER_16_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.OS2_V2_HEADER_SIZE));
@Override
protected void read(final int size, final DataInput stream) throws IOException {
if (size != DIB.OS2_V2_HEADER_SIZE && size != DIB.OS2_V2_HEADER_16_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.OS2_V2_HEADER_SIZE));
}
size = pSize;
this.size = size;
width = pStream.readInt();
height = pStream.readInt();
width = stream.readInt();
height = stream.readInt();
if (height < 0) {
height = -height;
topDown = true;
}
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
if (pSize != DIB.OS2_V2_HEADER_16_SIZE) {
compression = pStream.readInt();
if (size != DIB.OS2_V2_HEADER_16_SIZE) {
compression = stream.readInt();
imageSize = pStream.readInt();
imageSize = stream.readInt();
xPixelsPerMeter = pStream.readInt();
yPixelsPerMeter = pStream.readInt();
xPixelsPerMeter = stream.readInt();
yPixelsPerMeter = stream.readInt();
colorsUsed = pStream.readInt();
colorsImportant = pStream.readInt();
colorsUsed = stream.readInt();
colorsImportant = stream.readInt();
}
// TODO: Use? These fields are not reflected in metadata as per now...
int units = pStream.readShort();
int reserved = pStream.readShort();
int recording = pStream.readShort(); // Recording algorithm
int rendering = pStream.readShort(); // Halftoning algorithm
int size1 = pStream.readInt(); // Reserved for halftoning use
int size2 = pStream.readInt(); // Reserved for halftoning use
int colorEncoding = pStream.readInt(); // Color model used in bitmap
int identifier = pStream.readInt(); // Reserved for application use
int units = stream.readShort();
int reserved = stream.readShort();
int recording = stream.readShort(); // Recording algorithm
int rendering = stream.readShort(); // Halftoning algorithm
int size1 = stream.readInt(); // Reserved for halftoning use
int size2 = stream.readInt(); // Reserved for halftoning use
int colorEncoding = stream.readInt(); // Color model used in bitmap
int identifier = stream.readInt(); // Reserved for application use
}
@Override
protected void write(DataOutput stream) {
throw new UnsupportedOperationException();
}
public String getBMPVersion() {
@@ -288,7 +300,6 @@ abstract class DIBHeader {
}
}
/**
* Represents the DIB (Device Independent Bitmap) Windows 3.0 Bitmap Information header structure.
* This is the common format for persistent DIB structures, even if Windows
@@ -304,44 +315,46 @@ abstract class DIBHeader {
* @see <a href="https://forums.adobe.com/message/3272950#3272950">BITMAPV3INFOHEADER</a>.
*/
static final class BitmapInfoHeader extends DIBHeader {
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (!(pSize == DIB.BITMAP_INFO_HEADER_SIZE || pSize == DIB.BITMAP_V2_INFO_HEADER_SIZE || pSize == DIB.BITMAP_V3_INFO_HEADER_SIZE)) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_INFO_HEADER_SIZE));
@Override
protected void read(final int size, final DataInput stream) throws IOException {
if (!(size == DIB.BITMAP_INFO_HEADER_SIZE || size == DIB.BITMAP_V2_INFO_HEADER_SIZE || size == DIB.BITMAP_V3_INFO_HEADER_SIZE)) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_INFO_HEADER_SIZE));
}
size = pSize;
this.size = size;
width = pStream.readInt();
height = pStream.readInt();
width = stream.readInt();
height = stream.readInt();
if (height < 0) {
height = -height;
topDown = true;
}
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
compression = pStream.readInt();
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
compression = stream.readInt();
imageSize = pStream.readInt();
imageSize = stream.readInt();
xPixelsPerMeter = pStream.readInt();
yPixelsPerMeter = pStream.readInt();
xPixelsPerMeter = stream.readInt();
yPixelsPerMeter = stream.readInt();
colorsUsed = pStream.readInt();
colorsImportant = pStream.readInt();
colorsUsed = stream.readInt();
colorsImportant = stream.readInt();
// Read masks if we have V2 or V3
// or if we have compression BITFIELDS or ALPHA_BITFIELDS
if (size == DIB.BITMAP_V2_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_BITFIELDS) {
masks = readMasks(pStream, false);
if (this.size == DIB.BITMAP_V2_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_BITFIELDS) {
masks = readMasks(stream, false);
}
else if (size == DIB.BITMAP_V3_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_ALPHA_BITFIELDS) {
masks = readMasks(pStream, true);
else if (this.size == DIB.BITMAP_V3_INFO_HEADER_SIZE || compression == DIB.COMPRESSION_ALPHA_BITFIELDS) {
masks = readMasks(stream, true);
}
}
void write(final DataOutput stream) throws IOException {
@Override
protected void write(final DataOutput stream) throws IOException {
stream.writeInt(DIB.BITMAP_INFO_HEADER_SIZE);
stream.writeInt(width);
@@ -359,7 +372,7 @@ abstract class DIBHeader {
stream.writeInt(colorsUsed);
stream.writeInt(colorsImportant);
// TODO: Write masks, if bitfields
// TODO: Write masks, if COMPRESSION_BITFIELDS/COMPRESSION_ALPHA_BITFIELDS
}
public String getBMPVersion() {
@@ -376,105 +389,160 @@ abstract class DIBHeader {
* Represents the BITMAPV4INFOHEADER structure.
*/
static final class BitmapV4InfoHeader extends DIBHeader {
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (pSize != DIB.BITMAP_V4_INFO_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_V4_INFO_HEADER_SIZE));
@Override
protected void read(final int size, final DataInput stream) throws IOException {
if (size != DIB.BITMAP_V4_INFO_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_V4_INFO_HEADER_SIZE));
}
size = pSize;
this.size = size;
width = pStream.readInt();
height = pStream.readInt();
width = stream.readInt();
height = stream.readInt();
if (height < 0) {
height = -height;
topDown = true;
}
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
compression = pStream.readInt();
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
compression = stream.readInt();
imageSize = pStream.readInt();
imageSize = stream.readInt();
xPixelsPerMeter = pStream.readInt();
yPixelsPerMeter = pStream.readInt();
xPixelsPerMeter = stream.readInt();
yPixelsPerMeter = stream.readInt();
colorsUsed = pStream.readInt();
colorsImportant = pStream.readInt();
colorsUsed = stream.readInt();
colorsImportant = stream.readInt();
masks = readMasks(pStream, true);
masks = readMasks(stream, true);
colorSpaceType = pStream.readInt(); // Should be 0 for V4
colorSpaceType = stream.readInt(); // Should be 0 for V4
cieXYZEndpoints = new double[9];
for (int i = 0; i < cieXYZEndpoints.length; i++) {
cieXYZEndpoints[i] = pStream.readInt(); // TODO: Hmmm...?
cieXYZEndpoints[i] = stream.readInt(); // TODO: Hmmm...?
}
gamma = new int[3];
for (int i = 0; i < gamma.length; i++) {
gamma[i] = pStream.readInt();
gamma[i] = stream.readInt();
}
}
public String getBMPVersion() {
return "BMP v. 4.x";
}
@Override
protected void write(DataOutput stream) throws IOException {
stream.writeInt(DIB.BITMAP_V4_INFO_HEADER_SIZE);
stream.writeInt(width);
stream.writeInt(topDown ? -height : height);
stream.writeShort(planes);
stream.writeShort(bitCount);
stream.writeInt(compression);
stream.writeInt(imageSize);
stream.writeInt(xPixelsPerMeter);
stream.writeInt(yPixelsPerMeter);
stream.writeInt(colorsUsed);
stream.writeInt(colorsImportant);
// Red, Green, Blue, Alpha masks
stream.writeInt(masks[0]);
stream.writeInt(masks[1]);
stream.writeInt(masks[2]);
stream.writeInt(masks[3]);
// color space ("sRGB" LITTLE endian)
stream.writeInt(DIB.LCS_sRGB);
// 36 bytes CIE XYZ triples, unused for sRGB
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
// Red gamma, unused for sRGB
// Green gamma, unused for sRGB
// Blue gamma, unused for sRGB
stream.writeInt(0);
stream.writeInt(0);
stream.writeInt(0);
}
}
/**
* Represents the BITMAPV5INFOHEADER structure.
*/
static final class BitmapV5InfoHeader extends DIBHeader {
protected void read(final int pSize, final DataInput pStream) throws IOException {
if (pSize != DIB.BITMAP_V5_INFO_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", pSize, DIB.BITMAP_V5_INFO_HEADER_SIZE));
protected void read(final int size, final DataInput stream) throws IOException {
if (size != DIB.BITMAP_V5_INFO_HEADER_SIZE) {
throw new IIOException(String.format("Size: %s !=: %s", size, DIB.BITMAP_V5_INFO_HEADER_SIZE));
}
size = pSize;
this.size = size;
width = pStream.readInt();
height = pStream.readInt();
width = stream.readInt();
height = stream.readInt();
if (height < 0) {
height = -height;
topDown = true;
}
planes = pStream.readUnsignedShort();
bitCount = pStream.readUnsignedShort();
compression = pStream.readInt();
planes = stream.readUnsignedShort();
bitCount = stream.readUnsignedShort();
compression = stream.readInt();
imageSize = pStream.readInt();
imageSize = stream.readInt();
xPixelsPerMeter = pStream.readInt();
yPixelsPerMeter = pStream.readInt();
xPixelsPerMeter = stream.readInt();
yPixelsPerMeter = stream.readInt();
colorsUsed = pStream.readInt();
colorsImportant = pStream.readInt();
colorsUsed = stream.readInt();
colorsImportant = stream.readInt();
masks = readMasks(pStream, true);
masks = readMasks(stream, true);
colorSpaceType = pStream.readInt();
colorSpaceType = stream.readInt();
cieXYZEndpoints = new double[9];
for (int i = 0; i < cieXYZEndpoints.length; i++) {
cieXYZEndpoints[i] = pStream.readInt(); // TODO: Hmmm...?
cieXYZEndpoints[i] = stream.readInt(); // TODO: Hmmm...?
}
gamma = new int[3];
for (int i = 0; i < gamma.length; i++) {
gamma[i] = pStream.readInt();
gamma[i] = stream.readInt();
}
intent = pStream.readInt(); // TODO: Verify if this is same as ICC intent
profileData = pStream.readInt() & 0xffffffffL;
profileSize = pStream.readInt() & 0xffffffffL;
pStream.readInt(); // Reserved
intent = stream.readInt(); // TODO: Verify if this is same as ICC intent
profileData = stream.readInt() & 0xffffffffL;
profileSize = stream.readInt() & 0xffffffffL;
stream.readInt(); // Reserved
}
@Override
protected void write(DataOutput stream) {
throw new UnsupportedOperationException();
}
public String getBMPVersion() {
@@ -30,19 +30,11 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.ImageReaderBase;
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.util.WeakWeakMap;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
@@ -52,12 +44,18 @@ import javax.imageio.ImageTypeSpecifier;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.ImageReaderBase;
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.util.WeakWeakMap;
import java.awt.*;
import java.awt.color.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
/**
* ImageReader for Microsoft Windows ICO (icon) format.
@@ -81,13 +79,13 @@ abstract class DIBImageReader extends ImageReaderBase {
private Directory directory;
// TODO: Review these, make sure we don't have a memory leak
private Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<>();
private Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<>();
private final Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<>();
private final Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<>();
private ImageReader pngImageReader;
protected DIBImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
protected DIBImageReader(final ImageReaderSpi provider) {
super(provider);
}
protected void resetMembers() {
@@ -102,8 +100,8 @@ abstract class DIBImageReader extends ImageReaderBase {
}
}
public Iterator<ImageTypeSpecifier> getImageTypes(final int pImageIndex) throws IOException {
DirectoryEntry entry = getEntry(pImageIndex);
public Iterator<ImageTypeSpecifier> getImageTypes(final int imageIndex) throws IOException {
DirectoryEntry entry = getEntry(imageIndex);
// NOTE: Delegate to PNG reader
if (isPNG(entry)) {
@@ -155,39 +153,39 @@ abstract class DIBImageReader extends ImageReaderBase {
return getDirectory().count();
}
public int getWidth(final int pImageIndex) throws IOException {
return getEntry(pImageIndex).getWidth();
public int getWidth(final int imageIndex) throws IOException {
return getEntry(imageIndex).getWidth();
}
public int getHeight(final int pImageIndex) throws IOException {
return getEntry(pImageIndex).getHeight();
public int getHeight(final int imageIndex) throws IOException {
return getEntry(imageIndex).getHeight();
}
public BufferedImage read(final int pImageIndex, final ImageReadParam pParam) throws IOException {
checkBounds(pImageIndex);
public BufferedImage read(final int imageIndex, final ImageReadParam param) throws IOException {
checkBounds(imageIndex);
processImageStarted(pImageIndex);
processImageStarted(imageIndex);
DirectoryEntry entry = getEntry(pImageIndex);
DirectoryEntry entry = getEntry(imageIndex);
BufferedImage destination;
if (isPNG(entry)) {
// NOTE: Special case for Windows Vista, 256x256 PNG encoded images, with no DIB header...
destination = readPNG(entry, pParam);
destination = readPNG(entry, param);
}
else {
// NOTE: If param does not have explicit destination, we'll try to create a BufferedImage later,
// to allow for storing the cursor hotspot for CUR images
destination = hasExplicitDestination(pParam) ?
getDestination(pParam, getImageTypes(pImageIndex), getWidth(pImageIndex), getHeight(pImageIndex)) : null;
destination = hasExplicitDestination(param) ?
getDestination(param, getImageTypes(imageIndex), getWidth(imageIndex), getHeight(imageIndex)) : null;
BufferedImage image = readBitmap(entry);
// TODO: Handle AOI and subsampling inline, probably not of big importance...
if (pParam != null) {
image = fakeAOI(image, pParam);
image = ImageUtil.toBuffered(fakeSubsampling(image, pParam));
if (param != null) {
image = fakeAOI(image, param);
image = ImageUtil.toBuffered(fakeSubsampling(image, param));
}
if (destination == null) {
@@ -213,10 +211,10 @@ abstract class DIBImageReader extends ImageReaderBase {
return destination;
}
private boolean isPNG(final DirectoryEntry pEntry) throws IOException {
private boolean isPNG(final DirectoryEntry entry) throws IOException {
long magic;
imageInput.seek(pEntry.getOffset());
imageInput.seek(entry.getOffset());
imageInput.setByteOrder(ByteOrder.BIG_ENDIAN);
try {
@@ -229,22 +227,20 @@ abstract class DIBImageReader extends ImageReaderBase {
return magic == DIB.PNG_MAGIC;
}
private BufferedImage readPNG(final DirectoryEntry pEntry, final ImageReadParam pParam) throws IOException {
private BufferedImage readPNG(final DirectoryEntry entry, final ImageReadParam param) throws IOException {
// TODO: Consider delegating listener calls
return initPNGReader(pEntry).read(0, pParam);
return initPNGReader(entry).read(0, param);
}
private Iterator<ImageTypeSpecifier> getImageTypesPNG(final DirectoryEntry pEntry) throws IOException {
return initPNGReader(pEntry).getImageTypes(0);
private Iterator<ImageTypeSpecifier> getImageTypesPNG(final DirectoryEntry entry) throws IOException {
return initPNGReader(entry).getImageTypes(0);
}
private ImageReader initPNGReader(final DirectoryEntry pEntry) throws IOException {
private ImageReader initPNGReader(final DirectoryEntry entry) throws IOException {
ImageReader pngReader = getPNGReader();
imageInput.seek(pEntry.getOffset());
// InputStream inputStream = IIOUtil.createStreamAdapter(imageInput, pEntry.getSize());
// ImageInputStream stream = ImageIO.createImageInputStream(inputStream);
ImageInputStream stream = new SubImageInputStream(imageInput, pEntry.getSize());
imageInput.seek(entry.getOffset());
ImageInputStream stream = new SubImageInputStream(imageInput, entry.getSize());
// NOTE: Will throw IOException on later reads if input is not PNG
pngReader.setInput(stream);
@@ -271,31 +267,31 @@ abstract class DIBImageReader extends ImageReaderBase {
return pngImageReader;
}
private DIBHeader getHeader(final DirectoryEntry pEntry) throws IOException {
if (!headers.containsKey(pEntry)) {
imageInput.seek(pEntry.getOffset());
private DIBHeader getHeader(final DirectoryEntry entry) throws IOException {
if (!headers.containsKey(entry)) {
imageInput.seek(entry.getOffset());
DIBHeader header = DIBHeader.read(imageInput);
headers.put(pEntry, header);
headers.put(entry, header);
}
return headers.get(pEntry);
return headers.get(entry);
}
private BufferedImage readBitmap(final DirectoryEntry pEntry) throws IOException {
private BufferedImage readBitmap(final DirectoryEntry entry) throws IOException {
// TODO: Get rid of the caching, as the images are mutable
BitmapDescriptor descriptor = descriptors.get(pEntry);
BitmapDescriptor descriptor = descriptors.get(entry);
if (descriptor == null || !descriptors.containsKey(pEntry)) {
DIBHeader header = getHeader(pEntry);
if (descriptor == null || !descriptors.containsKey(entry)) {
DIBHeader header = getHeader(entry);
int offset = pEntry.getOffset() + header.getSize();
int offset = entry.getOffset() + header.getSize();
if (offset != imageInput.getStreamPosition()) {
imageInput.seek(offset);
}
// TODO: Support this, it's already in the BMP reader, spec allows RLE4 and RLE8
if (header.getCompression() != DIB.COMPRESSION_RGB) {
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported compression: %d", header.getCompression()));
descriptor = new BitmapUnsupported(entry, header, String.format("Unsupported compression: %d", header.getCompression()));
}
else {
int bitCount = header.getBitCount();
@@ -305,75 +301,75 @@ abstract class DIBImageReader extends ImageReaderBase {
case 1:
case 4:
case 8: // TODO: Gray!
descriptor = new BitmapIndexed(pEntry, header);
descriptor = new BitmapIndexed(entry, header);
readBitmapIndexed((BitmapIndexed) descriptor);
break;
// RGB style
case 16:
descriptor = new BitmapRGB(pEntry, header);
descriptor = new BitmapRGB(entry, header);
readBitmap16(descriptor);
break;
case 24:
descriptor = new BitmapRGB(pEntry, header);
descriptor = new BitmapRGB(entry, header);
readBitmap24(descriptor);
break;
case 32:
descriptor = new BitmapRGB(pEntry, header);
descriptor = new BitmapRGB(entry, header);
readBitmap32(descriptor);
break;
default:
descriptor = new BitmapUnsupported(pEntry, header, String.format("Unsupported bit count %d", bitCount));
descriptor = new BitmapUnsupported(entry, header, String.format("Unsupported bit count %d", bitCount));
}
}
descriptors.put(pEntry, descriptor);
descriptors.put(entry, descriptor);
}
return descriptor.getImage();
}
private void readBitmapIndexed(final BitmapIndexed pBitmap) throws IOException {
readColorMap(pBitmap);
private void readBitmapIndexed(final BitmapIndexed bitmap) throws IOException {
readColorMap(bitmap);
switch (pBitmap.getBitCount()) {
switch (bitmap.getBitCount()) {
case 1:
readBitmapIndexed1(pBitmap, false);
readBitmapIndexed1(bitmap, false);
break;
case 4:
readBitmapIndexed4(pBitmap);
readBitmapIndexed4(bitmap);
break;
case 8:
readBitmapIndexed8(pBitmap);
readBitmapIndexed8(bitmap);
break;
}
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
BitmapMask mask = new BitmapMask(bitmap.entry, bitmap.header);
readBitmapIndexed1(mask.bitMask, true);
pBitmap.setMask(mask);
bitmap.setMask(mask);
}
private void readColorMap(final BitmapIndexed pBitmap) throws IOException {
int colorCount = pBitmap.getColorCount();
private void readColorMap(final BitmapIndexed bitmap) throws IOException {
int colorCount = bitmap.getColorCount();
for (int i = 0; i < colorCount; i++) {
// aRGB (a is "Reserved")
pBitmap.colors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
bitmap.colors[i] = (imageInput.readInt() & 0xffffff) | 0xff000000;
}
}
private void readBitmapIndexed1(final BitmapIndexed pBitmap, final boolean pAsMask) throws IOException {
int width = adjustToPadding((pBitmap.getWidth() + 7) >> 3);
private void readBitmapIndexed1(final BitmapIndexed bitmap, final boolean asMask) throws IOException {
int width = adjustToPadding((bitmap.getWidth() + 7) >> 3);
byte[] row = new byte[width];
for (int y = 0; y < pBitmap.getHeight(); y++) {
for (int y = 0; y < bitmap.getHeight(); y++) {
imageInput.readFully(row, 0, width);
int rowPos = 0;
int xOrVal = 0x80;
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
for (int x = 0; x < pBitmap.getWidth(); x++) {
pBitmap.bits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF;
for (int x = 0; x < bitmap.getWidth(); x++) {
bitmap.bits[pos++] = ((row[rowPos] & xOrVal) / xOrVal) & 0xFF;
if (xOrVal == 1) {
xOrVal = 0x80;
@@ -384,29 +380,29 @@ abstract class DIBImageReader extends ImageReaderBase {
}
}
// NOTE: If we are reading the mask, we don't abort or report progress
if (!pAsMask) {
// NOTE: If we are reading the mask, we can't abort or report progress
if (!asMask) {
if (abortRequested()) {
processReadAborted();
break;
}
processImageProgress(100 * y / (float) pBitmap.getHeight());
processImageProgress(100 * y / (float) bitmap.getHeight());
}
}
}
private void readBitmapIndexed4(final BitmapIndexed pBitmap) throws IOException {
int width = adjustToPadding((pBitmap.getWidth() + 1) >> 1);
private void readBitmapIndexed4(final BitmapIndexed bitmap) throws IOException {
int width = adjustToPadding((bitmap.getWidth() + 1) >> 1);
byte[] row = new byte[width];
for (int y = 0; y < pBitmap.getHeight(); y++) {
for (int y = 0; y < bitmap.getHeight(); y++) {
imageInput.readFully(row, 0, width);
int rowPos = 0;
boolean high4 = true;
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
for (int x = 0; x < pBitmap.getWidth(); x++) {
for (int x = 0; x < bitmap.getWidth(); x++) {
int value;
if (high4) {
@@ -417,7 +413,7 @@ abstract class DIBImageReader extends ImageReaderBase {
rowPos++;
}
pBitmap.bits[pos++] = value & 0xFF;
bitmap.bits[pos++] = value & 0xFF;
high4 = !high4;
}
@@ -426,22 +422,22 @@ abstract class DIBImageReader extends ImageReaderBase {
break;
}
processImageProgress(100 * y / (float) pBitmap.getHeight());
processImageProgress(100 * y / (float) bitmap.getHeight());
}
}
private void readBitmapIndexed8(final BitmapIndexed pBitmap) throws IOException {
int width = adjustToPadding(pBitmap.getWidth());
private void readBitmapIndexed8(final BitmapIndexed bitmap) throws IOException {
int width = adjustToPadding(bitmap.getWidth());
byte[] row = new byte[width];
for (int y = 0; y < pBitmap.getHeight(); y++) {
for (int y = 0; y < bitmap.getHeight(); y++) {
imageInput.readFully(row, 0, width);
int rowPos = 0;
int pos = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
int pos = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
for (int x = 0; x < pBitmap.getWidth(); x++) {
pBitmap.bits[pos++] = row[rowPos++] & 0xFF;
for (int x = 0; x < bitmap.getWidth(); x++) {
bitmap.bits[pos++] = row[rowPos++] & 0xFF;
}
if (abortRequested()) {
@@ -449,40 +445,41 @@ abstract class DIBImageReader extends ImageReaderBase {
break;
}
processImageProgress(100 * y / (float) pBitmap.getHeight());
processImageProgress(100 * y / (float) bitmap.getHeight());
}
}
/**
* @param pWidth Bytes per scan line (i.e., 1BPP, width = 9 -> bytes = 1)
* @param width Bytes per scan line (i.e., 1BPP, width = 9 -> bytes = 2)
* @return padded width
*/
private static int adjustToPadding(final int pWidth) {
if ((pWidth & 0x03) != 0) {
return (pWidth & ~0x03) + 4;
private static int adjustToPadding(final int width) {
if ((width & 0x03) != 0) {
return (width & ~0x03) + 4;
}
return pWidth;
return width;
}
private void readBitmap16(final BitmapDescriptor pBitmap) throws IOException {
short[] pixels = new short[pBitmap.getWidth() * pBitmap.getHeight()];
private void readBitmap16(final BitmapDescriptor bitmap) throws IOException {
short[] pixels = new short[bitmap.getWidth() * bitmap.getHeight()];
// TODO: Support TYPE_USHORT_565 and the RGB 444/ARGB 4444 layouts
// Will create TYPE_USHORT_555
DirectColorModel cm = new DirectColorModel(16, 0x7C00, 0x03E0, 0x001F);
DataBuffer buffer = new DataBufferUShort(pixels, pixels.length);
WritableRaster raster = Raster.createPackedRaster(
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
buffer, bitmap.getWidth(), bitmap.getHeight(), bitmap.getWidth(), cm.getMasks(), null
);
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
imageInput.readFully(pixels, offset, pBitmap.getWidth());
for (int y = 0; y < bitmap.getHeight(); y++) {
int offset = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
imageInput.readFully(pixels, offset, bitmap.getWidth());
// Skip to 32 bit boundary
if (pBitmap.getWidth() % 2 != 0) {
if (bitmap.getWidth() % 2 != 0) {
imageInput.readShort();
}
@@ -491,14 +488,14 @@ abstract class DIBImageReader extends ImageReaderBase {
break;
}
processImageProgress(100 * y / (float) pBitmap.getHeight());
processImageProgress(100 * y / (float) bitmap.getHeight());
}
// TODO: Might be mask!?
}
private void readBitmap24(final BitmapDescriptor pBitmap) throws IOException {
byte[] pixels = new byte[pBitmap.getWidth() * pBitmap.getHeight() * 3];
private void readBitmap24(final BitmapDescriptor bitmap) throws IOException {
byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight() * 3];
// Create TYPE_3BYTE_BGR
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
@@ -509,17 +506,17 @@ abstract class DIBImageReader extends ImageReaderBase {
cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE
);
int scanlineStride = pBitmap.getWidth() * 3;
int scanlineStride = bitmap.getWidth() * 3;
// BMP rows are padded to 4 byte boundary
int rowSizeBytes = ((8 * scanlineStride + 31) / 32) * 4;
WritableRaster raster = Raster.createInterleavedRaster(
buffer, pBitmap.getWidth(), pBitmap.getHeight(), scanlineStride, 3, bOffs, null
buffer, bitmap.getWidth(), bitmap.getHeight(), scanlineStride, 3, bOffs, null
);
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * scanlineStride;
for (int y = 0; y < bitmap.getHeight(); y++) {
int offset = (bitmap.getHeight() - y - 1) * scanlineStride;
imageInput.readFully(pixels, offset, scanlineStride);
imageInput.skipBytes(rowSizeBytes - scanlineStride);
@@ -528,38 +525,38 @@ abstract class DIBImageReader extends ImageReaderBase {
break;
}
processImageProgress(100 * y / (float) pBitmap.getHeight());
processImageProgress(100 * y / (float) bitmap.getHeight());
}
// 24 bit icons usually have a bit mask
if (pBitmap.hasMask()) {
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
if (bitmap.hasMask()) {
BitmapMask mask = new BitmapMask(bitmap.entry, bitmap.header);
readBitmapIndexed1(mask.bitMask, true);
pBitmap.setMask(mask);
bitmap.setMask(mask);
}
}
private void readBitmap32(final BitmapDescriptor pBitmap) throws IOException {
int[] pixels = new int[pBitmap.getWidth() * pBitmap.getHeight()];
private void readBitmap32(final BitmapDescriptor bitmap) throws IOException {
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
// Will create TYPE_INT_ARGB
DirectColorModel cm = (DirectColorModel) ColorModel.getRGBdefault();
DataBuffer buffer = new DataBufferInt(pixels, pixels.length);
WritableRaster raster = Raster.createPackedRaster(
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), cm.getMasks(), null
buffer, bitmap.getWidth(), bitmap.getHeight(), bitmap.getWidth(), cm.getMasks(), null
);
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
bitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
for (int y = 0; y < pBitmap.getHeight(); y++) {
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
imageInput.readFully(pixels, offset, pBitmap.getWidth());
for (int y = 0; y < bitmap.getHeight(); y++) {
int offset = (bitmap.getHeight() - y - 1) * bitmap.getWidth();
imageInput.readFully(pixels, offset, bitmap.getWidth());
if (abortRequested()) {
processReadAborted();
break;
}
processImageProgress(100 * y / (float) pBitmap.getHeight());
processImageProgress(100 * y / (float) bitmap.getHeight());
}
// There might be a mask here as well, but we'll ignore it,
@@ -590,18 +587,18 @@ abstract class DIBImageReader extends ImageReaderBase {
directory = Directory.read(type, imageCount, imageInput);
}
final DirectoryEntry getEntry(final int pImageIndex) throws IOException {
final DirectoryEntry getEntry(final int imageIndex) throws IOException {
Directory directory = getDirectory();
if (pImageIndex < 0 || pImageIndex >= directory.count()) {
throw new IndexOutOfBoundsException(String.format("Index: %d, ImageCount: %d", pImageIndex, directory.count()));
if (imageIndex < 0 || imageIndex >= directory.count()) {
throw new IndexOutOfBoundsException(String.format("Index: %d, ImageCount: %d", imageIndex, directory.count()));
}
return directory.getEntry(pImageIndex);
return directory.getEntry(imageIndex);
}
/// Test code below, ignore.. :-)
public static void main(final String[] pArgs) throws IOException {
if (pArgs.length == 0) {
public static void main(final String[] args) throws IOException {
if (args.length == 0) {
System.err.println("Please specify the icon file name");
System.exit(1);
}
@@ -613,7 +610,7 @@ abstract class DIBImageReader extends ImageReaderBase {
// Ignore
}
String title = new File(pArgs[0]).getName();
String title = new File(args[0]).getName();
JFrame frame = createWindow(title);
JPanel root = new JPanel(new FlowLayout());
JScrollPane scroll =
@@ -629,7 +626,7 @@ abstract class DIBImageReader extends ImageReaderBase {
ImageReader reader = readers.next();
for (String arg : pArgs) {
for (String arg : args) {
JPanel panel = new JPanel(null);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
readImagesInFile(arg, reader, panel);
@@ -640,28 +637,28 @@ abstract class DIBImageReader extends ImageReaderBase {
frame.setVisible(true);
}
private static void readImagesInFile(String pFileName, ImageReader pReader, final Container pContainer) throws IOException {
File file = new File(pFileName);
private static void readImagesInFile(String fileName, ImageReader reader, final Container container) throws IOException {
File file = new File(fileName);
if (!file.isFile()) {
System.err.println(pFileName + " not found, or is no file");
System.err.println(fileName + " not found, or is no file");
}
pReader.setInput(ImageIO.createImageInputStream(file));
int imageCount = pReader.getNumImages(true);
reader.setInput(ImageIO.createImageInputStream(file));
int imageCount = reader.getNumImages(true);
for (int i = 0; i < imageCount; i++) {
try {
addImage(pContainer, pReader, i);
addImage(container, reader, i);
}
catch (Exception e) {
System.err.println("FileName: " + pFileName);
System.err.println("FileName: " + fileName);
System.err.println("Icon: " + i);
e.printStackTrace();
}
}
}
private static JFrame createWindow(final String pTitle) {
JFrame frame = new JFrame(pTitle);
private static JFrame createWindow(final String title) {
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
@@ -671,15 +668,15 @@ abstract class DIBImageReader extends ImageReaderBase {
return frame;
}
private static void addImage(final Container pParent, final ImageReader pReader, final int pImageNo) throws IOException {
private static void addImage(final Container parent, final ImageReader reader, final int imageNo) throws IOException {
final JButton button = new JButton();
BufferedImage image = pReader.read(pImageNo);
BufferedImage image = reader.read(imageNo);
button.setIcon(new ImageIcon(image) {
TexturePaint texture;
private void createTexture(final GraphicsConfiguration pGraphicsConfiguration) {
BufferedImage pattern = pGraphicsConfiguration.createCompatibleImage(20, 20);
private void createTexture(final GraphicsConfiguration graphicsConfiguration) {
BufferedImage pattern = graphicsConfiguration.createCompatibleImage(20, 20);
Graphics2D g = pattern.createGraphics();
try {
g.setColor(Color.LIGHT_GRAY);
@@ -714,6 +711,6 @@ abstract class DIBImageReader extends ImageReaderBase {
String.valueOf(((IndexColorModel) image.getColorModel()).getMapSize()) :
"TrueColor"));
pParent.add(button);
parent.add(button);
}
}
@@ -44,24 +44,25 @@ import java.util.List;
class Directory {
private final List<DirectoryEntry> entries;
private Directory(int pImageCount) {
entries = Arrays.asList(new DirectoryEntry[pImageCount]);
private Directory(int imageCount) {
entries = Arrays.asList(new DirectoryEntry[imageCount]);
}
public static Directory read(final int pType, final int pImageCount, final DataInput pStream) throws IOException {
Directory directory = new Directory(pImageCount);
directory.readEntries(pType, pStream);
public static Directory read(final int type, final int imageCount, final DataInput stream) throws IOException {
Directory directory = new Directory(imageCount);
directory.readEntries(type, stream);
return directory;
}
private void readEntries(final int pType, final DataInput pStream) throws IOException {
private void readEntries(final int type, final DataInput stream) throws IOException {
for (int i = 0; i < entries.size(); i++) {
entries.set(i, DirectoryEntry.read(pType, pStream));
entries.set(i, DirectoryEntry.read(type, stream));
}
}
public DirectoryEntry getEntry(final int pEntryIndex) {
return entries.get(pEntryIndex);
public DirectoryEntry getEntry(final int entryIndex) {
return entries.get(entryIndex);
}
public int count() {
@@ -32,8 +32,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import javax.imageio.IIOException;
import java.awt.*;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.*;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@@ -58,47 +57,43 @@ abstract class DirectoryEntry {
DirectoryEntry() {
}
public static DirectoryEntry read(final int pType, final DataInput pStream) throws IOException {
DirectoryEntry entry = createEntry(pType);
entry.read(pStream);
public static DirectoryEntry read(final int type, final DataInput stream) throws IOException {
DirectoryEntry entry = createEntry(type);
entry.read(stream);
return entry;
}
private static DirectoryEntry createEntry(int pType) throws IIOException {
switch (pType) {
private static DirectoryEntry createEntry(int type) throws IIOException {
switch (type) {
case DIB.TYPE_ICO:
return new ICOEntry();
case DIB.TYPE_CUR:
return new CUREntry();
default:
throw new IIOException(
String.format(
"Unknown DIB type: %s, expected: %s (ICO) or %s (CUR)",
pType, DIB.TYPE_ICO, DIB.TYPE_CUR
)
);
throw new IIOException(String.format("Unknown DIB type: %s, expected: %s (ICO) or %s (CUR)", type, DIB.TYPE_ICO, DIB.TYPE_CUR));
}
}
protected void read(final DataInput pStream) throws IOException {
protected void read(final DataInput stream) throws IOException {
// Width/height = 0, means 256
int w = pStream.readUnsignedByte();
int w = stream.readUnsignedByte();
width = w == 0 ? 256 : w;
int h = pStream.readUnsignedByte();
int h = stream.readUnsignedByte();
height = h == 0 ? 256 : h;
// Color count = 0, means 256 or more colors
colorCount = pStream.readUnsignedByte();
colorCount = stream.readUnsignedByte();
// Ignore. Should be 0, but .NET (System.Drawing.Icon.Save) sets this value to 255, according to Wikipedia
pStream.readUnsignedByte();
stream.readUnsignedByte();
planes = pStream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR
bitCount = pStream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR
planes = stream.readUnsignedShort(); // Should be 0 or 1 for ICO, x hotspot for CUR
bitCount = stream.readUnsignedShort(); // bit count for ICO, y hotspot for CUR
// Size of bitmap in bytes
size = pStream.readInt();
offset = pStream.readInt();
size = stream.readInt();
offset = stream.readInt();
}
void write(final DataOutput output) throws IOException {
@@ -157,8 +152,8 @@ abstract class DirectoryEntry {
private int yHotspot;
@Override
protected void read(final DataInput pStream) throws IOException {
super.read(pStream);
protected void read(final DataInput stream) throws IOException {
super.read(stream);
// NOTE: This is a hack...
xHotspot = planes;
@@ -46,7 +46,7 @@ public final class ICOImageReader extends DIBImageReader {
super(new ICOImageReaderSpi());
}
protected ICOImageReader(final ImageReaderSpi pProvider) {
super(pProvider);
ICOImageReader(final ImageReaderSpi provider) {
super(provider);
}
}
@@ -32,7 +32,6 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;
import java.util.Locale;
@@ -49,32 +48,32 @@ public final class ICOImageReaderSpi extends ImageReaderSpiBase {
super(new ICOProviderInfo());
}
public boolean canDecodeInput(final Object pSource) throws IOException {
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource, DIB.TYPE_ICO);
public boolean canDecodeInput(final Object source) throws IOException {
return source instanceof ImageInputStream && canDecode((ImageInputStream) source, DIB.TYPE_ICO);
}
static boolean canDecode(final ImageInputStream pInput, final int pType) throws IOException {
static boolean canDecode(final ImageInputStream input, final int type) throws IOException {
byte[] signature = new byte[4];
try {
pInput.mark();
pInput.readFully(signature);
input.mark();
input.readFully(signature);
int count = pInput.readByte() + (pInput.readByte() << 8);
int count = input.readByte() + (input.readByte() << 8);
return (signature[0] == 0x0 && signature[1] == 0x0 && signature[2] == pType
return (signature[0] == 0x0 && signature[1] == 0x0 && signature[2] == type
&& signature[3] == 0x0 && count > 0);
}
finally {
pInput.reset();
input.reset();
}
}
public ImageReader createReaderInstance(final Object pExtension) throws IOException {
public ICOImageReader createReaderInstance(final Object extension) {
return new ICOImageReader(this);
}
public String getDescription(final Locale pLocale) {
public String getDescription(final Locale locale) {
return "Windows Icon Format (ICO) Reader";
}
}
@@ -33,15 +33,19 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import javax.imageio.*;
import javax.imageio.IIOException;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.event.IIOWriteWarningListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
@@ -64,7 +68,7 @@ public final class ICOImageWriter extends DIBImageWriter {
private ImageWriter pngDelegate;
protected ICOImageWriter(final ImageWriterSpi provider) {
ICOImageWriter(final ImageWriterSpi provider) {
super(provider);
}
@@ -124,7 +128,7 @@ public final class ICOImageWriter extends DIBImageWriter {
}
@Override
public void endWriteSequence() throws IOException {
public void endWriteSequence() {
assertOutput();
if (sequenceIndex < 0) {
@@ -30,24 +30,14 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeNoException;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
import com.twelvemonkeys.xml.XMLSerializer;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.InOrder;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
@@ -57,16 +47,25 @@ import javax.imageio.ImageTypeSpecifier;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageReaderSpi;
import java.awt.*;
import java.awt.image.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.InOrder;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
import com.twelvemonkeys.xml.XMLSerializer;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeNoException;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
/**
* BMPImageReaderTest
@@ -326,10 +325,8 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest<BMPImageReader>
public void testMetadataEqualsJRE() throws IOException {
ImageReader jreReader;
try {
@SuppressWarnings("unchecked")
Class<ImageReader> jreReaderClass = (Class<ImageReader>) Class.forName("com.sun.imageio.plugins.bmp.BMPImageReader");
Constructor<ImageReader> constructor = jreReaderClass.getConstructor(ImageReaderSpi.class);
jreReader = constructor.newInstance(new Object[] {null});
ImageReaderSpi provider = (ImageReaderSpi) IIORegistry.getDefaultInstance().getServiceProviderByClass(Class.forName("com.sun.imageio.plugins.bmp.BMPImageReaderSpi"));
jreReader = provider.createReaderInstance();
}
catch (Exception e) {
e.printStackTrace();
+10 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-clippath</artifactId>
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
@@ -32,4 +32,13 @@
<artifactId>imageio-metadata</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -42,6 +42,7 @@ import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
@@ -307,7 +308,7 @@ public final class Paths {
throw new IllegalArgumentException("output == null!");
}
ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(image);
ImageTypeSpecifier type = ImageTypeSpecifiers.createFromRenderedImage(image);
Iterator<ImageWriter> writers = ImageIO.getImageWriters(type, formatName);
if (writers.hasNext()) {
+20 -1
View File
@@ -4,10 +4,13 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-core</artifactId>
<name>TwelveMonkeys :: ImageIO :: Core</name>
<description>
TwelveMonkeys ImageIO core support classes.
</description>
<properties>
<project.jpms.module.name>com.twelvemonkeys.imageio.core</project.jpms.module.name>
@@ -28,4 +31,20 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageInputStreamSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -188,7 +188,7 @@ public final class ColorSpaces {
// Will throw IllegalArgumentException or CMMException if the profile is bad
cs.fromRGB(new float[] {0.999f, 0.5f, 0.001f});
// This breaks *some times* after validation of bad profiles,
// This breaks *sometimes* after validation of bad profiles,
// we'll let it blow up early in this case
cs.getProfile().getData();
}
@@ -257,18 +257,18 @@ public final class ImageTypeSpecifiers {
return createFromIndexColorModel(new IndexColorModel(bits, colors.length, colors, 0, hasAlpha, transIndex, dataType));
}
public static ImageTypeSpecifier createFromIndexColorModel(final IndexColorModel pColorModel) {
return new IndexedImageTypeSpecifier(pColorModel);
public static ImageTypeSpecifier createFromIndexColorModel(final IndexColorModel colorModel) {
return new IndexedImageTypeSpecifier(colorModel);
}
public static ImageTypeSpecifier createDiscreteAlphaIndexedFromIndexColorModel(final IndexColorModel pColorModel) {
ColorModel colorModel = new DiscreteAlphaIndexColorModel(pColorModel);
return new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(1, 1));
public static ImageTypeSpecifier createDiscreteAlphaIndexedFromIndexColorModel(final IndexColorModel colorModel) {
ColorModel discreteAlphaIndexColorModel = new DiscreteAlphaIndexColorModel(colorModel);
return new ImageTypeSpecifier(discreteAlphaIndexColorModel, discreteAlphaIndexColorModel.createCompatibleSampleModel(1, 1));
}
public static ImageTypeSpecifier createDiscreteExtraSamplesIndexedFromIndexColorModel(final IndexColorModel pColorModel, int extraSamples, boolean hasAlpha) {
ColorModel colorModel = new DiscreteAlphaIndexColorModel(pColorModel, extraSamples, hasAlpha);
return new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(1, 1));
public static ImageTypeSpecifier createDiscreteExtraSamplesIndexedFromIndexColorModel(final IndexColorModel colorModel, int extraSamples, boolean hasAlpha) {
ColorModel discreteAlphaIndexColorModel = new DiscreteAlphaIndexColorModel(colorModel, extraSamples, hasAlpha);
return new ImageTypeSpecifier(discreteAlphaIndexColorModel, discreteAlphaIndexColorModel.createCompatibleSampleModel(1, 1));
}
public static ImageTypeSpecifier createFromRenderedImage(RenderedImage image) {
@@ -279,7 +279,9 @@ public final class ImageTypeSpecifiers {
if (image instanceof BufferedImage) {
int bufferedImageType = ((BufferedImage) image).getType();
if (bufferedImageType != BufferedImage.TYPE_CUSTOM) {
if (bufferedImageType != BufferedImage.TYPE_CUSTOM &&
// Need to retain the actual palette in the color model for IndexColorModel
bufferedImageType != BufferedImage.TYPE_BYTE_BINARY && bufferedImageType != BufferedImage.TYPE_BYTE_INDEXED) {
return createFromBufferedImageType(bufferedImageType);
}
}
@@ -52,12 +52,12 @@ final class IndexedImageTypeSpecifier extends ImageTypeSpecifier {
}
@Override
public final BufferedImage createBufferedImage(final int pWidth, final int pHeight) {
public BufferedImage createBufferedImage(final int width, final int height) {
try {
// This is a fix for the super-method, that first creates a sample model, and then
// creates a raster from it, using Raster.createWritableRaster. The problem with
// that approach, is that it always creates a TYPE_CUSTOM BufferedImage for indexed images.
WritableRaster raster = colorModel.createCompatibleWritableRaster(pWidth, pHeight);
WritableRaster raster = colorModel.createCompatibleWritableRaster(width, height);
return new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
}
catch (NegativeArraySizeException e) {
@@ -17,6 +17,7 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -170,7 +171,7 @@ public class StandardImageMetadataSupportTest {
@Test
public void withTextValuesMap() {
Map<String, String> entries = new HashMap<>();
Map<String, String> entries = new LinkedHashMap<>();
entries.put("foo", "bar");
entries.put("bar", "xyzzy");
@@ -36,9 +36,11 @@ import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assume.assumeFalse;
import static org.mockito.Mockito.*;
public class KCMSSanitizerStrategyTest {
@@ -56,6 +58,8 @@ public class KCMSSanitizerStrategyTest {
@Test
public void testFixProfileUpdateHeader() throws Exception {
assumeICC_ProfileNotSealed(); // Ignores test for JDK 19+
byte[] header = new byte[128];
header[ICC_Profile.icHdrRenderingIntent + 3] = 1;
ICC_Profile profile = mock(ICC_Profile.class);
@@ -69,6 +73,17 @@ public class KCMSSanitizerStrategyTest {
verify(profile).setData(eq(ICC_Profile.icSigHead), any(byte[].class));
}
static void assumeICC_ProfileNotSealed() {
try {
Method isSealed = Class.class.getMethod("isSealed");
Boolean result = (Boolean) isSealed.invoke(ICC_Profile.class);
assumeFalse("Can't mock ICC_Profile, class is sealed (as of JDK 19).", result);
}
catch (ReflectiveOperationException ignore) {
// We can't have sealed classes if we don't have the isSealed method...
}
}
@Test
public void testFixProfileCorbisRGB() throws IOException {
// TODO: Consider re-writing this using mocks, to avoid dependencies on the CMS implementation
@@ -34,6 +34,7 @@ import org.junit.Test;
import java.awt.color.ICC_Profile;
import static com.twelvemonkeys.imageio.color.KCMSSanitizerStrategyTest.assumeICC_ProfileNotSealed;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -46,6 +47,8 @@ public class LCMSSanitizerStrategyTest {
@Test
public void testFixProfile() throws Exception {
assumeICC_ProfileNotSealed(); // Ignores test for JDK 19+
ICC_Profile profile = mock(ICC_Profile.class);
new LCMSSanitizerStrategy().fixProfile(profile);
@@ -31,6 +31,7 @@
package com.twelvemonkeys.imageio.util;
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
import com.twelvemonkeys.lang.Validate;
import org.junit.Ignore;
import org.junit.Test;
@@ -38,14 +39,18 @@ import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import javax.imageio.*;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
@@ -53,6 +58,7 @@ import java.lang.reflect.ParameterizedType;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -602,7 +608,7 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
assertReadWithSourceRegionParamEqualImage(new Rectangle(3, 3, 9, 9), getTestData().get(0), 0);
}
protected void assertReadWithSourceRegionParamEqualImage(final Rectangle r, final TestData data, final int imageIndex) throws IOException {
protected void assertReadWithSourceRegionParamEqualImage(final Rectangle r, final TestData data, @SuppressWarnings("SameParameterValue") final int imageIndex) throws IOException {
ImageReader reader = createReader();
try (ImageInputStream inputStream = data.getInputStream()) {
reader.setInput(inputStream);
@@ -1828,52 +1834,51 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
private final List<Dimension> sizes;
private final List<BufferedImage> images;
public TestData(final Object pInput, final Dimension... pSizes) {
this(pInput, Arrays.asList(pSizes), null);
public TestData(final Object input, final Dimension... dimensions) {
this(input, Arrays.asList(dimensions), null);
}
public TestData(final Object pInput, final BufferedImage... pImages) {
this(pInput, null, Arrays.asList(pImages));
public TestData(final Object input, final BufferedImage... images) {
this(input, null, Arrays.asList(images));
}
public TestData(final Object pInput, final List<Dimension> pSizes, final List<BufferedImage> pImages) {
if (pInput == null) {
throw new IllegalArgumentException("input == null");
}
public TestData(final Object input, final List<Dimension> dimensions, final List<BufferedImage> images) {
Validate.notNull(input, "input");
Validate.isTrue(dimensions != null || images != null, "Need either dimensions or image");
sizes = new ArrayList<>();
images = new ArrayList<>();
List<Dimension> combinedDimensions;
if (dimensions == null) {
// Copy dimensions from images
combinedDimensions = new ArrayList<>(images.size());
List<Dimension> sizes = pSizes;
if (sizes == null) {
sizes = new ArrayList<>();
if (pImages != null) {
for (BufferedImage image : pImages) {
sizes.add(new Dimension(image.getWidth(), image.getHeight()));
}
}
else {
throw new IllegalArgumentException("Need either size or image");
for (BufferedImage image : images) {
combinedDimensions.add(new Dimension(image.getWidth(), image.getHeight()));
}
}
else if (pImages != null) {
if (pImages.size() != pSizes.size()) {
throw new IllegalArgumentException("Size parameter and image size differs");
}
for (int i = 0; i < sizes.size(); i++) {
if (!new Dimension(pImages.get(i).getWidth(), pImages.get(i).getHeight()).equals(sizes.get(i))) {
throw new IllegalArgumentException("Size parameter and image size differs");
else {
// Validate equal dimensions
if (images != null) {
if (images.size() != dimensions.size()) {
throw new IllegalArgumentException("Dimensions and images parameter's size differs");
}
for (int i = 0; i < dimensions.size(); i++) {
if (!new Dimension(images.get(i).getWidth(), images.get(i).getHeight()).equals(dimensions.get(i))) {
throw new IllegalArgumentException("Dimensions and images parameter's dimensions differ");
}
}
}
combinedDimensions = new ArrayList<>(dimensions);
}
this.sizes.addAll(sizes);
if (pImages != null) {
images.addAll(pImages);
}
this.sizes = Collections.unmodifiableList(combinedDimensions);
input = pInput;
this.images = images != null
? Collections.unmodifiableList(new ArrayList<>(images))
: Collections.<BufferedImage>emptyList();
this.input = input;
}
public Object getInput() {
@@ -1898,13 +1903,13 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
return sizes.size();
}
public Dimension getDimension(final int pIndex) {
return sizes.get(pIndex);
public Dimension getDimension(final int index) {
return sizes.get(index);
}
@SuppressWarnings("unused")
public BufferedImage getImage(final int pIndex) {
return images.get(pIndex);
public BufferedImage getImage(final int index) {
return images.get(index);
}
@Override
@@ -39,6 +39,7 @@ import java.awt.color.*;
import java.awt.image.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
public class ImageTypeSpecifiersTest {
@@ -736,6 +737,7 @@ public class ImageTypeSpecifiersTest {
ImageTypeSpecifier fromType = ImageTypeSpecifiers.createFromBufferedImageType(type);
assertEquals(fromConstructor.getColorModel(), fromType.getColorModel());
assertEquals(fromConstructor.getSampleModel(), fromType.getSampleModel());
}
}
@@ -747,13 +749,43 @@ public class ImageTypeSpecifiersTest {
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
assertEquals(fromConstructor.getColorModel(), fromImage.getColorModel());
assertEquals(fromConstructor.getSampleModel(), fromImage.getSampleModel());
}
}
@Test
public void testCreateFromRenderedImageIndexedBinaryShouldRetainPalette() {
IndexColorModel whiteIsZero = new IndexColorModel(1, 2, new int[]{0xFFFFFFFF, 0xFF000000}, 0, false, -1, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY, whiteIsZero);
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
assertEquals(whiteIsZero, fromImage.getColorModel());
assertSame(whiteIsZero, fromImage.getColorModel()); // Note: This can be relaxed to asserting the LUTs are equal
assertEquals(image.getSampleModel(), fromImage.getSampleModel());
}
@Test
public void testCreateFromRenderedImageIndexedShouldRetainPalette() {
IndexColorModel palette = new IndexColorModel(4, 16, new int[]{
0xFFFFFFFF, 0xFF999999, 0xFF666666, 0xFF333333,
0xFF000000, 0xFF00202E, 0xFF003F5C, 0xFF2C4875,
0xFF8A508F, 0xFFBC5090, 0xFFFF6361, 0xFFFF8531,
0xFFFFA600, 0xFFFFD380, 0xFF74A892, 0xFF008585
}, 0, false, -1, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED, palette);
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
assertEquals(palette, fromImage.getColorModel());
assertSame(palette, fromImage.getColorModel()); // Note: This can be relaxed to asserting the LUTs are equal
assertEquals(image.getSampleModel(), fromImage.getSampleModel());
}
private static byte[] createByteLut(final int count) {
byte[] lut = new byte[count];
for (int i = 0; i < count; i++) {
lut[i] = (byte) count;
lut[i] = (byte) (i * 255 / count);
}
return lut;
}
@@ -762,7 +794,8 @@ public class ImageTypeSpecifiersTest {
int[] lut = new int[count];
for (int i = 0; i < count; i++) {
lut[i] = 0xff000000 | count << 16 | count << 8 | count;
int val = (i * 255 / count);
lut[i] = 0xff000000 | val << 16 | val << 8 | val;
}
return lut;
@@ -43,15 +43,17 @@ import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.image.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.net.URL;
import java.util.List;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.*;
/**
@@ -108,8 +110,8 @@ public abstract class ImageWriterAbstractTest<T extends ImageWriter> {
return getTestData().get(index);
}
protected URL getClassLoaderResource(final String pName) {
return getClass().getResource(pName);
protected URL getClassLoaderResource(final String name) {
return getClass().getResource(name);
}
@Test
+18 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-hdr</artifactId>
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name>
@@ -32,4 +32,21 @@
<artifactId>imageio-metadata</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -59,7 +59,7 @@ public final class HDRImageReader extends ImageReaderBase {
private HDRHeader header;
protected HDRImageReader(final ImageReaderSpi provider) {
HDRImageReader(final ImageReaderSpi provider) {
super(provider);
}
@@ -196,7 +196,7 @@ public final class HDRImageReader extends ImageReaderBase {
int ySub = param != null ? param.getSourceYSubsampling() : 1;
byte[] rowRGBE = new byte[width * 4];
byte[] pixelRGBE = new byte[width];
byte[] pixelRGBE = new byte[4];
processImageStarted(imageIndex);
@@ -231,7 +231,7 @@ public final class HDRImageReader extends ImageReaderBase {
processImageComplete();
return destination.getRaster();
return raster;
}
@Override
@@ -5,7 +5,7 @@ import com.twelvemonkeys.imageio.StandardImageMetadataSupport;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataNode;
public class HDRMetadata extends StandardImageMetadataSupport {
final class HDRMetadata extends StandardImageMetadataSupport {
public HDRMetadata(ImageTypeSpecifier type, HDRHeader header) {
super(builder(type)
.withCompressionTypeName("RLE")
+20 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-icns</artifactId>
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>
@@ -26,4 +26,23 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+20 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-iff</artifactId>
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
@@ -29,4 +29,23 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-jpeg-jai-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG/JAI TIFF Interop</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-jpeg-jep262-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG/JEP-262 Interop</name>
+20 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-jpeg</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
@@ -32,4 +32,23 @@
<artifactId>imageio-metadata</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -145,8 +145,8 @@ final class HuffmanTable extends Segment {
}
int c = temp >> 4;
if (c > 2) {
throw new IIOException("Unexpected JPEG Huffman Table class (> 2): " + c);
if (c > 1) {
throw new IIOException("Unexpected JPEG Huffman Table class (> 1): " + c);
}
table.tc[t][c] = true;
@@ -888,20 +888,21 @@ public final class JPEGImageReader extends ImageReaderBase {
throw new IIOException("No SOF segment in stream");
}
private Application lastAppSegment(int marker, String identifier) throws IOException {
List<Application> appSegments = getAppSegments(marker, identifier);
return appSegments.isEmpty() ? null : appSegments.get(appSegments.size() - 1);
}
AdobeDCT getAdobeDCT() throws IOException {
List<Application> adobe = getAppSegments(JPEG.APP14, "Adobe");
return adobe.isEmpty() ? null : (AdobeDCT) adobe.get(0);
return (AdobeDCT) lastAppSegment(JPEG.APP14, "Adobe");
}
JFIF getJFIF() throws IOException{
List<Application> jfif = getAppSegments(JPEG.APP0, "JFIF");
return jfif.isEmpty() ? null : (JFIF) jfif.get(0);
return (JFIF) lastAppSegment(JPEG.APP0, "JFIF");
}
JFXX getJFXX() throws IOException {
List<Application> jfxx = getAppSegments(JPEG.APP0, "JFXX");
return jfxx.isEmpty() ? null : (JFXX) jfxx.get(0);
return (JFXX) lastAppSegment(JPEG.APP0, "JFXX");
}
private EXIF getExif() throws IOException {
@@ -52,7 +52,7 @@ import static com.twelvemonkeys.imageio.util.IIOUtil.lookupProviderByName;
* @version $Id: JPEGImageReaderSpi.java,v 1.0 24.01.11 22.12 haraldk Exp$
*/
public final class JPEGImageReaderSpi extends ImageReaderSpiBase {
protected ImageReaderSpi delegateProvider;
ImageReaderSpi delegateProvider;
/**
* Constructor for use by {@link javax.imageio.spi.IIORegistry} only.
@@ -32,19 +32,21 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
import com.twelvemonkeys.imageio.ImageWriterBase;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import org.w3c.dom.NodeList;
import javax.imageio.IIOImage;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.event.IIOWriteWarningListener;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.color.*;
import java.awt.image.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -161,7 +163,7 @@ public final class JPEGImageWriter extends ImageWriterBase {
else {
// If the image metadata is our substitute, convert it back to native com.sun format
if (image.getMetadata() instanceof JPEGImage10Metadata) {
ImageTypeSpecifier type = image.hasRaster() ? null : ImageTypeSpecifier.createFromRenderedImage(image.getRenderedImage());
ImageTypeSpecifier type = image.hasRaster() ? null : ImageTypeSpecifiers.createFromRenderedImage(image.getRenderedImage());
IIOMetadata nativeMetadata = delegate.getDefaultImageMetadata(type, param);
JPEGImage10Metadata metadata = (JPEGImage10Metadata) image.getMetadata();
@@ -184,23 +186,67 @@ public final class JPEGImageWriter extends ImageWriterBase {
RenderedImage renderedImage = image.getRenderedImage();
boolean overrideDestination = param != null && param.getDestinationType() != null;
ImageTypeSpecifier destinationType = overrideDestination
? param.getDestinationType()
: ImageTypeSpecifier.createFromRenderedImage(renderedImage);
? param.getDestinationType()
: ImageTypeSpecifiers.createFromRenderedImage(renderedImage);
ColorSpace cmykCS = destinationType.getColorModel().getColorSpace();
IIOMetadata metadata = convertCMYKMetadata(image.getMetadata(), destinationType, param);
IIOMetadata metadata = delegate.getDefaultImageMetadata(destinationType, param);
Raster raster = new InvertedRaster(getRaster(renderedImage));
// TODO: For YCCK we need oposite conversion
// for (int i = 0; i < data.length; i += 4) {
// YCbCrConverter.convertYCbCr2RGB(data, data, i);
// }
if (overrideDestination) {
// Avoid javax.imageio.IIOException: Invalid argument to native writeImage
param.setDestinationType(null);
}
try {
delegate.write(streamMetadata, new IIOImage(raster, null, metadata), param);
}
finally {
if (overrideDestination) {
param.setDestinationType(destinationType);
}
}
}
private IIOMetadata convertCMYKMetadata(IIOMetadata original, ImageTypeSpecifier destinationType, ImageWriteParam param) throws IIOInvalidTreeException {
IIOMetadataNode jpegMeta = new IIOMetadataNode(JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
jpegMeta.appendChild(new IIOMetadataNode("JPEGVariety")); // Just leave as default
jpegMeta.appendChild(new IIOMetadataNode("JPEGVariety")); // Just leave as default, we can't write JFIF
IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence");
jpegMeta.appendChild(markerSequence);
IIOMetadataNode originalTree = original != null
? (IIOMetadataNode) original.getAsTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0)
: new IIOMetadataNode("emptyNode");
// Append original unknown nodes, if present, but filter out any ICC Profiles
NodeList unknowns = originalTree.getElementsByTagName("unknown");
for (int i = 0; i < unknowns.getLength(); i++) {
IIOMetadataNode unknown = (IIOMetadataNode) unknowns.item(i);
// TODO: If the cmykCS is not an ICC profile, maybe it makes sense to NOT filter here? that's a corner case...
if ("226".equals(unknown.getAttribute("MarkerTag"))) {
Object userObject = unknown.getUserObject();
if (userObject instanceof byte[] && ((byte[]) userObject).length >= "ICC_PROFILE".length()
&& "ICC_PROFILE".equals(new String((byte[]) userObject, 0, "ICC_PROFILE".length()))) {
continue;
}
}
markerSequence.appendChild(unknown);
}
IIOMetadataNode app14Adobe = new IIOMetadataNode("app14Adobe");
app14Adobe.setAttribute("transform", "0"); // 0 for CMYK, 2 for YCCK
markerSequence.appendChild(app14Adobe);
ColorSpace cmykCS = destinationType.getColorModel().getColorSpace();
if (cmykCS instanceof ICC_ColorSpace) {
ICC_Profile profile = ((ICC_ColorSpace) cmykCS).getProfile();
byte[] profileData = profile.getData();
@@ -233,28 +279,16 @@ public final class JPEGImageWriter extends ImageWriterBase {
}
}
// Append original comment nodes, if present
NodeList comments = originalTree.getElementsByTagName("COM");
for (int i = 0; i < comments.getLength(); i++) {
markerSequence.appendChild(comments.item(i));
}
IIOMetadata metadata = delegate.getDefaultImageMetadata(destinationType, param);
metadata.mergeTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0, jpegMeta);
Raster raster = new InvertedRaster(getRaster(renderedImage));
// TODO: For YCCK we need oposite conversion
// for (int i = 0; i < data.length; i += 4) {
// YCbCrConverter.convertYCbCr2RGB(data, data, i);
// }
if (overrideDestination) {
// Avoid javax.imageio.IIOException: Invalid argument to native writeImage
param.setDestinationType(null);
}
try {
delegate.write(streamMetadata, new IIOImage(raster, null, metadata), param);
}
finally {
if (overrideDestination) {
param.setDestinationType(destinationType);
}
}
return metadata;
}
// TODO: Candidate util method
@@ -38,7 +38,13 @@ import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
import org.junit.Test;
import org.w3c.dom.NodeList;
import javax.imageio.*;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOMetadataNode;
@@ -48,8 +54,7 @@ import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.color.*;
import java.awt.image.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -211,7 +216,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter
// Test APP2/ICC_PROFILE segments form native metadata
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
assertEquals(11, unknown.getLength()); // We write longer segments than the original, so we get less segments
assertEquals(14, unknown.getLength()); // We write longer segments than the original, so we get less segments
ByteArrayOutputStream iccSegments = new ByteArrayOutputStream(1024 * 1024);
@@ -238,7 +243,6 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter
ImageWriter writer = createWriter();
ImageReader reader = ImageIO.getImageReader(writer);
// TODO: Add flag to allow removing the ICC profile from image
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"), writer, ColorSpace.TYPE_CMYK, false);
reader.reset();
@@ -259,7 +263,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter
// Test APP2/ICC_PROFILE segments form native metadata
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
assertEquals(0, unknown.getLength());
assertEquals(3, unknown.getLength());
}
// TODO: YCCK
+11 -2
View File
@@ -3,13 +3,13 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>imageio-metadata</artifactId>
<name>TwelveMonkeys :: ImageIO :: Metadata</name>
<description>
ImageIO metadata module.
TwelveMonkeys ImageIO metadata support classes.
</description>
<properties>
@@ -28,4 +28,13 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -35,8 +35,11 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
@@ -50,6 +53,7 @@ import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
import org.junit.Test;
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
@@ -490,12 +494,15 @@ public class XMPReaderTest extends MetadataReaderAbstractTest {
assertThat(exif.getEntryById("http://ns.adobe.com/exif/1.0/NativeDigest"), hasValue("36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;A7F21D25E2C562F152B2C4ECC9E534DA"));
}
@Test(timeout = 1500L)
@Test(timeout = 2500L)
public void testNoExternalRequest() throws Exception {
// TODO: Use dynamic port?
try (HTTPServer server = new HTTPServer(7777)) {
try {
createReader().read(getResourceAsIIS("/xmp/xmp-jpeg-xxe.xml"));
String maliciousXML = resourceAsString("/xmp/xmp-jpeg-xxe.xml");
try (HTTPServer server = new HTTPServer()) {
String dynamicXML = maliciousXML.replace("http://localhost:7777/", "http://localhost:" + server.port() + "/");
try (DirectImageInputStream input = new DirectImageInputStream(new ByteArrayInputStream(dynamicXML.getBytes(StandardCharsets.UTF_8)));) {
createReader().read(input);
} catch (IOException ioe) {
if (ioe.getMessage().contains("501")) {
throw new AssertionError("Reading should not cause external requests", ioe);
@@ -507,12 +514,26 @@ public class XMPReaderTest extends MetadataReaderAbstractTest {
}
}
private String resourceAsString(String name) throws IOException {
StringBuilder builder = new StringBuilder(1024);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(getResource(name).openStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
builder.append(line)
.append('\n');
}
}
return builder.toString();
}
private static class HTTPServer implements AutoCloseable {
private final ServerSocket server;
private final Thread thread;
HTTPServer(int port) throws IOException {
server = new ServerSocket(port, 1);
HTTPServer() throws IOException {
server = new ServerSocket(0, 1);
thread = new Thread(new Runnable() {
@Override public void run() {
serve();
@@ -521,6 +542,10 @@ public class XMPReaderTest extends MetadataReaderAbstractTest {
thread.start();
}
public final int port() {
return server.getLocalPort();
}
private void serve() {
try {
Socket client = server.accept();
+18 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-pcx</artifactId>
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name>
@@ -28,4 +28,21 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+10 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-pdf</artifactId>
<name>TwelveMonkeys :: ImageIO :: PDF plugin</name>
@@ -28,4 +28,13 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
+19 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-pict</artifactId>
<name>TwelveMonkeys :: ImageIO :: PICT plugin</name>
@@ -27,4 +27,22 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+20 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-pnm</artifactId>
<name>TwelveMonkeys :: ImageIO :: PNM plugin</name>
@@ -28,4 +28,23 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+20 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-psd</artifactId>
<name>TwelveMonkeys :: ImageIO :: PSD plugin</name>
@@ -31,4 +31,23 @@
<artifactId>imageio-metadata</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -709,4 +709,6 @@ interface PSD extends com.twelvemonkeys.imageio.metadata.psd.PSD {
int luni = 'l' << 24 | 'u' << 16 | 'n' << 8 | 'i';
int lyid = 'l' << 24 | 'y' << 16 | 'i' << 8 | 'd';
int lsct = 'l' << 24 | 's' << 16 | 'c' << 8 | 't';
// Undocumented: Nested section divider setting
int lsdk = 'l' << 24 | 's' << 16 | 'd' << 8 | 'k';
}
@@ -864,21 +864,27 @@ public final class PSDImageReader extends ImageReaderBase {
long imageResourcesLength = imageInput.readUnsignedInt();
if (pParseData && metadata.imageResources == null && imageResourcesLength > 0) {
long expectedEnd = imageInput.getStreamPosition() + imageResourcesLength;
metadata.imageResources = new ArrayList<>();
while (imageInput.getStreamPosition() < expectedEnd) {
PSDImageResource resource = PSDImageResource.read(imageInput);
metadata.imageResources.add(resource);
if (pParseData && metadata.imageResources == null) {
if (imageResourcesLength == 0) {
metadata.imageResources = Collections.emptyList();
}
else {
metadata.imageResources = new ArrayList<>();
if (DEBUG) {
System.out.println("imageResources: " + metadata.imageResources);
}
long expectedEnd = imageInput.getStreamPosition() + imageResourcesLength;
if (imageInput.getStreamPosition() != expectedEnd) {
throw new IIOException("Corrupt PSD document"); // ..or maybe just a bug in the reader.. ;-)
while (imageInput.getStreamPosition() < expectedEnd) {
PSDImageResource resource = PSDImageResource.read(imageInput);
metadata.imageResources.add(resource);
}
if (DEBUG) {
System.out.println("imageResources: " + metadata.imageResources);
}
if (imageInput.getStreamPosition() != expectedEnd) {
throw new IIOException("Corrupt PSD document"); // ..or maybe just a bug in the reader.. ;-)
}
}
}
@@ -1064,7 +1070,7 @@ public final class PSDImageReader extends ImageReaderBase {
final int height = getLayerHeight(layerIndex);
// TODO: This behaviour must be documented!
// If layer has no pixel data, return null
// If layer has no pixel data, return null, as we can't create a 0 x 0 sample model/raster
if (width <= 0 || height <= 0) {
return null;
}
@@ -155,6 +155,7 @@ final class PSDLayerInfo {
layerId = pInput.readInt();
break;
case PSD.lsdk:
case PSD.lsct:
if (resourceLength < 4) {
throw new IIOException(String.format("Expected sectionDividerSetting length >= 4: %d", resourceLength));
@@ -203,6 +203,7 @@ public final class PSDMetadata extends AbstractMetadata {
IIOMetadataNode guideNode = new IIOMetadataNode("Guide");
guideNode.setAttribute("location", Integer.toString(guide.location));
guideNode.setAttribute("orientation", GUIDE_ORIENTATIONS[guide.direction]);
node.appendChild(guideNode);
}
}
else if (imageResource instanceof PSDPixelAspectRatio) {
@@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.psd;
import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.io.SubStream;
import com.twelvemonkeys.io.enc.DecoderStream;
import com.twelvemonkeys.io.enc.PackBitsDecoder;
import com.twelvemonkeys.lang.StringUtil;
@@ -107,7 +108,8 @@ final class PSDUtil {
return new SubImageInputStream(stream, streamLength < 0 ? Long.MAX_VALUE : streamLength);
case PSD.COMPRESSION_RLE:
return new DirectImageInputStream(new SequenceInputStream(new LazyPackBitsStreamEnumeration(byteCounts, stream)));
int rowLength = (columns * bitsPerSample + 7) / 8;
return new DirectImageInputStream(new SequenceInputStream(new LazyPackBitsStreamEnumeration(stream, byteCounts, rowLength)));
case PSD.COMPRESSION_ZIP:
return new DirectImageInputStream(new InflaterInputStream(createStreamAdapter(stream, compressedLength)));
@@ -124,11 +126,13 @@ final class PSDUtil {
private static class LazyPackBitsStreamEnumeration implements Enumeration<InputStream> {
private final ImageInputStream stream;
private final int[] byteCounts;
private final int rowLength;
private int index;
public LazyPackBitsStreamEnumeration(int[] byteCounts, ImageInputStream stream) {
this.byteCounts = byteCounts;
public LazyPackBitsStreamEnumeration(ImageInputStream stream, int[] byteCounts, int rowLength) {
this.stream = stream;
this.byteCounts = byteCounts;
this.rowLength = rowLength;
}
@Override
@@ -138,7 +142,7 @@ final class PSDUtil {
@Override
public InputStream nextElement() {
return new DecoderStream(createStreamAdapter(stream, byteCounts[index++]), new PackBitsDecoder());
return new SubStream(new DecoderStream(createStreamAdapter(stream, byteCounts[index++]), new PackBitsDecoder(), rowLength), rowLength);
}
}
}
@@ -47,6 +47,7 @@ import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import java.io.EOFException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -695,6 +696,30 @@ public class PSDImageReaderTest extends ImageReaderAbstractTest<PSDImageReader>
}
}
@Test(timeout = 1000)
public void testBrokenPackBitsThrowsEOFException() throws IOException {
PSDImageReader imageReader = createReader();
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/broken-psd/short-packbits.psd"))) {
imageReader.setInput(stream);
assertEquals(1, imageReader.getNumImages(true));
assertEquals(427, imageReader.getWidth(0));
assertEquals(107, imageReader.getHeight(0));
try {
imageReader.read(0);
fail("Expected EOFException, is the test broken?");
}
catch (EOFException expected) {
assertTrue(expected.getMessage().contains("PackBits"));
}
}
}
final static class FakeCMYKColorSpace extends ColorSpace {
FakeCMYKColorSpace() {
super(ColorSpace.TYPE_CMYK, 4);
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-reference</artifactId>
<name>TwelveMonkeys :: ImageIO :: JDK Reference Tests</name>
+18 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-sgi</artifactId>
<name>TwelveMonkeys :: ImageIO :: SGI plugin</name>
@@ -28,4 +28,21 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+20 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-tga</artifactId>
<name>TwelveMonkeys :: ImageIO :: TGA plugin</name>
@@ -28,4 +28,23 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+18 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-thumbsdb</artifactId>
<name>TwelveMonkeys :: ImageIO :: Thumbs.db plugin</name>
@@ -28,4 +28,21 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-tiff-jai-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: TIFF/JAI Metadata Interop</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-tiff-jdk-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: TIFF/JDK JPEG Interop</name>
+20 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-tiff</artifactId>
<name>TwelveMonkeys :: ImageIO :: TIFF plugin</name>
@@ -37,4 +37,23 @@
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi,
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageWriterSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,198 @@
/*
* Copyright (c) 2023, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.imageio.plugins.tiff;
import com.twelvemonkeys.lang.Validate;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
/**
* A decoder for data converted using "floating point horizontal differencing predictor".
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haraldk$
* @version $Id: HorizontalDeDifferencingStream.java,v 1.0 11.03.13 14:20 haraldk Exp$
*/
final class HorizontalDeDifferencingFloatingPointStream extends InputStream {
// See TIFF 6.0 Specification, Section 14: "Differencing Predictor", page 64.
// Adapted from the C code in Adobe Photoshop® TIFF Technical Note 3
private final int columns;
// NOTE: PlanarConfiguration == 2 may be treated as samplesPerPixel == 1
private final int samplesPerPixel;
private final int bytesPerSample;
private final ReadableByteChannel channel;
private final ByteBuffer buffer;
private final byte[] fpRow;
public HorizontalDeDifferencingFloatingPointStream(final InputStream stream, final int columns, final int samplesPerPixel, final int bitsPerSample, final ByteOrder byteOrder) {
this.columns = Validate.isTrue(columns > 0, columns, "width must be greater than 0");
this.samplesPerPixel = samplesPerPixel;
Validate.isTrue(isValidBPS(bitsPerSample), bitsPerSample, "Unsupported bits per sample value: %s");
bytesPerSample = (samplesPerPixel * bitsPerSample + 7) / 8;
channel = Channels.newChannel(Validate.notNull(stream, "stream"));
buffer = ByteBuffer.allocate(columns * bytesPerSample)
.order(byteOrder);
fpRow = buffer.array().clone();
buffer.flip();
}
private static boolean isValidBPS(final int bitsPerSample) {
switch (bitsPerSample) {
case 16:
case 24:
case 32:
case 64:
return true;
default:
return false;
}
}
@SuppressWarnings("StatementWithEmptyBody")
private boolean fetch() throws IOException {
buffer.clear();
// This *SHOULD* read an entire row of pixels (or nothing at all) into the buffer,
// otherwise we will throw EOFException below
while (channel.read(buffer) > 0);
if (buffer.position() > 0) {
if (buffer.hasRemaining()) {
throw new EOFException("Unexpected end of stream");
}
decodeRow();
buffer.flip();
return true;
}
else {
buffer.position(buffer.capacity());
return false;
}
}
private void decodeDeltaBytes(byte[] bytes, int columns, int samplesPerPixel) {
for (int column = 1; column < columns; column++) {
for (int channel = 0; channel < samplesPerPixel; channel++) {
bytes[column * samplesPerPixel + channel] = (byte) (bytes[column * samplesPerPixel + channel] + bytes[(column - 1) * samplesPerPixel + channel]);
}
}
}
private void decodeFloatingPointDelta(byte[] input, byte[] output, int columns, int channels, int bytesPerSample, final ByteOrder order) {
// undo byte difference on input
decodeDeltaBytes(input, columns * bytesPerSample, channels);
// reorder the bytes into the floating point buffer
int rowIncrement = columns * channels;
for (int column = 0; column < rowIncrement; column++) {
for (int b = 0; b < bytesPerSample; b++) {
output[bytesPerSample * column + b] = order == ByteOrder.BIG_ENDIAN
? input[b * rowIncrement + column]
: input[(bytesPerSample - b - 1) * rowIncrement + column];
}
}
}
private void decodeRow() {
// Un-apply horizontal predictor
decodeFloatingPointDelta(buffer.array(), fpRow, columns, samplesPerPixel, bytesPerSample, buffer.order());
System.arraycopy(fpRow, 0, buffer.array(), 0, fpRow.length);
}
@Override
public int read() throws IOException {
if (!buffer.hasRemaining()) {
if (!fetch()) {
return -1;
}
}
return buffer.get() & 0xff;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (!buffer.hasRemaining()) {
if (!fetch()) {
return -1;
}
}
int read = Math.min(buffer.remaining(), len);
buffer.get(b, off, read);
return read;
}
@Override
public long skip(long n) throws IOException {
if (n < 0) {
return 0;
}
if (!buffer.hasRemaining()) {
if (!fetch()) {
return 0; // SIC
}
}
int skipped = (int) Math.min(buffer.remaining(), n);
buffer.position(buffer.position() + skipped);
return skipped;
}
@Override
public void close() throws IOException {
try {
super.close();
}
finally {
if (channel.isOpen()) {
channel.close();
}
}
}
}
@@ -68,7 +68,8 @@ final class HorizontalDeDifferencingStream extends InputStream {
channel = Channels.newChannel(Validate.notNull(stream, "stream"));
buffer = ByteBuffer.allocate((columns * samplesPerPixel * bitsPerSample + 7) / 8).order(byteOrder);
buffer = ByteBuffer.allocate((columns * samplesPerPixel * bitsPerSample + 7) / 8)
.order(byteOrder);
buffer.flip();
}
@@ -93,7 +93,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import static com.twelvemonkeys.imageio.util.IIOUtil.createStreamAdapter;
@@ -911,7 +910,7 @@ public final class TIFFImageReader extends ImageReaderBase {
Set<ImageTypeSpecifier> specs = new LinkedHashSet<>(5);
// TODO: Based on raw type, we can probably convert to most RGB types at least, maybe gray etc
if (rawType.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_RGB) {
if (rawType.getColorModel().getColorSpace().isCS_sRGB()) {
if (rawType.getNumBands() == 3 && rawType.getBitsPerBand(0) == 8) {
specs.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR));
// specs.add(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_BGR));
@@ -2429,7 +2428,7 @@ public final class TIFFImageReader extends ImageReaderBase {
case TIFFExtension.COMPRESSION_DEFLATE:
// TIFF specification, supplement 2 says ZLIB (8) and DEFLATE (32946) algorithms are identical
case TIFFCustom.COMPRESSION_PIXTIFF_ZIP:
return new InflaterInputStream(stream, new Inflater(), 1024);
return new InflaterInputStream(stream);
case TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE:
case TIFFExtension.COMPRESSION_CCITT_T4:
case TIFFExtension.COMPRESSION_CCITT_T6:
@@ -2484,7 +2483,7 @@ public final class TIFFImageReader extends ImageReaderBase {
case TIFFExtension.PREDICTOR_HORIZONTAL_DIFFERENCING:
return new HorizontalDeDifferencingStream(stream, width, samplesPerPixel, bitsPerSample, byteOrder);
case TIFFExtension.PREDICTOR_HORIZONTAL_FLOATINGPOINT:
throw new IIOException("Unsupported TIFF Predictor value: " + predictor);
return new HorizontalDeDifferencingFloatingPointStream(stream, width, samplesPerPixel, bitsPerSample, byteOrder);
default:
throw new IIOException("Unknown TIFF Predictor value: " + predictor);
}
@@ -40,6 +40,7 @@ import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFWriter;
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
import com.twelvemonkeys.imageio.util.IIOUtil;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import com.twelvemonkeys.io.enc.EncoderStream;
import com.twelvemonkeys.io.enc.PackBitsEncoder;
@@ -149,9 +150,9 @@ public final class TIFFImageWriter extends ImageWriterBase {
RenderedImage renderedImage = image.getRenderedImage();
SampleModel sampleModel = renderedImage.getSampleModel();
// Can't use createFromRenderedImage in this case, as it does not consider palette for TYPE_BYTE_BINARY...
// TODO: Consider writing workaround in ImageTypeSpecifiers
ImageTypeSpecifier spec = new ImageTypeSpecifier(renderedImage);
// Need ImageTypeSpecifiers.createFromRenderedImage in this case, as the JDK method does not consider
// palette for TYPE_BYTE_BINARY/TYPE_BYTE_INDEXED...
ImageTypeSpecifier spec = ImageTypeSpecifiers.createFromRenderedImage(renderedImage);
// TODO: Handle case where convertImageMetadata returns null, due to unknown metadata format, or reconsider if that's a valid case...
TIFFImageMetadata metadata = image.getMetadata() != null
@@ -249,7 +250,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
ListenerDelegate listener = new ListenerDelegate(imageIndex);
jpegWriter.addIIOWriteProgressListener(listener);
jpegWriter.addIIOWriteWarningListener(listener);
jpegWriter.write(null, image, copyParams(param, jpegWriter));
jpegWriter.write(null, imageOnly(image), copyParams(param, jpegWriter));
}
finally {
jpegWriter.dispose();
@@ -284,6 +285,17 @@ public final class TIFFImageWriter extends ImageWriterBase {
return nextIFDPointerOffset;
}
private IIOImage imageOnly(final IIOImage image) {
if (image.getMetadata() == null && image.getNumThumbnails() == 0) {
// Just image data here, no need to copy
return image;
}
return image.hasRaster()
? new IIOImage(image.getRaster(), null, null)
: new IIOImage(image.getRenderedImage(), null, null);
}
// TODO: Candidate util method
private ImageWriteParam copyParams(final ImageWriteParam param, final ImageWriter writer) {
if (param == null) {
@@ -531,6 +543,10 @@ public final class TIFFImageWriter extends ImageWriterBase {
final int sampleSize = renderedImage.getSampleModel().getSampleSize(0);
final int numBands = renderedImage.getSampleModel().getNumBands();
// TODO: This buffer should probably have order matching that of imageOutput, but only if writing "actual" 16 or 32 bit samples, not "packed" samples
final byte[] buffer = new byte[(tileWidth * numBands * sampleSize + 7) / 8];
int bufferPos = 0;
for (int yTile = minTileY; yTile < maxYTiles; yTile++) {
for (int xTile = minTileX; xTile < maxXTiles; xTile++) {
final Raster tile = renderedImage.getTile(xTile, yTile);
@@ -568,16 +584,17 @@ public final class TIFFImageWriter extends ImageWriterBase {
for (int s = 0; s < numBands; s++) {
if (sampleSize == 8 || shift == 0) {
// Normal interleaved/planar case
stream.writeByte((byte) (dataBuffer.getElem(b, xOff + bandOffsets[s]) & 0xff));
buffer[bufferPos++] = ((byte) (dataBuffer.getElem(b, xOff + bandOffsets[s]) & 0xff));
}
else {
// "Packed" case
stream.writeByte((byte) (rowBuffer.getElem(b, x - offsetX + bandOffsets[s]) & 0xff));
buffer[bufferPos++] = ((byte) (rowBuffer.getElem(b, x - offsetX + bandOffsets[s]) & 0xff));
}
}
}
flushBuffer(buffer, bufferPos, stream);
bufferPos = 0;
flushStream(stream);
}
}
@@ -597,9 +614,13 @@ public final class TIFFImageWriter extends ImageWriterBase {
for (int x = offsetX; x < tileWidth + offsetX; x++) {
int xOff = yOff + x;
stream.writeShort((short) (dataBuffer.getElem(b, xOff) & 0xffff));
int elem = dataBuffer.getElem(b, xOff);
buffer[bufferPos++] = (byte) ((elem >>> 8) & 0xff);
buffer[bufferPos++] = (byte) (elem & 0xff);
}
flushBuffer(buffer, bufferPos, stream);
bufferPos = 0;
flushStream(stream);
}
}
@@ -642,9 +663,15 @@ public final class TIFFImageWriter extends ImageWriterBase {
for (int x = offsetX; x < tileWidth + offsetX; x++) {
int xOff = yOff + x;
stream.writeInt(dataBuffer.getElem(b, xOff));
int elem = dataBuffer.getElem(b, xOff);
buffer[bufferPos++] = (byte) ((elem >>> 24) & 0xff);
buffer[bufferPos++] = (byte) ((elem >>> 16) & 0xff);
buffer[bufferPos++] = (byte) ((elem >>> 8) & 0xff);
buffer[bufferPos++] = (byte) (elem & 0xff);
}
flushBuffer(buffer, bufferPos, stream);
bufferPos = 0;
flushStream(stream);
}
}
@@ -661,10 +688,12 @@ public final class TIFFImageWriter extends ImageWriterBase {
int element = dataBuffer.getElem(b, xOff);
for (int s = 0; s < numBands; s++) {
stream.writeByte((byte) ((element >> bitOffsets[s]) & 0xff));
buffer[bufferPos++] = (byte) ((element >> bitOffsets[s]) & 0xff);
}
}
flushBuffer(buffer, bufferPos, stream);
bufferPos = 0;
flushStream(stream);
}
}
@@ -690,14 +719,18 @@ public final class TIFFImageWriter extends ImageWriterBase {
processImageComplete();
}
private void flushStream(DataOutput stream) throws IOException {
// Need to flush/start new compression for each row, for proper LZW/PackBits/Deflate/ZLib compression
private static void flushStream(DataOutput stream) throws IOException {
// Need to flush/start new compression for each row, for proper LZW/PackBits/Deflate/ZLib
if (stream instanceof DataOutputStream) {
DataOutputStream dataOutputStream = (DataOutputStream) stream;
dataOutputStream.flush();
}
}
private static void flushBuffer(final byte[] buffer, final int bufferPos, final DataOutput stream) throws IOException {
stream.write(buffer, 0, bufferPos);
}
// Metadata
@Override
@@ -34,6 +34,7 @@ import com.twelvemonkeys.imageio.metadata.Directory;
import com.twelvemonkeys.imageio.metadata.Entry;
import com.twelvemonkeys.imageio.metadata.tiff.Rational;
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
@@ -73,6 +74,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.twelvemonkeys.imageio.metadata.tiff.TIFF.TAG_X_RESOLUTION;
import static com.twelvemonkeys.imageio.metadata.tiff.TIFF.TAG_Y_RESOLUTION;
import static com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME;
import static com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataTest.createTIFFFieldNode;
import static com.twelvemonkeys.imageio.util.ImageReaderAbstractTest.assertRGBEquals;
@@ -133,8 +136,8 @@ public class TIFFImageWriterTest extends ImageWriterAbstractTest<TIFFImageWriter
customMeta.appendChild(ifd);
createTIFFFieldNode(ifd, TIFF.TAG_RESOLUTION_UNIT, TIFF.TYPE_SHORT, resolutionUnitValue);
createTIFFFieldNode(ifd, TIFF.TAG_X_RESOLUTION, TIFF.TYPE_RATIONAL, resolutionValue);
createTIFFFieldNode(ifd, TIFF.TAG_Y_RESOLUTION, TIFF.TYPE_RATIONAL, resolutionValue);
createTIFFFieldNode(ifd, TAG_X_RESOLUTION, TIFF.TYPE_RATIONAL, resolutionValue);
createTIFFFieldNode(ifd, TAG_Y_RESOLUTION, TIFF.TYPE_RATIONAL, resolutionValue);
metadata.mergeTree(nativeFormat, customMeta);
@@ -153,11 +156,11 @@ public class TIFFImageWriterTest extends ImageWriterAbstractTest<TIFFImageWriter
assertNotNull(resolutionUnit);
assertEquals(resolutionUnitValue, ((Number) resolutionUnit.getValue()).intValue());
Entry xResolution = ifds.getEntryById(TIFF.TAG_X_RESOLUTION);
Entry xResolution = ifds.getEntryById(TAG_X_RESOLUTION);
assertNotNull(xResolution);
assertEquals(resolutionValue, xResolution.getValue());
Entry yResolution = ifds.getEntryById(TIFF.TAG_Y_RESOLUTION);
Entry yResolution = ifds.getEntryById(TAG_Y_RESOLUTION);
assertNotNull(yResolution);
assertEquals(resolutionValue, yResolution.getValue());
}
@@ -272,11 +275,11 @@ public class TIFFImageWriterTest extends ImageWriterAbstractTest<TIFFImageWriter
assertNotNull(resolutionUnit);
assertEquals(resolutionUnitValue, ((Number) resolutionUnit.getValue()).intValue());
Entry xResolution = ifds.getEntryById(TIFF.TAG_X_RESOLUTION);
Entry xResolution = ifds.getEntryById(TAG_X_RESOLUTION);
assertNotNull(xResolution);
assertEquals(expectedResolutionValue, xResolution.getValue());
Entry yResolution = ifds.getEntryById(TIFF.TAG_Y_RESOLUTION);
Entry yResolution = ifds.getEntryById(TAG_Y_RESOLUTION);
assertNotNull(yResolution);
assertEquals(expectedResolutionValue, yResolution.getValue());
}
@@ -1304,6 +1307,79 @@ public class TIFFImageWriterTest extends ImageWriterAbstractTest<TIFFImageWriter
}
}
@Test
public void testWriteBinaryWhiteIsZero() throws IOException {
IndexColorModel whiteIsZero = new IndexColorModel(1, 2, new int[] {-1, 0}, 0, false, -1, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_BINARY, whiteIsZero);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ImageOutputStream output = ImageIO.createImageOutputStream(bytes)) {
ImageWriter imageWriter = createWriter();
imageWriter.setOutput(output);
imageWriter.write(image);
}
Directory directory = new TIFFReader().read(new ByteArrayImageInputStream(bytes.toByteArray()));
assertNotNull(directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION));
assertEquals(TIFFBaseline.PHOTOMETRIC_WHITE_IS_ZERO, directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION).getValue());
}
@Test
public void testWriteBinaryBlackIsZero() throws IOException {
IndexColorModel blackIsZero = new IndexColorModel(1, 2, new int[] {0, -1}, 0, false, -1, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_BINARY, blackIsZero);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ImageOutputStream output = ImageIO.createImageOutputStream(bytes)) {
ImageWriter imageWriter = createWriter();
imageWriter.setOutput(output);
imageWriter.write(image);
}
Directory directory = new TIFFReader().read(new ByteArrayImageInputStream(bytes.toByteArray()));
assertNotNull(directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION));
assertEquals(TIFFBaseline.PHOTOMETRIC_BLACK_IS_ZERO, directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION).getValue());
}
@Test
public void testWriteBinaryPalette() throws IOException {
IndexColorModel redAndBluePalette = new IndexColorModel(1, 2, new int[] {0xFF00FF00, 0xFF0000FF}, 0, false, -1, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_BINARY, redAndBluePalette);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (ImageOutputStream output = ImageIO.createImageOutputStream(bytes)) {
ImageWriter imageWriter = createWriter();
imageWriter.setOutput(output);
imageWriter.write(image);
}
Directory directory = new TIFFReader().read(new ByteArrayImageInputStream(bytes.toByteArray()));
assertNotNull(directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION));
assertEquals(TIFFBaseline.PHOTOMETRIC_PALETTE, directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION).getValue());
}
@Test
public void testWriteJPEGCompressedShouldNotPassMetadata() throws IOException {
BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR);
try (ImageOutputStream output = new NullImageOutputStream()) {
ImageWriter imageWriter = createWriter();
imageWriter.setOutput(output);
ImageWriteParam param = imageWriter.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionType("JPEG");
// From #815
// Prior to fix, this would throw IIOException: Metadata components != number of destination bands
// (empty metadata defaults to 1 channel gray, while image data is 3 channel BGR)
imageWriter.write(null, new IIOImage(image, null, new TIFFImageMetadata()), param);
}
}
@Test
public void testShortOverflowHuge() throws IOException {
int width = 34769;
+18 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.4</version>
<version>3.10.2-SNAPSHOT</version>
</parent>
<artifactId>imageio-webp</artifactId>
<name>TwelveMonkeys :: ImageIO :: WebP plugin</name>
@@ -31,4 +31,21 @@
<type>test-jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Provide-Capability>
osgi.serviceloader;
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
</Provide-Capability>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -61,6 +61,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static com.twelvemonkeys.imageio.plugins.webp.lossless.VP8LDecoder.copyIntoRasterWithParams;
import static java.lang.Math.max;
import static java.lang.Math.min;
@@ -76,6 +77,11 @@ final class WebPImageReader extends ImageReaderBase {
// Either VP8_, VP8L or VP8X chunk
private long fileSize;
private VP8xChunk header;
// The ICC Profile contained in the stream, only suitable for metadata.
private ICC_Profile containedICCP;
// A safe, verified RGB ICC Profile used for color conversion.
private ICC_Profile iccProfile;
private final List<AnimationFrame> frames = new ArrayList<>();
@@ -87,6 +93,7 @@ final class WebPImageReader extends ImageReaderBase {
protected void resetMembers() {
fileSize = -1;
header = null;
containedICCP = null;
iccProfile = null;
lsbBitReader = null;
frames.clear();
@@ -132,8 +139,8 @@ final class WebPImageReader extends ImageReaderBase {
if (DEBUG) {
System.out.printf("chunk: '%s'\n", fourCC(nextChunk));
System.out.println("chunkLength: " + chunkLength);
System.out.println("chunkStart: " + chunkStart);
System.out.println("chunkLength: " + chunkLength);
}
switch (nextChunk) {
@@ -298,13 +305,20 @@ final class WebPImageReader extends ImageReaderBase {
if (header.containsICCP) {
// ICCP chunk must be first chunk, if present
while (iccProfile == null && imageInput.getStreamPosition() < fileSize) {
while (containedICCP == null && imageInput.getStreamPosition() < fileSize) {
int nextChunk = imageInput.readInt();
long chunkLength = imageInput.readUnsignedInt();
long chunkStart = imageInput.getStreamPosition();
if (nextChunk == WebP.CHUNK_ICCP) {
iccProfile = ColorProfiles.readProfile(IIOUtil.createStreamAdapter(imageInput, chunkLength));
containedICCP = ColorProfiles.readProfile(IIOUtil.createStreamAdapter(imageInput, chunkLength));
if (containedICCP.getColorSpaceType() == ColorSpace.TYPE_RGB) {
iccProfile = containedICCP;
}
else {
processWarningOccurred("Encountered non-RGB ICC Profile, ignoring color profile, colors may appear incorrect");
}
}
else {
processWarningOccurred(String.format("Expected 'ICCP' chunk, '%s' chunk encountered", fourCC(nextChunk)));
@@ -385,9 +399,10 @@ final class WebPImageReader extends ImageReaderBase {
if (iccProfile != null && !ColorProfiles.isCS_sRGB(iccProfile)) {
ICC_ColorSpace colorSpace = ColorSpaces.createColorSpace(iccProfile);
int[] bandOffsets = header.containsALPH ? new int[] {0, 1, 2, 3} : new int[] {0, 1, 2};
int[] bandOffsets = header.containsALPH ? new int[]{0, 1, 2, 3} : new int[]{0, 1, 2};
return ImageTypeSpecifiers.createInterleaved(colorSpace, bandOffsets, DataBuffer.TYPE_BYTE, header.containsALPH, false);
}
// Non-RGB profile is simply ignored
return ImageTypeSpecifiers.createFromBufferedImageType(header.containsALPH ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR);
}
@@ -464,6 +479,8 @@ final class WebPImageReader extends ImageReaderBase {
}
private void readVP8Extended(BufferedImage destination, ImageReadParam param, long streamEnd, final int width, final int height) throws IOException {
boolean seenALPH = false;
while (imageInput.getStreamPosition() < streamEnd) {
int nextChunk = imageInput.readInt();
long chunkLength = imageInput.readUnsignedInt();
@@ -471,18 +488,25 @@ final class WebPImageReader extends ImageReaderBase {
if (DEBUG) {
System.out.printf("chunk: '%s'\n", fourCC(nextChunk));
System.out.println("chunkLength: " + chunkLength);
System.out.println("chunkStart: " + chunkStart);
System.out.println("chunkLength: " + chunkLength);
}
switch (nextChunk) {
case WebP.CHUNK_ALPH:
seenALPH = true;
readAlpha(destination, param, width, height);
break;
case WebP.CHUNK_VP8_:
readVP8(RasterUtils.asByteRaster(destination.getRaster())
.createWritableChild(0, 0, destination.getWidth(), destination.getHeight(), 0, 0, new int[] {0, 1, 2}), param);
if (header.containsALPH && !seenALPH) {
// May happen for animation frames, if some frames are fully opaque
opaqueAlpha(destination.getAlphaRaster());
}
break;
case WebP.CHUNK_VP8L:
@@ -536,21 +560,26 @@ final class WebPImageReader extends ImageReaderBase {
// Simulate header
imageInput.seek(imageInput.getStreamPosition() - 5);
WritableRaster tempRaster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, destination.getWidth(), destination.getHeight(), 4, null);
readVP8Lossless(tempRaster, param, width, height);
// Temp alpha raster must have same dimensions as the source, because of filtering.
WritableRaster tempRaster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, 4, null);
readVP8Lossless(tempRaster, null, width, height);
// Copy from green (band 1) in temp to alpha in destination
alphaRaster.setRect(tempRaster.createChild(0, 0, tempRaster.getWidth(), tempRaster.getHeight(), 0, 0, new int[] {1}));
WritableRaster alphaChannel = tempRaster.createWritableChild(0, 0, tempRaster.getWidth(), tempRaster.getHeight(), 0, 0, new int[]{1});
alphaFilter(alphaChannel, filtering);
copyIntoRasterWithParams(alphaChannel, alphaRaster, param);
break;
default:
processWarningOccurred("Unknown WebP alpha compression: " + compression);
opaqueAlpha(alphaRaster);
break;
}
}
private void alphaFilter(WritableRaster alphaRaster, int filtering) {
if (filtering != AlphaFiltering.NONE) {
for (int y = 0; y < destination.getHeight(); y++) {
for (int x = 0; x < destination.getWidth(); x++) {
for (int y = 0; y < alphaRaster.getHeight(); y++) {
for (int x = 0; x < alphaRaster.getWidth(); x++) {
int predictorAlpha = getPredictorAlpha(alphaRaster, filtering, y, x);
alphaRaster.setSample(x, y, 0, alphaRaster.getSample(x, y, 0) + predictorAlpha % 256);
}
@@ -677,8 +706,8 @@ final class WebPImageReader extends ImageReaderBase {
long chunkStart = imageInput.getStreamPosition();
// System.err.printf("chunk: '%s'\n", fourCC(nextChunk));
// System.err.println("chunkLength: " + chunkLength);
// System.err.println("chunkStart: " + chunkStart);
// System.err.println("chunkLength: " + chunkLength);
switch (nextChunk) {
case WebP.CHUNK_EXIF:
@@ -67,6 +67,11 @@ final class ColorIndexingTransform implements Transform {
// Arraycopy for 4 elements might not be beneficial
System.arraycopy(colorTable, index * 4, rgba, 0, 4);
// rgba[0] = colorTable[index * 4];
// rgba[1] = colorTable[index * 4 + 1];
// rgba[2] = colorTable[index * 4 + 2];
// rgba[3] = colorTable[index * 4 + 3];
raster.setDataElements(x, y, rgba);
}
}

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