Compare commits

...

220 Commits

Author SHA1 Message Date
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
143 changed files with 3346 additions and 1318 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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</version>
</parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
@@ -47,7 +47,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</version>
</parent>
<artifactId>imageio-batik</artifactId>
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
@@ -17,7 +17,7 @@
<properties>
<project.jpms.module.name>com.twelvemonkeys.imageio.batik</project.jpms.module.name>
<batik.version>1.15</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</version>
</parent>
<artifactId>imageio-core</artifactId>
<name>TwelveMonkeys :: ImageIO :: Core</name>
<description>
TwelveMonkeys ImageIO core support classes.
</description>
<properties>
<project.jpms.module.name>com.twelvemonkeys.imageio.core</project.jpms.module.name>
@@ -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();
}
@@ -31,6 +31,7 @@
package com.twelvemonkeys.imageio.stream;
import javax.imageio.stream.ImageInputStreamImpl;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -52,6 +53,10 @@ import static java.lang.Math.max;
* for shorter reads, like single byte or bit reads.
*/
final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
private static final Closeable CLOSEABLE_STUB = new Closeable() {
@Override public void close() {}
};
static final int DEFAULT_BUFFER_SIZE = 8192;
private ByteBuffer byteBuffer = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
@@ -63,6 +68,7 @@ final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
private final byte[] integralCacheArray = integralCache.array();
private SeekableByteChannel channel;
private Closeable closeable;
/**
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code File}.
@@ -86,49 +92,62 @@ final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
* @throws SecurityException if a security manager is installed, and it denies read access to the file.
*/
public BufferedChannelImageInputStream(final Path file) throws IOException {
this(FileChannel.open(notNull(file, "file"), StandardOpenOption.READ));
this(FileChannel.open(notNull(file, "file"), StandardOpenOption.READ), true);
}
/**
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code RandomAccessFile}.
* <p>
* Closing this stream will close the {@code RandomAccessFile}.
* </p>
*
* @param file a {@code RandomAccessFile} to read from.
* @throws IllegalArgumentException if {@code file} is {@code null}.
*/
public BufferedChannelImageInputStream(final RandomAccessFile file) {
// Assumption: Closing the FileChannel will also close its backing RandomAccessFile
// (it does in the OpenJDK implementation, and it makes sense, although I can't see this is documented behaviour).
this(notNull(file, "file").getChannel());
// Closing the RAF is inconsistent, but emulates the behavior of javax.imageio.stream.FileImageInputStream
this(notNull(file, "file").getChannel(), true);
}
/**
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code FileInputStream}.
* <p>
* Closing this stream will close the {@code FileInputStream}.
* Closing this stream will <em>not</em> close the {@code FileInputStream}.
* </p>
*
* @param inputStream a {@code FileInputStream} to read from.
* @throws IllegalArgumentException if {@code inputStream} is {@code null}.
*/
public BufferedChannelImageInputStream(final FileInputStream inputStream) {
// Assumption: Closing the FileChannel will also close its backing FileInputStream (it does in the OpenJDK implementation, although I can't see this is documented).
this(notNull(inputStream, "inputStream").getChannel());
this(notNull(inputStream, "inputStream").getChannel(), false);
}
/**
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code SeekableByteChannel}.
* <p>
* Closing this stream will close the {@code SeekableByteChannel}.
* Closing this stream will <em>not</em> close the {@code SeekableByteChannel}.
* </p>
*
* @param channel a {@code SeekableByteChannel} to read from.
* @throws IllegalArgumentException if {@code channel} is {@code null}.
*/
public BufferedChannelImageInputStream(final SeekableByteChannel channel) {
this(notNull(channel, "channel"), false);
}
/**
* Constructs a {@code BufferedChannelImageInputStream} that will read from a given {@code Cache}.
* <p>
* Closing this stream will close the {@code Cache}.
* </p>
*
* @param cache a {@code SeekableByteChannel} to read from.
* @throws IllegalArgumentException if {@code channel} is {@code null}.
*/
BufferedChannelImageInputStream(final Cache cache) {
this(notNull(cache, "cache"), true);
}
private BufferedChannelImageInputStream(final SeekableByteChannel channel, boolean closeChannelOnClose) {
this.channel = notNull(channel, "channel");
this.closeable = closeChannelOnClose ? this.channel : CLOSEABLE_STUB;
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
@@ -246,8 +265,14 @@ final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
buffer = null;
byteBuffer = null;
channel.close();
channel = null;
try {
closeable.close();
}
finally {
closeable = null;
}
}
// Need to override the readShort(), readInt() and readLong() methods,
@@ -315,9 +340,9 @@ final class BufferedChannelImageInputStream extends ImageInputStreamImpl {
public void flushBefore(final long pos) throws IOException {
super.flushBefore(pos);
if (channel instanceof MemoryCache) {
if (channel instanceof Cache) {
// In case of memory cache, free up memory
((MemoryCache) channel).flushBefore(pos);
((Cache) channel).flushBefore(pos);
}
}
}
@@ -53,7 +53,7 @@ public final class BufferedInputStreamImageInputStreamSpi extends ImageInputStre
}
// Otherwise, create a cache for backwards seeking
return new BufferedChannelImageInputStream(useCacheFile ? new DiskCache(channel, cacheDir): new MemoryCache(channel));
return new BufferedChannelImageInputStream(useCacheFile ? new FileCache(channel, cacheDir) : new MemoryCache(channel));
}
throw new IllegalArgumentException("Expected input of type InputStream: " + input);
@@ -48,18 +48,18 @@ public final class ByteArrayImageInputStream extends ImageInputStreamImpl {
private final int dataOffset;
private final int dataLength;
public ByteArrayImageInputStream(final byte[] pData) {
this(pData, 0, pData != null ? pData.length : -1);
public ByteArrayImageInputStream(final byte[] data) {
this(data, 0, data != null ? data.length : -1);
}
public ByteArrayImageInputStream(final byte[] pData, int offset, int length) {
data = notNull(pData, "data");
dataOffset = isBetween(0, pData.length, offset, "offset");
dataLength = isBetween(0, pData.length - offset, length, "length");
public ByteArrayImageInputStream(final byte[] data, int offset, int length) {
this.data = notNull(data, "data");
dataOffset = isMax(data.length, offset, "offset");
dataLength = isMax(data.length - offset, length, "length");
}
private static int isBetween(final int low, final int high, final int value, final String name) {
return isTrue(value >= low && value <= high, value, String.format("%s out of range [%d, %d]: %d", name, low, high, value));
private static int isMax(final int high, final int value, final String name) {
return isTrue(value >= 0 && value <= high, value, String.format("%s out of range [0, %d]: %d", name, high, value));
}
public int read() throws IOException {
@@ -72,14 +72,14 @@ public final class ByteArrayImageInputStream extends ImageInputStreamImpl {
return data[((int) streamPos++) + dataOffset] & 0xff;
}
public int read(byte[] pBuffer, int pOffset, int pLength) throws IOException {
public int read(byte[] buffer, int offset, int len) throws IOException {
if (streamPos >= dataLength) {
return -1;
}
int length = (int) Math.min(this.dataLength - streamPos, pLength);
int length = (int) Math.min(dataLength - streamPos, len);
bitOffset = 0;
System.arraycopy(data, (int) streamPos + dataOffset, pBuffer, pOffset, length);
System.arraycopy(data, (int) streamPos + dataOffset, buffer, offset, length);
streamPos += length;
return length;
@@ -0,0 +1,7 @@
package com.twelvemonkeys.imageio.stream;
import java.nio.channels.SeekableByteChannel;
interface Cache extends SeekableByteChannel {
void flushBefore(long pos);
}
@@ -26,19 +26,19 @@ import static java.nio.file.StandardOpenOption.WRITE;
// the usual {@link #read read} and {@link #write write} methods. From the
// standpoint of performance it is generally only worth mapping relatively
// large files into memory.
final class DiskCache implements SeekableByteChannel {
final class FileCache implements Cache {
final static int BLOCK_SIZE = 1 << 13;
private final FileChannel cache;
private final ReadableByteChannel channel;
// TODO: Perhaps skip this constructor?
DiskCache(InputStream stream, File cacheDir) throws IOException {
FileCache(InputStream stream, File cacheDir) throws IOException {
// Stream will be closed with channel, documented behavior
this(Channels.newChannel(notNull(stream, "stream")), cacheDir);
}
public DiskCache(ReadableByteChannel channel, File cacheDir) throws IOException {
public FileCache(ReadableByteChannel channel, File cacheDir) throws IOException {
this.channel = notNull(channel, "channel");
isTrue(cacheDir == null || cacheDir.isDirectory(), cacheDir, "%s is not a directory");
@@ -65,12 +65,7 @@ final class DiskCache implements SeekableByteChannel {
@Override
public void close() throws IOException {
try {
cache.close();
}
finally {
channel.close();
}
cache.close();
}
@Override
@@ -110,5 +105,8 @@ final class DiskCache implements SeekableByteChannel {
public SeekableByteChannel truncate(long size) {
throw new NonWritableChannelException();
}
@Override public void flushBefore(long pos) {
}
}
@@ -13,12 +13,16 @@ import java.util.List;
import static com.twelvemonkeys.lang.Validate.notNull;
import static java.lang.Math.min;
public final class MemoryCache implements SeekableByteChannel {
final class MemoryCache implements Cache {
final static int BLOCK_SIZE = 1 << 13;
private static final byte[] NULL_BLOCK = new byte[0];
private final List<byte[]> cache = new ArrayList<>();
private final ReadableByteChannel channel;
private int maxBlock = Integer.MAX_VALUE;
private long length;
private long position;
private long start;
@@ -34,12 +38,14 @@ public final class MemoryCache implements SeekableByteChannel {
byte[] fetchBlock() throws IOException {
long currPos = position;
long index = currPos / BLOCK_SIZE;
if (index >= Integer.MAX_VALUE) {
throw new IOException("Memory cache max size exceeded");
}
if (index > maxBlock) {
return NULL_BLOCK;
}
while (index >= cache.size()) {
byte[] block;
@@ -51,7 +57,14 @@ public final class MemoryCache implements SeekableByteChannel {
}
cache.add(block);
length += readBlock(block);
int bytesRead = readBlock(block);
length += bytesRead;
if (bytesRead < BLOCK_SIZE) {
// Last block, EOF found
maxBlock = (int) index;
return block;
}
}
return cache.get((int) index);
@@ -63,7 +76,7 @@ public final class MemoryCache implements SeekableByteChannel {
while (wrapped.hasRemaining()) {
int count = channel.read(wrapped);
if (count == -1) {
// Last block
// Last block, EOF found
break;
}
}
@@ -78,23 +91,18 @@ public final class MemoryCache implements SeekableByteChannel {
@Override
public void close() throws IOException {
try {
cache.clear();
}
finally {
channel.close();
}
cache.clear();
}
@Override
public int read(ByteBuffer dest) throws IOException {
byte[] buffer = fetchBlock();
int bufferPos = (int) (position % BLOCK_SIZE);
if (position >= length) {
return -1;
}
int bufferPos = (int) (position % BLOCK_SIZE);
int len = min(dest.remaining(), (int) min(BLOCK_SIZE - bufferPos, length - position));
dest.put(buffer, bufferPos, len);
@@ -135,7 +143,8 @@ public final class MemoryCache implements SeekableByteChannel {
throw new NonWritableChannelException();
}
void flushBefore(long pos) {
@Override
public void flushBefore(long pos) {
if (pos < start) {
throw new IndexOutOfBoundsException("pos < flushed position");
}
@@ -53,20 +53,20 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
/**
* Creates a {@link ImageInputStream}, reading up to a maximum number of bytes from the underlying stream.
*
* @param pStream the underlying stream
* @param pLength the maximum length to read from the stream.
* Note that {@code pStream} may contain less than this maximum number of bytes.
* @param stream the underlying stream
* @param length the maximum length to read from the stream.
* Note that {@code stream} may contain less than this maximum number of bytes.
*
* @throws IOException if {@code pStream}'s position can't be determined.
* @throws IllegalArgumentException if {@code pStream == null} or {@code pLength < 0}
* @throws IOException if {@code stream}'s position can't be determined.
* @throws IllegalArgumentException if {@code stream == null} or {@code length < 0}
*/
public SubImageInputStream(final ImageInputStream pStream, final long pLength) throws IOException {
Validate.notNull(pStream, "stream");
Validate.isTrue(pLength >= 0, pLength, "length < 0: %d");
public SubImageInputStream(final ImageInputStream stream, final long length) throws IOException {
Validate.notNull(stream, "stream");
Validate.isTrue(length >= 0, length, "length < 0: %d");
stream = pStream;
startPos = pStream.getStreamPosition();
length = pLength;
this.stream = stream;
this.startPos = stream.getStreamPosition();
this.length = length;
}
public int read() throws IOException {
@@ -84,14 +84,14 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
}
}
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 (streamPos >= length) { // Local EOF
return -1;
}
// Safe cast, as pLength can never cause int overflow
int length = (int) Math.min(pLength, this.length - streamPos);
int count = stream.read(pBytes, pOffset, length);
// Safe cast, as len can never cause int overflow
int length = (int) Math.min(len, this.length - streamPos);
int count = stream.read(bytes, off, length);
if (count >= 0) {
streamPos += count;
@@ -113,18 +113,18 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
}
@Override
public void seek(final long pPosition) throws IOException {
if (pPosition < getFlushedPosition()) {
public void seek(final long position) throws IOException {
if (position < getFlushedPosition()) {
throw new IndexOutOfBoundsException("pos < flushedPosition");
}
stream.seek(startPos + pPosition);
streamPos = pPosition;
stream.seek(startPos + position);
streamPos = position;
}
@SuppressWarnings({"FinalizeDoesntCallSuperFinalize"})
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
protected void finalize() throws Throwable {
protected void finalize() {
// Empty finalizer (for improved performance; no need to call super.finalize() in this case)
}
}
@@ -80,7 +80,7 @@ public final class URLImageInputStreamSpi extends ImageInputStreamSpi {
// Otherwise revert to cached
InputStream urlStream = url.openStream();
return new BufferedChannelImageInputStream(useCacheFile ? new DiskCache(urlStream, cacheDir) : new MemoryCache(urlStream));
return new BufferedChannelImageInputStream(useCacheFile ? new FileCache(urlStream, cacheDir) : new MemoryCache(urlStream));
}
throw new IllegalArgumentException("Expected input of type URL: " + input);
@@ -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);
@@ -57,7 +57,7 @@ import static org.mockito.Mockito.verify;
* @version $Id: BufferedFileImageInputStreamTestCase.java,v 1.0 Apr 21, 2009 10:58:48 AM haraldk Exp$
*/
// TODO: Remove this test, and instead test the disk cache directly!
public class BufferedChannelImageInputStreamDiskCacheTest {
public class BufferedChannelImageInputStreamFileCacheTest {
private final Random random = new Random(170984354357234566L);
private InputStream randomDataToInputStream(byte[] data) {
@@ -68,7 +68,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
@Test
public void testCreate() throws IOException {
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(new ByteArrayInputStream(new byte[0]), null))) {
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(new ByteArrayInputStream(new byte[0]), null))) {
assertEquals("Stream length should be unknown", -1, stream.length());
}
}
@@ -76,7 +76,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
@Test
public void testCreateNullStream() throws IOException {
try {
new DiskCache((InputStream) null, null);
new FileCache((InputStream) null, null);
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException expected) {
@@ -90,7 +90,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
@Test
public void testCreateNullChannel() throws IOException {
try {
new DiskCache((ReadableByteChannel) null, null);
new FileCache((ReadableByteChannel) null, null);
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException expected) {
@@ -106,7 +106,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
byte[] data = new byte[1024 * 1024];
InputStream input = randomDataToInputStream(data);
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
assertEquals("Stream length should be unknown", -1, stream.length());
for (byte value : data) {
@@ -122,7 +122,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
byte[] data = new byte[1024 * 1024];
InputStream input = randomDataToInputStream(data);
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
assertEquals("Stream length should be unknown", -1, stream.length());
byte[] result = new byte[1024];
@@ -141,7 +141,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
byte[] data = new byte[1024 * 14];
InputStream input = randomDataToInputStream(data);
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
assertEquals("Stream length should be unknown", -1, stream.length());
byte[] result = new byte[7];
@@ -159,7 +159,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
byte[] data = new byte[1024 * 18];
InputStream input = randomDataToInputStream(data);
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
assertEquals("Stream length should be unknown", -1, stream.length());
byte[] result = new byte[9];
@@ -180,7 +180,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
byte[] data = new byte[256];
InputStream input = randomDataToInputStream(data);
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
assertEquals("Stream length should be unknown", -1, stream.length());
byte[] buffer = new byte[data.length * 2];
@@ -198,7 +198,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
long value = ByteBuffer.wrap(bytes).getLong();
// Create stream
try (ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
for (int i = 1; i <= 64; i++) {
assertEquals(String.format("bit %d differ", i), (value << (i - 1L)) >>> 63L, stream.readBit());
}
@@ -212,7 +212,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
long value = ByteBuffer.wrap(bytes).getLong();
// Create stream
try (ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
for (int i = 1; i <= 64; i++) {
stream.seek(0);
assertEquals(String.format("bit %d differ", i), value >>> (64L - i), stream.readBits(i));
@@ -228,7 +228,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
long value = ByteBuffer.wrap(bytes).getLong();
// Create stream
try (ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
for (int i = 1; i <= 60; i++) {
stream.seek(0);
stream.setBitOffset(i % 8);
@@ -244,7 +244,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
InputStream input = randomDataToInputStream(bytes);
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
for (int i = 0; i < bytes.length / 2; i++) {
@@ -282,7 +282,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
InputStream input = randomDataToInputStream(bytes);
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
for (int i = 0; i < bytes.length / 4; i++) {
@@ -320,7 +320,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
InputStream input = randomDataToInputStream(bytes);
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
for (int i = 0; i < bytes.length / 8; i++) {
@@ -357,7 +357,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
byte[] bytes = new byte[9];
InputStream input = randomDataToInputStream(bytes);
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
stream.seek(1000);
assertEquals(-1, stream.read());
@@ -406,11 +406,11 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
@Test
public void testClose() throws IOException {
// Create wrapper stream
InputStream mock = mock(InputStream.class);
ImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(mock, null));
Cache cache = mock(Cache.class);
ImageInputStream stream = new BufferedChannelImageInputStream(cache);
stream.close();
verify(mock, only()).close();
verify(cache, only()).close();
}
@Test
@@ -422,7 +422,7 @@ public class BufferedChannelImageInputStreamDiskCacheTest {
byte[] bytes = new byte[size];
InputStream input = randomDataToInputStream(bytes);
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new DiskCache(input, null))) {
try (BufferedChannelImageInputStream stream = new BufferedChannelImageInputStream(new FileCache(input, null))) {
byte[] result = new byte[size];
int head = stream.read(result, 0, 12); // Provoke a buffered read
int len = stream.read(result, 12, size - 12); // Rest of buffer + direct read
@@ -402,15 +402,33 @@ public class BufferedChannelImageInputStreamMemoryCacheTest {
assertEquals(-1, stream.read());
}
}
@Test
public void testSeekWayPastEOFShouldNotThrowOOME() throws IOException {
byte[] bytes = new byte[9];
InputStream input = randomDataToInputStream(bytes);
try (final ImageInputStream stream = new BufferedChannelImageInputStream(new MemoryCache(input))) {
stream.seek(Integer.MAX_VALUE * 4L * 512L); // ~4 TB
assertEquals(-1, stream.read()); // No OOME should happen...
stream.seek(0);
for (byte value : bytes) {
assertEquals(value, stream.readByte());
}
assertEquals(-1, stream.read());
}
}
@Test
public void testClose() throws IOException {
// Create wrapper stream
InputStream mock = mock(InputStream.class);
ImageInputStream stream = new BufferedChannelImageInputStream(new MemoryCache(mock));
Cache cache = mock(Cache.class);
ImageInputStream stream = new BufferedChannelImageInputStream(cache);
stream.close();
verify(mock, only()).close();
verify(cache, only()).close();
}
@Test
@@ -47,7 +47,7 @@ import java.util.Random;
import static com.twelvemonkeys.imageio.stream.BufferedImageInputStreamTest.rangeEquals;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
/**
@@ -403,14 +403,11 @@ public class BufferedChannelImageInputStreamTest {
@Test
public void testCloseChannel() throws IOException {
// NOTE: As the stream-based constructor is chained to the channel-based one,
// we'll rely on the fact that closing the channel will close the stream.
SeekableByteChannel mock = mock(SeekableByteChannel.class);
ImageInputStream stream = new BufferedChannelImageInputStream(mock);
SeekableByteChannel channel = mock(SeekableByteChannel.class);
ImageInputStream stream = new BufferedChannelImageInputStream(channel);
stream.close();
verify(mock, only()).close();
verify(channel, never()).close();
}
@Test
@@ -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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</version>
</parent>
<artifactId>imageio-jpeg-jai-interop</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG/JAI TIFF Interop</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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>
@@ -13,7 +13,6 @@ final class PCXMetadata extends StandardImageMetadataSupport {
}
private static PlanarConfiguration planarConfiguration(PCXHeader header) {
System.out.println("header = " + header);
return header.getChannels() > 1 ? PlanarConfiguration.LineInterleaved : null;
}
@@ -25,6 +24,6 @@ final class PCXMetadata extends StandardImageMetadataSupport {
return "RLE";
}
return "Uknown";
return "Unknown";
}
}
+10 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.9.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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.0</version>
<version>3.10.1</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>
@@ -30,8 +30,6 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.ImageWriterBase;
import org.w3c.dom.NodeList;
import javax.imageio.IIOImage;
@@ -40,7 +38,7 @@ import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.DataBuffer;
import java.awt.image.*;
import java.io.IOException;
import java.util.Locale;
@@ -53,11 +51,7 @@ abstract class HeaderWriter {
this.imageOutput = imageOutput;
}
public static void write(final IIOImage image, final ImageWriterBase writer, final ImageOutputStream imageOutput) throws IOException {
createHeaderWriter(writer.getFormatName(), imageOutput).writeHeader(image, writer.getOriginatingProvider());
}
private static HeaderWriter createHeaderWriter(final String formatName, final ImageOutputStream imageOutput) {
static HeaderWriter createHeaderWriter(final String formatName, final ImageOutputStream imageOutput) {
if (formatName.equals("pam")) {
return new PAMHeaderWriter(imageOutput);
}
@@ -83,25 +77,36 @@ abstract class HeaderWriter {
return image.hasRaster() ? image.getRaster().getNumBands() : image.getRenderedImage().getSampleModel().getNumBands();
}
protected final SampleModel getSampleModel(final IIOImage image) {
return image.hasRaster() ? image.getRaster().getSampleModel() : image.getRenderedImage().getSampleModel();
}
protected int getMaxVal(final IIOImage image) {
int transferType = getTransferType(image);
if (transferType == DataBuffer.TYPE_BYTE) {
return PNM.MAX_VAL_8BIT;
}
else if (transferType == DataBuffer.TYPE_USHORT) {
return PNM.MAX_VAL_16BIT;
}
// else if (transferType == DataBuffer.TYPE_INT) {
// TODO: Support TYPE_INT through conversion, if number of channels is 3 or 4 (TYPE_INT_RGB, TYPE_INT_ARGB)
// }
else {
throw new IllegalArgumentException("Unsupported data type: " + transferType);
switch (transferType) {
case DataBuffer.TYPE_BYTE:
return PNM.MAX_VAL_8BIT;
case DataBuffer.TYPE_USHORT:
return PNM.MAX_VAL_16BIT;
case DataBuffer.TYPE_INT:
// We support TYPE_INT through conversion, if number of channels is 3 or 4 (TYPE_INT_RGB, TYPE_INT_ARGB)
SampleModel sampleModel = getSampleModel(image);
int numBands = sampleModel.getNumBands();
if (sampleModel instanceof SinglePixelPackedSampleModel && (numBands == 3 || numBands == 4)) {
return PNM.MAX_VAL_8BIT;
}
// ...else fall through
default:
throw new IllegalArgumentException("Unsupported data type: " + transferType);
}
}
protected final int getTransferType(final IIOImage image) {
return image.hasRaster() ? image.getRaster().getTransferType() : image.getRenderedImage().getSampleModel().getTransferType();
return image.hasRaster() ? image.getRaster().getTransferType() : image.getRenderedImage().getSampleModel().getTransferType();
}
protected final void writeComments(final IIOMetadata metadata, final ImageWriterSpi provider) throws IOException {
@@ -120,5 +125,4 @@ abstract class HeaderWriter {
}
}
}
}
@@ -30,6 +30,8 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import javax.imageio.IIOImage;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
@@ -44,6 +46,8 @@ final class PAMHeaderWriter extends HeaderWriter {
@Override
public void writeHeader(final IIOImage image, final ImageWriterSpi provider) throws IOException {
TupleType tupleType = tupleType(image);
// Write PAM magic
imageOutput.writeShort(PNM.PAM);
imageOutput.write('\n');
@@ -52,12 +56,19 @@ final class PAMHeaderWriter extends HeaderWriter {
// Write width/height and number of channels
imageOutput.write(String.format("WIDTH %s\nHEIGHT %s\n", getWidth(image), getHeight(image)).getBytes(UTF_8));
imageOutput.write(String.format("DEPTH %s\n", getNumBands(image)).getBytes(UTF_8));
// TODO: maxSample (8 or16 bit)
imageOutput.write(String.format("MAXVAL %s\n", getMaxVal(image)).getBytes(UTF_8));
// TODO: Determine tuple type based on input color model and image data
TupleType tupleType = getNumBands(image) > 3 ? TupleType.RGB_ALPHA : TupleType.RGB;
imageOutput.write(String.format("TUPLTYPE %s\nENDHDR\n", tupleType).getBytes(UTF_8));
}
private static TupleType tupleType(IIOImage image) {
TupleType tupleType = image.hasRaster()
? TupleType.forPAM(image.getRaster())
: TupleType.forPAM(ImageTypeSpecifiers.createFromRenderedImage(image.getRenderedImage()));
if (tupleType == null) {
throw new IllegalArgumentException("Unknown TupleType for " + (image.hasRaster() ? image.getRaster() : image.getRenderedImage()));
}
return tupleType;
}
}
@@ -45,12 +45,11 @@ public final class PAMImageWriterSpi extends ImageWriterSpiBase {
super(new PAMProviderInfo());
}
public boolean canEncodeImage(final ImageTypeSpecifier pType) {
// TODO: FixMe
return true;
public boolean canEncodeImage(final ImageTypeSpecifier type) {
return TupleType.forPAM(type) != null;
}
public ImageWriter createWriterInstance(final Object pExtension) {
public ImageWriter createWriterInstance(final Object extension) {
return new PNMImageWriter(this);
}
@@ -69,7 +69,7 @@ final class PFMHeaderParser extends HeaderParser {
public PNMHeader parse() throws IOException {
int width = 0;
int height = 0;
float maxSample = tupleType == TupleType.BLACKANDWHITE_WHITE_IS_ZERO ? 1 : 0; // PBM has no maxSample line
float maxSample = 0;
List<String> comments = new ArrayList<>();
@@ -77,7 +77,7 @@ final class PFMHeaderParser extends HeaderParser {
String line = input.readLine();
if (line == null) {
throw new IIOException("Unexpeced end of stream");
throw new IIOException("Unexpected end of stream");
}
int commentStart = line.indexOf('#');
@@ -30,6 +30,8 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import javax.imageio.IIOImage;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
@@ -45,8 +47,7 @@ final class PNMHeaderWriter extends HeaderWriter {
@Override
public void writeHeader(final IIOImage image, final ImageWriterSpi provider) throws IOException {
// Write P4/P5/P6 magic (Support only RAW formats for now; if we are to support PLAIN formats, pass parameter)
// TODO: Determine PBM, PBM or PPM based on input color model and image data?
short type = PNM.PPM;
short type = type(image);
imageOutput.writeShort(type);
imageOutput.write('\n');
@@ -61,4 +62,35 @@ final class PNMHeaderWriter extends HeaderWriter {
imageOutput.write(String.format("%s\n", getMaxVal(image)).getBytes(UTF_8));
}
}
private short type(IIOImage image) {
TupleType type = tupleType(image);
if (type != null) {
switch (type) {
case BLACKANDWHITE_WHITE_IS_ZERO:
return PNM.PBM;
case GRAYSCALE:
return PNM.PGM;
case RGB:
return PNM.PPM;
default:
// fall through...
}
}
throw new IllegalArgumentException("Unsupported tupleType: " + type);
}
private static TupleType tupleType(IIOImage image) {
TupleType tupleType = image.hasRaster()
? TupleType.forPNM(image.getRaster())
: TupleType.forPNM(ImageTypeSpecifiers.createFromRenderedImage(image.getRenderedImage()));
if (tupleType == null) {
throw new IllegalArgumentException("Unknown TupleType for " + (image.hasRaster() ? image.getRaster() : image.getRenderedImage()));
}
return tupleType;
}
}
@@ -31,14 +31,17 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.ImageWriterBase;
import com.twelvemonkeys.imageio.util.RasterUtils;
import javax.imageio.*;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageWriterSpi;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
@@ -69,7 +72,7 @@ public final class PNMImageWriter extends ImageWriterBase {
// TODO: Issue warning if streamMetadata is non-null?
// TODO: Issue warning if IIOImage contains thumbnails or other data we can't store?
HeaderWriter.write(image, this, imageOutput);
writeHeader(image, this, imageOutput);
// TODO: Sub region
// TODO: Subsampling
@@ -80,16 +83,20 @@ public final class PNMImageWriter extends ImageWriterBase {
processImageComplete();
}
private void writeHeader(final IIOImage image, final ImageWriterBase writer, final ImageOutputStream imageOutput) throws IOException {
HeaderWriter.createHeaderWriter(writer.getFormatName(), imageOutput).writeHeader(image, writer.getOriginatingProvider());
}
private void writeImageData(final IIOImage image) throws IOException {
// - dump data as is (or convert, if TYPE_INT_xxx)
// - dump data as is (or convert, if TYPE_INT_xxx
// Enforce RGB/CMYK order for such data!
// TODO: Loop over x/y tiles, using 0,0 is only valid for BufferedImage
// TODO: PNM/PAM does not support tiling, we must iterate all tiles along the x-axis for each row we write
Raster tile = image.hasRaster() ? image.getRaster() : image.getRenderedImage().getTile(0, 0);
tile = tile.getTransferType() == DataBuffer.TYPE_INT ? RasterUtils.asByteRaster(tile) : tile;
SampleModel sampleModel = tile.getSampleModel();
DataBuffer dataBuffer = tile.getDataBuffer();
int tileWidth = tile.getWidth();
@@ -48,12 +48,11 @@ public final class PNMImageWriterSpi extends ImageWriterSpiBase {
super(new PNMProviderInfo());
}
public boolean canEncodeImage(final ImageTypeSpecifier pType) {
// TODO: FixMe: Support only 1 bit b/w, 8-16 bit gray and 8-16 bit/sample RGB
return true;
public boolean canEncodeImage(final ImageTypeSpecifier type) {
return TupleType.forPNM(type) != null;
}
public ImageWriter createWriterInstance(final Object pExtension) {
public ImageWriter createWriterInstance(final Object extension) {
return new PNMImageWriter(this);
}
@@ -30,7 +30,10 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import javax.imageio.ImageTypeSpecifier;
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
enum TupleType {
// Official:
@@ -80,4 +83,150 @@ enum TupleType {
public boolean isValidMaxSample(int maxSample) {
return maxSample >= minMaxSample && maxSample <= maxMaxSample;
}
static TupleType forPNM(Raster raster) {
return filterPNM(forPAM(raster));
}
static TupleType forPNM(ImageTypeSpecifier type) {
return filterPNM(forPAM(type));
}
private static TupleType filterPNM(TupleType tupleType) {
if (tupleType == null) {
return null;
}
switch (tupleType) {
case BLACKANDWHITE:
return BLACKANDWHITE_WHITE_IS_ZERO;
case GRAYSCALE:
case RGB:
return tupleType;
default:
return null;
}
}
static TupleType forPAM(Raster raster) {
SampleModel sampleModel = raster.getSampleModel();
switch (sampleModel.getTransferType()) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_INT:
// B/W, Gray or RGB
int bands = sampleModel.getNumBands();
if (bands == 1 && sampleModel.getSampleSize(0) == 1) {
return TupleType.BLACKANDWHITE;
}
else if (bands == 2 && sampleModel.getSampleSize(0) == 1 && sampleModel.getSampleSize(1) == 1) {
return TupleType.BLACKANDWHITE_ALPHA;
}
// We can only write 8 or 16 bits/band
if (!(sampleModel.getSampleSize(0) == 8 || sampleModel.getSampleSize(0) == 16)) {
return null;
}
for (int i = 1; i < bands; i++) {
if (sampleModel.getSampleSize(0) != sampleModel.getSampleSize(i)) {
return null;
}
}
if (bands == 1) {
return TupleType.GRAYSCALE;
}
else if (bands == 2) {
return TupleType.GRAYSCALE_ALPHA;
}
else if (bands == 3) {
return TupleType.RGB;
}
else if (bands == 4) {
return TupleType.RGB_ALPHA;
}
// ...else fall through...
}
return null;
}
static TupleType forPAM(ImageTypeSpecifier type) {
// Support only 1 bit b/w, 8-16 bit gray and 8-16 bit/sample RGB
switch (type.getBufferedImageType()) {
// 1 bit b/w or b/w + a
case BufferedImage.TYPE_BYTE_BINARY:
switch (type.getNumBands()) {
case 1:
return type.getBitsPerBand(0) == 1 ? TupleType.BLACKANDWHITE : null;
case 2:
return type.getBitsPerBand(0) == 2 || type.getBitsPerBand(0) == 1 && type.getBitsPerBand(1) == 1 ? TupleType.BLACKANDWHITE_ALPHA : null;
default:
return null;
}
// Gray
case BufferedImage.TYPE_BYTE_GRAY:
case BufferedImage.TYPE_USHORT_GRAY:
return TupleType.GRAYSCALE;
// RGB
case BufferedImage.TYPE_3BYTE_BGR:
case BufferedImage.TYPE_INT_RGB:
case BufferedImage.TYPE_INT_BGR:
return TupleType.RGB;
// RGBA
case BufferedImage.TYPE_4BYTE_ABGR:
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
case BufferedImage.TYPE_INT_ARGB:
case BufferedImage.TYPE_INT_ARGB_PRE:
return TupleType.RGB_ALPHA;
default:
// BYTE, USHORT or INT (packed)
switch (type.getSampleModel().getTransferType()) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_INT:
// Gray or RGB
ColorModel colorModel = type.getColorModel();
if (!(colorModel instanceof IndexColorModel)) {
ColorSpace cs = colorModel.getColorSpace();
// We can only write 8 or 16 bits/band
int bands = type.getNumBands();
if (!(type.getBitsPerBand(0) == 8 || type.getBitsPerBand(0) == 16)) {
return null;
}
for (int i = 1; i < bands; i++) {
if (type.getBitsPerBand(0) != type.getBitsPerBand(i)) {
return null;
}
}
if (cs.getType() == ColorSpace.TYPE_GRAY && bands == 1) {
return TupleType.GRAYSCALE;
}
else if (cs.getType() == ColorSpace.TYPE_GRAY && colorModel.hasAlpha() && bands == 2) {
return TupleType.GRAYSCALE_ALPHA;
}
else if (cs.getType() == ColorSpace.TYPE_RGB && bands == 3) {
return TupleType.RGB;
}
else if (cs.getType() == ColorSpace.TYPE_RGB && colorModel.hasAlpha() && bands == 4) {
return TupleType.RGB_ALPHA;
}
else if (cs.getType() == ColorSpace.TYPE_CMYK && bands == 4) {
return TupleType.CMYK;
}
else if (cs.getType() == ColorSpace.TYPE_CMYK && colorModel.hasAlpha() && bands == 5) {
return TupleType.CMYK_ALPHA;
}
// ...else fall through...
}
}
}
return null;
}
}
@@ -30,15 +30,23 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.color.ColorSpaces;
import org.junit.Test;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.spi.ImageWriterSpi;
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassExists;
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassesExist;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* PAMImageWriterSpiTest.
@@ -65,4 +73,85 @@ public class PAMImageWriterSpiTest {
public void getOutputTypes() {
assertNotNull(spi.getOutputTypes());
}
@Test
public void canEncodeImageBinary() {
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY)));
}
@Test
public void canNotEncodeImageIndexed() {
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED)));
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_INDEXED)));
}
@Test
public void canEncodeImageGray() {
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY)));
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_USHORT_GRAY)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY)));
}
@Test
public void canEncodeImageGrayAlpha() {
ComponentColorModel grayAlphaByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaByte, grayAlphaByte.createCompatibleSampleModel(1, 1))));
ComponentColorModel grayAlphaUShort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT);
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaUShort, grayAlphaUShort.createCompatibleSampleModel(1, 1))));
}
@Test
public void canEncodeImageRGB() {
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR)));
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB)));
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_BGR)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_BGR)));
}
@Test
public void canEncodeImageARGB() {
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR)));
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR_PRE)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR_PRE)));
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB)));
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB_PRE)));
}
@Test
public void canEncodeImageCMYK() {
ComponentColorModel cmykByte = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykByte, cmykByte.createCompatibleSampleModel(1, 1))));
ComponentColorModel cmykUShort = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykUShort, cmykUShort.createCompatibleSampleModel(1, 1))));
ComponentColorModel cmykAlphaByte = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykAlphaByte, cmykAlphaByte.createCompatibleSampleModel(1, 1))));
ComponentColorModel cmykAlphaUShort = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT);
assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykAlphaUShort, cmykAlphaUShort.createCompatibleSampleModel(1, 1))));
}
@Test
public void canNotEncodeImageNonGrayOrRGB() {
ComponentColorModel xyzByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzByte, xyzByte.createCompatibleSampleModel(1, 1))));
ComponentColorModel xyzUshort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzUshort, xyzUshort.createCompatibleSampleModel(1, 1))));
}
}
@@ -0,0 +1,37 @@
package com.twelvemonkeys.imageio.plugins.pnm;
import com.twelvemonkeys.imageio.color.ColorSpaces;
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
import javax.imageio.spi.ImageWriterSpi;
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import java.util.Arrays;
import java.util.List;
public class PAMImageWriterTest extends ImageWriterAbstractTest<PNMImageWriter> {
// NOTE: It's the same writer, however, the different SPI configures PAM mode, and enables extra formats
@Override
protected ImageWriterSpi createProvider() {
return new PAMImageWriterSpi();
}
@Override
protected List<? extends RenderedImage> getTestData() {
return Arrays.asList(
new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_BINARY),
new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR),
new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY),
new BufferedImage(100, 100, BufferedImage.TYPE_USHORT_GRAY),
new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR),
new BufferedImage(100, 100, BufferedImage.TYPE_INT_BGR),
new BufferedImage(10, 10, BufferedImage.TYPE_INT_BGR),
new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB),
new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB_PRE),
new BufferedImage(new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT), Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, 10, 10, 2, null), false, null),
new BufferedImage(new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE), Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 10, 10, 4, null), false, null),
new BufferedImage(new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT), Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, 10, 10, 5, null), false, null)
);
}
}
@@ -32,13 +32,19 @@ package com.twelvemonkeys.imageio.plugins.pnm;
import org.junit.Test;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.spi.ImageWriterSpi;
import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassExists;
import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassesExist;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* PNMImageWriterSpiTest.
@@ -65,4 +71,70 @@ public class PNMImageWriterSpiTest {
public void getOutputTypes() {
assertNotNull(spi.getOutputTypes());
}
@Test
public void canEncodeImageBinary() {
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY)));
}
@Test
public void canNotEncodeImageIndexed() {
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED)));
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_INDEXED)));
}
@Test
public void canEncodeImageGray() {
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY)));
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_USHORT_GRAY)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY)));
}
@Test
public void canNotEncodeImageGrayAlpha() {
ComponentColorModel grayAlphaByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaByte, grayAlphaByte.createCompatibleSampleModel(1, 1))));
ComponentColorModel grayAlphaUShort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT);
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaUShort, grayAlphaUShort.createCompatibleSampleModel(1, 1))));
}
@Test
public void canEncodeImageRGB() {
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR)));
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB)));
assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_BGR)));
assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_BGR)));
}
@Test
public void canNotEncodeImageARGB() {
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR)));
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR)));
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR_PRE)));
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR_PRE)));
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)));
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB)));
assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE)));
assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB_PRE)));
}
@Test
public void canNotEncodeImageNonGrayOrRGB() {
ComponentColorModel xyzByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzByte, xyzByte.createCompatibleSampleModel(1, 1))));
ComponentColorModel xyzUshort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzUshort, xyzUshort.createCompatibleSampleModel(1, 1))));
}
}

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