Compare commits

...

1064 Commits

Author SHA1 Message Date
Harald Kuhr 1dc6045079 Sonar issues 2026-03-11 19:08:53 +01:00
Harald Kuhr b9b3c364be Added raster write test
+ fixed a small issue for PAM
2026-03-11 18:53:24 +01:00
Harald Kuhr 26ecf18c68 Mipmap support using ImageIO sequence API 2026-03-11 18:26:02 +01:00
Harald Kuhr 3f356a8197 More clean-up: Now keeps stream byte order consistent (LE), support for Raster, more tests 2026-03-11 15:59:48 +01:00
Harald Kuhr dc59c66209 More clean-up: Removed optional flags from param, header size validation, metadata now reports compresion as lossy 2026-03-11 14:51:01 +01:00
Harald Kuhr 2a0b15f33f Sonar issues + roll back accidental check-in 2026-03-10 23:02:47 +01:00
Harald Kuhr 9ca9569537 Fix JavaDoc 🎉 2026-03-10 22:42:39 +01:00
Harald Kuhr 0a717ea0af Major rework/standardization:
* DDSEncoderType, DX10DXGIFormat merged with DDSType for a single way to describe a DDS format
 * Added constants for DXGI formats
 * DDSImageWriteParam is now mutable and supports standard way of setting compression type
 * DDSImageMetadata now supports more of the format
 Performance:
 * DDSReader now use seek() to jump to correct mipmap instead of reading all bytes
 * DDSImageWriter now uses getTile(0, 0) instead of getData() for better performance
2026-03-10 22:38:58 +01:00
Harald Kuhr 7f2eb517ef Refactorings and code clean-up 2026-03-05 21:02:04 +01:00
KhanhTypo a7a4445ce8 [DDS] Adding Block Compression 1 -> 5 Encoding Support (#1237)
* dds dxt10 support, with some certain supported DXGI Formats only.
* expand the supporting range for some DX10 DXGI Format in the DXGI_FORMAT enumeration
* readability and maintainability fixes, adding DXT10 test cases.
* java.awt.* -> java.awt.Dimension
* DDS header & BC1 writer
* BC4 Writer
* BC3 Writer
* BC1-5 writer support
* remove unused methods
* code fixes
* BC4 fix to resolve unwanted blocky effect.
* CI test fixes
* change bitflag setter functions
* temporary disable formats that does not have an encoder yet.
* resolving SonaQube issues.
2026-03-04 10:35:40 +01:00
Harald Kuhr 4c1b268325 Javadoc cleanup (#1255)
* #1234: Fixed JavaDoc for Java 21 + JavaDoc verification step
* #1234: Simplify build matrix
* #1234: Javadoc in parallell
2026-03-04 10:35:04 +01:00
dependabot[bot] e3c3f640a4 Bump github/codeql-action from 4.32.2 to 4.32.4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.2 to 4.32.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/45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2...89a39a4e59826350b863aa6b6252a07ad50cf83e)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-02 10:01:45 +01:00
dependabot[bot] ecc938a666 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.5.4 to 3.5.5
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.4 to 3.5.5.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.4...surefire-3.5.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-25 19:23:46 +01:00
dependabot[bot] 25fdfb1947 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.5.4 to 3.5.5.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.4...surefire-3.5.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-25 19:23:19 +01:00
dependabot[bot] 0c05918d8a Bump junit.jupiter.version from 5.14.2 to 5.14.3
Bumps `junit.jupiter.version` from 5.14.2 to 5.14.3.

Updates `org.junit.jupiter:junit-jupiter-api` from 5.14.2 to 5.14.3
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.14.2...r5.14.3)

Updates `org.junit.jupiter:junit-jupiter-params` from 5.14.2 to 5.14.3
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.14.2...r5.14.3)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-version: 5.14.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.junit.jupiter:junit-jupiter-params
  dependency-version: 5.14.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-23 10:26:02 +01:00
Harald Kuhr 4de2a38dd8 New version + snapshot fix 2026-02-23 10:05:29 +01:00
Harald Kuhr 5b4fa64dc0 [maven-release-plugin] prepare for next development iteration 2026-02-22 16:13:49 +01:00
Harald Kuhr 2ad522a9fa [maven-release-plugin] prepare release twelvemonkeys-3.13.1 2026-02-22 16:13:44 +01:00
dependabot[bot] 20af575fbd Bump github/codeql-action from 4.31.10 to 4.32.2 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.10 to 4.32.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/cdefb33c0f6224e58673d9004f47f7cb3e328b89...45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-13 11:08:19 +01:00
dependabot[bot] 02a6ed1ac1 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/a294a61c909bd8a4b563024a2faa28897fd53ebc...74626db7353a25a20a72816467ebf035f674c5f8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-09 10:28:21 +01:00
Harald Kuhr 146d5926bb #1244: Created test + fixed inverted PSD hidden flag in metadata 2026-02-05 13:54:51 +01:00
dependabot[bot] 561b25022c Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.14.1 to 3.15.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.14.1...maven-compiler-plugin-3.15.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-03 11:09:22 +01:00
dependabot[bot] 4cd6b893de Bump actions/setup-java from 5.1.0 to 5.2.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/f2beeb24e141e01a676f977032f5a29d81c9e27e...be666c2fcd27ec809703dec50e508c2fdc7f6654)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-29 13:45:17 +01:00
dependabot[bot] dabff3abce Bump actions/checkout from 6.0.1 to 6.0.2 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2.
- [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/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-23 09:50:45 +01:00
Will Ezell 1b889b1b4b Fixes Lossless Alpha Channel WebP (#1243)
* Fix alpha channel dimensions in WebP lossless decoding

  Use the expected width and height values instead of tempRaster.getWidth()/getHeight() when creating the alpha channel's writable child raster. This ensures the alpha channel is correctly sized when the temp raster dimensions differ from the expected dimensions.

* Fixes Lossless Huffman table based on libwebp

* Remove redundant flush call in image reader test

Removed unnecessary image.flush() call in WebPImageReaderTest.

* adding code to generate good hash for reproducability
2026-01-23 09:40:06 +01:00
dependabot[bot] 29a3bd591d Bump github/codeql-action from 4.31.9 to 4.31.10 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.9 to 4.31.10.
- [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/5d4e8d1aca955e8d8589aabd499c5cae939e33c7...cdefb33c0f6224e58673d9004f47f7cb3e328b89)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-20 13:25:57 +01:00
Harald Kuhr cd79ef4409 #1240: Fixes TIFFWriter overwrite of nested values issue 2026-01-15 19:42:56 +01:00
dependabot[bot] a604cb83fb Bump org.sonatype.central:central-publishing-maven-plugin
Bumps [org.sonatype.central:central-publishing-maven-plugin](https://github.com/sonatype/central-publishing-maven-plugin) from 0.9.0 to 0.10.0.
- [Commits](https://github.com/sonatype/central-publishing-maven-plugin/commits)

---
updated-dependencies:
- dependency-name: org.sonatype.central:central-publishing-maven-plugin
  dependency-version: 0.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-15 10:50:33 +01:00
dependabot[bot] eb1735ab33 Bump junit.jupiter.version from 5.14.1 to 5.14.2
Bumps `junit.jupiter.version` from 5.14.1 to 5.14.2.

Updates `org.junit.jupiter:junit-jupiter-api` from 5.14.1 to 5.14.2
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.14.1...r5.14.2)

Updates `org.junit.jupiter:junit-jupiter-engine` from 5.14.1 to 5.14.2
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.14.1...r5.14.2)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-version: 5.14.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.junit.jupiter:junit-jupiter-engine
  dependency-version: 5.14.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-14 11:25:14 +01:00
dependabot[bot] 357eeb2236 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 6.0.1 to 6.1.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/e08919a3b1fb83a78393dfb775a9c37f17d8eea6...a294a61c909bd8a4b563024a2faa28897fd53ebc)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-07 10:59:50 +01:00
dependabot[bot] d634b9d93f Bump github/codeql-action from 4.31.4 to 4.31.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.4 to 4.31.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/e12f0178983d466f2f6028f5cc7a6d786fd97f4b...5d4e8d1aca955e8d8589aabd499c5cae939e33c7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-05 22:18:20 +01:00
dependabot[bot] 7e3241d64b Bump org.sonatype.central:central-publishing-maven-plugin
Bumps [org.sonatype.central:central-publishing-maven-plugin](https://github.com/sonatype/central-publishing-maven-plugin) from 0.7.0 to 0.9.0.
- [Commits](https://github.com/sonatype/central-publishing-maven-plugin/commits)

---
updated-dependencies:
- dependency-name: org.sonatype.central:central-publishing-maven-plugin
  dependency-version: 0.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-23 10:53:27 +01:00
Harald Kuhr b86d82720d [maven-release-plugin] prepare for next development iteration 2025-12-22 15:40:16 +01:00
Harald Kuhr 47e90a657a [maven-release-plugin] prepare release twelvemonkeys-3.13.0 2025-12-22 15:40:12 +01:00
Harald Kuhr bdd8b2f1fb #1198: Fix snapshot URL 2025-12-22 12:10:29 +01:00
Harald Kuhr 8d08c9565b Fix JavaDoc error 2025-12-22 10:08:43 +01:00
Harald Kuhr c11f61d132 #1198: Re-enable snapshot builds 2025-12-22 10:02:16 +01:00
Harald Kuhr e6b38cb547 #1198: Migrate from ossrh to central 2025-12-22 09:56:19 +01:00
dependabot[bot] e11d888809 Bump actions/upload-artifact from 5.0.0 to 6.0.0 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5.0.0 to 6.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/330a01c490aca151604b8cf639adc76d48f6c5d4...b7c566a772e6b6bfb58ed0dc250532a479d7789f)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 09:47:16 +01:00
KhanhTypo 46a399ff02 DDS DXT10 support, with some certain supported DXGI Formats only. (#1230)
* dds dxt10 support, with some certain supported DXGI Formats only.
* expand the supporting range for some DX10 DXGI Format in the DXGI_FORMAT enumeration
* readability and maintainability fixes, adding DXT10 test cases.
* java.awt.* -> java.awt.Dimension
2025-12-17 17:38:47 +01:00
dependabot[bot] a09629be32 Bump org.apache.maven.plugins:maven-release-plugin from 3.3.0 to 3.3.1
Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.3.0...maven-release-3.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-17 17:22:29 +01:00
dependabot[bot] 57fb1ca1bb Bump actions/setup-java from 5.0.0 to 5.1.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/dded0888837ed1f317902acf8a20df0ad188d165...f2beeb24e141e01a676f977032f5a29d81c9e27e)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-12 15:42:49 +01:00
Vincent Privat c9063ca02d add unit test 2025-12-09 13:25:26 +01:00
Vincent Privat 340e79eb8a fix webp decoding using source region without subsampling 2025-12-09 13:25:26 +01:00
Vincent Privat 355a916225 Optimize buffer by allocating enough space up front 2025-12-09 13:24:39 +01:00
Vincent Privat 8da45b5f05 take code review into account 2025-12-09 13:24:39 +01:00
Vincent Privat 6c8b0cdc2f Fix #1211 - SVG: support namespace prefix 2025-12-09 13:24:39 +01:00
dependabot[bot] 8af219e669 Bump org.apache.maven.plugins:maven-jar-plugin from 3.4.2 to 3.5.0
Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.4.2 to 3.5.0.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.2...maven-jar-plugin-3.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 13:23:04 +01:00
dependabot[bot] 7e10b9242d Bump org.apache.maven.plugins:maven-source-plugin from 3.3.1 to 3.4.0
Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.3.1 to 3.4.0.
- [Release notes](https://github.com/apache/maven-source-plugin/releases)
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.1...maven-source-plugin-3.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 13:22:51 +01:00
dependabot[bot] 36103046a5 Bump org.apache.maven.plugins:maven-resources-plugin from 3.3.1 to 3.4.0
Bumps [org.apache.maven.plugins:maven-resources-plugin](https://github.com/apache/maven-resources-plugin) from 3.3.1 to 3.4.0.
- [Release notes](https://github.com/apache/maven-resources-plugin/releases)
- [Commits](https://github.com/apache/maven-resources-plugin/compare/maven-resources-plugin-3.3.1...v3.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 13:22:38 +01:00
dependabot[bot] 95787449ea Bump org.apache.maven.plugins:maven-release-plugin from 3.2.0 to 3.3.0
Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.2.0...maven-release-3.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 13:22:21 +01:00
dependabot[bot] 3223743f2c Bump actions/checkout from 5.0.0 to 6.0.1 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 6.0.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/08c6903cd8c0fde910a37f88322edcfb5dd907a8...8e8c483db84b4bee98b60c0593521ed34d9990e8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 12:46:28 +01:00
dependabot[bot] 234c7f59d4 Bump github/codeql-action from 4.31.3 to 4.31.4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.3 to 4.31.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/014f16e7ab1402f30e7c3329d33797e7948572db...e12f0178983d466f2f6028f5cc7a6d786fd97f4b)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 12:46:04 +01:00
Harald Kuhr 1cb0da2967 Add cooldown period for all dependencies, 7 days 2025-11-24 10:44:51 +01:00
dependabot[bot] d1525828fa Bump github/codeql-action from 4.31.2 to 4.31.3 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.2 to 4.31.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/0499de31b99561a6d14a36a5f662c2a54f91beee...014f16e7ab1402f30e7c3329d33797e7948572db)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-14 15:51:00 +01:00
dependabot[bot] 194fd5a446 Bump org.apache.maven.plugins:maven-release-plugin from 3.1.1 to 3.2.0
Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.1.1...maven-release-3.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 09:39:04 +01:00
dependabot[bot] 21e5a465b9 Bump commons-io:commons-io from 2.20.0 to 2.21.0
Bumps [commons-io:commons-io](https://github.com/apache/commons-io) from 2.20.0 to 2.21.0.
- [Changelog](https://github.com/apache/commons-io/blob/master/RELEASE-NOTES.txt)
- [Commits](https://github.com/apache/commons-io/compare/rel/commons-io-2.20.0...rel/commons-io-2.21.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 09:33:25 +01:00
dependabot[bot] 6309bc5765 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4...e08919a3b1fb83a78393dfb775a9c37f17d8eea6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 09:29:34 +01:00
dependabot[bot] 5011e98184 Bump junit.jupiter.version from 5.14.0 to 5.14.1
Bumps `junit.jupiter.version` from 5.14.0 to 5.14.1.

Updates `org.junit.jupiter:junit-jupiter-api` from 5.14.0 to 5.14.1
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.14.0...r5.14.1)

Updates `org.junit.jupiter:junit-jupiter-engine` from 5.14.0 to 5.14.1
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.14.0...r5.14.1)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-version: 5.14.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.junit.jupiter:junit-jupiter-engine
  dependency-version: 5.14.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 09:25:22 +01:00
dependabot[bot] a9aa5cc66e Bump github/codeql-action from 4.31.0 to 4.31.2 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.0 to 4.31.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/4e94bd11f71e507f7f87df81788dff88d1dacbfb...0499de31b99561a6d14a36a5f662c2a54f91beee)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-02 13:24:13 +01:00
dependabot[bot] ac107196eb Bump github/codeql-action from 4.30.9 to 4.31.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.9 to 4.31.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/16140ae1a102900babc80a33c44059580f687047...4e94bd11f71e507f7f87df81788dff88d1dacbfb)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 10:03:26 +01:00
dependabot[bot] 489a419df1 Bump actions/upload-artifact from 4.6.2 to 5.0.0 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 5.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/ea165f8d65b6e75b540449e92b4886f43607fa02...330a01c490aca151604b8cf639adc76d48f6c5d4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 09:35:37 +01:00
dependabot[bot] 51891b45ea Bump github/codeql-action from 4.30.8 to 4.30.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.8 to 4.30.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/f443b600d91635bebf5b0d9ebc620189c0d6fba5...16140ae1a102900babc80a33c44059580f687047)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-20 11:16:14 +02:00
dependabot[bot] 90e60f509d Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.6.2 to 6.0.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/3585e9575db828022551b4231f165eb59a0e74e3...5b7ee5a21e8674b695313d769f3cbdfd5d4d53a4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 11:50:22 +02:00
dependabot[bot] 53e5eff0c9 Bump github/codeql-action from 4.30.7 to 4.30.8 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.7 to 4.30.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/e296a935590eb16afc0c0108289f68c87e2a89a5...f443b600d91635bebf5b0d9ebc620189c0d6fba5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 11:49:53 +02:00
dependabot[bot] 8670e1fd8a Bump org.apache.maven.plugins:maven-pmd-plugin from 3.27.0 to 3.28.0
Bumps [org.apache.maven.plugins:maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.27.0 to 3.28.0.
- [Release notes](https://github.com/apache/maven-pmd-plugin/releases)
- [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.27.0...maven-pmd-plugin-3.28.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 10:34:48 +02:00
Harald Kuhr 6395fd33e9 Temporarily disable deploy 2025-10-09 09:13:53 +02:00
Harald Kuhr 0834a2b1be Fix JDK 8 name in CI output 2025-10-09 09:05:06 +02:00
Harald Kuhr 6c75661ab4 Update ci.yml 2025-10-09 09:00:16 +02:00
dependabot[bot] 9c25c962cc Bump github/codeql-action from 3.30.6 to 4.30.7 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.6 to 4.30.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/64d10c13136e1c5bce3e5fbde8d4906eeaafc885...e296a935590eb16afc0c0108289f68c87e2a89a5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-09 08:41:40 +02:00
zcronix 1328dbf763 Handle lossless JPEG with non-zero point transform (#1183)
* Handle lossless JPEG with non-zero point transform (Pt parameter)
* Add unit test
* Inserting a fix for last pixel not being output
* Address issues from code review

---------

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2025-10-03 10:49:40 +02:00
dependabot[bot] 8bccdef371 Bump github/codeql-action from 3.30.5 to 3.30.6 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.5 to 3.30.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/3599b3baa15b485a2e49ef411a7a4bb2452e7f93...64d10c13136e1c5bce3e5fbde8d4906eeaafc885)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-03 10:45:04 +02:00
Harald Kuhr 2d6f7d89fa JDK 25 seems to have added Exif thumbnail read support 2025-10-03 10:42:16 +02:00
dependabot[bot] 1afa35ccd6 Bump org.apache.maven.scm:maven-scm-provider-gitexe from 2.1.0 to 2.2.1
Bumps org.apache.maven.scm:maven-scm-provider-gitexe from 2.1.0 to 2.2.1.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 09:31:59 +02:00
dependabot[bot] 5b184a2a8a Bump junit.jupiter.version from 5.13.4 to 5.14.0
Bumps `junit.jupiter.version` from 5.13.4 to 5.14.0.

Updates `org.junit.jupiter:junit-jupiter-api` from 5.13.4 to 5.14.0
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.4...r5.14.0)

Updates `org.junit.jupiter:junit-jupiter-engine` from 5.13.4 to 5.14.0
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.4...r5.14.0)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-version: 5.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.junit.jupiter:junit-jupiter-engine
  dependency-version: 5.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 09:13:48 +02:00
dependabot[bot] 39bd218085 Bump ossf/scorecard-action from 2.4.2 to 2.4.3 in /.github/workflows
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.2 to 2.4.3.
- [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/05b42c624433fc40578a4040d5cf5e36ddca8cde...4eaacf0543bb3f2c246792bd56e8cdeffafb205a)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 09:12:52 +02:00
dependabot[bot] 87af2f6212 Bump github/codeql-action from 3.30.1 to 3.30.5 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.1 to 3.30.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/f1f6e5f6af878fb37288ce1c627459e94dbf7d01...3599b3baa15b485a2e49ef411a7a4bb2452e7f93)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 09:12:03 +02:00
dependabot[bot] 598ea1e486 Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.14.0 to 3.14.1.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.14.0...maven-compiler-plugin-3.14.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 09:10:20 +02:00
dependabot[bot] 93180e7a2d Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.11.3 to 3.12.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.3 to 3.12.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.3...maven-javadoc-plugin-3.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 09:10:09 +02:00
dependabot[bot] 2cc6d1d28e Bump org.apache.maven.plugins:maven-shade-plugin from 3.6.0 to 3.6.1
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.6.0 to 3.6.1.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.6.0...v3.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 09:09:56 +02:00
dependabot[bot] 8ea9d6f318 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.5.3 to 3.5.4
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.3 to 3.5.4.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.3...surefire-3.5.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 09:09:46 +02:00
dependabot[bot] 029fa843f6 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.5.3 to 3.5.4.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.3...surefire-3.5.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-02 09:09:03 +02:00
Harald Kuhr 2cb4c0a661 Update ci.yml 2025-10-02 09:06:21 +02:00
dependabot[bot] bf40c81123 Bump github/codeql-action from 3.30.0 to 3.30.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.0 to 3.30.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/2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d...f1f6e5f6af878fb37288ce1c627459e94dbf7d01)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 11:32:17 +02:00
dependabot[bot] 78a90fab95 Bump github/codeql-action from 3.29.11 to 3.30.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.11 to 3.30.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/3c3833e0f8c1c83d449a7478aa59c036a9165498...2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-03 09:09:05 +02:00
dependabot[bot] b03f7a5582 Bump github/codeql-action from 3.29.10 to 3.29.11 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.10 to 3.29.11.
- [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/96f518a34f7a870018057716cc4d7a5c014bd61c...3c3833e0f8c1c83d449a7478aa59c036a9165498)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-22 11:08:08 +02:00
dependabot[bot] 96470c3897 Bump actions/setup-java from 4.7.1 to 5.0.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.1 to 5.0.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/c5195efecf7bdfc987ee8bae7a71cb8b11521c00...dded0888837ed1f317902acf8a20df0ad188d165)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-21 16:09:00 +02:00
dependabot[bot] 365b19998f Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.11.2 to 3.11.3
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.2 to 3.11.3.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.2...maven-javadoc-plugin-3.11.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 14:21:09 +02:00
dependabot[bot] b1846e1aed Bump github/codeql-action from 3.29.9 to 3.29.10 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.9 to 3.29.10.
- [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/df559355d593797519d70b90fc8edd5db049e7a2...96f518a34f7a870018057716cc4d7a5c014bd61c)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 14:20:24 +02:00
dependabot[bot] ec63fbbd85 Bump github/codeql-action from 3.29.8 to 3.29.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.8 to 3.29.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/76621b61decf072c1cee8dd1ce2d2a82d33c17ed...df559355d593797519d70b90fc8edd5db049e7a2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 10:57:39 +02:00
dependabot[bot] fbea929bc5 Bump actions/checkout from 4.2.2 to 5.0.0 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.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/11bd71901bbe5b1630ceea73d27597364c9af683...08c6903cd8c0fde910a37f88322edcfb5dd907a8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 19:22:26 +02:00
dependabot[bot] 18372944f1 Bump github/codeql-action from 3.29.2 to 3.29.8 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.2 to 3.29.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/181d5eefc20863364f96762470ba6f862bdef56b...76621b61decf072c1cee8dd1ce2d2a82d33c17ed)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-11 15:59:16 +02:00
dependabot[bot] 488608b312 Bump junit.jupiter.version from 5.13.3 to 5.13.4
Bumps `junit.jupiter.version` from 5.13.3 to 5.13.4.

Updates `org.junit.jupiter:junit-jupiter-api` from 5.13.3 to 5.13.4
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.3...r5.13.4)

Updates `org.junit.jupiter:junit-jupiter-params` from 5.13.3 to 5.13.4
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.3...r5.13.4)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-version: 5.13.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.junit.jupiter:junit-jupiter-params
  dependency-version: 5.13.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-11 15:58:37 +02:00
dependabot[bot] b3ae8a8ba6 Bump commons-io:commons-io from 2.19.0 to 2.20.0
Bumps [commons-io:commons-io](https://github.com/apache/commons-io) from 2.19.0 to 2.20.0.
- [Changelog](https://github.com/apache/commons-io/blob/master/RELEASE-NOTES.txt)
- [Commits](https://github.com/apache/commons-io/compare/rel/commons-io-2.19.0...rel/commons-io-2.20.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-11 15:58:09 +02:00
dependabot[bot] fc3455d2c6 Bump mikepenz/action-junit-report in /.github/workflows
---
updated-dependencies:
- dependency-name: mikepenz/action-junit-report
  dependency-version: 5.6.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-07 12:38:30 +02:00
dependabot[bot] f653279c62 Bump junit.jupiter.version from 5.13.2 to 5.13.3
Bumps `junit.jupiter.version` from 5.13.2 to 5.13.3.

Updates `org.junit.jupiter:junit-jupiter-api` from 5.13.2 to 5.13.3
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.2...r5.13.3)

Updates `org.junit.jupiter:junit-jupiter-engine` from 5.13.2 to 5.13.3
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.2...r5.13.3)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-version: 5.13.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.junit.jupiter:junit-jupiter-engine
  dependency-version: 5.13.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-07 12:38:09 +02:00
dependabot[bot] 0eff483d72 Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.7 to 3.2.8
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.7 to 3.2.8.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.7...maven-gpg-plugin-3.2.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-02 10:36:43 +02:00
dependabot[bot] 9c044b132b Bump github/codeql-action from 3.29.1 to 3.29.2 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.1 to 3.29.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/39edc492dbe16b1465b0cafca41432d857bdb31a...181d5eefc20863364f96762470ba6f862bdef56b)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-01 12:50:51 +02:00
dependabot[bot] 1ec4088e49 Bump github/codeql-action from 3.29.0 to 3.29.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.0 to 3.29.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/ce28f5bb42b7a9f2c824e633a3f6ee835bab6858...39edc492dbe16b1465b0cafca41432d857bdb31a)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-01 08:27:44 +02:00
dependabot[bot] 5ac415d019 Bump org.apache.maven.plugins:maven-pmd-plugin from 3.26.0 to 3.27.0
Bumps [org.apache.maven.plugins:maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.26.0 to 3.27.0.
- [Release notes](https://github.com/apache/maven-pmd-plugin/releases)
- [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.26.0...maven-pmd-plugin-3.27.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-26 11:00:28 +02:00
dependabot[bot] 133eafc8c2 Bump junit.jupiter.version from 5.13.1 to 5.13.2
Bumps `junit.jupiter.version` from 5.13.1 to 5.13.2.

Updates `org.junit.jupiter:junit-jupiter-api` from 5.13.1 to 5.13.2
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.1...r5.13.2)

Updates `org.junit.jupiter:junit-jupiter-params` from 5.13.1 to 5.13.2
- [Release notes](https://github.com/junit-team/junit-framework/releases)
- [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.1...r5.13.2)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-version: 5.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.junit.jupiter:junit-jupiter-params
  dependency-version: 5.13.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-25 12:41:59 +02:00
Harald Kuhr 85346a82e1 Fix JavaDoc that breaks build... 2025-06-17 08:30:43 +02:00
Harald Kuhr e718e58b65 #1152 Fix TIFF CCITT T.4/T.6 metadata compression names 2025-06-16 21:18:30 +02:00
dependabot[bot] 13a64ed3bb Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.6.0 to 5.6.1.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/65fe03598d8d251738592a497a9e8547a5c48eaa...a83fd2b5d58d4fc702e690c1ea688d702d28d281)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-16 11:38:50 +02:00
dependabot[bot] 3c6df6ad1b Bump github/codeql-action from 3.28.19 to 3.29.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.19 to 3.29.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/fca7ace96b7d713c7035871441bd52efbe39e27e...ce28f5bb42b7a9f2c824e633a3f6ee835bab6858)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-12 13:40:43 +02:00
dependabot[bot] 9abe154ed3 Bump junit.jupiter.version from 5.13.0 to 5.13.1
Bumps `junit.jupiter.version` from 5.13.0 to 5.13.1.

Updates `org.junit.jupiter:junit-jupiter-api` from 5.13.0 to 5.13.1
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.13.0...r5.13.1)

Updates `org.junit.jupiter:junit-jupiter-params` from 5.13.0 to 5.13.1
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.13.0...r5.13.1)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-version: 5.13.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.junit.jupiter:junit-jupiter-params
  dependency-version: 5.13.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-09 14:49:17 +02:00
Harald Kuhr 0e752a2d2c Bump org.junit.jupiter:junit-jupiter-api from 5.12.2 to 5.13.0 (#1149) 2025-06-06 13:03:03 +02:00
Harald Kuhr 867a46d281 Bump org.junit.jupiter:junit-jupiter-all from 5.12.2 to 5.13.0 (#1147) 2025-06-06 10:32:42 +02:00
dependabot[bot] 9972f966f7 Bump github/codeql-action from 3.28.18 to 3.28.19 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.18 to 3.28.19.
- [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/ff0a06e83cb2de871e5a09832bc6a81e7276941f...fca7ace96b7d713c7035871441bd52efbe39e27e)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-04 10:42:51 +02:00
dependabot[bot] f066a48d55 Bump ossf/scorecard-action from 2.4.1 to 2.4.2 in /.github/workflows
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.1 to 2.4.2.
- [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/f49aabe0b5af0936a0987cfb85d86b75731b0186...05b42c624433fc40578a4040d5cf5e36ddca8cde)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 12:20:31 +02:00
Rolf Howarth 5af87372aa Use signed arithmetic when reading rectangle (#1131)
* Use signed arithmetic when reading rectangle

An operation such as DirectBitsRect can fail if the origin is -ve and we're applying a screen image ratio. See for example P564B1400.pict

* Fix copy/paste error in testNegativeOrigin()

---------

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2025-05-30 16:14:23 +02:00
Rolf Howarth defadbbbcd Set 'frame' to correct image bounds (#1130)
Ensure the x,y offset for extended v2 pictures is respected by updating 'frame' to the correct bounding rectangle. As a result we
need to base output image directly on frame size rather than applying screen image ratio. See cow.pict.

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2025-05-30 16:07:16 +02:00
Rolf Howarth 66363f8d09 Fix bounds issue in some v2 PICT files (#1129)
x2 and y2 were swapped over, resulting in an "invalid bounds" exception with -ve height on some nonV2Ext images,
see for example CatDV==2.0=1=.pict or Picture14.pict

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2025-05-30 15:59:00 +02:00
Rolf Howarth 1bef35daba Fix rendering of images with JPEG slices (#1124)
* Third attempt

* Add test file

* Only suppress lastQTRect if PackBitsRect immediately follows CompressedQuickTime opcode

* Only suppress lastQTRect if PackBitsRect immediately follows CompressedQuickTime opcode

* Add unit test that checks pixel values

* Add missing ImageIO import

* Fix formatting issues

---------

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2025-05-30 15:51:06 +02:00
Harald Kuhr 0be5efc534 Add static import of Assumptions.assumeTrue 2025-05-30 15:50:02 +02:00
Rolf Howarth 35da57dfcf JUnit confusion about parameter order 2025-05-30 15:50:02 +02:00
Rolf Howarth 5d09bb664e Add assumption for TIFF reader being present as test will fail under jdk 1.8 2025-05-30 15:50:02 +02:00
Rolf Howarth 5590072cc7 Fix assertRGBEquals() failure message 2025-05-30 15:50:02 +02:00
Rolf Howarth 31117c7cea Add unit test for QuickTime mask issue 2025-05-30 15:50:02 +02:00
Rolf Howarth ae0899fe76 Make sure maskSize bytes are skipped
If the CompressedQuickTime opcode has a mask then this wasn't processed properly. See for example P30946BDC.pict.
2025-05-30 15:50:02 +02:00
dependabot[bot] df51ef340d Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.5.1 to 5.6.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/cf701569b05ccdd861a76b8607a66d76f6fd4857...65fe03598d8d251738592a497a9e8547a5c48eaa)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-30 11:30:35 +02:00
dependabot[bot] 71d8295042 Bump github/codeql-action from 3.28.17 to 3.28.18 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.17 to 3.28.18.
- [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/60168efe1c415ce0f5521ea06d5c2062adbeed1b...ff0a06e83cb2de871e5a09832bc6a81e7276941f)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-19 10:49:33 +02:00
dependabot[bot] a8f77a9a45 Bump batik.version from 1.18 to 1.19
Bumps `batik.version` from 1.18 to 1.19.

Updates `org.apache.xmlgraphics:batik-rasterizer-ext` from 1.18 to 1.19

Updates `org.apache.xmlgraphics:batik-extension` from 1.18 to 1.19

Updates `org.apache.xmlgraphics:batik-anim` from 1.18 to 1.19

Updates `org.apache.xmlgraphics:batik-svggen` from 1.18 to 1.19

Updates `org.apache.xmlgraphics:batik-transcoder` from 1.18 to 1.19

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-07 12:40:47 +02:00
dependabot[bot] eb3176b447 Bump github/codeql-action from 3.28.16 to 3.28.17 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.16 to 3.28.17.
- [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/28deaeda66b76a05916b6923827895f2b14ab387...60168efe1c415ce0f5521ea06d5c2062adbeed1b)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-05 12:08:45 +02:00
dependabot[bot] 20e308dd8f Bump github/codeql-action from 3.28.15 to 3.28.16 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.15 to 3.28.16.
- [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/45775bd8235c68ba998cffa5171334d58593da47...28deaeda66b76a05916b6923827895f2b14ab387)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-24 13:21:38 +02:00
dependabot[bot] 9fa9bc5fe0 Bump commons-io:commons-io from 2.18.0 to 2.19.0
Bumps commons-io:commons-io from 2.18.0 to 2.19.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 10:59:33 +02:00
dependabot[bot] 4da3e2e441 Bump org.junit.jupiter:junit-jupiter-api from 5.12.1 to 5.12.2
Bumps [org.junit.jupiter:junit-jupiter-api](https://github.com/junit-team/junit5) from 5.12.1 to 5.12.2.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.12.1...r5.12.2)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-version: 5.12.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 10:51:39 +02:00
dependabot[bot] 4516d84e54 Bump org.junit.jupiter:junit-jupiter-engine from 5.12.1 to 5.12.2
Bumps [org.junit.jupiter:junit-jupiter-engine](https://github.com/junit-team/junit5) from 5.12.1 to 5.12.2.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.12.1...r5.12.2)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-engine
  dependency-version: 5.12.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 10:51:29 +02:00
dependabot[bot] a815e5f180 Bump org.junit.jupiter:junit-jupiter-params from 5.12.1 to 5.12.2
Bumps [org.junit.jupiter:junit-jupiter-params](https://github.com/junit-team/junit5) from 5.12.1 to 5.12.2.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.12.1...r5.12.2)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-params
  dependency-version: 5.12.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 10:51:16 +02:00
dependabot[bot] 35658a888f Bump actions/setup-java from 4.7.0 to 4.7.1 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.0 to 4.7.1.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/3a4f6e1af504cf6a31855fa899c6aa5355ba6c12...c5195efecf7bdfc987ee8bae7a71cb8b11521c00)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-09 11:47:11 +02:00
dependabot[bot] 6cd6b6113d Bump github/codeql-action from 3.28.13 to 3.28.15 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.13 to 3.28.15.
- [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/1b549b9259bda1cb5ddde3b41741a82a2d15a841...45775bd8235c68ba998cffa5171334d58593da47)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-08 12:44:13 +02:00
Rolf Howarth f8b919ee58 Improve debug output (#1115)
Include hex opcode and file offset in debug output. Condense scan line messages in readOpDirectBits().

---------

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2025-03-31 21:38:09 +02:00
dependabot[bot] 8989ba07d8 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.5.0 to 5.5.1.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/97744eca465b8df9e6e33271cb155003f85327f1...cf701569b05ccdd861a76b8607a66d76f6fd4857)

---
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>
2025-03-31 14:36:41 +02:00
dependabot[bot] bc38ec1034 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.5.2 to 3.5.3.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.2...surefire-3.5.3)

---
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>
2025-03-31 14:20:26 +02:00
dependabot[bot] e37c1fbb50 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.5.2 to 3.5.3
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.2...surefire-3.5.3)

---
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>
2025-03-31 14:20:14 +02:00
dependabot[bot] 75b6de7102 Bump github/codeql-action from 3.28.12 to 3.28.13 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.12 to 3.28.13.
- [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/5f8171a638ada777af81d42b55959a643bb29017...1b549b9259bda1cb5ddde3b41741a82a2d15a841)

---
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>
2025-03-25 09:31:43 +01:00
dependabot[bot] 22a16db463 Bump actions/upload-artifact from 4.6.1 to 4.6.2 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.1 to 4.6.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1...ea165f8d65b6e75b540449e92b4886f43607fa02)

---
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>
2025-03-20 11:52:58 +01:00
dependabot[bot] 3e93753073 Bump github/codeql-action from 3.28.11 to 3.28.12 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.11 to 3.28.12.
- [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/6bb031afdd8eb862ea3fc1848194185e076637e5...5f8171a638ada777af81d42b55959a643bb29017)

---
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>
2025-03-20 11:49:03 +01:00
dependabot[bot] ad3cbbd86d Bump org.junit.jupiter:junit-jupiter-api from 5.12.0 to 5.12.1
Bumps [org.junit.jupiter:junit-jupiter-api](https://github.com/junit-team/junit5) from 5.12.0 to 5.12.1.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.12.0...r5.12.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 09:52:07 +01:00
dependabot[bot] 076e417010 Bump org.junit.jupiter:junit-jupiter-engine from 5.12.0 to 5.12.1
Bumps [org.junit.jupiter:junit-jupiter-engine](https://github.com/junit-team/junit5) from 5.12.0 to 5.12.1.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.12.0...r5.12.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 09:51:58 +01:00
dependabot[bot] 0b84a99954 Bump org.junit.jupiter:junit-jupiter-params from 5.12.0 to 5.12.1
Bumps [org.junit.jupiter:junit-jupiter-params](https://github.com/junit-team/junit5) from 5.12.0 to 5.12.1.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.12.0...r5.12.1)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-params
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-17 09:51:47 +01:00
dependabot[bot] e2f4241a99 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.4.0 to 5.5.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/b14027d33d3a745ccc4d6a12f649e83110b5a373...97744eca465b8df9e6e33271cb155003f85327f1)

---
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>
2025-03-10 10:37:11 +01:00
dependabot[bot] 6eedaa129d Bump github/codeql-action from 3.28.10 to 3.28.11 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.10 to 3.28.11.
- [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/b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d...6bb031afdd8eb862ea3fc1848194185e076637e5)

---
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>
2025-03-10 10:05:51 +01:00
Harald Kuhr f5dbc0c2f4 Remove JDK 22 from test matrix [skip ci] 2025-03-07 19:51:05 +01:00
Harald Kuhr 7d79185fb2 Add JDK 23 to test matrix 2025-03-07 19:46:59 +01:00
Harald Kuhr c885ed6dbb Add JDK 22 to test matrix 2025-03-07 19:42:58 +01:00
dependabot[bot] e116c98db2 Bump org.junit.jupiter:junit-jupiter-engine from 5.11.4 to 5.12.0
Bumps [org.junit.jupiter:junit-jupiter-engine](https://github.com/junit-team/junit5) from 5.11.4 to 5.12.0.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.4...r5.12.0)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-engine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-05 14:00:26 +01:00
dependabot[bot] be9493af20 Bump org.junit.jupiter:junit-jupiter-api from 5.11.4 to 5.12.0
Bumps [org.junit.jupiter:junit-jupiter-api](https://github.com/junit-team/junit5) from 5.11.4 to 5.12.0.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.4...r5.12.0)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-05 14:00:18 +01:00
dependabot[bot] 5ffe3087ad Bump org.junit.jupiter:junit-jupiter-params from 5.11.4 to 5.12.0
Bumps [org.junit.jupiter:junit-jupiter-params](https://github.com/junit-team/junit5) from 5.11.4 to 5.12.0.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.4...r5.12.0)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-params
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-05 13:59:36 +01:00
dependabot[bot] ffc7dad821 Bump org.apache.maven.plugins:maven-deploy-plugin from 3.1.3 to 3.1.4
Bumps [org.apache.maven.plugins:maven-deploy-plugin](https://github.com/apache/maven-deploy-plugin) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/apache/maven-deploy-plugin/releases)
- [Commits](https://github.com/apache/maven-deploy-plugin/compare/maven-deploy-plugin-3.1.3...maven-deploy-plugin-3.1.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-27 09:45:43 +01:00
dependabot[bot] 2a4ff2aa12 Bump github/codeql-action from 3.28.9 to 3.28.10 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.9 to 3.28.10.
- [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/9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0...b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d)

---
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>
2025-02-24 14:50:06 +01:00
dependabot[bot] 1e9669d6c3 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.3.0 to 5.4.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/ee6b445351cd81e2f73a16a0e52d598aeac2197f...b14027d33d3a745ccc4d6a12f649e83110b5a373)

---
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>
2025-02-24 14:02:40 +01:00
dependabot[bot] caca51d5ce Bump ossf/scorecard-action from 2.4.0 to 2.4.1 in /.github/workflows
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.0 to 2.4.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/62b2cac7ed8198b15735ed49ab1e5cf35480ba46...f49aabe0b5af0936a0987cfb85d86b75731b0186)

---
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>
2025-02-24 14:02:26 +01:00
dependabot[bot] 015728a57d Bump actions/upload-artifact from 4.6.0 to 4.6.1 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.0 to 4.6.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08...4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1)

---
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>
2025-02-24 14:02:08 +01:00
dependabot[bot] 4272c6c8ed Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.13.0 to 3.14.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.13.0...maven-compiler-plugin-3.14.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>
2025-02-24 14:00:37 +01:00
dependabot[bot] b5582e32f6 Bump github/codeql-action from 3.28.8 to 3.28.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.8 to 3.28.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/dd746615b3b9d728a6a37ca2045b68ca76d4841a...9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0)

---
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>
2025-02-10 10:42:25 +01:00
dependabot[bot] 76045ab0d9 Bump github/codeql-action from 3.28.6 to 3.28.8 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.6 to 3.28.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/17a820bf2e43b47be2c72b39cc905417bc1ab6d0...dd746615b3b9d728a6a37ca2045b68ca76d4841a)

---
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>
2025-01-30 11:46:40 +01:00
dependabot[bot] 4fc8f28cc6 Bump actions/setup-java from 4.6.0 to 4.7.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.6.0 to 4.7.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/7a6d8a8234af8eb26422e24e3006232cccaa061b...3a4f6e1af504cf6a31855fa899c6aa5355ba6c12)

---
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>
2025-01-29 10:17:07 +01:00
dependabot[bot] 7198a92a2e Bump github/codeql-action from 3.28.5 to 3.28.6 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.5 to 3.28.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/f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4...17a820bf2e43b47be2c72b39cc905417bc1ab6d0)

---
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>
2025-01-29 10:12:25 +01:00
dependabot[bot] e2fbd80c36 Bump github/codeql-action from 3.28.4 to 3.28.5 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.4 to 3.28.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/ee117c905ab18f32fa0f66c2fe40ecc8013f3e04...f6091c0113d1dcf9b98e269ee48e8a7e51b7bdd4)

---
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>
2025-01-27 10:09:58 +01:00
dependabot[bot] 6b28cbe4a1 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/62516aa379bff6370c95fd5894d5a27fb6619d9b...ee6b445351cd81e2f73a16a0e52d598aeac2197f)

---
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>
2025-01-27 10:09:42 +01:00
dependabot[bot] 76198b0655 Bump github/codeql-action from 3.28.3 to 3.28.4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.3 to 3.28.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/dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7...ee117c905ab18f32fa0f66c2fe40ecc8013f3e04)

---
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>
2025-01-24 10:11:05 +01:00
dependabot[bot] f81b14df71 Bump github/codeql-action from 3.28.2 to 3.28.3 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.2 to 3.28.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/d68b2d4edb4189fd2a5366ac14e72027bd4b37dd...dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7)

---
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>
2025-01-23 09:47:58 +01:00
dependabot[bot] da3f79f0c9 Bump github/codeql-action from 3.28.1 to 3.28.2 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.1 to 3.28.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/b6a472f63d85b9c78a3ac5e89422239fc15e9b3c...d68b2d4edb4189fd2a5366ac14e72027bd4b37dd)

---
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>
2025-01-22 09:50:16 +01:00
dependabot[bot] d39418eca2 Bump github/codeql-action from 3.28.0 to 3.28.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.0 to 3.28.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/48ab28a6f5dbc2a99bf1e0131198dd8f1df78169...b6a472f63d85b9c78a3ac5e89422239fc15e9b3c)

---
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>
2025-01-13 10:26:53 +01:00
dependabot[bot] cbbc2bc6fe Bump actions/upload-artifact from 4.5.0 to 4.6.0 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.5.0 to 4.6.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/6f51ac03b9356f520e9adb1b1b7802705f340c2b...65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-10 09:58:49 +01:00
dependabot[bot] b0b423de4f Bump github/codeql-action from 3.27.9 to 3.28.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.9 to 3.28.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/df409f7d9260372bd5f19e5b04e83cb3c43714ae...48ab28a6f5dbc2a99bf1e0131198dd8f1df78169)

---
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>
2024-12-23 10:12:32 +01:00
dependabot[bot] 1c4ec8d20e Bump actions/setup-java from 4.5.0 to 4.6.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.5.0 to 4.6.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/8df1039502a15bceb9433410b1a100fbe190c53b...7a6d8a8234af8eb26422e24e3006232cccaa061b)

---
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>
2024-12-18 10:05:43 +01:00
dependabot[bot] ec99a8ce1f Bump actions/upload-artifact from 4.4.3 to 4.5.0 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.4.3 to 4.5.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882...6f51ac03b9356f520e9adb1b1b7802705f340c2b)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-18 10:05:23 +01:00
dependabot[bot] c49a887cd3 Bump org.junit.jupiter:junit-jupiter-engine from 5.11.3 to 5.11.4
Bumps [org.junit.jupiter:junit-jupiter-engine](https://github.com/junit-team/junit5) from 5.11.3 to 5.11.4.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.3...r5.11.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-17 10:13:45 +01:00
dependabot[bot] 14af75d191 Bump org.junit.jupiter:junit-jupiter-params from 5.11.3 to 5.11.4
Bumps [org.junit.jupiter:junit-jupiter-params](https://github.com/junit-team/junit5) from 5.11.3 to 5.11.4.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.3...r5.11.4)

---
updated-dependencies:
- dependency-name: org.junit.jupiter:junit-jupiter-params
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-17 10:13:10 +01:00
dependabot[bot] 0ce205638e Bump org.junit.jupiter:junit-jupiter-api from 5.11.3 to 5.11.4
Bumps [org.junit.jupiter:junit-jupiter-api](https://github.com/junit-team/junit5) from 5.11.3 to 5.11.4.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.3...r5.11.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-17 10:07:30 +01:00
dependabot[bot] fe4119ca1c Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/992d97d6eb2e5f3de985fbf9df6a04386874114d...62516aa379bff6370c95fd5894d5a27fb6619d9b)

---
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>
2024-12-16 10:37:17 +01:00
dependabot[bot] c927f4c1ec Bump github/codeql-action from 3.27.6 to 3.27.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.6 to 3.27.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/aa578102511db1f4524ed59b8cc2bae4f6e88195...df409f7d9260372bd5f19e5b04e83cb3c43714ae)

---
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>
2024-12-13 10:08:56 +01:00
Harald Kuhr 161368084a Project goal improvement. 2024-12-10 16:46:42 +01:00
dependabot[bot] d958aba69e Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.11.1 to 3.11.2
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.1 to 3.11.2.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.1...maven-javadoc-plugin-3.11.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>
2024-12-09 10:16:03 +01:00
dependabot[bot] 931429724c Bump github/codeql-action from 3.27.5 to 3.27.6 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.5 to 3.27.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/f09c1c0a94de965c15400f5634aa42fac8fb8f88...aa578102511db1f4524ed59b8cc2bae4f6e88195)

---
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>
2024-12-04 09:46:15 +01:00
Harald Kuhr dcd21db2ef Readme code cleanup. 2024-12-03 08:59:23 +01:00
dependabot[bot] 7a3022ebf2 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/a427a90771729d8f85b6ab0cdaa1a5929cab985d...992d97d6eb2e5f3de985fbf9df6a04386874114d)

---
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>
2024-11-29 12:33:57 +01:00
Sam Stephens 274886b1d9 Add readme section about working with damaged images 2024-11-28 18:24:18 +01:00
Harald Kuhr 0cf784ee60 Change Maven GPG plugin to use Bounce Castle signer. Closes #915 2024-11-21 10:29:37 +01:00
Harald Kuhr a797f1ea26 Maven signing issue 2024-11-21 10:20:31 +01:00
dependabot[bot] baff849b6c Bump github/codeql-action from 3.27.4 to 3.27.5 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.4 to 3.27.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/ea9e4e37992a54ee68a9622e985e60c8e8f12d9f...f09c1c0a94de965c15400f5634aa42fac8fb8f88)

---
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>
2024-11-21 10:00:55 +01:00
dependabot[bot] 408977d896 Bump commons-io:commons-io from 2.17.0 to 2.18.0
Bumps commons-io:commons-io from 2.17.0 to 2.18.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>
2024-11-20 12:35:00 +01:00
Harald Kuhr d78e6373a8 Minor improvement, use real length when known. 2024-11-19 10:36:41 +01:00
Harald Kuhr 9610256ddb #1058: JPEG fix ClassCastException for Unknown segments 2024-11-19 10:36:12 +01:00
dependabot[bot] 34c9b9b4b5 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 5.0.0.pre.rc01 to 5.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/ec3a351c13e080dc4fa94c49ab7ad5bf778a9668...a427a90771729d8f85b6ab0cdaa1a5929cab985d)

---
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>
2024-11-18 09:41:37 +01:00
dependabot[bot] 9d5823d982 Bump github/codeql-action from 3.27.3 to 3.27.4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.3 to 3.27.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/396bb3e45325a47dd9ef434068033c6d5bb0d11a...ea9e4e37992a54ee68a9622e985e60c8e8f12d9f)

---
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>
2024-11-15 10:21:18 +01:00
dependabot[bot] 10e824df36 Bump github/codeql-action from 3.27.1 to 3.27.3 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.1 to 3.27.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/4f3212b61783c3c68e8309a0f18a699764811cda...396bb3e45325a47dd9ef434068033c6d5bb0d11a)

---
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>
2024-11-13 10:16:56 +01:00
dependabot[bot] 3bc90bfad1 Bump github/codeql-action from 3.27.0 to 3.27.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.0 to 3.27.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/662472033e021d55d94146f66f6058822b0b39fd...4f3212b61783c3c68e8309a0f18a699764811cda)

---
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>
2024-11-12 13:15:24 +01:00
Vyshak Puthusseri 543acce8a3 Upgrade to Junit5 (#1050)
* chore: Update to junit5 for servlet package

* chore: Update to junit5 for contrib package

* chore: Update to junit5 for common-image package

* chore: Update to junit5 for common-lang package

* chore: Update to junit5 for entire project files

* fix: test case for JPEGImageReaderTest failed for java 8 and 11

assertEquals was using old signature of junit4.

* Update common/common-io/src/test/java/com/twelvemonkeys/io/InputStreamAbstractTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update common/common-io/src/test/java/com/twelvemonkeys/io/InputStreamAbstractTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageReaderTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-jpeg/src/test/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReaderTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageMetadataTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReaderTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriterTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/BufferedChannelImageInputStreamTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/stream/BufferedChannelImageInputStreamTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* refactor: few indentation changes and missed test case

- review change related to missing test annotation
- unwanted new lines inside test case
- duplicate assertions

* refactor: moved the lambda expression to method reference

* review: testNotNullWithParameterNull catch block was never executed.

Added the suggested change

* Apply suggestions from code review

chore: adjust suggested indentation

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageWriterAbstractTest.java

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* refactor: using assertTimeout doesnot kill the execution, even if the timeout happens.

It is better to use assertTimeoutPreemptively in cases, where we really want to kill the execution after timeout.
https://stackoverflow.com/questions/57116801/how-to-fail-a-test-after-a-timeout-is-exceeded-in-junit-5/57116959#57116959

---------

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2024-11-12 10:13:15 +01:00
dependabot[bot] a67fdd4b80 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.5.1 to 3.5.2
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.1...surefire-3.5.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>
2024-11-04 13:13:25 +01:00
dependabot[bot] 9c936d3f11 Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.10.1 to 3.11.1
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.1 to 3.11.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.1...maven-javadoc-plugin-3.11.1)

---
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>
2024-11-04 13:13:14 +01:00
dependabot[bot] fb2bff1404 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.5.1 to 3.5.2.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.1...surefire-3.5.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>
2024-11-04 13:13:01 +01:00
dependabot[bot] 3c605f8796 Bump mikepenz/action-junit-report from 4.3.1 to 5 in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.3.1 to 5.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/db71d41eb79864e25ab0337e395c352e84523afe...ec3a351c13e080dc4fa94c49ab7ad5bf778a9668)

---
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>
2024-11-04 09:47:59 +01:00
dependabot[bot] 7817af91a3 Bump org.apache.maven.plugins:maven-pmd-plugin from 3.25.0 to 3.26.0
Bumps [org.apache.maven.plugins:maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.25.0 to 3.26.0.
- [Release notes](https://github.com/apache/maven-pmd-plugin/releases)
- [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.25.0...maven-pmd-plugin-3.26.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>
2024-10-29 10:15:49 +01:00
dependabot[bot] 1ed1076714 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.5.0 to 3.6.0.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.5.0...maven-checkstyle-plugin-3.6.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>
2024-10-28 09:27:45 +01:00
dependabot[bot] a90d375422 Bump actions/setup-java from 4.4.0 to 4.5.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/b36c23c0d998641eff861008f374ee103c25ac73...8df1039502a15bceb9433410b1a100fbe190c53b)

---
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>
2024-10-25 11:19:01 +02:00
dependabot[bot] 815007ab2b Bump actions/checkout from 4.2.1 to 4.2.2 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.1 to 4.2.2.
- [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/eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871...11bd71901bbe5b1630ceea73d27597364c9af683)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-24 10:20:21 +02:00
dependabot[bot] b3c8f53512 Bump github/codeql-action from 3.26.13 to 3.27.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.13 to 3.27.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/f779452ac5af1c261dce0346a8f964149f49322b...662472033e021d55d94146f66f6058822b0b39fd)

---
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>
2024-10-23 11:03:31 +02:00
dependabot[bot] d2977a18ac Bump org.apache.maven.plugins:maven-help-plugin from 3.5.0 to 3.5.1
Bumps [org.apache.maven.plugins:maven-help-plugin](https://github.com/apache/maven-help-plugin) from 3.5.0 to 3.5.1.
- [Commits](https://github.com/apache/maven-help-plugin/compare/maven-help-plugin-3.5.0...maven-help-plugin-3.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-22 11:17:04 +02:00
dependabot[bot] 7e5e905d18 Bump github/codeql-action from 3.26.12 to 3.26.13 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.12 to 3.26.13.
- [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/c36620d31ac7c881962c3d9dd939c40ec9434f2b...f779452ac5af1c261dce0346a8f964149f49322b)

---
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>
2024-10-15 11:35:35 +02:00
dependabot[bot] 0fcba279f1 Bump batik.version from 1.17 to 1.18
Bumps `batik.version` from 1.17 to 1.18.

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

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

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

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

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

---
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>
2024-10-10 11:25:24 +02:00
dependabot[bot] d7d9552216 Bump actions/upload-artifact from 4.4.2 to 4.4.3 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.4.2 to 4.4.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/84480863f228bb9747b473957fcc9e309aa96097...b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882)

---
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>
2024-10-10 11:24:37 +02:00
dependabot[bot] e48a78aa77 Bump actions/upload-artifact from 4.4.1 to 4.4.2 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.4.1 to 4.4.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/604373da6381bf24206979c74d06a550515601b9...84480863f228bb9747b473957fcc9e309aa96097)

---
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>
2024-10-09 10:45:58 +02:00
Harald Kuhr bf351c01a6 Add DDS format to readme + minor enhancements 2024-10-08 11:25:42 +02:00
dependabot[bot] 9bd4389142 Bump actions/upload-artifact from 4.4.0 to 4.4.1 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.4.0 to 4.4.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/50769540e7f4bd5e21e526ee35c689e35e0d6874...604373da6381bf24206979c74d06a550515601b9)

---
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>
2024-10-08 11:02:05 +02:00
dependabot[bot] 984383bd56 Bump github/codeql-action from 3.26.11 to 3.26.12 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.11 to 3.26.12.
- [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/6db8d6351fd0be61f9ed8ebd12ccd35dcec51fea...c36620d31ac7c881962c3d9dd939c40ec9434f2b)

---
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>
2024-10-08 11:01:39 +02:00
dependabot[bot] 77247772d0 Bump actions/checkout from 4.2.0 to 4.2.1 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.0 to 4.2.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/d632683dd7b4114ad314bca15554477dd762a938...eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-08 11:01:13 +02:00
Harald Kuhr ae482bc7e5 [maven-release-plugin] prepare for next development iteration 2024-10-07 20:36:52 +02:00
Harald Kuhr 119700487b [maven-release-plugin] prepare release twelvemonkeys-3.12.0 2024-10-07 20:36:47 +02:00
Harald Kuhr 5e5d530498 RIP MagickAccelerator & friends, remove JMagick dependency 2024-10-07 20:24:43 +02:00
dependabot[bot] 3dfc0850cc 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.5.0 to 3.5.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.0...surefire-3.5.1)

---
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>
2024-10-07 11:12:34 +02:00
dependabot[bot] 8f285327fc Bump org.apache.maven.plugins:maven-surefire-plugin from 3.5.0 to 3.5.1
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.0 to 3.5.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.0...surefire-3.5.1)

---
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>
2024-10-07 11:12:13 +02:00
Vincent Privat 734b90863a TIFF: Add support for SAMPLEFORMAT_COMPLEXINT/SAMPLEFORMAT_COMPLEXIEEEFP 2024-10-06 13:45:48 +02:00
dependabot[bot] 18f31f2dd4 Bump github/codeql-action from 3.26.10 to 3.26.11 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.10 to 3.26.11.
- [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/e2b3eafc8d227b0241d48be5f425d47c2d750a13...6db8d6351fd0be61f9ed8ebd12ccd35dcec51fea)

---
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>
2024-10-04 11:53:37 +02:00
dependabot[bot] a7294af89c Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.6 to 3.2.7
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.6 to 3.2.7.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.6...maven-gpg-plugin-3.2.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-02 10:13:22 +02:00
dependabot[bot] ea63a5bdc1 Bump github/codeql-action from 3.26.9 to 3.26.10 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.9 to 3.26.10.
- [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/461ef6c76dfe95d5c364de2f431ddbd31a417628...e2b3eafc8d227b0241d48be5f425d47c2d750a13)

---
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>
2024-10-01 12:37:34 +02:00
dependabot[bot] 2cc50bbdad Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.10.0 to 3.10.1
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.0 to 3.10.1.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.0...maven-javadoc-plugin-3.10.1)

---
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>
2024-10-01 12:37:07 +02:00
Harald Kuhr f4a5f57d52 Fixes an issue where the CCITTFaxDecoderStream could cause endless reading (and potential OOME) 2024-09-27 10:58:11 +02:00
Harald Kuhr 7fc47a338c Add minimal metadata + minor clean-up 2024-09-26 11:16:26 +02:00
Harald Kuhr f8311164af Move test to correct package, rename + add missing test. License headers. 2024-09-26 10:33:11 +02:00
Harald Kuhr 84c10ed96d Fully support period == 1 (no subsampling) in subsampleRow even if different arrays 2024-09-26 10:31:27 +02:00
dependabot[bot] 9c8ae4ac3e Bump actions/checkout from 4.1.7 to 4.2.0 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 4.2.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/692973e3d937129bcbf40652eb9f2f61becf3332...d632683dd7b4114ad314bca15554477dd762a938)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-26 10:23:40 +02:00
Harald Kuhr aab7b6f7f5 Add source region and subsample support + license.txt 2024-09-25 17:47:57 +02:00
Paul Allen 3c01071452 Microsoft Direct DrawSurface (DDS) support. (#1021)
* Basic wrapper around DDSReader.

Nasty hack to get initial plugin working...
Mark and Reset the imageinput stream when reading the header.  Then read the whole buffer into DDSReader and generate a fixed BufferedImage ignoring the getDestination() BufferedImage.

* Read header (DDSHeader) and pass into DDSReader

Remove header methods using buffer offset addressing.
Switch endian for DX1-DX5 types

* Fix pixel order to ARGB

* Push ImageInputStream into DDSReader

Unable to determine buffer length (so as a hack I over allocate buffer and read)

```
byte[] buffer = new byte[width * height * 4];
int len = imageInput.read(buffer);
```

Added test files for all supported formats.

* Added processImageStarted and stubbed out processImageProgress and processReadAborted

Added all DDS format test cases to getTestData

* Remove offset and use imageInput.readFully

Reads next image calculating/updating width/height from mipmapLevel.
Probably will never get used as we only want the largest image returned.

* Code cleanup and added exception handling.

* Use Enum DDSType instead of int values.

Pass imageIndex into mipmap.

* Update imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSHeader.java

Improve IIOException "Invalid DDS header size"

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Update imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSHeader.java

Improve Magic IIOException

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>

* Delete .run directory

* Format tabs -> 4 spaces

* Convert 4byte array into %08x string format.

* Don't need to expose classes outside the package

DDSHeader, DDSReader, DDSType

* (fix) wrong public...

* Move setByteOrder to DDSImageReader.readHeader

* Use imageIndex to calculate height/width and buffer offset.

* Delete .gitignore

* Revert "Delete .gitignore"

This reverts commit 71a4e73ca6.

* Undelete/Restore .gitignore

* Simplify String.format into one.

* Override failing tests and ignore.

* Revert formatting on PNGImageReaderTest.java

---------

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2024-09-25 15:40:09 +02:00
dependabot[bot] 4fc9c3513b Bump github/codeql-action from 3.26.8 to 3.26.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.8 to 3.26.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/294a9d92911152fe08befb9ec03e240add280cb3...461ef6c76dfe95d5c364de2f431ddbd31a417628)

---
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>
2024-09-25 11:21:12 +02:00
dependabot[bot] 59b08bfc79 Bump actions/setup-java from 4.3.0 to 4.4.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.3.0 to 4.4.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/2dfa2011c5b2a0f1489bf9e433881c92c1631f88...b36c23c0d998641eff861008f374ee103c25ac73)

---
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>
2024-09-25 11:21:01 +02:00
Harald Kuhr 743f1f9356 Add RGBE acknowledgement to license.txt 2024-09-24 10:21:09 +02:00
dependabot[bot] d90b1c984c Bump github/codeql-action from 3.26.7 to 3.26.8 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.7 to 3.26.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/8214744c546c1e5c8f03dde8fab3a7353211988d...294a9d92911152fe08befb9ec03e240add280cb3)

---
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>
2024-09-20 11:32:33 +02:00
dependabot[bot] 1160be4995 Bump commons-io:commons-io from 2.16.1 to 2.17.0
Bumps commons-io:commons-io from 2.16.1 to 2.17.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>
2024-09-19 10:32:44 +02:00
dependabot[bot] 2978c901ae Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.5 to 3.2.6
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.5 to 3.2.6.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.5...maven-gpg-plugin-3.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 11:42:35 +02:00
dependabot[bot] e4b465a0d4 Bump github/codeql-action from 3.26.6 to 3.26.7 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.6 to 3.26.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/4dd16135b69a43b6c8efb853346f8437d92d3c93...8214744c546c1e5c8f03dde8fab3a7353211988d)

---
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>
2024-09-16 11:41:49 +02:00
dependabot[bot] 297a27c5be Bump actions/setup-java from 4.2.2 to 4.3.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.2.2 to 4.3.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/6a0805fcefea3d4657a47ac4c165951e33482018...2dfa2011c5b2a0f1489bf9e433881c92c1631f88)

---
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>
2024-09-10 15:01:47 +02:00
dependabot[bot] 9d9593dba2 Bump actions/upload-artifact from 4.3.6 to 4.4.0 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.6 to 4.4.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/834a144ee995460fba8ed112a2fc961b36a5ec5a...50769540e7f4bd5e21e526ee35c689e35e0d6874)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-02 11:01:44 +02:00
dependabot[bot] 66683a2ead Bump github/codeql-action from 3.26.5 to 3.26.6 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.5 to 3.26.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/2c779ab0d087cd7fe7b826087247c2c81f27bfa6...4dd16135b69a43b6c8efb853346f8437d92d3c93)

---
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>
2024-08-30 11:03:10 +02:00
dependabot[bot] 4be4f4e2b6 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.4.0 to 3.5.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.4.0...surefire-3.5.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>
2024-08-28 14:04:22 +02:00
dependabot[bot] 7f59d41b2a Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.8.0 to 3.10.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.8.0 to 3.10.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.8.0...maven-javadoc-plugin-3.10.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>
2024-08-28 14:04:10 +02:00
dependabot[bot] a060c105e1 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.4.0 to 3.5.0
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.4.0...surefire-3.5.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>
2024-08-28 11:59:56 +02:00
dependabot[bot] f3318ee818 Bump org.apache.maven.plugins:maven-pmd-plugin from 3.24.0 to 3.25.0
Bumps [org.apache.maven.plugins:maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.24.0 to 3.25.0.
- [Release notes](https://github.com/apache/maven-pmd-plugin/releases)
- [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.24.0...maven-pmd-plugin-3.25.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>
2024-08-28 11:59:33 +02:00
dependabot[bot] afa306a787 Bump github/codeql-action from 3.26.4 to 3.26.5 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.4 to 3.26.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/f0f3afee809481da311ca3a6ff1ff51d81dbeb24...2c779ab0d087cd7fe7b826087247c2c81f27bfa6)

---
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>
2024-08-26 10:52:32 +02:00
dependabot[bot] ed032b6c7a 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.4.0 to 3.5.0.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.4.0...maven-checkstyle-plugin-3.5.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>
2024-08-23 11:02:56 +02:00
dependabot[bot] 894e5dc30a Bump github/codeql-action from 3.26.3 to 3.26.4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.3 to 3.26.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/883d8588e56d1753a8a58c1c86e88976f0c23449...f0f3afee809481da311ca3a6ff1ff51d81dbeb24)

---
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>
2024-08-22 12:22:35 +02:00
dependabot[bot] 8e02fb36e9 Bump org.apache.maven.plugins:maven-help-plugin from 3.4.1 to 3.5.0
Bumps [org.apache.maven.plugins:maven-help-plugin](https://github.com/apache/maven-help-plugin) from 3.4.1 to 3.5.0.
- [Commits](https://github.com/apache/maven-help-plugin/compare/maven-help-plugin-3.4.1...maven-help-plugin-3.5.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>
2024-08-22 12:22:07 +02:00
dependabot[bot] 88a2e226ca Bump org.apache.maven.plugins:maven-deploy-plugin from 3.1.2 to 3.1.3
Bumps [org.apache.maven.plugins:maven-deploy-plugin](https://github.com/apache/maven-deploy-plugin) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/apache/maven-deploy-plugin/releases)
- [Commits](https://github.com/apache/maven-deploy-plugin/compare/maven-deploy-plugin-3.1.2...maven-deploy-plugin-3.1.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-20 11:22:24 +02:00
dependabot[bot] 203ad0258f Bump github/codeql-action from 3.26.2 to 3.26.3 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.2 to 3.26.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/429e1977040da7a23b6822b13c129cd1ba93dbb2...883d8588e56d1753a8a58c1c86e88976f0c23449)

---
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>
2024-08-20 11:21:57 +02:00
dependabot[bot] 2a1ecf80fa Bump org.apache.maven.plugins:maven-surefire-plugin from 3.3.1 to 3.4.0
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.3.1 to 3.4.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.4.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>
2024-08-19 10:54:59 +02:00
dependabot[bot] 4239ce5e31 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.3.1 to 3.4.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.4.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>
2024-08-19 10:54:47 +02:00
dependabot[bot] 61ca2fc3e0 Bump github/codeql-action from 3.26.1 to 3.26.2 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.1 to 3.26.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/29d86d22a34ea372b1bbf3b2dced2e25ca6b3384...429e1977040da7a23b6822b13c129cd1ba93dbb2)

---
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>
2024-08-15 11:23:24 +02:00
dependabot[bot] 9e502899ac Bump github/codeql-action from 3.26.0 to 3.26.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.0 to 3.26.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/eb055d739abdc2e8de2e5f4ba1a8b246daa779aa...29d86d22a34ea372b1bbf3b2dced2e25ca6b3384)

---
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>
2024-08-14 10:24:25 +02:00
dependabot[bot] 16fd8d1453 Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.4 to 3.2.5
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.4 to 3.2.5.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.4...maven-gpg-plugin-3.2.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-13 10:29:47 +02:00
dependabot[bot] 81ae64b65c Bump actions/upload-artifact from 4.3.5 to 4.3.6 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.5 to 4.3.6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/89ef406dd8d7e03cfd12d9e0a4a378f454709029...834a144ee995460fba8ed112a2fc961b36a5ec5a)

---
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>
2024-08-07 11:55:36 +02:00
dependabot[bot] b0d5480445 Bump github/codeql-action from 3.25.15 to 3.26.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.15 to 3.26.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/afb54ba388a7dca6ecae48f608c4ff05ff4cc77a...eb055d739abdc2e8de2e5f4ba1a8b246daa779aa)

---
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>
2024-08-07 11:55:14 +02:00
Harald Kuhr 9e989680c6 Made SubImageOutputStream class final + fixed doc 2024-08-06 15:40:51 +02:00
dependabot[bot] dd174c7f7e Bump actions/setup-java from 4.2.1 to 4.2.2 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/99b8673ff64fbf99d8d325f52d9a5bdedb8483e9...6a0805fcefea3d4657a47ac4c165951e33482018)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-06 10:35:38 +02:00
dependabot[bot] 72ef50b677 Bump org.hamcrest:hamcrest from 2.2 to 3.0
Bumps [org.hamcrest:hamcrest](https://github.com/hamcrest/JavaHamcrest) from 2.2 to 3.0.
- [Release notes](https://github.com/hamcrest/JavaHamcrest/releases)
- [Changelog](https://github.com/hamcrest/JavaHamcrest/blob/master/CHANGES.md)
- [Commits](https://github.com/hamcrest/JavaHamcrest/compare/v2.2...v3.0)

---
updated-dependencies:
- dependency-name: org.hamcrest:hamcrest
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 10:48:01 +02:00
dependabot[bot] a7349278b2 Bump actions/upload-artifact from 4.3.4 to 4.3.5 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.4 to 4.3.5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/0b2256b8c012f0828dc542b3febcab082c67f72b...89ef406dd8d7e03cfd12d9e0a4a378f454709029)

---
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>
2024-08-05 10:33:50 +02:00
dependabot[bot] 858f519f0b Bump github/codeql-action from 3.25.14 to 3.25.15 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.14 to 3.25.15.
- [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/5cf07d8b700b67e235fbb65cbc84f69c0cf10464...afb54ba388a7dca6ecae48f608c4ff05ff4cc77a)

---
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>
2024-07-29 10:53:59 +02:00
dependabot[bot] d797ff0bb3 Bump ossf/scorecard-action from 2.3.3 to 2.4.0 in /.github/workflows
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.3.3 to 2.4.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/dc50aa9510b46c811795eb24b2f1ba02a914e534...62b2cac7ed8198b15735ed49ab1e5cf35480ba46)

---
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>
2024-07-29 10:53:29 +02:00
dependabot[bot] fef4c4dd7a Bump github/codeql-action from 3.25.13 to 3.25.14 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.13 to 3.25.14.
- [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/2d790406f505036ef40ecba973cc774a50395aac...5cf07d8b700b67e235fbb65cbc84f69c0cf10464)

---
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>
2024-07-26 10:31:22 +02:00
dependabot[bot] a99762b5de Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.7.0 to 3.8.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.7.0...maven-javadoc-plugin-3.8.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>
2024-07-22 11:47:05 +02:00
dependabot[bot] c7d0c902db Bump github/codeql-action from 3.25.12 to 3.25.13 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.12 to 3.25.13.
- [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/4fa2a7953630fd2f3fb380f21be14ede0169dd4f...2d790406f505036ef40ecba973cc774a50395aac)

---
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>
2024-07-22 11:46:43 +02:00
dependabot[bot] e8e2026d48 Bump github/codeql-action from 3.25.11 to 3.25.12 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.11 to 3.25.12.
- [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/b611370bb5703a7efb587f9d136a52ea24c5c38c...4fa2a7953630fd2f3fb380f21be14ede0169dd4f)

---
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>
2024-07-15 10:48:54 +02:00
dependabot[bot] f1dc50c276 Bump org.apache.maven.plugins:maven-release-plugin from 3.1.0 to 3.1.1
Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.1.0...maven-release-3.1.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>
2024-07-15 10:48:32 +02:00
dependabot[bot] 0e615192e7 Bump org.apache.maven.plugins:maven-pmd-plugin from 3.23.0 to 3.24.0
Bumps [org.apache.maven.plugins:maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.23.0 to 3.24.0.
- [Release notes](https://github.com/apache/maven-pmd-plugin/releases)
- [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.23.0...maven-pmd-plugin-3.24.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>
2024-07-15 10:48:07 +02:00
dependabot[bot] d9b82f80ef 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.3.0 to 3.3.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.0...surefire-3.3.1)

---
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>
2024-07-11 11:03:41 +02:00
dependabot[bot] 41f316e621 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.3.0 to 3.3.1
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.0...surefire-3.3.1)

---
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>
2024-07-11 11:03:25 +02:00
dependabot[bot] 5f2b0c0ccf Bump actions/upload-artifact from 4.3.3 to 4.3.4 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.3 to 4.3.4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/65462800fd760344b1a7b4382951275a0abb4808...0b2256b8c012f0828dc542b3febcab082c67f72b)

---
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>
2024-07-08 11:03:51 +02:00
Harald Kuhr ee7d4ba724 #975: Fix for broken decoding gray + extra samples 2024-07-05 15:42:49 +02:00
Harald Kuhr f7d4557c57 #972: Fix for AAIOBE in decodeDeltaBytes 2024-07-02 21:47:05 +02:00
dependabot[bot] 20d8c34dae Bump github/codeql-action from 3.25.10 to 3.25.11 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.10 to 3.25.11.
- [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/23acc5c183826b7a8a97bce3cecc52db901f8251...b611370bb5703a7efb587f9d136a52ea24c5c38c)

---
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>
2024-07-01 11:12:18 +02:00
dependabot[bot] eaee82f3e7 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/eb1a2b2dbd4c45341235503b2c3edfa46d2ec3de...db71d41eb79864e25ab0337e395c352e84523afe)

---
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>
2024-06-24 11:45:09 +02:00
dependabot[bot] a0d87ec6d8 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.2.2 to 4.3.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/ac30be7acb0a361e5492575ab42e47fcadec4928...eb1a2b2dbd4c45341235503b2c3edfa46d2ec3de)

---
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>
2024-06-21 11:28:23 +02:00
dependabot[bot] ac5d4a02a9 Bump org.apache.maven.plugins:maven-jar-plugin from 3.4.1 to 3.4.2
Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.4.1 to 3.4.2.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.1...maven-jar-plugin-3.4.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-20 10:27:37 +02:00
dependabot[bot] a26932cd70 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.5 to 3.3.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.5...surefire-3.3.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>
2024-06-17 10:40:13 +02:00
dependabot[bot] 7b8e5433dd Bump org.apache.maven.plugins:maven-release-plugin from 3.0.1 to 3.1.0
Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.0.1 to 3.1.0.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.1...maven-release-3.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 10:39:58 +02:00
dependabot[bot] 1471af3e68 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.5 to 3.3.0
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.5 to 3.3.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.5...surefire-3.3.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>
2024-06-17 10:39:48 +02:00
dependabot[bot] 4f0dd84cf6 Bump github/codeql-action from 3.25.9 to 3.25.10 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.9 to 3.25.10.
- [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/530d4feaa9c62aaab2d250371e2061eb7a172363...23acc5c183826b7a8a97bce3cecc52db901f8251)

---
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>
2024-06-14 10:29:59 +02:00
Harald Kuhr 143e25c39c Fixed Deploy job needs clause, to also require jdk8 job success 2024-06-13 10:43:50 +02:00
dependabot[bot] 3d0ba82422 Bump github/codeql-action from 3.25.8 to 3.25.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.8 to 3.25.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/2e230e8fe0ad3a14a340ad0815ddb96d599d2aff...530d4feaa9c62aaab2d250371e2061eb7a172363)

---
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>
2024-06-13 10:33:43 +02:00
dependabot[bot] 34f626914a Bump actions/checkout from 4.1.6 to 4.1.7 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7.
- [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/a5ac7e51b41094c92402da3b24376905380afc29...692973e3d937129bcbf40652eb9f2f61becf3332)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-13 10:33:15 +02:00
dependabot[bot] d6587ad292 Bump org.apache.maven.plugins:maven-pmd-plugin from 3.22.0 to 3.23.0
Bumps [org.apache.maven.plugins:maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.22.0 to 3.23.0.
- [Release notes](https://github.com/apache/maven-pmd-plugin/releases)
- [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.22.0...maven-pmd-plugin-3.23.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>
2024-06-12 11:01:22 +02:00
Harald Kuhr 46eaa72a13 Typo in POM description. 2024-06-09 13:05:54 +02:00
Harald Kuhr b3d48bdc50 [maven-release-plugin] prepare for next development iteration 2024-06-08 14:12:14 +02:00
Harald Kuhr 981d2da1e6 [maven-release-plugin] prepare release twelvemonkeys-3.11.0 2024-06-08 14:12:10 +02:00
dependabot[bot] cf40b5f4a0 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.1 to 3.4.0.
- [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.1...maven-checkstyle-plugin-3.4.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>
2024-06-06 11:00:03 +02:00
dependabot[bot] 34128c66a4 Bump org.apache.maven.plugins:maven-help-plugin from 3.4.0 to 3.4.1
Bumps [org.apache.maven.plugins:maven-help-plugin](https://github.com/apache/maven-help-plugin) from 3.4.0 to 3.4.1.
- [Commits](https://github.com/apache/maven-help-plugin/compare/maven-help-plugin-3.4.0...maven-help-plugin-3.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-06 10:59:18 +02:00
dependabot[bot] 1aa02477a7 Bump github/codeql-action from 3.25.7 to 3.25.8 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.7 to 3.25.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/f079b8493333aace61c81488f8bd40919487bd9f...2e230e8fe0ad3a14a340ad0815ddb96d599d2aff)

---
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>
2024-06-05 11:40:34 +02:00
Harald Kuhr fa49dd93a7 #955: PSD: Fix overflow issue found in GIMP PSD 2024-06-04 22:52:03 +02:00
dependabot[bot] 83cff35076 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.3 to 3.6.0
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.3 to 3.6.0.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.3...maven-shade-plugin-3.6.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>
2024-06-03 11:52:51 +02:00
dependabot[bot] 93e3ae5ef8 Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.3 to 3.7.0
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.3 to 3.7.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.3...maven-javadoc-plugin-3.7.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>
2024-06-03 11:52:31 +02:00
dependabot[bot] d8857c2997 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/9379f0ccddcab154835d4e2487555ee79614fe95...ac30be7acb0a361e5492575ab42e47fcadec4928)

---
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>
2024-05-31 11:12:36 +02:00
dependabot[bot] 7b119ce7dc Bump github/codeql-action from 3.25.6 to 3.25.7 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.6 to 3.25.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/9fdb3e49720b44c48891d036bb502feb25684276...f079b8493333aace61c81488f8bd40919487bd9f)

---
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>
2024-05-31 11:11:34 +02:00
Harald Kuhr 3e7ad05973 #948: TIFF 64 bit FP support 2024-05-28 20:18:54 +02:00
dependabot[bot] 1e574ca429 Bump org.sonatype.plugins:nexus-staging-maven-plugin
Bumps org.sonatype.plugins:nexus-staging-maven-plugin from 1.6.13 to 1.7.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-28 10:37:24 +02:00
dependabot[bot] dce193b113 ---
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>
2024-05-21 10:46:07 +02:00
dependabot[bot] 05517e1fed Bump actions/checkout from 4.1.5 to 4.1.6 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.5 to 4.1.6.
- [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/44c2b7a8a4ea60a981eaca3cf939b5f4305c123b...a5ac7e51b41094c92402da3b24376905380afc29)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-17 12:12:57 +02:00
dependabot[bot] d707793211 Bump github/codeql-action from 3.25.4 to 3.25.5 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.4 to 3.25.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/ccf74c947955fd1cf117aef6a0e4e66191ef6f61...b7cec7526559c32f1616476ff32d17ba4c59b2d6)

---
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>
2024-05-15 10:44:03 +02:00
dependabot[bot] 39cfeedc6b Bump ossf/scorecard-action from 2.3.1 to 2.3.3 in /.github/workflows
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.3.1 to 2.3.3.
- [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/0864cf19026789058feabb7e87baa5f140aac736...dc50aa9510b46c811795eb24b2f1ba02a914e534)

---
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>
2024-05-10 10:59:49 +02:00
dependabot[bot] 1dcbbc39e3 Bump github/codeql-action from 3.25.3 to 3.25.4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.3 to 3.25.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/d39d31e687223d841ef683f52467bd88e9b21c14...ccf74c947955fd1cf117aef6a0e4e66191ef6f61)

---
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>
2024-05-09 12:03:15 +02:00
dependabot[bot] c933dbf69f Bump actions/checkout from 4.1.4 to 4.1.5 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.4 to 4.1.5.
- [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/0ad4b8fadaa221de15dcec353f45205ec38ea70b...44c2b7a8a4ea60a981eaca3cf939b5f4305c123b)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-07 10:28:26 +02:00
dependabot[bot] 5fc7dc1963 Bump org.apache.maven.plugins:maven-deploy-plugin from 3.1.1 to 3.1.2
Bumps [org.apache.maven.plugins:maven-deploy-plugin](https://github.com/apache/maven-deploy-plugin) from 3.1.1 to 3.1.2.
- [Release notes](https://github.com/apache/maven-deploy-plugin/releases)
- [Commits](https://github.com/apache/maven-deploy-plugin/compare/maven-deploy-plugin-3.1.1...maven-deploy-plugin-3.1.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-29 10:16:03 +02:00
dependabot[bot] f42d5e0a32 Bump github/codeql-action from 3.25.2 to 3.25.3 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.2 to 3.25.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/8f596b4ae3cb3c588a5c46780b86dd53fef16c52...d39d31e687223d841ef683f52467bd88e9b21c14)

---
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>
2024-04-27 12:08:54 +02:00
Harald Kuhr d1c3a9bacb Re-adding matrix for JDK 8. 2024-04-27 12:00:15 +02:00
Harald Kuhr 21ad54b820 actions/setup-java no longer supports Java 8 on macos-latest (no Temurin JDK 8 build for M1) 2024-04-27 11:57:51 +02:00
dependabot[bot] e11fc63730 Bump actions/checkout from 4.1.3 to 4.1.4 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.3 to 4.1.4.
- [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/1d96c772d19495a3b5c517cd2bc0cb401ea0529f...0ad4b8fadaa221de15dcec353f45205ec38ea70b)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-25 11:08:40 +02:00
dependabot[bot] 2a70e744e0 Bump org.apache.maven.plugins:maven-pmd-plugin from 3.21.2 to 3.22.0
Bumps [org.apache.maven.plugins:maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.21.2 to 3.22.0.
- [Release notes](https://github.com/apache/maven-pmd-plugin/releases)
- [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.21.2...maven-pmd-plugin-3.22.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>
2024-04-25 11:03:57 +02:00
dependabot[bot] 60550ba8a8 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.2 to 3.5.3
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.2 to 3.5.3.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.2...maven-shade-plugin-3.5.3)

---
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>
2024-04-24 10:59:50 +02:00
dependabot[bot] d3b16cdd35 Bump actions/upload-artifact from 4.3.2 to 4.3.3 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.2 to 4.3.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/1746f4ab65b179e0ea60a494b83293b640dd5bba...65462800fd760344b1a7b4382951275a0abb4808)

---
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>
2024-04-23 10:52:09 +02:00
dependabot[bot] add7b06fa4 Bump github/codeql-action from 3.25.1 to 3.25.2 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.1 to 3.25.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/c7f9125735019aa87cfc361530512d50ea439c71...8f596b4ae3cb3c588a5c46780b86dd53fef16c52)

---
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>
2024-04-23 10:51:47 +02:00
dependabot[bot] b99391854d Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.3 to 3.2.4
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.3 to 3.2.4.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.3...maven-gpg-plugin-3.2.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-22 18:25:46 +02:00
dependabot[bot] a22188bd72 Bump org.apache.maven.plugins:maven-jar-plugin from 3.4.0 to 3.4.1
Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.4.0...maven-jar-plugin-3.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-22 18:24:56 +02:00
dependabot[bot] d5f5f295f5 Bump actions/checkout from 4.1.2 to 4.1.3 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.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/9bb56186c3b09b4f86b1c65136769dd318469633...1d96c772d19495a3b5c517cd2bc0cb401ea0529f)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-22 10:40:00 +02:00
dependabot[bot] d95de31908 Bump actions/upload-artifact from 4.3.1 to 4.3.2 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/5d5d22a31266ced268874388b861e4b58bb5c2f3...1746f4ab65b179e0ea60a494b83293b640dd5bba)

---
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>
2024-04-19 10:35:58 +02:00
dependabot[bot] 4fda5af141 Bump github/codeql-action from 3.25.0 to 3.25.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.0 to 3.25.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/df5a14dc28094dc936e103b37d749c6628682b60...c7f9125735019aa87cfc361530512d50ea439c71)

---
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>
2024-04-18 10:58:50 +02:00
dependabot[bot] b54827ae1b Bump github/codeql-action from 3.24.10 to 3.25.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.10 to 3.25.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/4355270be187e1b672a7a1c7c7bae5afdc1ab94a...df5a14dc28094dc936e103b37d749c6628682b60)

---
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>
2024-04-16 10:43:24 +02:00
dependabot[bot] 2762b9705a Bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.0
Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/apache/maven-jar-plugin/releases)
- [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 13:02:19 +02:00
dependabot[bot] 2d6248e293 Bump org.apache.maven.scm:maven-scm-provider-gitexe from 2.0.1 to 2.1.0
Bumps org.apache.maven.scm:maven-scm-provider-gitexe from 2.0.1 to 2.1.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 12:26:55 +02:00
dependabot[bot] 8a43e4539c Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.2 to 3.2.3
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.2...maven-gpg-plugin-3.2.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-11 10:47:20 +02:00
dependabot[bot] 8ecf203263 Bump commons-io:commons-io from 2.16.0 to 2.16.1
Bumps commons-io:commons-io from 2.16.0 to 2.16.1.

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-09 10:54:07 +02:00
dependabot[bot] 8e50af2804 Bump github/codeql-action from 3.24.9 to 3.24.10 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.9 to 3.24.10.
- [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/1b1aada464948af03b950897e5eb522f92603cc2...4355270be187e1b672a7a1c7c7bae5afdc1ab94a)

---
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>
2024-04-08 11:35:45 +02:00
dependabot[bot] 58e31aebd1 Bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1
Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.3.0 to 3.3.1.
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-05 11:46:11 +02:00
dependabot[bot] b8e3e7825c Bump commons-io:commons-io from 2.15.1 to 2.16.0
Bumps commons-io:commons-io from 2.15.1 to 2.16.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>
2024-03-29 14:22:03 +01:00
dependabot[bot] 155e9850fb Bump org.apache.maven.plugins:maven-gpg-plugin from 3.2.1 to 3.2.2
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.1...maven-gpg-plugin-3.2.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-26 10:23:02 +01:00
dependabot[bot] 0c4adf36ba Bump github/codeql-action from 3.24.8 to 3.24.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.8 to 3.24.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/05963f47d870e2cb19a537396c1f668a348c7d8f...1b1aada464948af03b950897e5eb522f92603cc2)

---
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>
2024-03-25 09:39:53 +01:00
dependabot[bot] fd32bc9089 Bump org.apache.maven.plugins:maven-gpg-plugin from 3.1.0 to 3.2.1
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.1.0 to 3.2.1.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.1.0...maven-gpg-plugin-3.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-19 10:31:02 +01:00
dependabot[bot] 6ad010dc44 Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.1 to 3.13.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.1...maven-compiler-plugin-3.13.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>
2024-03-19 10:30:39 +01:00
dependabot[bot] c9b14ea4af Bump github/codeql-action from 3.24.7 to 3.24.8 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.7 to 3.24.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/3ab4101902695724f9365a384f86c1074d94e18c...05963f47d870e2cb19a537396c1f668a348c7d8f)

---
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>
2024-03-19 10:30:04 +01:00
dependabot[bot] f162c873ed Bump actions/setup-java from 4.2.0 to 4.2.1 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/5896cecc08fd8a1fbdfaf517e29b571164b031f7...99b8673ff64fbf99d8d325f52d9a5bdedb8483e9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-15 09:47:52 +01:00
dependabot[bot] c21b971655 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.2.0 to 4.2.1.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/034100ce493a281e4915c3aecc842c6ba3b80cfc...9379f0ccddcab154835d4e2487555ee79614fe95)

---
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>
2024-03-15 09:47:29 +01:00
dependabot[bot] d1b0247055 Bump actions/setup-java from 4.1.0 to 4.2.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/9704b39bf258b59bc04b50fa2dd55e9ed76b47a8...5896cecc08fd8a1fbdfaf517e29b571164b031f7)

---
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>
2024-03-14 10:01:14 +01:00
dependabot[bot] 6d3605c080 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/5f47764eec0e1c1f19f40c8e60a5ba47e47015c5...034100ce493a281e4915c3aecc842c6ba3b80cfc)

---
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>
2024-03-14 10:00:35 +01:00
dependabot[bot] a188dcf9fd Bump github/codeql-action from 3.24.6 to 3.24.7 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.6 to 3.24.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/8a470fddafa5cbb6266ee11b37ef4d8aae19c571...3ab4101902695724f9365a384f86c1074d94e18c)

---
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>
2024-03-13 10:37:54 +01:00
dependabot[bot] 08938c6b4d Bump actions/checkout from 4.1.1 to 4.1.2 in /.github/workflows
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
- [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/b4ffde65f46336ab88eb53be808477a3936bae11...9bb56186c3b09b4f86b1c65136769dd318469633)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-13 10:36:23 +01:00
Harald Kuhr 016ef952ce Downgrade Maven GPG for now. 2024-03-11 10:41:46 +01:00
dependabot[bot] 2844c396c8 Bump org.apache.maven.plugins:maven-gpg-plugin from 3.1.0 to 3.2.0
Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/apache/maven-gpg-plugin/releases)
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.1.0...maven-gpg-plugin-3.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 10:25:31 +01:00
dependabot[bot] 2f95716b8a Bump github/codeql-action from 3.24.5 to 3.24.6 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.5 to 3.24.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/47b3d888fe66b639e431abf22ebca059152f1eea...8a470fddafa5cbb6266ee11b37ef4d8aae19c571)

---
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>
2024-03-01 09:28:21 +01:00
dependabot[bot] cf7fce647d Bump actions/setup-java from 4.0.0 to 4.1.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/387ac29b308b003ca37ba93a6cab5eb57c8f5f93...9704b39bf258b59bc04b50fa2dd55e9ed76b47a8)

---
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>
2024-02-28 10:06:10 +01:00
dependabot[bot] 4014ae4644 Bump github/codeql-action from 3.24.4 to 3.24.5 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.4 to 3.24.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/e2e140ad1441662206e8f97754b166877dfa1c73...47b3d888fe66b639e431abf22ebca059152f1eea)

---
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>
2024-02-26 10:00:14 +01:00
dependabot[bot] 4e46e81e3f Bump github/codeql-action from 3.24.3 to 3.24.4 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.3 to 3.24.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/379614612a29c9e28f31f39a59013eb8012a51f0...e2e140ad1441662206e8f97754b166877dfa1c73)

---
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>
2024-02-23 10:47:50 +01:00
dependabot[bot] ec43410fa6 Bump org.apache.maven.plugins:maven-shade-plugin from 3.5.1 to 3.5.2
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.1...maven-shade-plugin-3.5.2)

---
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>
2024-02-21 09:39:46 +01:00
dependabot[bot] 721fc5b5a5 Bump github/codeql-action from 3.24.1 to 3.24.3 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.1 to 3.24.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/e675ced7a7522a761fc9c8eb26682c8b27c42b2b...379614612a29c9e28f31f39a59013eb8012a51f0)

---
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>
2024-02-16 10:23:56 +01:00
dependabot[bot] 0c71981158 Bump github/codeql-action from 3.24.0 to 3.24.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.24.0 to 3.24.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/e8893c57a1f3a2b659b6b55564fdfdbbd2982911...e675ced7a7522a761fc9c8eb26682c8b27c42b2b)

---
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>
2024-02-14 10:19:19 +01:00
dependabot[bot] ac0ed5ed8f Bump actions/upload-artifact from 4.3.0 to 4.3.1 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/26f96dfa697d77e81fd5907df203aa23a56210a8...5d5d22a31266ced268874388b861e4b58bb5c2f3)

---
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>
2024-02-06 10:34:48 +01:00
dependabot[bot] d1b11ee1d1 Bump github/codeql-action from 3.23.2 to 3.24.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.23.2 to 3.24.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/b7bf0a3ed3ecfa44160715d7c442788f65f0f923...e8893c57a1f3a2b659b6b55564fdfdbbd2982911)

---
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>
2024-02-05 10:52:04 +01:00
Harald Kuhr 210eeccb39 Added section about Jakarta EE + minor improvements 2024-01-30 10:40:22 +01:00
dependabot[bot] e07e7c3685 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.0.4 to 4.1.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/b1b7f659602565970688b2e2588738b9398e895d...5f47764eec0e1c1f19f40c8e60a5ba47e47015c5)

---
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>
2024-01-30 10:11:58 +01:00
dependabot[bot] 611cb6cb4d Bump github/codeql-action from 3.23.1 to 3.23.2 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.23.1 to 3.23.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/0b21cf2492b6b02c465a3e5d7c473717ad7721ba...b7bf0a3ed3ecfa44160715d7c442788f65f0f923)

---
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>
2024-01-29 10:10:32 +01:00
dependabot[bot] 54d9feef94 Bump actions/upload-artifact from 4.2.0 to 4.3.0 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/694cdabd8bdb0f10b2cea11669e1bf5453eed0a6...26f96dfa697d77e81fd5907df203aa23a56210a8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-24 09:43:27 +01:00
dependabot[bot] 54b4ded602 Bump actions/upload-artifact from 4.1.0 to 4.2.0 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/1eb3cb2b3e0f29609092a73eb033bb759a334595...694cdabd8bdb0f10b2cea11669e1bf5453eed0a6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-19 09:45:39 +01:00
dependabot[bot] e360ed2a6a Bump github/codeql-action from 3.23.0 to 3.23.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.23.0 to 3.23.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/e5f05b81d5b6ff8cfa111c80c22c5fd02a384118...0b21cf2492b6b02c465a3e5d7c473717ad7721ba)

---
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>
2024-01-18 11:05:01 +01:00
dependabot[bot] 2325cef5a3 Bump actions/upload-artifact from 4.0.0 to 4.1.0 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/c7d193f32edcb7bfad88892161225aeda64e9392...1eb3cb2b3e0f29609092a73eb033bb759a334595)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 09:56:36 +01:00
dependabot[bot] 465eb09dd3 Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 4.0.3 to 4.0.4.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/0831a82caad2465c31c6dd929978f640cb42556c...b1b7f659602565970688b2e2588738b9398e895d)

---
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>
2024-01-12 10:43:02 +01:00
dependabot[bot] feae2a0f79 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.3 to 3.2.5
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.3 to 3.2.5.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.3...surefire-3.2.5)

---
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>
2024-01-10 10:02:50 +01:00
dependabot[bot] 860cb32a58 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.3 to 3.2.5.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.3...surefire-3.2.5)

---
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>
2024-01-10 10:02:15 +01:00
dependabot[bot] b9bd19b950 Bump github/codeql-action from 3.22.12 to 3.23.0 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.22.12 to 3.23.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/012739e5082ff0c22ca6d6ab32e07c36df03c4a4...e5f05b81d5b6ff8cfa111c80c22c5fd02a384118)

---
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>
2024-01-09 13:06:51 +01:00
Bertil Chapuis 3742e6ef08 Test against an array of float values 2024-01-05 15:52:22 +01:00
Bertil Chapuis 52aa582ccd Add a random test geotiff generated with qgis to improve 2024-01-05 15:52:22 +01:00
Bertil Chapuis adda52053b Add a unit test 2024-01-05 15:52:22 +01:00
Bertil Chapuis 6501321fac Wrap all invokations of normalizeColor and normalizeColorPlanar 2024-01-05 15:52:22 +01:00
Bertil Chapuis 57d9bfda59 Rename the flag and skip normalization completely 2024-01-05 15:52:22 +01:00
Bertil Chapuis 1226375ba6 Disable clamping when reading raw tiff data 2024-01-05 15:52:22 +01:00
dependabot[bot] 9c2d3058fd Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.12.0 to 3.12.1.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.12.0...maven-compiler-plugin-3.12.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-25 11:44:34 +01:00
dependabot[bot] e89cadd95f Bump github/codeql-action from 3.22.11 to 3.22.12 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.22.11 to 3.22.12.
- [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/b374143c1149a9115d881581d29b8390bbcbb59c...012739e5082ff0c22ca6d6ab32e07c36df03c4a4)

---
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-12-22 10:05:04 +01:00
dependabot[bot] 0ec299c2e6 Bump org.apache.maven.plugins:maven-compiler-plugin
Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.11.0 to 3.12.0.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.11.0...maven-compiler-plugin-3.12.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-12-19 10:09:51 +01:00
Harald Kuhr b91d02a562 #878: Now detects APP14/Adobe markers with full 2 byte version 2023-12-16 17:57:49 +01:00
dependabot[bot] 2b5f897841 Bump actions/upload-artifact from 3.1.3 to 4.0.0 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.3 to 4.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/a8a3f3ad30e3422c9c7b888a15615d19a852ae32...c7d193f32edcb7bfad88892161225aeda64e9392)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-15 10:15:14 +01:00
dependabot[bot] e65078bdb7 Bump org.apache.maven.plugins:maven-surefire-plugin from 3.2.2 to 3.2.3
Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.2...surefire-3.2.3)

---
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-12-14 09:42:46 +01:00
dependabot[bot] 36d8555172 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.2 to 3.2.3.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.2...surefire-3.2.3)

---
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-12-14 09:42:29 +01:00
dependabot[bot] 80e3170820 Bump github/codeql-action from 2.22.10 to 3.22.11 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.10 to 3.22.11.
- [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/305f6546310b9203e892c28c1484e82977f4f63d...b374143c1149a9115d881581d29b8390bbcbb59c)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-14 09:42:10 +01:00
dependabot[bot] 90bc04b030 Bump github/codeql-action from 2.22.9 to 2.22.10 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.9 to 2.22.10.
- [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/c0d1daa7f7e14667747d73a7dbbe8c074bc8bfe2...305f6546310b9203e892c28c1484e82977f4f63d)

---
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-12-13 09:44:27 +01:00
dependabot[bot] dcba9b0667 Bump github/codeql-action from 2.22.8 to 2.22.9 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.8 to 2.22.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/407ffafae6a767df3e0230c3df91b6443ae8df75...c0d1daa7f7e14667747d73a7dbbe8c074bc8bfe2)

---
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-12-08 10:00:17 +01:00
dependabot[bot] dc755c4c3c Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.6.2 to 3.6.3
Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.2 to 3.6.3.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.2...maven-javadoc-plugin-3.6.3)

---
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-12-04 14:05:03 +01:00
dependabot[bot] 6e4f1e0739 Bump actions/setup-java from 3.13.0 to 4.0.0 in /.github/workflows
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.13.0 to 4.0.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/0ab4596768b603586c0de567f2430c30f5b0d2b0...387ac29b308b003ca37ba93a6cab5eb57c8f5f93)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-30 10:53:47 +01:00
dependabot[bot] 7117cd1fd6 Bump commons-io:commons-io from 2.15.0 to 2.15.1
Bumps commons-io:commons-io from 2.15.0 to 2.15.1.

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-30 10:53:17 +01:00
dependabot[bot] 2b954c1067 Bump github/codeql-action from 2.22.7 to 2.22.8 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.7 to 2.22.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/66b90a5db151a8042fa97405c6cf843bbe433f7b...407ffafae6a767df3e0230c3df91b6443ae8df75)

---
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-11-24 10:07:23 +01:00
dependabot[bot] 77a1745106 Bump github/codeql-action from 2.22.6 to 2.22.7 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.6 to 2.22.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/689fdc5193eeb735ecb2e52e819e3382876f93f4...66b90a5db151a8042fa97405c6cf843bbe433f7b)

---
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-11-17 10:09:22 +01:00
Harald Kuhr 0378f504e7 #865 TIFF: Half decoding fix, now uses standard conversion. 2023-11-15 10:50:06 +01:00
dependabot[bot] 1d3a7fe812 Bump github/codeql-action from 2.22.5 to 2.22.6 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.5 to 2.22.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/74483a38d39275f33fcff5f35b679b5ca4a26a99...689fdc5193eeb735ecb2e52e819e3382876f93f4)

---
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-11-15 10:36:48 +01:00
Harald Kuhr 8715b6b696 Update examples to latest version. 2023-11-09 10:55:56 +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
Harald Kuhr 6581e2e2a1 [maven-release-plugin] prepare release twelvemonkeys-3.9.0 2022-10-15 12:12:49 +02:00
Harald Kuhr c2873b1f27 Minor test optimization... 2022-10-15 12:05:33 +02:00
Harald Kuhr 35f2f0be9f Revert "Replace Java 18 with 19 in build matrix."
This reverts commit a77b62b6ba.
2022-10-15 11:55:34 +02:00
Harald Kuhr b5856fd110 Revert "Update test to pass on JDK 19."
This reverts commit 081f2efea2.
2022-10-15 11:55:34 +02:00
Harald Kuhr 1919d77a45 Revert "Update test to pass on JDK 19."
This reverts commit 37afe24aac.
2022-10-15 11:55:34 +02:00
Harald Kuhr 37afe24aac Update test to pass on JDK 19. 2022-10-14 18:51:40 +02:00
Harald Kuhr 081f2efea2 Update test to pass on JDK 19. 2022-10-14 18:44:54 +02:00
Harald Kuhr 627bb1bf1f Update action versions. 2022-10-14 18:27:29 +02:00
Harald Kuhr a77b62b6ba Replace Java 18 with 19 in build matrix. 2022-10-14 18:22:50 +02:00
Harald Kuhr 2500d8cc15 #687 #691 Stream performance regressions... and JDK 17+ support :-P 2022-10-14 18:20:47 +02:00
Harald Kuhr c01336fb8a #687 #691 Stream performance regressions, now with JDK 11 support... 2022-10-14 18:16:18 +02:00
Harald Kuhr 6f9b9bee01 #687 #691 Stream performance regressions 2022-10-14 18:00:43 +02:00
Harald Kuhr b9b1a35408 Replaced Map.Entry with StandardImageMetadataSupport.TextEntry 2022-10-10 14:15:57 +02:00
Harald Kuhr 7ed5663633 More tests of StandardImageMetadataSupport + minor API changes 2022-10-08 14:28:10 +02:00
Harald Kuhr 6458fcdcbd Major ImageMetadata refactor for more consistent standard metadata support.
Fixes a few related bugs as a bonus.
2022-10-08 13:43:26 +02:00
Harald Kuhr 9375bfda9a #703: Workaround for 32 bit issue in ImageTypeSpecifier 2022-10-06 16:00:43 +02:00
Harald Kuhr 0160fb70f8 #702 Fix NPE while reading an WebP animation without alpha
+ bonus cleanup
2022-10-06 15:24:40 +02:00
Harald Kuhr 29dca0f124 Removed explicit version number for Apache Batik 2022-09-29 14:36:57 +02:00
Harald Kuhr c21f14efe1 Merge pull request #698 from KoenDG/batik_upgrade115
Batik has released version 1.15
2022-09-23 15:24:45 +02:00
Koen De Groote 81ba43e1e8 Batik has released version 1.15
Tickets fixed in this release: https://issues.apache.org/jira/browse/BATIK-1334?jql=project%20%3D%20BATIK%20AND%20status%20in%20(Resolved%2C%20Closed)%20AND%20fixVersion%20%3D%201.15%20ORDER%20BY%20affectedVersion%20DESC%2C%20priority%20DESC
2022-09-22 14:51:57 +02:00
Harald Kuhr a1fcfc3958 Fix WebP visibility issues. 2022-09-09 14:09:58 +02:00
Harald Kuhr c60116a611 Inserted license header + author tags for contributed WebP files. 2022-09-09 14:06:41 +02:00
Harald Kuhr 15e6ddc1fd Fix typo. :-) 2022-09-09 14:05:51 +02:00
Harald Kuhr 49f4e5401e Add JDK 18 to the build matrix. 2022-09-09 12:35:22 +02:00
Harald Kuhr e333c7d1b2 Merge pull request #696 from Simon04090/webp-lossless
WebP lossless
2022-09-09 08:43:48 +02:00
Simon Kammermeier cda34b704b Indicate support for lossless to ImageIO 2022-09-09 01:18:53 +02:00
Simon Kammermeier 7c4487be04 Add tests for lossless decoder 2022-09-09 01:18:53 +02:00
Simon Kammermeier 5a4525aaa1 Remove debug prints 2022-09-09 01:18:53 +02:00
Simon Kammermeier b766420e3e Parse ANIM metadata
Still need to expose them in image metadata
2022-09-09 01:18:53 +02:00
Simon Kammermeier c858454c5a Support ImageReadParam Settings limiting Raster size
On animation frames dimension has to be passed as it is not guaranteed
the same as in the file header.
2022-09-09 01:18:53 +02:00
Simon Kammermeier 67b48ce1e3 Implement decoding of compressed alpha chunks, alpha filtering 2022-09-09 01:18:53 +02:00
Simon Kammermeier 6608f61353 Fix starting to read at wrong offset, now skips header 2022-09-09 01:18:53 +02:00
Simon Kammermeier 326b98d5e5 Implement applying of the inverse transforms 2022-09-09 01:18:53 +02:00
Simon Kammermeier fafa58b718 Implement actual decoding including resolving backward refs and cache 2022-09-09 01:18:45 +02:00
Simon Kammermeier 0ed0246762 Implement Huffman Table parsing and decoding
Uses a 2 level table approach inspired by libwebp
2022-09-09 01:15:04 +02:00
Simon Kammermeier b3004a1227 Implement buffering in LSBBitReader
This optimizes away the constant re-reading of bytes.
Also allows peeking at coming bits without consuming them.
2022-09-09 01:15:04 +02:00
Simon Kammermeier 7ab627a754 Setup Huffman Table framework, decode meta groups 2022-09-09 01:14:36 +02:00
Simon Kammermeier 008e57a7ce Move helper methods to transforms needing them 2022-09-09 01:09:28 +02:00
Simon Kammermeier 28270b4d5b Objectify Transforms
Deduplicate code for parsing predictor and color transforms.
Add missing subtraction code removal on indexing transform.
2022-09-09 00:46:48 +02:00
Simon Kammermeier 7382151db8 Convert transforms list and colorCache to local variables
This is needed because on recursion new (empty) ones are necessary.
2022-09-09 00:10:33 +02:00
Simon Kammermeier b856ce07af Fix not using LSBBitReader 2022-09-09 00:04:41 +02:00
Harald Kuhr 190fe87ee9 DiscreteAlphaIndexColorModel num components fix 2022-08-19 16:38:45 +02:00
Harald Kuhr d1872ce94f #694: Fixed import order 2022-08-19 14:08:26 +02:00
Harald Kuhr a5c52a99b4 #694 BMP: Fixed subsampling for 24 bit/pixel case 2022-08-16 13:56:51 +02:00
Harald Kuhr 4170b393fa #684 Add some tolerance for JDK 8... 2022-06-10 17:48:20 +02:00
Harald Kuhr 53f9ba91e0 #684 Remove TODO as it's now fixed 2022-06-10 17:44:53 +02:00
Harald Kuhr be2d7d5f10 #684 Fix some render size issues in SVGImageReader
Bonus: Minor code clean-up.
2022-06-10 17:24:47 +02:00
Harald Kuhr 00aec2c90e Minor code clean-up for WMFImageReader 2022-06-10 17:01:55 +02:00
Harald Kuhr 2b04f7205c Minor optimizations. 2022-06-10 16:58:23 +02:00
Harald Kuhr 7d401d0194 #675 PSD 16/32 bit layer support pt2: Cross-platform test 2022-06-10 15:19:14 +02:00
Harald Kuhr 48691139a3 #675 PSD 16/32 bit layer support 2022-06-10 10:14:41 +02:00
Harald Kuhr bcb87c09d2 #681: Fix for little-endian "packed" USHORT types + rewritten stream handling 2022-06-03 19:23:50 +02:00
Harald Kuhr 84a8ceeb93 #683: Fix TIFF stripByteCounts computation for uncompressed data 2022-06-03 16:04:43 +02:00
Harald Kuhr 0cb99feedf A new ImageInputStream adapter for InputStream. 2022-06-01 22:00:37 +02:00
Harald Kuhr 91493c5145 #682 TIFF Lab w/alpha support 2022-06-01 19:30:01 +02:00
Harald Kuhr 6ddb799a95 Fix bad format in validator message. 2022-05-29 14:55:17 +02:00
Harald Kuhr 8a187f6657 TGAImageReader no longer reads single byte 0-terminator as Image Identification 2022-05-18 22:47:45 +02:00
Harald Kuhr b7d865f2cf #680 TGAImageReader now reads attribute bits with no extension area as alpha 2022-05-18 22:18:20 +02:00
Harald Kuhr d50fb1a51e Fix bug in 0-terminated ASCII string parsing + test. 2022-05-18 21:01:17 +02:00
Harald Kuhr 8992406f50 Documentation & details. 2022-05-18 20:31:28 +02:00
Harald Kuhr 44eebff62f #678, #679: TIFF read support for YCbCr Planar with or without subsampling 2022-05-12 23:01:12 +02:00
Harald Kuhr 8c85c4ca96 Simplified TIFF writing. 2022-05-06 19:49:06 +02:00
Harald Kuhr fa5c77bff0 Added test cases for EncoderStream/DecoderStream and fixed a bug
+ code clean-up to make IntelliJ happy :-)
2022-05-06 19:31:16 +02:00
Harald Kuhr d87b80deea PCX: Minor clean up 2022-05-06 19:27:44 +02:00
Harald Kuhr ae138c3b4e Write LONG8 offsets for BigTIFF 2022-05-05 15:53:20 +02:00
Harald Kuhr ab13fdd09d #677 Fixed integer overflow + added tests 2022-05-04 18:23:25 +02:00
Harald Kuhr aab5b062bd Fixed test typo. 2022-05-04 18:22:14 +02:00
Harald Kuhr 00d6acd1bf [skip ci] Fixed some typos in comments. :-) 2022-04-26 19:25:52 +02:00
Harald Kuhr 0f8a7ea482 Update feature_request.md 2022-04-25 16:58:39 +02:00
Harald Kuhr 9fe87fe10d #672: WebPImageReader now supports unknown stream lengths 2022-04-22 14:41:57 +02:00
Harald Kuhr a33dbaf897 Merge pull request #669 from haraldk/snyk-upgrade-a0c5c60996f8b405ed1deadc1666ddc0
[Snyk] Upgrade jmagick:jmagick from 6.2.4 to 6.6.9
2022-04-11 17:01:44 +02:00
Harald Kuhr 9e2f369459 #666 Clean-up: No alpha for RGB 3/components 2022-03-11 19:58:38 +01:00
Harald Kuhr d34b0b7fcf #666 Support for TIFF RGB 2/4 bit per sample. 2022-03-11 19:54:33 +01:00
snyk-bot 5effcb1344 fix: upgrade jmagick:jmagick from 6.2.4 to 6.6.9
Snyk has created this PR to upgrade jmagick:jmagick from 6.2.4 to 6.6.9.

See this package in Maven Repository:
https://mvnrepository.com/artifact/jmagick/jmagick/

See this project in Snyk:
https://app.snyk.io/org/haraldk/project/eca06326-94ac-456d-a029-f411089e7f16?utm_source=github&utm_medium=referral&page=upgrade-pr
2022-03-04 21:50:39 +00:00
Oliver Schmidtmer b67d687761 TIFFImageMetadata: ImageOrientation in mergeTree (#667)
TIFFImageMetadata: ImageOrientation in mergeTree
2022-02-28 15:53:49 +01:00
Harald Kuhr d0881c8b5c Attempt at adding JavaDocs + use "release" profile for release-plugin [skip ci] 2022-02-22 14:46:14 +01:00
Harald Kuhr 976928f48c Adding description to top-level POM [skip ci] 2022-02-22 13:19:49 +01:00
Harald Kuhr e1c2f2ee73 Thank you, Travis [skip ci] 2022-02-21 09:34:34 +01:00
Harald Kuhr 92632fa2a3 #661: JUnit test results take 4 2022-02-17 19:09:26 +01:00
Harald Kuhr 5a563e315f #661: JUnit test results take 3 2022-02-17 18:42:54 +01:00
Harald Kuhr c06d47d123 #661: JUnit test results take 2 2022-02-17 18:33:20 +01:00
Harald Kuhr fea6beb364 #661: JUnit test results 2022-02-17 18:32:18 +01:00
Harald Kuhr 4b951c06cc PNM: New attempt at making the new header parser work on Windows. 2022-02-14 22:00:04 +01:00
Harald Kuhr a3e6e52c95 PNM Windows issue. Temporary roll-back to working version. 2022-02-14 19:33:28 +01:00
Harald Kuhr 5347015cbd PNM clean-up: Avoid leading/trailing whitespace in comments. 2022-02-14 19:27:55 +01:00
Harald Kuhr 4d190892df PNM clean-up. 2022-02-09 20:13:49 +01:00
Harald Kuhr 60eab81709 #660: Attempt at making the comment parsing more Windows-friendly... 2022-02-08 11:19:38 +01:00
Harald Kuhr b400b6b157 #660: Make sure region is within bounds of new test image... 2022-02-08 10:38:53 +01:00
Harald Kuhr 499b3ef120 #660: Farewell, Lena 2022-02-08 10:16:42 +01:00
Harald Kuhr 92bc9c73f6 IFF: Simplified aspect. 2022-02-08 08:43:21 +01:00
Harald Kuhr 2a77558cac IFF: XS24 clean-up (again...) 2022-02-04 12:33:28 +01:00
Harald Kuhr 816cad60a8 IFF: XS24 clean-up 2022-02-04 12:23:44 +01:00
Harald Kuhr 7167f81c69 IFF: Thumbnail support for XS24 chunk (now without stderr output) 2022-02-04 12:13:53 +01:00
Harald Kuhr f5cfa0e619 IFF: Thumbnail support for XS24 chunk. 2022-02-04 11:46:32 +01:00
Harald Kuhr 73ad024833 IFF: Read support for TVPaint DEEP and TVPP
+ Bonus: Massive code clean-up/refactor.
2022-02-03 17:26:41 +01:00
Harald Kuhr 379449b621 IFF: More clean-up 2022-01-29 14:41:49 +01:00
Harald Kuhr e17faad6fb IFF: Read support for Impulse (Imagine, Turbo Silver) RGB8 format. 2022-01-28 16:36:34 +01:00
Harald Kuhr 1271a3d55e IFF clean-up. 2022-01-28 16:07:15 +01:00
Harald Kuhr 1cd594d113 RIP: Sandbox 2022-01-24 09:01:53 +01:00
Harald Kuhr b76f74e79a A little safer way to skip 6 bytes... 2022-01-19 09:00:13 +01:00
Harald Kuhr 78817a489b #658: TGAImageReader now allows extension area of size 0 2022-01-19 09:00:13 +01:00
Harald Kuhr b8f2a80ca6 #658: TGAImageReaderSpi now recognizes "true color" images with valid palette depth != 0 2022-01-19 09:00:13 +01:00
Oliver Schmidtmer ac8a36db1c findCompressionType always uses RLE if leading EOL is missing (#657)
Update of the last read byte is missing since the last update. So if only the first EOL is missing, further EOLs after the lines are not detected.
2022-01-15 00:21:47 +01:00
Harald Kuhr 7e0d8922da #655 Experimental force raster conversion switch. 2022-01-12 19:51:56 +01:00
Harald Kuhr 9a6b8c9bfe Fix for IIOInvalidTreeException: Invalid DHT node #559 2022-01-12 19:33:21 +01:00
Harald Kuhr eced5b8efd #656 Code clean-up + minor refactorings. 2022-01-12 19:11:52 +01:00
Oliver Schmidtmer 74611e4e52 Support writing ASCII array in TIFF metadata (#656)
* Support writing ASCII array in TIFF metadata

* corrected formatting and extracted string writing to method
2022-01-12 18:56:22 +01:00
Harald Kuhr b8614eca4d New CI badge + new maven badges, replaces #653 2022-01-12 18:45:14 +01:00
Harald Kuhr efd24456ac #636: Correct name for shaded artifact. 2022-01-05 15:47:16 +01:00
Gauthier 191b2371c8 add support for Github Actions, publish snapshots to OSSRH automatically (#633)
* remove oss-parent

* add github workflow

* use java 16 for now

* disable fail fast

* add java 15

* use only java 8 and 11 for now

* snapshot deploy

* snapshot deploy

* oracle jdk

* oracle jdk

* oracle jdk

* kcms matrix

* kcms job name

* only deploy for snapshots

* try not operator

* prepare PR

* restore groupId

* Fixed Travis link + bonus project summary updates

* Readme improvements

* #629: Preliminary WebP animation (ANIM/ANMF) support

* #629: Fixed build

* Make tests pass on JDK 16 and 17 (#635)

* make tests pass on JDK 16 and 17
replace deprecated mockito-all by mockito-core, and updated to latest 3.x
replace deprecated org.mockito.Matchers

* code cleanup from IDE suggestions

* add oracle jdk 16 and 17 to Travis

* test on java 17

* try to fix warning about maven-source-plugin

Co-authored-by: Harald Kuhr <harald.kuhr@gmail.com>
2022-01-05 12:34:52 +01:00
Harald Kuhr 33419ef291 #652: Avoid OOME for large values outside TIFF, even if length is unknown 2022-01-03 12:51:52 +01:00
Harald Kuhr 123f0bb7fc #648: (Re-)Added support for nested layer groups 2021-12-29 16:20:02 +01:00
Harald Kuhr 99b5f28a49 #648: Removed unnecessary parentheses. 2021-12-29 12:38:04 +01:00
Harald Kuhr b30fb4f8c3 #648: Simplified logic, code style fixes and clean up. 2021-12-28 16:49:41 +01:00
Jack Yun dc0bdcbd5b Support Group Layer in psd (#648) 2021-12-27 13:39:39 +01:00
Harald Kuhr 0cf29c167d Updated with latest versions. 2021-12-27 12:59:24 +01:00
Harald Kuhr 98e4b76206 #651: Fix ExtraSamplesColorModel equals + hashcode to behave nicely with ImageTypeSpecifier comparison. 2021-12-24 12:57:24 +01:00
Harald Kuhr aa4b5db054 Minor clean-up. 2021-12-24 12:27:10 +01:00
Harald Kuhr 433311c10d #651: Fix ExtraSamplesColorModel to create correct length elements array. 2021-12-24 12:25:31 +01:00
Harald Kuhr f50178bc78 Alternative fix for #650: Allow usage in OSGi environment. 2021-12-23 11:02:27 +01:00
Snyk bot e016e970e5 fix: upgrade commons-io:commons-io from 2.9.0 to 2.11.0 (#647)
Snyk has created this PR to upgrade commons-io:commons-io from 2.9.0 to 2.11.0.

See this package in Maven Repository:
https://mvnrepository.com/artifact/commons-io/commons-io/

See this project in Snyk:
https://app.snyk.io/org/haraldk/project/9a1f6304-68e0-49c5-af4f-db1f87bd4f90?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-12-16 08:46:44 +01:00
Harald Kuhr 4223d13898 Update jakarta servlet dependency classifier. 2021-12-15 18:34:03 +01:00
Harald Kuhr 444aeabf21 Overriding transitive dependency. 2021-12-15 16:58:27 +01:00
Harald Kuhr 05507a59d6 Getting rid of the dependencies too. 2021-12-15 16:29:38 +01:00
Harald Kuhr c4c89a0a25 Delete deprecated servlet classes 2021-12-15 16:23:08 +01:00
Harald Kuhr b0ad6b2a4b Delete deprecated Servlet classes 2021-12-14 19:35:13 +01:00
Harald Kuhr 25c703f4b2 #646: Spi now recognizes VP8 encoded images in VP8X ("extended format"). 2021-12-14 19:30:08 +01:00
Oleh Astappiev 529c59f93f Create jakartified package on build (#636)
* feat(servlet): create jakartified package on build

* feat(servlet): update README to include Jakarta classifier
2021-12-14 19:25:02 +01:00
Harald Kuhr 584b1d9b21 Updated with the latest versions. 2021-12-14 09:18:36 +01:00
Harald Kuhr 312ce364cc [maven-release-plugin] prepare for next development iteration 2021-12-12 13:17:20 +01:00
Harald Kuhr 7de8231471 [maven-release-plugin] prepare release twelvemonkeys-3.8.0 2021-12-12 13:17:16 +01:00
Harald Kuhr 0de9f79029 [maven-release-plugin] rollback the release of twelvemonkeys-3.8.0 2021-12-12 13:13:54 +01:00
Harald Kuhr eeb56acdde [maven-release-plugin] prepare for next development iteration 2021-12-11 23:26:21 +01:00
Harald Kuhr a6862cfec8 Fixed JavaDoc. 2021-12-11 23:23:05 +01:00
Harald Kuhr f8284700b4 #631 Attempt to fix tests for JDK 15 & 16 2021-12-11 22:38:42 +01:00
Harald Kuhr 38caeb22e0 #631 Introduced ColorProfiles. Profile activation through SPI to force early activation. 2021-12-11 18:58:25 +01:00
Harald Kuhr b2c5915db8 #631 New way of forcing profile activation + guarding all invocations of ICC_Profile.getInstance() 2021-12-11 18:13:07 +01:00
Harald Kuhr 3911191b04 #645 AAIOBE in CCITTFaxDecoderStream now wrapped in IOException 2021-12-11 17:48:57 +01:00
Snyk bot bc328419ac fix: upgrade commons-fileupload:commons-fileupload from 1.3.3 to 1.4 (#642)
Snyk has created this PR to upgrade commons-fileupload:commons-fileupload from 1.3.3 to 1.4.

See this package in Maven Repository:
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload/

See this project in Snyk:
https://app.snyk.io/org/haraldk/project/3eb50c00-e586-4f4c-a39c-90c80f89cc60?utm_source=github&utm_medium=referral&page=upgrade-pr
2021-12-10 16:13:29 +01:00
Harald Kuhr da4efe98bf Avoid fetching external resources in XMPReader. 2021-12-10 13:41:05 +01:00
Harald Kuhr 6653f4a85d Minor clean-up. 2021-12-10 13:33:28 +01:00
Harald Kuhr 511a29beb9 Minor AffineTransformOp clean-up + removed test output. 2021-10-29 11:05:24 +02:00
Gauthier 5617b4323c Make tests pass on JDK 16 and 17 (#635)
* make tests pass on JDK 16 and 17
replace deprecated mockito-all by mockito-core, and updated to latest 3.x
replace deprecated org.mockito.Matchers

* code cleanup from IDE suggestions

* add oracle jdk 16 and 17 to Travis
2021-10-26 18:38:33 +02:00
Harald Kuhr 16d0af357d #629: Fixed build 2021-10-15 16:04:53 +02:00
Harald Kuhr 74927d5396 #629: Preliminary WebP animation (ANIM/ANMF) support 2021-10-15 15:08:39 +02:00
Harald Kuhr 7e809dd834 Readme improvements 2021-10-15 14:48:39 +02:00
Harald Kuhr 7aa95a08bc Fixed Travis link + bonus project summary updates 2021-10-15 09:41:47 +02:00
Harald Kuhr c28963ae49 Minor servlet clean-up. 2021-09-21 14:23:59 +02:00
Harald Kuhr 0327f5fc1a Servlet deprecation 2021-09-21 14:22:16 +02:00
Harald Kuhr 1c59057c30 #628: Stabilized build + better dependency scopes and module names in interop modules 2021-09-17 20:32:25 +02:00
Harald Kuhr 3e1f85c4dc #626 Clean up + fill order support for all compression types 2021-09-17 19:37:28 +02:00
Harald Kuhr 11227a68a0 #628 TIFF metadata fix, now always outputs denominator for rationals.
+ Bonus: Added JAI TIFF interop module with test and other minor fixes.
2021-09-17 16:34:38 +02:00
Oliver Schmidtmer 62ba73a30e #626: Handle fillOrder in TIFFImageReader, not in CCITTFaxDecoderStream (#627) 2021-09-17 16:16:30 +02:00
Harald Kuhr 1f33afb5a1 Fixed NullPointerException due to missing PhotometricInterpretation, now uses fallback as we do when reading. 2021-09-16 22:56:13 +02:00
Harald Kuhr 9d3f271867 #626 TIFF CCITT detection only once per IFD 2021-09-16 22:25:06 +02:00
Harald Kuhr 812e12acb0 #623: TGAImageReader, PCXImageReader and SGIImageReader now return more standard image types as default, for better AffineTransformOp compatibility. Added tests.
Bonus: Subsampling fix for TGAImageReader and BMPImageReader.
2021-09-07 09:29:13 +02:00
Harald Kuhr 060b6cf852 #624: Added metadata support for 16 bit USHORT gray. 2021-09-07 09:24:27 +02:00
Koen De Groote e68ce7ffd1 Certain pixeldepth-16 TGA files fail to process, classcast exception (#624)
* Added fixed for monochrome tga16 bit. Uncertain if that description is complete.
Test files added. Without the changed code, the tests fail.

* Fix suggested by HaraldK

Co-authored-by: Koen De Groote <koen.degroote@limecraft.com>
2021-09-03 16:19:05 +02:00
Harald Kuhr 778cdef69c Fix typo in TIFFImageMetadataFormat mk II. 2021-08-31 22:34:47 +02:00
Harald Kuhr d46a76fca8 Fix typo in TIFFImageMetadataFormat. 2021-08-31 22:26:32 +02:00
Harald Kuhr 105a1ee466 #621 Don't add ICC profile for default gray images 2021-08-31 22:16:08 +02:00
Harald Kuhr aa030f526c #617 BigTIFF write clean-up. 2021-08-31 20:24:42 +02:00
Harald Kuhr 976e5d6210 #619: Fix WebP Y'CbCr->RGB conversion (now uses rec 601) 2021-08-26 16:47:51 +02:00
Harald Kuhr 6daca00fcd Minor clean-up. 2021-08-09 21:24:32 +02:00
Harald Kuhr ef05872934 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/tiff/TIFFWriter.java
2021-08-09 21:22:46 +02:00
Harald Kuhr 1ddab866fd #617 BigTIFF write support. 2021-08-09 21:11:40 +02:00
Harald Kuhr ce997a6951 Some more minor clean-up. 2021-08-06 10:10:34 +02:00
Harald Kuhr 23bf5cb7b2 Minor clean-up. 2021-08-06 09:59:07 +02:00
Harald Kuhr 564778f415 #616: Remove dependency on old xmlgraphics-commons (no longer needed) 2021-08-04 11:25:58 +02:00
Harald Kuhr e28bf8fb44 Fix WebP ICC handling for images with alpha. 2021-07-12 10:01:16 +02:00
Harald Kuhr cf8d630d01 Add WebP to BOM. 2021-07-12 09:38:20 +02:00
Harald Kuhr 0ff7224912 Switch build from travis.ci.org to com 2021-06-29 16:56:58 +02:00
Koen De Groote 196081a317 Documentation cleanup (#612)
* Added the `@Deprecated` tag to instances where is was mentioned in documentation, but not for the actual code itself.

Changed one documentation link pointing at a non-existing item.

* As per PR suggestion.
2021-06-29 13:06:07 +02:00
Harald Kuhr ff50180d86 #609 Fixed ICC Profile handling in WebP. 2021-06-03 21:31:54 +02:00
Harald Kuhr 8f2c482167 Minor code clean-up. 2021-06-03 18:21:00 +02:00
Harald Kuhr eab24890ca Merge pull request #608 from Schmidor/ccitt_eol_search
#579 Deeper EOL search in the CCITT stream
2021-05-31 10:40:20 +02:00
Oliver Schmidtmer cd42d81817 Invert EOF check 2021-05-28 14:38:44 +02:00
Oliver Schmidtmer ba5c667b6c #579 Deeper EOL search in the CCITT stream 2021-05-27 22:11:13 +02:00
Harald Kuhr 4e9fa9442c PR template update. 2021-05-13 15:15:09 +02:00
Harald Kuhr 4d2326c18d Update issue templates 2021-05-09 18:12:34 +02:00
Harald Kuhr 94eac2d6e5 XXX: Remove another old servlet class. 2021-05-09 18:08:56 +02:00
Harald Kuhr f63a33d541 HTTPS links in README.md 2021-05-09 18:08:43 +02:00
Harald Kuhr 00f8d87f36 PR template + rename issue template. 2021-05-09 18:08:16 +02:00
Harald Kuhr 4c2ab6da7b Update issue templates 2021-05-08 20:41:13 +02:00
Harald Kuhr b5088312e2 Update issue templates 2021-05-07 19:39:41 +02:00
Harald Kuhr f04f968f12 Update issue templates 2021-05-07 19:35:02 +02:00
Harald Kuhr 8896092e31 Update issue templates 2021-05-07 19:29:52 +02:00
Harald Kuhr 2f9768a1d4 XXX: Remove old servlet class. 2021-05-06 00:14:21 +02:00
Harald Kuhr 06bcf22242 #483 Minor optimization 2021-05-06 00:12:19 +02:00
Harald Kuhr 20c7f8e60e #483 Add license headers. 2021-05-06 00:08:27 +02:00
Harald Kuhr 15a9ad0a9b #483 Initial PSD Write support 2021-05-06 00:01:54 +02:00
Harald Kuhr 7ae2d636dc Merge pull request #607 from haraldk/snyk-upgrade-b72dc0a35c77c27ccf914333993bfcb1
[Snyk] Upgrade com.github.jai-imageio:jai-imageio-core from 1.3.0 to 1.4.0
2021-04-30 08:45:03 +02:00
snyk-bot 12e756b23c fix: upgrade com.github.jai-imageio:jai-imageio-core from 1.3.0 to 1.4.0
Snyk has created this PR to upgrade com.github.jai-imageio:jai-imageio-core from 1.3.0 to 1.4.0.

See this package in Maven Repository:
https://mvnrepository.com/artifact/com.github.jai-imageio/jai-imageio-core/

See this project in Snyk:
https://app.snyk.io/org/haraldk/project/33153897-db54-44bf-a11a-efd834cecdae?utm_source=github&utm_medium=upgrade-pr
2021-04-30 00:42:19 +00:00
Harald Kuhr 4e2bf131d2 #606: Fix bug introduced by more aggressive readDirect. 2021-04-29 20:06:36 +02:00
Harald Kuhr d0c4a07556 #606: Workaround for broken JDK WBMPImageReader 2021-04-29 16:55:24 +02:00
Harald Kuhr 21059c8d5a Cleaner tests for Java 6 or later... A little late. :-) 2021-04-29 16:46:16 +02:00
Harald Kuhr fa7b530809 Adding GitHub sponsors link. 2021-04-28 14:21:37 +02:00
Harald Kuhr 790cf3b32e Test clean-up. 2021-04-26 22:42:44 +02:00
Harald Kuhr b1baaad23b Rename file, add missing file extension. 2021-04-25 19:55:33 +02:00
Harald Kuhr 7fa704ace5 Bump plugins and stop deploying useless (internal) artifacts. 2021-04-24 19:26:32 +02:00
Harald Kuhr 8d07f4fe90 Updated versions to 3.7.0. 2021-04-24 13:20:40 +02:00
Harald Kuhr 32bba6857b [maven-release-plugin] prepare for next development iteration 2021-04-24 12:31:07 +02:00
Harald Kuhr ab7b08dfa9 [maven-release-plugin] prepare release twelvemonkeys-3.7.0 2021-04-24 12:31:00 +02:00
Harald Kuhr e0d6fa0d84 Better JPMS automatic module names. 2021-04-24 12:26:36 +02:00
Harald Kuhr 51bdd370da Fix some JavaDoc issues that broke the release build... 2021-04-24 12:05:49 +02:00
Harald Kuhr ee2be3f88f [maven-release-plugin] rollback the release of twelvemonkeys-3.7.0 2021-04-24 11:24:15 +02:00
Harald Kuhr c5511833cc Fix SemVer issue. 2021-04-24 11:12:09 +02:00
Harald Kuhr 6ac8a5d8b4 Minor optimization for standard case with only one image. 2021-04-20 22:41:41 +02:00
Harald Kuhr 3f7cb24407 #395 Removed WebP lossless and extended format (until it's implemented). 2021-04-15 19:24:52 +02:00
Harald Kuhr 8bf9f7a8f0 Minor clean-up. 2021-04-10 18:25:27 +02:00
Harald Kuhr 03ab9558a0 #573: And error message. 2021-04-10 18:17:34 +02:00
Harald Kuhr 715bde8358 Comment too. 2021-04-10 18:17:01 +02:00
Harald Kuhr 0151efb5f6 #573: License headers too. 2021-04-10 18:15:27 +02:00
Harald Kuhr bd796429c5 #573: Better naming: LuminanceToGray 2021-04-10 18:14:09 +02:00
Harald Kuhr b4ef5823f3 #417: Half precision support (clean-up) 2021-04-10 18:13:04 +02:00
Harald Kuhr 9adf0f4da3 #417: Half precision support (clean-up) 2021-04-10 14:17:38 +02:00
Harald Kuhr 01a4e55185 Merge pull request #602 from haraldk/webp
We have Webp
2021-04-10 12:10:45 +02:00
Harald Kuhr 2e2ab11091 Merge branch 'master' into webp 2021-04-10 11:46:28 +02:00
Harald Kuhr 419ffc9373 #573: Always return RAWImageType for JPEG.
+ Bonus: Fix luma to gray conversion
2021-04-10 11:44:09 +02:00
Harald Kuhr b67975eef7 Better naming. 2021-04-09 17:19:15 +02:00
Harald Kuhr b32a861b2d #443 Automatic-Module-Name in each JARs MANIFEST.MF 2021-04-09 16:56:26 +02:00
Harald Kuhr 6930168c93 #362: JPEG metadata names in ProviderInfo. 2021-04-08 19:37:03 +02:00
Harald Kuhr fac9f1a927 #532 Write TGA with RLE compression. 2021-04-08 19:31:25 +02:00
Harald Kuhr 913a03608c #600 TimeoutMap now longer gets Long.MAX_VALUE as next expiry time if map is empty when removeExpiredEntries() is invoked. 2021-04-07 22:31:13 +02:00
Harald Kuhr 46ce99e10f Added links to metadata formats. 2021-04-07 13:21:31 +02:00
Harald Kuhr 3e4460ac41 Removed TODO (that has been done for some time). 2021-03-30 17:13:00 +02:00
Harald Kuhr 5b7fc25520 #584 Fix "No SOF segment in stream" for JPEG in TIFF
+ interoperability testing for JEP-262, JAI and JDK readers.
2021-03-30 16:26:48 +02:00
Harald Kuhr 42196e8513 No longer unregister the old Apple provided spi. 2021-03-30 12:31:56 +02:00
Harald Kuhr bc07524e7a Simplified/optimized TIFF file recognition code. 2021-03-30 11:31:34 +02:00
Harald Kuhr 0011b9a480 #417: TIFF 16 bit FP 2021-03-29 10:26:47 +02:00
Harald Kuhr 7b09ec8919 Merge branch 'master' into webp 2021-03-27 15:29:23 +01:00
Harald Kuhr 9c8977062d #554, #416: Relaxed custom metadata restrictions. 2021-03-27 15:20:59 +01:00
Harald Kuhr b01b820ec8 Remove unintended debug output. 2021-03-27 15:19:15 +01:00
Harald Kuhr b61f2c179c Merge branch 'master' into webp 2021-03-27 14:44:23 +01:00
Harald Kuhr 967f8e6984 PICT metadata + PNTG support 2021-03-27 14:39:59 +01:00
Harald Kuhr bb650e5280 Easier subsampling with xSub == 1 as no-op 2021-03-27 14:37:33 +01:00
Harald Kuhr 3b34d6e7ce General clean-up 2021-03-27 14:37:11 +01:00
Harald Kuhr db782cfe9e Merge pull request #599 from Schmidor/svg_data_url
Allow embedded resource URLs if external resources are disabled
2021-03-26 17:26:19 +01:00
Oliver Schmidtmer 96223f9f9f Allow embedded resource URLs if external resources are disabled 2021-03-26 16:05:21 +01:00
Harald Kuhr da45c5783d Forgot we actually had PICT write support.. ;-) 2021-03-23 13:15:06 +01:00
Harald Kuhr 5b6c819ac4 JPEG Lossless in non-bold :-) 2021-03-08 21:42:38 +01:00
Harald Kuhr 6d41f2db86 Updated version numbers for latest release. 2021-03-08 14:54:26 +01:00
Harald Kuhr ba0bb7b903 #595 Avoid infinite loop on corrupted JPEG stream 2021-03-06 14:15:44 +01:00
Harald Kuhr d03dc28764 Readme updates, mentioning JPEG lossless and built-in support (closes #471). 2021-03-01 18:42:59 +01:00
Harald Kuhr 20a785ea5e Updated version numbers. 2021-02-26 19:36:49 +01:00
Harald Kuhr 0286fa4268 JPEG Exif/thumbnail refactoring pt II. 2021-02-26 18:27:58 +01:00
Harald Kuhr 85fb9e6af3 JPEG Exif/thumbnail refactoring 2021-02-26 17:13:16 +01:00
Harald Kuhr 97a8806bfb Better name for source y... 2021-02-26 17:13:16 +01:00
Harald Kuhr 970f4f3a7e #588 Clipping path from JPEG with multiple APP13 segments 2021-02-26 17:13:16 +01:00
Harald Kuhr 6d192968d1 Fix SGI source subsampling + test optimizations. 2021-02-26 17:13:16 +01:00
Harald Kuhr f5959af2e1 New stream SPIs now behave more like the built-in SPIs. 2021-02-26 17:13:16 +01:00
Harald Kuhr ea74ac2714 JPEG Exif/thumbnail fixes pt II. 2021-02-26 17:13:16 +01:00
Harald Kuhr 80c595cea8 No longer reads thumbnails, as part of the readWithOrientation method. 2021-02-26 17:13:16 +01:00
Harald Kuhr fbc738f2d4 JPEG Exif/thumbnail fixes. 2021-02-26 17:13:16 +01:00
Harald Kuhr 3e3acf3332 More standard key mapping, more correct fit size. Nicer color! 2021-02-26 17:13:16 +01:00
Harald Kuhr 0a77520d67 Merge pull request #591 from KoenDG/batik_upgrade
Upgraded the Apache Batik library from 1.12 to 1.14 due to fixed CVEs.
2021-02-25 14:22:56 +01:00
Koen De Groote 72cd3aade3 Upgraded the Apache Batik library from 1.12 to 1.14 due to fixed CVEs. 2021-02-24 14:54:46 +01:00
Harald Kuhr 88bd9cd2ba Update README.md
Removed JDK 7 from recommended build.
2021-02-04 19:47:45 +01:00
Harald Kuhr 5ee8678a29 Removed XWD plugin that will be in 3.7.
Fixed some incorrect code escaping.
2021-01-23 18:13:18 +01:00
Harald Kuhr fb1937ae63 Updated README with latest version numbers. 2021-01-23 17:53:28 +01:00
Harald Kuhr de02e3d7e0 #582: Fix for missing Exif thumbnail, now only issues warning. 2021-01-11 22:10:25 +01:00
Harald Kuhr ebaa69713f Deprecate for BufferedImageInputStream, now using buffered streams directly in all readers. 2021-01-11 22:07:31 +01:00
Harald Kuhr 8a1a90dafd Fix some corner cases in BufferedImageInputStream. 2021-01-11 21:44:14 +01:00
Harald Kuhr 6f6e65be12 Added zoom to fit option. 2021-01-11 21:18:11 +01:00
Harald Kuhr 253f04066b #579 More reliable CCITT compression type detection 2020-12-23 11:46:58 +01:00
Harald Kuhr 74902b3fb4 StandardCharsets.US_ASCII instead of Charset.forName("ascii") 2020-12-21 17:30:34 +01:00
Harald Kuhr af1a6492d4 #577 Fix TGA subsampling + bonus metadata fix and palette conversion. 2020-12-15 22:19:04 +01:00
Harald Kuhr 0da007ec8c Minor clean-up. 2020-12-11 18:32:02 +01:00
Harald Kuhr 9053fb3816 Minor clean-up. 2020-12-11 18:28:48 +01:00
Harald Kuhr c1d4e474f0 Fix source region reading in VP8Frame. 2020-12-09 09:24:19 +01:00
Harald Kuhr 6bac13eb84 Merge branch 'master' into webp 2020-12-07 17:05:17 +01:00
Harald Kuhr 0e48ddd306 #292 Add legacy CMM option only for JDK 8. 2020-12-03 10:15:26 +01:00
Harald Kuhr 8682decbbc #292 Remove legacy CMM option. 2020-12-03 09:33:08 +01:00
Harald Kuhr bb615b90bf Merge branch 'master' into webp 2020-12-03 08:47:53 +01:00
Harald Kuhr cb0c320b45 #292 Build on Java 8, 11 and 15. 2020-12-03 07:55:30 +01:00
Harald Kuhr 73044bea58 #292 Now builds on Java 8, 11 and 15. 2020-12-02 22:08:40 +01:00
Harald Kuhr 3bb312e9e1 WebP source subsampling. 2020-11-30 22:10:54 +01:00
Harald Kuhr c7d2f422b8 BufferedImageInputStream performance optimizations. 2020-11-30 17:54:21 +01:00
Harald Kuhr 4dedf76ebc WebP performance optimizations & clean up. 2020-11-30 17:10:35 +01:00
Harald Kuhr 2376d16ffd WebP initial commit 2020-11-23 09:34:34 +01:00
Harald Kuhr 1fe0bdd41f Updated code samples to use more modern try-with-resource syntax. 2020-11-23 08:58:43 +01:00
Harald Kuhr 1b4d25342f Minor readme tweaks. 2020-11-22 13:19:43 +01:00
Harald Kuhr bc391550fb Minor readme tweaks. 2020-11-22 13:18:22 +01:00
Harald Kuhr b563f573de Better input validation. 2020-11-21 20:49:21 +01:00
Harald Kuhr 25150b421c Updated links to latest version. 2020-11-21 15:28:51 +01:00
Harald Kuhr 94031a2913 Add XWD to BOM. 2020-11-21 15:26:39 +01:00
Harald Kuhr 64fb421b38 IFF format clean-up + standard metadata support 2020-11-21 15:23:18 +01:00
Harald Kuhr 78af95d747 Merge branch 'master' of github.com:haraldk/TwelveMonkeys 2020-11-19 21:24:23 +01:00
Harald Kuhr 1d4f681b8f #574 Better test data. 2020-11-19 20:59:12 +01:00
Harald Kuhr eda2cd76db #574 Fix for possible OOME in Exif metadata. 2020-11-19 20:42:10 +01:00
Harald Kuhr 4adc60a6c6 Some minor code clean-up. 2020-11-19 20:35:37 +01:00
Harald Kuhr 0d5577a9a4 #330 ImageReaderBase.getDestination now throws IIOException for too large dimension/size. 2020-11-17 23:07:09 +01:00
Harald Kuhr 918f92aba7 #330 Now correctly calculates scanline for 1 & 4 bits 2020-11-17 22:57:25 +01:00
Harald Kuhr 7a24d55be7 #330 Now correctly uses USHORT instead of SHORT for 16 bit DIB. 2020-11-17 22:40:23 +01:00
Harald Kuhr a84cc1c060 #330 Now guards against buffer overruns in RLE decoder. 2020-11-17 22:33:50 +01:00
Harald Kuhr 31cb79d2b9 #330 Minor improvements to avoid RuntimeExceptions. 2020-11-17 22:11:31 +01:00
Harald Kuhr d995e7baa0 Fixed Maven Central link URL to more relevant URL. 2020-11-17 09:15:19 +01:00
Harald Kuhr e7fe6d5c22 Fixed Maven Central link URL 2020-11-16 19:44:41 +01:00
Harald Kuhr 918b698e50 Release notes already on the Github page. 2020-11-16 19:42:47 +01:00
Harald Kuhr 2427b2323f ...and again. 2020-11-16 19:36:40 +01:00
Harald Kuhr 0a8222fea3 ...and again. 2020-11-16 19:36:06 +01:00
Harald Kuhr 60a00b89ae Fixed metadata support (not all formats have it yet). 2020-11-16 19:31:58 +01:00
Harald Kuhr 4c88efa19d Removed empty lines. Added missing BMP info. 2020-11-16 19:18:58 +01:00
Harald Kuhr 17d65a1f6f New & improved README with tables and link to Wiki! 2020-11-16 19:13:36 +01:00
Harald Kuhr fcd03eb903 Added PayPal donation link. Go use it! :-) 2020-11-13 18:29:15 +01:00
Harald Kuhr 4e69efce28 Now correctly uses Image*Input*Stream instead of ImageOutputStream... 2020-11-13 15:52:17 +01:00
Harald Kuhr 16caec4a22 ...and fix the broken test. 2020-10-28 18:48:16 +01:00
Harald Kuhr 08282ea09d Minor improvements and better test cases. 2020-10-28 17:07:59 +01:00
Harald Kuhr c04fed1aff Fixed URL now works, ideally should point to correct branch... 2020-10-28 17:07:59 +01:00
Harald Kuhr 97e788883a More standard way for getting vendor name and version info. 2020-10-28 17:07:59 +01:00
Harald Kuhr a16fce0749 Update README.md 2020-10-27 14:42:18 +01:00
Harald Kuhr 26e2fa0168 Fixed URL now works, ideally should point to correct branch... 2020-10-26 15:49:46 +01:00
Harald Kuhr 120deb3ad4 More standard way for getting vendor name and version info. 2020-10-26 15:40:38 +01:00
Harald Kuhr 0a9e2df5de NetBPM clean-up, fixes and better tests. 2020-10-23 19:25:54 +02:00
Harald Kuhr 6ffcb88872 Verify that RGB data is correct. 2020-10-16 18:21:40 +02:00
Harald Kuhr 960e764c7b Added test to verify how to write CMYK JPEG without ICC profile. 2020-10-16 18:19:08 +02:00
Harald Kuhr d88f27b251 Code clean-up. 2020-10-16 18:17:51 +02:00
Harald Kuhr e5b3e9755e Added missing tests. 2020-10-14 19:13:28 +02:00
Harald Kuhr 6c34fb211f ImageWriterAbstractTest refactorings. 2020-10-14 18:54:46 +02:00
Harald Kuhr 9fdbc3b1fc ImageReaderAbstractTest refactorings. 2020-10-14 17:06:35 +02:00
Harald Kuhr 622c6f40d4 Getting rid of more JUnit deprecation. 2020-10-13 19:29:58 +02:00
Harald Kuhr 107da17ca9 Dependabot broke my build... 2020-10-13 19:16:58 +02:00
Harald Kuhr f9871b73a3 Merge pull request #568 from haraldk/dependabot/maven/sandbox/junit-junit-4.13.1
Bump junit from 4.7 to 4.13.1 in /sandbox
2020-10-13 10:36:50 +02:00
Harald Kuhr 7605b646fe Merge pull request #567 from haraldk/dependabot/maven/common/junit-junit-4.13.1
Bump junit from 4.7 to 4.13.1 in /common
2020-10-13 10:36:37 +02:00
dependabot[bot] 19c62ac7da Bump junit from 4.7 to 4.13.1 in /sandbox
Bumps [junit](https://github.com/junit-team/junit4) from 4.7 to 4.13.1.
- [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.7...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-13 08:36:22 +00:00
Harald Kuhr a5e4412d1a Merge pull request #566 from haraldk/dependabot/maven/imageio/junit-junit-4.13.1
Bump junit from 4.7 to 4.13.1 in /imageio
2020-10-13 10:36:20 +02:00
Harald Kuhr 651246566a Merge pull request #564 from haraldk/dependabot/maven/servlet/junit-junit-4.13.1
Bump junit from 4.7 to 4.13.1 in /servlet
2020-10-13 10:36:00 +02:00
Harald Kuhr fe8f854b17 Merge pull request #565 from haraldk/dependabot/maven/contrib/junit-junit-4.13.1
Bump junit from 4.7 to 4.13.1 in /contrib
2020-10-13 10:35:47 +02:00
dependabot[bot] a4d20a4af4 Bump junit from 4.7 to 4.13.1 in /common
Bumps [junit](https://github.com/junit-team/junit4) from 4.7 to 4.13.1.
- [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.7...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-13 07:58:59 +00:00
dependabot[bot] 0643d5910a Bump junit from 4.7 to 4.13.1 in /imageio
Bumps [junit](https://github.com/junit-team/junit4) from 4.7 to 4.13.1.
- [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.7...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-13 07:58:58 +00:00
dependabot[bot] c78a456985 Bump junit from 4.7 to 4.13.1 in /contrib
Bumps [junit](https://github.com/junit-team/junit4) from 4.7 to 4.13.1.
- [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.7...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-13 07:49:27 +00:00
dependabot[bot] 27017576d3 Bump junit from 4.7 to 4.13.1 in /servlet
Bumps [junit](https://github.com/junit-team/junit4) from 4.7 to 4.13.1.
- [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.7...r4.13.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-13 07:39:02 +00:00
Harald Kuhr f1810be10a X Window dump support. 2020-10-07 19:50:00 +02:00
Harald Kuhr 021aba1a98 Better output when debugging readers. 2020-10-07 19:47:09 +02:00
Harald Kuhr a0b68adff3 Removed work in progress... 2020-10-02 09:58:34 +02:00
Harald Kuhr fa4586663c Fixed a minor dependency issue. All test-jar dependencies now has correct test scope. 2020-10-02 09:41:39 +02:00
Harald Kuhr 623d13a517 Better PFM support. 2020-09-25 19:35:55 +02:00
Harald Kuhr a7ebc1b52f Code clean-up. 2020-09-24 17:12:12 +02:00
Harald Kuhr f54f4370c0 Added PNMImageWriterTest 2020-09-24 17:11:19 +02:00
Harald Kuhr 5040e9fe8a Add missing tests. 2020-09-24 15:07:40 +02:00
Harald Kuhr fc72cd34a1 Minor language fix. 2020-09-24 09:54:14 +02:00
Harald Kuhr 6d71a3d306 Added section about re-packaging and Shade plugin. 2020-09-24 09:51:30 +02:00
Harald Kuhr 86f8cf52a5 Comment fix 2020-08-07 16:36:08 +02:00
Harald Kuhr bda6544a5f #556 PICTImageReaderSpi no longer claim to decode known formats 2020-08-07 16:31:29 +02:00
Harald Kuhr 49c7cd1979 #466 TGA extension size fix for 3ds max files 2020-08-07 11:24:55 +02:00
Harald Kuhr 9dae58d5a6 Code clean-up. 2020-08-07 08:49:37 +02:00
Harald Kuhr ed14b97199 Update readme to 3.6. 2020-07-10 23:51:15 +02:00
Harald Kuhr b94135a91c [maven-release-plugin] prepare for next development iteration 2020-07-10 22:49:24 +02:00
Harald Kuhr 7384118357 [maven-release-plugin] prepare release twelvemonkeys-3.6 2020-07-10 22:49:16 +02:00
Harald Kuhr 4d833a50e5 TIFF constants. 2020-07-10 22:41:47 +02:00
Harald Kuhr 57b0fdac0b Fix JPEG tests mk II. 2020-07-10 22:29:23 +02:00
Harald Kuhr e6bd94025f JPEG Metadata clean-up 2020-07-10 22:26:53 +02:00
Harald Kuhr 330a0414f0 Fix JPEG tests 2020-07-10 22:26:12 +02:00
Harald Kuhr 5cc201b46d JPEG Exif rotation in metadata + support 2020-07-10 22:05:46 +02:00
Harald Kuhr 7e55d7765d #550 Adobe path points now constrained to a more robust [-16...16] range 2020-07-10 19:29:50 +02:00
Harald Kuhr 8f942922fd #547 BMPImageWriterSpi now only claims to write TYPE_4BYTE_ABGR, and registers with low pri.
Better exception message for other image types.
2020-06-28 11:50:17 +02:00
Harald Kuhr db5635e844 #535: Detect incorrect compression in TIFF CCITT stream. 2020-06-16 21:54:16 +02:00
Harald Kuhr 8bc952ba66 #464/#465 Collection fixes for forward compatibility. 2020-04-15 16:03:12 +02:00
Harald Kuhr 96cb3a07f4 #525: Fix for negative arrays size in old style JPEG in TIFF. 2020-04-15 13:28:56 +02:00
Harald Kuhr cd6a6258b6 Formatting and proper comments 2020-04-15 12:26:41 +02:00
Harald Kuhr a0fa2c08ac Merge pull request #529 from actinium15/issue/526
#526 Preventing SSRF due to external resource refs in SVGs
2020-04-03 13:57:57 +02:00
Ashish Chopra 6642b1647a #526 Incorporating review comments
* moved the system-property-evaluation to static-block for more
  reliability
* updated impacted existing tests (which relied on external-resources) to
  leverage the new API
* set the value of system-property controlling external-resource-access
  to true in the test JVM for the sake of existing tests using
  SVGImageReader APIs not backed by SVRReadParams (.getWidth/.getHeight
  and such)
2020-03-30 18:29:34 +05:30
Ashish Chopra 5315caf830 #526 Fixed unnecessary 'overenginnering' in previous commit 🤦 2020-03-30 10:38:52 +05:30
Ashish Chopra 872523b0f0 #526 Incorporating review comments
* renaming accessors
* changing the default to disallow external resources
* introduced system-property for backwards compatibility
* honor system-property (if present) and SVGReadParams.isAllowExternalResources hasn't been called
  (as against ignoring system-property and reverting to 'block-by-default' if SVGReadParams.isAllowExternalResources invoked)
* added + updated test cases
2020-03-24 18:40:01 +05:30
Ashish Chopra 7bf99fb496 #526 Preventing SSRF due to external resource refs in SVGs 2020-02-25 11:26:16 +05:30
Harald Kuhr a1047edddb Merge pull request #522 from Schmidor/svg_size
#518 Parsing SVG width/height attributes
2020-01-31 15:50:24 +01:00
Oliver Schmidtmer e956176872 #518 Fallbacks for aspect ratio, if only one dimension is given 2020-01-30 18:40:11 +01:00
Oliver Schmidtmer 6d2947b080 #518 Parsing SVG width/height attributes 2020-01-30 15:54:59 +01:00
Harald Kuhr fb304d6c27 #520: Fix for incorrect serialization of single element arrays in metadata. 2020-01-29 20:58:34 +01:00
Harald Kuhr 903289caa4 Merge pull request #517 from KoenDG/small_cleanup
Minor code cleanup: Intellij suggested changes from static code analysis.
2020-01-29 09:38:57 +01:00
Koen De Groote aff31ebd1b Intellij suggested changes from static code analysis. 2020-01-28 16:18:07 +01:00
Harald Kuhr b6773f6983 Updated versions. 2020-01-22 22:43:42 +01:00
Harald Kuhr 0d28eb31d2 [maven-release-plugin] prepare for next development iteration 2020-01-22 21:47:25 +01:00
Harald Kuhr 4922ccf80b [maven-release-plugin] prepare release twelvemonkeys-3.5 2020-01-22 21:47:17 +01:00
Harald Kuhr f7ce772f84 Merge pull request #516 from haraldk/adobe-path-write
Adobe Path write support
2020-01-22 21:38:43 +01:00
Harald Kuhr 3d4bc0e69d #490: License. 2020-01-22 21:03:02 +01:00
Harald Kuhr c721291a78 #490: Last minute API changes... 2020-01-22 20:51:39 +01:00
Harald Kuhr 5f9ea2e7c2 #490: Doc. 2020-01-22 20:49:18 +01:00
Harald Kuhr c48af5acc7 #490: Minor API clean-up and documentation. 2020-01-22 20:35:41 +01:00
Harald Kuhr 8b86b57e63 #490: Fix for "incomplete" paths with implicit line back to start. 2020-01-22 20:06:30 +01:00
Harald Kuhr 420f78be88 #490: Fix for "incomplete" paths with implicit line back to start. 2020-01-17 16:44:42 +01:00
Harald Kuhr d2b58ed20e #490: Now allows writing using standard TIFF writer in Java 9+ 2020-01-17 16:43:27 +01:00
Harald Kuhr 278ce6ef33 #490: Now allows writing paths in TIFF and JPEG. 2020-01-16 19:31:54 +01:00
Harald Kuhr 768bc30653 Merge branch 'master' into adobe-path-write 2020-01-15 15:11:31 +01:00
Harald Kuhr d9d8419803 #514: Fix integer overflow in stripbytecounts computation. 2020-01-14 21:18:13 +01:00
Harald Kuhr 7a9523690c Update LICENSE.txt 2020-01-14 20:40:38 +01:00
Harald Kuhr e5c6832ec0 #490: Allow writing more TIFF fields. 2020-01-13 21:05:04 +01:00
Harald Kuhr 167686bdea #490: Minor debug cleanup. 2020-01-09 21:28:37 +01:00
Harald Kuhr d3249dc3d5 #490: Refactorings. 2020-01-09 21:25:41 +01:00
Harald Kuhr 5c1f51f3ca #490: Fixed roundtrip tests and tuned collinearity threshold. 2020-01-09 21:23:20 +01:00
Harald Kuhr fde3a5c2ab Updated version numbers. 2020-01-09 20:24:22 +01:00
Harald Kuhr ae213dcf5e log4j removal 2020-01-09 19:18:15 +01:00
Harald Kuhr 51ace4ca7f #490: Refactorings, added initial detection of linked/unlinked segments, more tests. 2020-01-09 19:17:35 +01:00
Harald Kuhr f15bcc7df9 log4j removal 2020-01-07 13:44:40 +01:00
Harald Kuhr 6be86affd6 #490: Fixed tests 2020-01-02 15:32:06 +01:00
Harald Kuhr eec8268eb9 #490: Adobe Path PoC 2020-01-02 15:26:48 +01:00
Harald Kuhr 859b232f64 #490: Initial commit Adobe Path write. 2020-01-02 15:24:22 +01:00
Harald Kuhr 5501c0e709 #510: Fixes possible hang situation 2020-01-02 14:55:16 +01:00
Harald Kuhr 306d8ac5f6 Merge pull request #505 from KoenDG/intellij_performance_analysis
Changes suggested by Intellij in the category "Performance".
2019-11-04 08:43:22 +01:00
Koen De Groote d41f6a4465 Update BMPImageReader.java
Not using this change for now
2019-11-02 21:09:25 +01:00
Koen De Groote 8ed5f06151 Changes suggested by Intellij in the category "Performance".
Updated.
2019-10-22 11:51:24 +02:00
Harald Kuhr 42e17f2063 #501: Fix for TYPE_USHORT_555/565_RGB, ColorModel now 16 bits 2019-10-11 16:56:00 +02:00
Harald Kuhr f449a50d64 TIFF tile support. 2019-08-29 19:11:14 +02:00
Harald Kuhr 0c2433dc9f #289, #493: Finally implemented subsampling for < 8 bit samples 2019-08-29 19:11:14 +02:00
Harald Kuhr a5def1ba3d Merge pull request #495 from Schmidor/svg_rescale_viewbox
Svg scale by ViewBox
2019-08-22 19:59:07 +02:00
Oliver Schmidtmer 810b7197ab Test correction for ViewBox based svg sizes 2019-08-22 16:51:34 +02:00
Oliver Schmidtmer 24a0786d64 When rescaling SVGs use the ViewBox, if defined, for default sizes 2019-08-22 16:35:40 +02:00
Harald Kuhr c1ce4b066d Updated version numbers. 2019-08-12 21:54:15 +02:00
Harald Kuhr b6aec25f00 Stick to the git user, when using ssh 2019-08-12 21:12:17 +02:00
Harald Kuhr c1834dc78d Switched Maven SCM to use ssh. 2019-08-12 20:40:50 +02:00
Harald Kuhr 9e23413456 Fixed JavaDoc errors to enable Java 8 build. 2019-08-10 00:41:36 +02:00
Harald Kuhr 7d2c692663 Fixed encoding issues in readme. 2019-08-09 20:58:56 +02:00
Harald Kuhr 9ce1a86cae #398: Better exception message when BufferedImage size > Integer.MAX 2019-08-09 19:52:07 +02:00
Harald Kuhr b0b5de5fa4 #477: Better tests to for cyclic loops in IFDs. 2019-08-09 19:32:52 +02:00
Harald Kuhr 64178bd636 #474: Fix java.awt.color.CMMException: Can not access specified profile 2019-08-08 23:33:08 +02:00
Harald Kuhr 7985cdd4a7 449# Missing test to verify that we ignore bogus 0 byte counts. 2019-08-08 23:17:08 +02:00
Harald Kuhr 8247861095 #492: Now correctly parses multiple strings for ASCII fields. 2019-08-08 23:03:13 +02:00
Harald Kuhr 8480c929c1 #477: Avoid cyclic loops in IFDs. 2019-08-08 22:41:41 +02:00
Harald Kuhr e6f437f55b Moving travis build to trusty, to fix JDK8 build 2019-08-08 09:25:29 +02:00
Harald Kuhr ee049d9465 #488: Fix for AIOOBE in getEmbeddedICCProfile when ICC profile is empty 2019-08-07 16:18:01 +02:00
Harald Kuhr f6aa810f8b #489 Fix for Unexpected End of PackBits Stream for padded streams. 2019-08-07 16:04:46 +02:00
Harald Kuhr e8d1b999a2 #469 Fix for OOME while reading Exif with corrupted IFDs/counts 2019-08-07 15:55:24 +02:00
Harald Kuhr d7fbd6594e JPEG Exif parsing optimization. 2019-08-07 15:47:33 +02:00
Harald Kuhr caef9b6a9e XMLSerializer speedup. 2019-02-12 20:44:34 +01:00
Harald Kuhr 7fad4d5cd8 #475: Fix support for writing TIFF > 2 GB 2019-02-12 20:40:08 +01:00
Harald Kuhr 3e4b14f984 #473: Fix for ColorMap (Indexed) TIFF with non-alpha ExtraSamples. 2019-02-12 20:34:31 +01:00
Harald Kuhr 5ade293445 Merge pull request #458 from Schmidor/455
Fix for #455: Ignore profiles PhotometricInterpretation MinIsWhite wi…
2019-02-12 20:29:31 +01:00
Harald Kuhr a0fc5f560d Merge pull request #472 from paulvi/patch-2
colorize code snippets in README using GFM ```java, ```xml
2019-01-30 10:58:08 +01:00
Paul Verest 51b0734462 colorize code snippets in README using GFM ``java, ``xml 2019-01-28 15:31:42 +08:00
Harald Kuhr 8e3cd5aedb Updated commons-fileupload dependency to safe version, even if in scope provided, just in case. 2019-01-08 21:47:05 +01:00
Oliver Schmidtmer cbaa0dc688 Fix for #455: Ignore profiles PhotometricInterpretation MinIsWhite with 1bit/pixel 2018-11-22 12:20:58 +01:00
Harald Kuhr 61bac97933 Fix test case for #446 in case of "Gerenic CMYK" profile not being available. 2018-10-26 22:28:31 +02:00
Harald Kuhr 3e9be32279 Better assertion failed messages. 2018-10-26 22:14:57 +02:00
Harald Kuhr d41acaee05 Remnoved System.err.println 2018-10-26 22:13:25 +02:00
Harald Kuhr a0955875d8 Test case for #446. 2018-10-26 20:34:57 +02:00
Harald Kuhr 38ea0989d4 Merge pull request #446 from bernhardf-ro/master
Fix for corrupted output from non-RGB TIFF images with extra samples
2018-10-26 20:21:12 +02:00
Harald Kuhr 7e0de14783 Various Java 9 and beyond fixes:
- ExtraSamplesColorModel now overrides getComponentSize for correct size
 - TIFFImageReader/WriterSpi now recognizes the JEP 262 TIFF plugin
 - CCITTFaxEncoderStreamTest now directly creates writer (not JDK one)
2018-10-26 19:48:31 +02:00
Harald Kuhr de34d4642e Various Java 9 and beyond fixes. 2018-10-26 19:40:00 +02:00
Harald Kuhr b86bad2bf9 Equals method for DiscreteAlphaIndexColorModel, needed for Java 10. 2018-10-11 22:36:41 +02:00
Harald Kuhr cc5af0134c #442 SVG BaseURI issue fix 2018-10-11 21:38:10 +02:00
Bernhard Fey edcac25f5e Added test file for non-alpha extra channel
Added test file for CMYK TIFF with non-alpha extra channel
2018-09-27 10:07:57 +02:00
Bernhard Fey 5a5c1f996b Modified new create[ImageTypeSpecifier] method according to suggestions by @haraldk
Renamed "create" method to "createImageTypeSpecifier".
Added exception thrown for unsupported planarConfiguration values.
2018-09-26 10:56:49 +02:00
Bernhard Fey f9b8cae0ea Fix for non-RGB images with extra sample
Added "create" method to TIFFImageReader that centralizes the use of "createBanded" and "createInterleaved" as well as the "extra samples" special case and fixes non-RGB images with non-alpha extra samples
2018-09-25 10:24:20 +02:00
Harald Kuhr 62538c3db9 Updated readme 2018-09-10 13:37:29 +02:00
Harald Kuhr 48aa504be4 Fixed release date. 2018-09-08 17:32:09 +02:00
Harald Kuhr ed2eb7642a Updated versions from 3.4 to 3.4.1. 2018-09-08 17:23:01 +02:00
Harald Kuhr 24ec5ae34d #408 Added servlet JAR to dependency example. 2018-09-08 17:21:55 +02:00
Harald Kuhr 0cd250646a #438 CompoundDocument file descriptor fix
(cherry picked from commit 04f27a1)
2018-09-08 16:23:43 +02:00
Harald Kuhr 586359e7ab #379 TGA write 2018-09-08 16:04:06 +02:00
Harald Kuhr 5a3945c411 Merge remote-tracking branch 'origin/master' 2018-09-07 21:07:23 +02:00
Harald Kuhr a7b374e51a #311 Updated some more license headers that was left out in the initial change. 2018-09-07 21:07:08 +02:00
Harald Kuhr 1a1067a6bd #82 ICO write 2018-09-07 21:02:12 +02:00
Harald Kuhr d8d0131806 #437 Catching exception from static init, prints a warning and moves on. 2018-08-30 15:02:04 +02:00
Harald Kuhr 60180938d2 #439: Unclear exception message when passing image metadata as stream metadata 2018-08-30 14:46:55 +02:00
Harald Kuhr c74630656f Removed a deprecated method. 2018-08-26 10:35:53 +02:00
Harald Kuhr 96901e020f #83 ICNS write 2018-08-25 15:34:07 +02:00
Harald Kuhr 5e3229c9b7 Merge pull request #425 from ckovorodkin/jpeg-lossless-decoder-components
JPEGLosslessDecoder: Support for various component count.
2018-08-21 17:50:24 +02:00
Harald Kuhr fc8c891f07 Merge pull request #436 from Schmidor/contrib_tiffutilities_jpeg6
TIFFUtilities: Enhanced support for old-style to new-style JPEG transformation
2018-08-21 17:44:09 +02:00
Oliver Schmidtmer 632e5e6664 TIFFUtilities: Enhanced support for old-style to new-style JPEG transformation 2018-08-21 15:04:21 +02:00
Harald Kuhr 7af0cfaa78 Update README.md 2018-08-20 11:38:46 +02:00
Harald Kuhr f4b154f6c8 Update README.md 2018-08-20 11:32:29 +02:00
Harald Kuhr b09a8a5dbe Updated License. 2018-08-18 23:37:59 +02:00
Harald Kuhr a651939274 Updated readme. 2018-08-18 23:26:44 +02:00
Harald Kuhr 08283299ba #311 Updated license headers to be the same as in the LICENSE.txt 2018-08-18 23:17:54 +02:00
Harald Kuhr 1228043d57 [maven-release-plugin] prepare for next development iteration 2018-08-18 20:29:07 +02:00
oermolaev c924f284a0 JPEGLosslessDecoder: Support for various component count. 2018-05-05 01:38:37 +03:00
1072 changed files with 74975 additions and 80460 deletions
+1
View File
@@ -0,0 +1 @@
github: haraldk
+53
View File
@@ -0,0 +1,53 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: Reported bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**Version information**
1. The version of the TwelveMonkeys ImageIO library in use.
For example: 4.0.0
2. The *exact* output of `java --version` (or `java -version` for older Java releases).
For example:
java version "1.8.0_271"
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)
3. Extra information about OS version, server version, standalone program or web application packaging, executable wrapper, etc. Please state exact version numbers where applicable.
**To Reproduce**
Steps to reproduce the behavior:
1. Compile the below sample code
2. Download the sample image file
3. Run the code with the sample file
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Example code**
Preferably as a failing JUnit test, or a standalone program with a `main` method that showcases the problem.
Less is more. Don't add your entire project, only the code required to reproduce the problem. 😀
**Sample file(s)**
Attach any sample files needed to reproduce the problem. Use a ZIP-file if the format is not directly supported by GitHub.
**Stak trace**
Always include the stack trace you experience.
**Screenshots**
If applicable, add screenshots to help explain your problem.
Do not add screenshots of code or stack traces. 😀
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: New feature
assignees: ''
---
**Is your feature request related to a use case or a problem you are working on? Please describe.**
A clear and concise description of what the problem or use case is. Understanding the rationale is key, to be able to implemeent the right solution.
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've already considered, and why they won't work.
**Additional context**
Add any other context or screenshots about the feature request here, like links to specifications or sample files.
@@ -0,0 +1,13 @@
---
name: Trouble shooting and programming help
about: "General programming issues will reach a wider audience at StackOverflow. Tag
questions with javax-imageio and/or twelvemonkeys \U0001F600 "
title: ''
labels: Trouble-shooting
assignees: ''
---
General programming issues and problems will reach a much wider audience at StackOverflow, we suggest you ask them there. This will offload our work with maintaining the library, and make sure you get better help sooner.
Tag the question with `javax-imageio` and/or `twelvemonkeys` and we'll find them there.
@@ -0,0 +1,11 @@
**What is fixed** Add link to the issue this PR fixes.
Example: Fixes #42.
**Why is this change proposed** If this change does *not* fix an open issue, briefly describe the rationale for this PR.
**What is changed** Briefly describe the changes proposed in this pull request:
* Fixed rare exception happening in `x >= 42` case
* Small optimization of `decompress()` method
* Corrected API doc for `compress()` method to reflect current implementation
+17
View File
@@ -0,0 +1,17 @@
version: 2
updates:
# Maven/Java library updates
- package-ecosystem: "maven"
directory: "/"
schedule:
interval: "daily"
cooldown:
default-days: 7
open-pull-requests-limit: 10
# GitHub actions updates
- package-ecosystem: "github-actions"
directory: "/.github/workflows"
schedule:
interval: "daily"
cooldown:
default-days: 7
+143
View File
@@ -0,0 +1,143 @@
name: CI
on:
push:
branches:
- '**'
- '!dependabot/**'
pull_request:
branches: [ 'master' ]
permissions: read-all
jobs:
test:
name: Test OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
java: [ 8, 11, 17, 21, 25 ]
exclude:
- os: macos-latest
java: 8
runs-on: ${{ matrix.os }}
permissions:
checks: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
java-package: jdk
cache: 'maven'
- name: Run Tests
run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
test-jdk8-macos:
name: Test OpenJDK 8 on macos-14
runs-on: macos-14
permissions:
checks: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'zulu'
java-version: '8'
java-package: jdk
cache: 'maven'
- name: Run Tests
run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
test-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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- run: |
download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292"
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'jdkfile'
jdkFile: ${{ runner.temp }}/java_package.tar.gz
java-version: '8'
cache: 'maven'
- name: Set MAVEN_OPTS
if: ${{ matrix.kcms }}
run: |
echo "MAVEN_OPTS=-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider" >> $GITHUB_ENV
- name: Display Java version
run: java -version
- name: Run Tests
run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
check_name: Unit Test Results for Oracle JDK 8 with KCMS=${{ matrix.kcms }}
javadoc:
name: Build JavaDoc on OpenJDK ${{ matrix.java }}
runs-on: ubuntu-latest
strategy:
matrix:
java: [8, 11, 25 ] # We only need a few versions here
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
java-package: jdk
cache: 'maven'
- name: Create JavaDoc
run: mvn --batch-mode --no-transfer-progress -DskipTests package javadoc:javadoc
release:
name: Deploy
needs: [ test, test-jdk8-macos, test-oracle, javadoc ]
if: github.ref == 'refs/heads/master' # only perform on latest master
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up Maven Central
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: # running setup-java again overwrites the settings.xml
distribution: 'temurin'
java-version: '8'
java-package: jdk
server-id: central # Value of the distributionManagement/repository/id field of the pom.xml
server-username: MAVEN_CENTRAL_USERNAME # env variable for username in deploy (1)
server-password: MAVEN_CENTRAL_PASSWORD # env variable for token in deploy (2)
- name: Get Project Version
run: |
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 --batch-mode --no-transfer-progress deploy -P release -DskipTests -Dgpg.signer=bc
env:
MAVEN_CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }} # must be the same env variable name as (1)
MAVEN_CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }} # must be the same env variable name as (2)
MAVEN_GPG_KEY: ${{ secrets.GPG_KEY }} # Value of the GPG private key to import
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
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@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
# ️ 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@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
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@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
with:
sarif_file: results.sarif
+1
View File
@@ -15,3 +15,4 @@ private
profiles.xml
Thumbs.db
.DS_Store
/.metadata/
-13
View File
@@ -1,13 +0,0 @@
language: java
jdk:
- oraclejdk8
# Oracle JDK 7 no longer supported, we use env matrix to test various CMM providers
# - oraclejdk7
# Some JPEGImageReader tests fail on OpenJDK, need to investigate/fix before enabling
# - openjdk7
env:
- MAVEN_OPTS=-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider
- MAVEN_OPTS=""
cache:
directories:
- $HOME/.m2
+1 -1
View File
@@ -1,6 +1,6 @@
BSD 3-Clause License
Copyright (c) 2017, Harald Kuhr
Copyright (c) 2008-2020, Harald Kuhr
All rights reserved.
Redistribution and use in source and binary forms, with or without
+377 -457
View File
@@ -1,261 +1,85 @@
## Latest
[![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)
Master branch build status: [![Build Status](https://travis-ci.org/haraldk/TwelveMonkeys.svg?branch=master)](https://travis-ci.org/haraldk/TwelveMonkeys)
[![Maven Central](https://img.shields.io/maven-central/v/com.twelvemonkeys.imageio/imageio?color=slateblue)](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio)
[![Maven Snapshot](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fcentral.sonatype.com%2Frepository%2Fmaven-snapshots%2Fcom%2Ftwelvemonkeys%2Fimageio%2Fimageio%2Fmaven-metadata.xml&label=development&server=https%3A%2F%2Foss.sonatype.org&color=slateblue)](https://central.sonatype.com/repository/maven-snapshots/com/twelvemonkeys/imageio/imageio/maven-metadata.xml)
[![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)
Latest release is TwelveMonkeys ImageIO [3.3.2](http://search.maven.org/#search%7Cga%7C1%7Cg%3Acom.twelvemonkeys*%20AND%20v%3A%223.3.2%22) (Feb. 2nd, 2017).
[Release notes](https://github.com/haraldk/TwelveMonkeys/releases/latest).
![Logo](logo.png)
## About
TwelveMonkeys ImageIO is a collection of plugins and extensions for Java's ImageIO.
TwelveMonkeys ImageIO provides extended image file format support for the Java platform, through plugins for the `javax.imageio.*` package.
These plugins extends the number of image file formats supported in Java, using the javax.imageio.* package.
The main purpose of this project is to provide support for formats not covered by the JRE itself.
Support for formats is important, both to be able to read data found
The main goal of this project is to provide support for file formats not covered by the JDK.
Support for these formats is important, to be able to read data found
"in the wild", as well as to maintain access to data in legacy formats.
Because there is lots of legacy data out there, we see the need for open implementations of readers for popular formats.
The goal is to create a set of efficient and robust ImageIO plug-ins, that can be distributed independently.
As there is lots of legacy data out there, we see the need for open implementations of readers for popular formats.
----
## Features
## File formats supported
Mainstream format support
| Plugin | Format | Description | R | W | Metadata | Notes |
| ------ | -------- |---------------------------------------------------------|:---:|:---:| -------- | ----- |
| Batik | **SVG** | Scalable Vector Graphics | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/) |
| | WMF | MS Windows Metafile | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/) |
| [BMP](https://github.com/haraldk/TwelveMonkeys/wiki/BMP-Plugin) | **BMP** | MS Windows and IBM OS/2 Device Independent Bitmap | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/bmp_metadata.html), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | CUR | MS Windows Cursor Format | ✔ | - | - |
| | ICO | MS Windows Icon Format | ✔ | ✔ | - |
| [DDS](https://github.com/haraldk/TwelveMonkeys/wiki/DDS-Plugin) | DDS | MS Direct Draw Surface Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [HDR](https://github.com/haraldk/TwelveMonkeys/wiki/HDR-Plugin) | HDR | Radiance High Dynamic Range RGBE Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [ICNS](https://github.com/haraldk/TwelveMonkeys/wiki/ICNS-Plugin) | ICNS | Apple Icon Image | ✔ | ✔ | - |
| [IFF](https://github.com/haraldk/TwelveMonkeys/wiki/IFF-Plugin) | IFF | Commodore Amiga/Electronic Arts Interchange File Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [JPEG](https://github.com/haraldk/TwelveMonkeys/wiki/JPEG-Plugin) | **JPEG** | Joint Photographers Expert Group | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | JPEG Lossless | | ✔ | - | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [PCX](https://github.com/haraldk/TwelveMonkeys/wiki/PCX-Plugin) | PCX | ZSoft Paintbrush Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | DCX | Multi-page PCX fax document | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [PICT](https://github.com/haraldk/TwelveMonkeys/wiki/PICT-Plugin) | PICT | Apple QuickTime Picture Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | PNTG | Apple MacPaint Picture Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [PNM](https://github.com/haraldk/TwelveMonkeys/wiki/PNM-Plugin) | PAM | NetPBM Portable Any Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | PBM | NetPBM Portable Bit Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | PGM | NetPBM Portable Grey Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | PPM | NetPBM Portable Pix Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | PFM | Portable Float Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [PSD](https://github.com/haraldk/TwelveMonkeys/wiki/PSD-Plugin) | **PSD** | Adobe Photoshop Document | ✔ | (✔) | Native, [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | PSB | Adobe Photoshop Large Document | ✔ | - | Native, [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [SGI](https://github.com/haraldk/TwelveMonkeys/wiki/SGI-Plugin) | SGI | Silicon Graphics Image Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [TGA](https://github.com/haraldk/TwelveMonkeys/wiki/TGA-Plugin) | TGA | Truevision TGA Image Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|ThumbsDB| Thumbs.db| MS Windows Thumbs DB | ✔ | - | - | OLE2 Compound Document based format only |
| [TIFF](https://github.com/haraldk/TwelveMonkeys/wiki/TIFF-Plugin) | **TIFF** | Aldus/Adobe Tagged Image File Format | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| | BigTIFF | | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| [WebP](https://github.com/haraldk/TwelveMonkeys/wiki/WebP-Plugin) | **WebP** | Google WebP Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
| XWD | XWD | X11 Window Dump Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
#### BMP - MS Windows/IBM OS/2 Device Independent Bitmap
* Read support for all known versions of the DIB/BMP format
* Indexed color, 1, 4 and 8 bit, including 4 and 8 bit RLE
* RGB, 16, 24 and 32 bit
* Embedded PNG and JPEG data
* Windows and OS/2 versions
* Native and standard metadata format
#### JPEG
* Read support for the following JPEG "flavors":
* All JFIF compliant JPEGs
* All Exif compliant JPEGs
* YCbCr JPEGs without JFIF segment (converted to RGB, using embedded ICC profile)
* CMYK JPEGs (converted to RGB by default or as CMYK, using embedded ICC profile)
* Adobe YCCK JPEGs (converted to RGB by default or as CMYK, using embedded ICC profile)
* JPEGs containing ICC profiles with interpretation other than 'Perceptual' or class other than 'Display'
* JPEGs containing ICC profiles that are incompatible with stream data, corrupted ICC profiles or corrupted `ICC_PROFILE` segments
* JPEGs using non-standard color spaces, unsupported by Java 2D
* JPEGs with APP14/Adobe segments with length other than 14 bytes
* 8 bit JPEGs with 16 bit DQT segments
* Issues warnings instead of throwing exceptions in cases of corrupted or non-conformant data where ever the image
data can still be read in a reasonable way
* Thumbnail support:
* JFIF thumbnails (even if stream contains "inconsistent metadata")
* JFXX thumbnails (JPEG, Indexed and RGB)
* EXIF thumbnails (JPEG, RGB and YCbCr)
* Metadata support:
* JPEG metadata in both standard and native formats (even if stream contains "inconsistent metadata")
* `javax_imageio_jpeg_image_1.0` format (currently as native format, may change in the future)
* Non-conforming combinations of JFIF, Exif and Adobe markers, using "unknown" segments in the
"MarkerSequence" tag for the unsupported segments (for `javax_imageio_jpeg_image_1.0` format)
* Extended write support in progress:
* CMYK JPEGs
* YCCK JPEGs
#### JPEG-2000
* Possibly coming in the future, pending some license issues.
If you are one of the authors, or know one of the authors and/or the current license holders of either the original
jj2000 package or the JAI ImageIO project, please contact me (I've tried to get in touch in various ways,
without success so far).
Alternatively, if you have or know of a JPEG-2000 implementation in Java with a suitable license, get in touch. :-)
#### PNM - NetPBM Portable Any Map
* Read support for the following file types:
* PBM in 'P1' (ASCII) and 'P4' (binary) formats, 1 bit per pixel
* PGM in 'P2' (ASCII) and 'P5' (binary) formats, up to 16/32 bits per pixel
* PPM in 'P3' (ASCII) and 'P6' (binary) formats, up to 16/32 bits per pixel component
* PAM in 'P7' (binary) format up to 32 bits per pixel component
* Limited support for PFM in 'Pf' (gray) and 'PF' (RGB) formats, 32 bits floating point
* Write support for the following formats:
* PPM in 'P6' (binary) format
* PAM in 'P7' (binary) format
* Standard metadata support
#### PSD - Adobe Photoshop Document
* Read support for the following file types:
* Monochrome, 1 channel, 1 bit
* Indexed, 1 channel, 8 bit
* Gray, 1 channel, 8, 16 and 32 bit
* Duotone, 1 channel, 8, 16 and 32 bit
* RGB, 3-4 channels, 8, 16 and 32 bit
* CMYK, 4-5 channels, 8, 16 and 32 bit
* Read support for the following compression types:
* Uncompressed
* RLE (PackBits)
* Layer support
* Image layers only, in all of the above types
* Thumbnail support
* JPEG
* RAW (RGB)
* Support for "Large Document Format" (PSB)
* Native and Standard metadata support
#### TIFF - Aldus/Adobe Tagged Image File Format
* Read support for the following "Baseline" TIFF file types:
* Class B (Bi-level), all relevant compression types, 1 bit per sample
* Class G (Gray), all relevant compression types, 2, 4, 8, 16 or 32 bits per sample, unsigned integer
* Class P (Palette/indexed color), all relevant compression types, 1, 2, 4, 8 or 16 bits per sample, unsigned integer
* Class R (RGB), all relevant compression types, 8 or 16 bits per sample, unsigned integer
* Read support for the following TIFF extensions:
* Tiling
* Class F (Facsimile), CCITT Modified Huffman RLE, T4 and T6 (type 2, 3 and 4) compressions.
* LZW Compression (type 5)
* "Old-style" JPEG Compression (type 6), as a best effort, as the spec is not well-defined
* JPEG Compression (type 7)
* ZLib (aka Adobe-style Deflate) Compression (type 8)
* Deflate Compression (type 32946)
* Horizontal differencing Predictor (type 2) for LZW, ZLib, Deflate and PackBits compression
* Alpha channel (ExtraSamples type 1/Associated Alpha and type 2/Unassociated Alpha)
* CMYK data (PhotometricInterpretation type 5/Separated)
* YCbCr data (PhotometricInterpretation type 6/YCbCr) for JPEG
* CIELab data in TIFF, ITU and ICC variants (PhotometricInterpretation type 9, 10 and 11)
* Planar data (PlanarConfiguration type 2/Planar)
* ICC profiles (ICCProfile)
* BitsPerSample values up to 16 for most PhotometricInterpretations
* Multiple images (pages) in one file
* Write support for most "Baseline" TIFF options
* Uncompressed, PackBits, ZLib and Deflate
* Additional support for CCITT T4 and and T6 compressions.
* Additional support for LZW and JPEG (type 7) compressions
* Horizontal differencing Predictor (type 2) for LZW, ZLib, Deflate
* Native and Standard metadata support
Legacy formats
#### HDR - Radiance High Dynamic Range RGBE Format
* Read support for the most common RGBE (.hdr) format
* Samples are converted to 32 bit floating point (`float`) and normalized using a global tone mapper by default.
* Support for custom global tone mappers
* Alternatively, use a "null-tone mapper", for unnormalized data (allows local tone mapping)
* Unconverted RGBE samples accessible using `readRaster`
* Standard metadata support
#### IFF - Commodore Amiga/Electronic Arts Interchange File Format
* Legacy format, allows reading popular image format from the Commodore Amiga computer.
* Read support for the following file types:
* ILBM Indexed color, 1-8 interleaved bit planes, including 6 bit EHB
* ILBM Gray, 8 bit interleaved bit planes
* ILBM RGB, 24 and 32 bit interleaved bit planes
* ILBM HAM6 and HAM8
* PBM Indexed color, 1-8 bit,
* PBM Gray, 8 bit
* PBM RGB, 24 and 32 bit
* PBM HAM6 and HAM8
* Write support
* ILBM Indexed color, 1-8 bits per sample, 8 bit gray, 24 and 32 bit true color.
* Support for the following compression types (read/write):
* Uncompressed
* RLE (PackBits)
#### PCX - ZSoft Paintbrush Format
* Read support for the following file types:
* Indexed color, 1, 2, 4 or 8 bits per pixel, bit planes or interleaved
* Grayscale, 8 bits per pixel
* Color (RGB), 8 bits per pixel component
* Read support for DCX (multi-page) fax format, containing any of the above types
* Support for the following compression types:
* Uncompressed (experimental)
* RLE compressed
* Standard metadata support
#### PICT - Apple Mac Paint Picture Format
* Legacy format, especially useful for reading OS X clipboard data.
* Read support for the following file types:
* QuickDraw (format support is not complete, but supports most OS X clipboard data as well as RGB pixel data)
* QuickDraw bitmap
* QuickDraw pixmap
* QuickTime stills
* Write support for RGB pixel data:
* QuickDraw pixmap
#### SGI - Silicon Graphics Image Format
* Read support for the following file types:
* 1, 2, 3 or 4 channel image data
* 8 or 16 bits per pixel component
* Support for the following compression types:
* Uncompressed
* RLE compressed
* Standard metadata support
#### TGA - Truevision TGA Image Format
* Read support for the following file types:
* ColorMapped
* Monochrome
* TrueColor
* Support for the following compression types:
* Uncompressed
* RLE compressed
* Standard metadata support
Icon/other formats
#### ICNS - Apple Icon Image
* Read support for the following icon types:
* All known "native" icon types
* Large PNG encoded icons
* Large JPEG 2000 encoded icons (requires JPEG 2000 ImageIO plugin or fallback to `sips` command line tool)
#### ICO & CUR - MS Windows Icon and Cursor Formats
* Read support for the following file types:
* ICO Indexed color, 1, 4 and 8 bit
* ICO RGB, 16, 24 and 32 bit
* CUR Indexed color, 1, 4 and 8 bit
* CUR RGB, 16, 24 and 32 bit
* *3.1* Note: These formats are now part of the BMP plugin
#### Thumbs.db - MS Windows Thumbs DB
* Read support
Other formats, using 3rd party libraries
#### SVG - Scalable Vector Graphics
* Read-only support using Batik
#### WMF - MS Windows MetaFile
* Limited read-only support using Batik
**Important note on using Batik:** *Please read [The Apache™ XML Graphics Project - Security](http://xmlgraphics.apache.org/security.html), and make sure you use
either version 1.6.1, 1.7.1 or 1.8+.*
**Important note on using Batik:** *Please read [The Apache™ XML Graphics Project - Security](https://xmlgraphics.apache.org/security.html),
and make sure you use an updated and secure version.*
Note that GIF, PNG and WBMP formats are already supported through the ImageIO API, using the
[JDK standard plugins](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/package-summary.html).
For BMP, JPEG, and TIFF formats the TwelveMonkeys plugins provides extended format support and additional features.
## Basic usage
Most of the time, all you need to do is simply include the plugins in your project and write:
BufferedImage image = ImageIO.read(file);
```java
BufferedImage image = ImageIO.read(file);
```
This will load the first image of the file, entirely into memory.
The basic and simplest form of writing is:
if (!ImageIO.write(image, format, file)) {
// Handle image not written case
}
```java
if (!ImageIO.write(image, format, file)) {
// Handle image not written case
}
```
This will write the entire image into a single file, using the default settings for the given format.
@@ -265,50 +89,46 @@ The plugins are discovered automatically at run time. See the [FAQ](#faq) for mo
If you need more control of read parameters and the reading process, the common idiom for reading is something like:
// Create input stream
ImageInputStream input = ImageIO.createImageInputStream(file);
```java
// Create input stream (in try-with-resource block to avoid leaks)
try (ImageInputStream input = ImageIO.createImageInputStream(file)) {
// Get the reader
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (!readers.hasNext()) {
throw new IllegalArgumentException("No reader for: " + file);
}
ImageReader reader = readers.next();
try {
// Get the reader
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
reader.setInput(input);
if (!readers.hasNext()) {
throw new IllegalArgumentException("No reader for: " + file);
}
// Optionally, listen for read warnings, progress, etc.
reader.addIIOReadWarningListener(...);
reader.addIIOReadProgressListener(...);
ImageReader reader = readers.next();
ImageReadParam param = reader.getDefaultReadParam();
try {
reader.setInput(input);
// Optionally, control read settings like sub sampling, source region or destination etc.
param.setSourceSubsampling(...);
param.setSourceRegion(...);
param.setDestination(...);
// ...
// Optionally, listen for read warnings, progress, etc.
reader.addIIOReadWarningListener(...);
reader.addIIOReadProgressListener(...);
// Finally read the image, using settings from param
BufferedImage image = reader.read(0, param);
ImageReadParam param = reader.getDefaultReadParam();
// Optionally, control read settings like sub sampling, source region or destination etc.
param.setSourceSubsampling(...);
param.setSourceRegion(...);
param.setDestination(...);
// ...
// Finally read the image, using settings from param
BufferedImage image = reader.read(0, param);
// Optionally, read thumbnails, meta data, etc...
int numThumbs = reader.getNumThumbnails(0);
// ...
}
finally {
// Dispose reader in finally block to avoid memory leaks
reader.dispose();
}
// Optionally, read thumbnails, meta data, etc...
int numThumbs = reader.getNumThumbnails(0);
// ...
}
finally {
// Close stream in finally block to avoid resource leaks
input.close();
// Dispose reader in finally block to avoid memory leaks
reader.dispose();
}
}
```
Query the reader for source image dimensions using `reader.getWidth(n)` and `reader.getHeight(n)` without reading the
entire image into memory first.
@@ -318,129 +138,142 @@ It's also possible to read multiple images from the same file in a loop, using `
If you need more control of write parameters and the writing process, the common idiom for writing is something like:
// Get the writer
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format);
```java
// Get the writer
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(format);
if (!writers.hasNext()) {
throw new IllegalArgumentException("No writer for: " + format);
}
ImageWriter writer = writers.next();
try {
// Create output stream
ImageOutputStream output = ImageIO.createImageOutputStream(file);
try {
writer.setOutput(output);
// Optionally, listen to progress, warnings, etc.
ImageWriteParam param = writer.getDefaultWriteParam();
// Optionally, control format specific settings of param (requires casting), or
// control generic write settings like sub sampling, source region, output type etc.
// Optionally, provide thumbnails and image/stream metadata
writer.write(..., new IIOImage(..., image, ...), param);
}
finally {
// Close stream in finally block to avoid resource leaks
output.close();
}
}
finally {
// Dispose writer in finally block to avoid memory leaks
writer.dispose();
if (!writers.hasNext()) {
throw new IllegalArgumentException("No writer for: " + format);
}
ImageWriter writer = writers.next();
try {
// Create output stream (in try-with-resource block to avoid leaks)
try (ImageOutputStream output = ImageIO.createImageOutputStream(file)) {
writer.setOutput(output);
// Optionally, listen to progress, warnings, etc.
ImageWriteParam param = writer.getDefaultWriteParam();
// Optionally, control format specific settings of param (requires casting), or
// control generic write settings like sub sampling, source region, output type etc.
// Optionally, provide thumbnails and image/stream metadata
writer.write(..., new IIOImage(..., image, ...), param);
}
}
finally {
// Dispose writer in finally block to avoid memory leaks
writer.dispose();
}
```
For more advanced usage, and information on how to use the ImageIO API, I suggest you read the
[Java Image I/O API Guide](http://docs.oracle.com/javase/7/docs/technotes/guides/imageio/spec/imageio_guideTOC.fm.html)
[Java Image I/O API Guide](https://docs.oracle.com/javase/7/docs/technotes/guides/imageio/spec/imageio_guideTOC.fm.html)
from Oracle.
#### Adobe Clipping Path support
#### Deploying the plugins in a web app
```java
import com.twelvemonkeys.imageio.path.Paths;
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it doesn't by default work well with
servlet contexts. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
Unless you add `ImageIO.scanForPlugins()` somewhere in your code, the plugins might never be available at all.
...
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context).
If you restart your application, old classes will by default remain in memory forever (because the next time
`scanForPlugins` is called, it's another `ClassLoader` that scans/loads classes, and thus they will be new instances
in the registry). If a read is attempted using one of the remaining "old" readers, weird exceptions
(like `NullPointerException`s when accessing `static final` initialized fields or `NoClassDefFoundError`s
for uninitialized inner classes) may occur.
try (ImageInputStream stream = ImageIO.createImageInputStream(new File("image_with_path.jpg")) {
BufferedImage image = Paths.readClipped(stream);
To work around both the discovery problem and the resource leak,
it is *strongly recommended* to use the `IIOProviderContextListener` that implements
dynamic loading and unloading of ImageIO plugins for web applications.
// Do something with the clipped image...
}
```
See [Adobe Clipping Path support on the Wiki](https://github.com/haraldk/TwelveMonkeys/wiki/Photoshop-Clipping-Path-support) for more details and example code.
<web-app ...>
...
<listener>
<display-name>ImageIO service provider loader/unloader</display-name>
<listener-class>com.twelvemonkeys.servlet.image.IIOProviderContextListener</listener-class>
</listener>
...
</web-app>
Loading plugins from `WEB-INF/lib` without the context listener installed is unsupported and will not work correctly.
The context listener has no dependencies to the TwelveMonkeys ImageIO plugins, and may be used with JAI ImageIO
or other ImageIO plugins as well.
Another safe option, is to place the JAR files in the application server's shared or common lib folder.
#### Using the ResampleOp
The library comes with a resampling (image resizing) operation, that contains many different algorithms
to provide excellent results at reasonable speed.
import com.twelvemonkeys.image.ResampleOp;
```java
import com.twelvemonkeys.image.ResampleOp;
...
...
BufferedImage input = ...; // Image to resample
int width, height = ...; // new width/height
BufferedImageOp resampler = new ResampleOp(width, height, ResampleOp.FILTER_LANCZOS); // A good default filter, see class documentation for more info
BufferedImage output = resampler.filter(input, null);
BufferedImage input = ...; // Image to resample
int width, height = ...; // new width/height
BufferedImageOp resampler = new ResampleOp(width, height, ResampleOp.FILTER_LANCZOS); // A good default filter, see class documentation for more info
BufferedImage output = resampler.filter(input, null);
```
#### Using the DiffusionDither
The library comes with a dithering operation, that can be used to convert `BufferedImage`s to `IndexColorModel` using
Floyd-Steinberg error-diffusion dither.
import com.twelvemonkeys.image.DiffusionDither;
```java
import com.twelvemonkeys.image.DiffusionDither;
...
...
BufferedImage input = ...; // Image to dither
BufferedImage input = ...; // Image to dither
BufferedImageOp ditherer = new DiffusionDither();
BufferedImage output = ditherer.filter(input, null);
BufferedImageOp ditherer = new DiffusionDither();
BufferedImage output = ditherer.filter(input, null);
```
#### Working with damaged images
When using the normal patterns for loading images, trying to load a damaged image will result in an `IOException` being thrown.
```java
BufferedImage image = null;
try {
image = ImageIO.read(file);
} catch (IOException exception) {
// Handle, log a warning/error etc
}
```
In this scenario, if the image is damaged, and `ImageIO.read` throws an exception, `image` is still `null` - it's not possible for a function to both return a value and throw an exception.
However, in some cases it may be possible to get usable image data from a damaged image. The way to do this is use an `ImageReadParam` to set a `BufferedImage` as a destination.
```java
int width = reader.getWidth(0);
int height = reader.getHeight(0);
ImageTypeSpecifier imageType = reader.getRawImageType(0);
BufferedImage image = imageType.createBufferedImage(width, height);
ImageReadParam param = reader.getDefaultReadParam();
param.setDestination(image);
try {
reader.read(0, param);
}
catch (IOException e) {
// Handle, log a warning/error etc
}
```
In theory this should work for all plugins, but the result is very much plugin/implementation specific. With some formats and some forms of damaged file, you may get an image that is mostly useful.
However, you should be prepared for the possibility this just gives a blank or empty image.
## Building
Download the project (using [Git](http://git-scm.com/downloads)):
Download the project (using [Git](https://git-scm.com/downloads)):
$ git clone git@github.com:haraldk/TwelveMonkeys.git
This should create a folder named `TwelveMonkeys` in your current directory. Change directory to the `TwelveMonkeys`
folder, and issue the command below to build.
Build the project (using [Maven](http://maven.apache.org/download.cgi)):
Build the project (using [Maven](https://maven.apache.org/download.cgi)):
$ mvn package
Currently, the recommended JDK for making a build is Oracle JDK 7.x or 8.x.
Currently, the recommended JDK for making a build is Oracle JDK 8.x.
It's possible to build using OpenJDK, but some tests might fail due to some minor differences between the color management systems used. You will need to either disable the tests in question, or build without tests altogether.
@@ -461,10 +294,12 @@ The ImageIO registry and service lookup mechanism will make sure the plugins are
To verify that the JPEG plugin is installed and used at run-time, you could use the following code:
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
while (readers.hasNext()) {
System.out.println("reader: " + readers.next());
}
```java
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JPEG");
while (readers.hasNext()) {
System.out.println("reader: " + readers.next());
}
```
The first line should print:
@@ -474,143 +309,209 @@ The first line should print:
To depend on the JPEG and TIFF plugin using Maven, add the following to your POM:
```xml
...
<dependencies>
...
<dependencies>
...
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.3.2</version> <!-- Alternatively, build your own version -->
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.3.2</version> <!-- Alternatively, build your own version -->
</dependency>
</dependencies>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.13.1</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.13.1</version>
</dependency>
<!--
Optional dependency. Needed only if you deploy ImageIO plugins as part of a web app.
Make sure you add the IIOProviderContextListener to your web.xml, see above.
-->
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.13.1</version>
</dependency>
<!--
Or Jakarta version, for Servlet API 5.0
-->
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.13.1</version>
<classifier>jakarta</classifier>
</dependency>
</dependencies>
```
#### Manual dependency example
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.3.2.jar
twelvemonkeys-common-io-3.3.2.jar
twelvemonkeys-common-image-3.3.2.jar
twelvemonkeys-imageio-core-3.3.2.jar
twelvemonkeys-imageio-metadata-3.3.2.jar
twelvemonkeys-imageio-jpeg-3.3.2.jar
twelvemonkeys-imageio-tiff-3.3.2.jar
twelvemonkeys-common-lang-3.13.1.jar
twelvemonkeys-common-io-3.13.1.jar
twelvemonkeys-common-image-3.13.1.jar
twelvemonkeys-imageio-core-3.13.1.jar
twelvemonkeys-imageio-metadata-3.13.1.jar
twelvemonkeys-imageio-jpeg-3.13.1.jar
twelvemonkeys-imageio-tiff-3.13.1.jar
#### Deploying the plugins in a web app
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it does not work well with
servlet contexts as-is. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
Unless you add `ImageIO.scanForPlugins()` somewhere in your code, the plugins might never be available at all.
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context).
If you restart your application, old classes will by default remain in memory forever (because the next time
`scanForPlugins` is called, it's another `ClassLoader` that scans/loads classes, and thus they will be new instances
in the registry). If a read is attempted using one of the remaining "old" readers, weird exceptions
(like `NullPointerException`s when accessing `static final` initialized fields or `NoClassDefFoundError`s
for uninitialized inner classes) may occur.
To work around both the discovery problem and the resource leak,
it is *strongly recommended* to use the `IIOProviderContextListener` that implements
dynamic loading and unloading of ImageIO plugins for web applications.
```xml
<web-app ...>
...
<listener>
<display-name>ImageIO service provider loader/unloader</display-name>
<listener-class>com.twelvemonkeys.servlet.image.IIOProviderContextListener</listener-class>
</listener>
...
</web-app>
```
Loading plugins from `WEB-INF/lib` without the context listener installed is unsupported and will not work correctly.
The context listener has no dependencies to the TwelveMonkeys ImageIO plugins, and may be used with JAI ImageIO
or other ImageIO plugins as well.
Another safe option, is to place the JAR files in the application server's shared or common lib folder.
##### Jakarta Servlet Support
For those transitioning from the old `javax.servlet` to the new `jakarta.servlet` package, there is a separate
dependency available. It contains exactly the same servlet classes as mentioned above, but built against the new Jakarta EE
packages. The dependency has the same group name and identifier as before, but a `jakarta` *classifier* appended, to
distinguish it from the non-Jakarta package.
See the [Maven dependency example](#maven-dependency-example) for how to enable it with Maven.
Gradle or other build tools will have similar options.
#### Including the plugins in a "fat" JAR
The recommended way to use the plugins, is just to include the JARs as-is in your project, through a Maven dependency or similar.
Re-packaging is not necessary to use the library, and not recommended.
However, if you like to create a "fat"
JAR, or otherwise like to re-package the JARs for some reason, it's important to remember that automatic discovery of
the plugins by ImageIO depends on the
[Service Provider Interface (SPI)](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html) mechanism.
In short, each JAR contains a special folder, named `META-INF/services` containing one or more files,
typically `javax.imageio.spi.ImageReaderSpi` and `javax.imageio.spi.ImageWriterSpi`.
These files exist *with the same name in every JAR*,
so if you simply unpack everything to a single folder or create a JAR, files will be overwritten and behavior be
unspecified (most likely you will end up with a single plugin being installed).
The solution is to make sure all files with the same name, are merged to a single file,
containing all the SPI information of each type. If using the Maven Shade plugin, you should use the
[ServicesResourceTransformer](https://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#ServicesResourceTransformer)
to properly merge these files. You may also want to use the
[ManifestResourceTransforme](https://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#ManifestResourceTransformer)
to get the correct vendor name, version info etc.
Other "fat" JAR bundlers will probably have similar mechanisms to merge entries with the same name.
### Links to prebuilt binaries
##### Latest version (3.2.x)
##### Latest version (3.13.1)
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.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.3.2/common-lang-3.3.2.jar)
* [common-io-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.3.2/common-io-3.3.2.jar)
* [common-image-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.3.2/common-image-3.3.2.jar)
* [common-lang-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.13.1/common-lang-3.13.1.jar)
* [common-io-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.13.1/common-io-3.13.1.jar)
* [common-image-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.13.1/common-image-3.13.1.jar)
ImageIO dependencies
* [imageio-core-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.3.2/imageio-core-3.3.2.jar)
* [imageio-metadata-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.3.2/imageio-metadata-3.3.2.jar)
* [imageio-core-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.13.1/imageio-core-3.13.1.jar)
* [imageio-metadata-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.13.1/imageio-metadata-3.13.1.jar)
ImageIO plugins
* [imageio-bmp-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.3.2/imageio-bmp-3.3.2.jar)
* [imageio-jpeg-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.3.2/imageio-jpeg-3.3.2.jar)
* [imageio-tiff-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.3.2/imageio-tiff-3.3.2.jar)
* [imageio-pnm-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.3.2/imageio-pnm-3.3.2.jar)
* [imageio-psd-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.3.2/imageio-psd-3.3.2.jar)
* [imageio-hdr-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.3.2/imageio-hdr-3.3.2.jar)
* [imageio-iff-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.3.2/imageio-iff-3.3.2.jar)
* [imageio-pcx-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.3.2/imageio-pcx-3.3.2.jar)
* [imageio-pict-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.3.2/imageio-pict-3.3.2.jar)
* [imageio-sgi-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.3.2/imageio-sgi-3.3.2.jar)
* [imageio-tga-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.3.2/imageio-tga-3.3.2.jar)
* [imageio-icns-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.3.2/imageio-icns-3.3.2.jar)
* [imageio-thumbsdb-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.3.2/imageio-thumbsdb-3.3.2.jar)
* [imageio-bmp-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.13.1/imageio-bmp-3.13.1.jar)
* [imageio-dds-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-dds/3.13.1/imageio-dds-3.13.1.jar)
* [imageio-hdr-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.13.1/imageio-hdr-3.13.1.jar)
* [imageio-icns-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.13.1/imageio-icns-3.13.1.jar)
* [imageio-iff-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.13.1/imageio-iff-3.13.1.jar)
* [imageio-jpeg-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.13.1/imageio-jpeg-3.13.1.jar)
* [imageio-pcx-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.13.1/imageio-pcx-3.13.1.jar)
* [imageio-pict-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.13.1/imageio-pict-3.13.1.jar)
* [imageio-pnm-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.13.1/imageio-pnm-3.13.1.jar)
* [imageio-psd-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.13.1/imageio-psd-3.13.1.jar)
* [imageio-sgi-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.13.1/imageio-sgi-3.13.1.jar)
* [imageio-tga-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.13.1/imageio-tga-3.13.1.jar)
* [imageio-thumbsdb-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.13.1/imageio-thumbsdb-3.13.1.jar)
* [imageio-tiff-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.13.1/imageio-tiff-3.13.1.jar)
* [imageio-webp-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.13.1/imageio-webp-3.13.1.jar)
* [imageio-xwd-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.13.1/imageio-xwd-3.13.1.jar)
ImageIO plugins requiring 3rd party libs
* [imageio-batik-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.3.2/imageio-batik-3.3.2.jar)
* [imageio-batik-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.13.1/imageio-batik-3.13.1.jar)
Photoshop Path support for ImageIO
* [imageio-clippath-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.3.2/imageio-clippath-3.3.2.jar)
* [imageio-clippath-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.13.1/imageio-clippath-3.13.1.jar)
Servlet support
* [servlet-3.3.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.3.2/servlet-3.3.2.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](http://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](http://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](http://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](http://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](http://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](http://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](http://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](http://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](http://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](http://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](http://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](http://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](http://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](http://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](http://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](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.0.2/servlet-3.0.2.jar)
* [servlet-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.13.1/servlet-3.13.1.jar) for legacy Java EE (javax.servlet)
* [servlet-3.13.1-jakarta.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.13.1/servlet-3.13.1-jakrta.jar) for Jakarta EE (jakarta.servlet)
## License
The project is distributed under the OSI approved [BSD license](http://opensource.org/licenses/BSD-3-Clause):
This project is provided under the OSI approved [BSD license](https://opensource.org/licenses/BSD-3-Clause):
Copyright (c) 2008-2015, Harald Kuhr
Copyright (c) 2008-2022, Harald Kuhr
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
o Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
o Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
o Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
o Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
o Neither the name "TwelveMonkeys" nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
o Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## FAQ
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?
@@ -628,28 +529,47 @@ 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](http://docs.oracle.com/javase/7/docs/api/javax/imageio/spi/IIORegistry.html).
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 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 formats, JAI has some major issues.
a: While JAI (and jai-imageio in particular) have support for some of the same formats, JAI has some major issues.
The most obvious being:
- It's not actively developed. No issues has been fixed for years.
- It's not actively developed. No issue has been fixed for years.
- To get full format support, you need native libs.
Native libs does not exist for several popular platforms/architectures, and further the native libs are not open source.
Some environments may also prevent deployment of native libs, which brings us back to square one.
q: What about JMagick or IM4Java? Can't you just use what´s already available?
q: What about JMagick or IM4Java? Can't you just use what's already available?
a: While great libraries with a wide range of formats support, the ImageMagick-based libraries has some disadvantages
compared to ImageIO.
+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.
+16 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4</version>
<version>3.13.2-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.bom</groupId>
@@ -63,6 +63,11 @@
<artifactId>imageio-hdr</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-dds</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-icns</artifactId>
@@ -123,6 +128,16 @@
<artifactId>imageio-tiff</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-webp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-xwd</artifactId>
<version>${project.version}</version>
</dependency>
<!-- ImageIO 3rd party dependent plugins -->
<dependency>
+15 -9
View File
@@ -4,15 +4,19 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.4</version>
<version>3.13.2-SNAPSHOT</version>
</parent>
<artifactId>common-image</artifactId>
<packaging>jar</packaging>
<name>TwelveMonkeys :: Common :: Image</name>
<description>
The TwelveMonkeys Common Image support
TwelveMonkeys Common image support classes.
</description>
<properties>
<project.jpms.module.name>com.twelvemonkeys.common.image</project.jpms.module.name>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
@@ -24,12 +28,14 @@
<artifactId>common-io</artifactId>
</dependency>
<dependency>
<groupId>jmagick</groupId>
<artifactId>jmagick</artifactId>
<version>6.2.4</version>
<optional>true</optional>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -1,110 +1,109 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.util.ArrayList;
import java.util.List;
/**
* AbstractImageSource
* <p/>
*
* @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/image/AbstractImageSource.java#1 $
*/
public abstract class AbstractImageSource implements ImageProducer {
private List<ImageConsumer> consumers = new ArrayList<ImageConsumer>();
protected int width;
protected int height;
protected int xOff;
protected int yOff;
// ImageProducer interface
public void addConsumer(final ImageConsumer pConsumer) {
if (consumers.contains(pConsumer)) {
return;
}
consumers.add(pConsumer);
try {
initConsumer(pConsumer);
sendPixels(pConsumer);
if (isConsumer(pConsumer)) {
pConsumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
// Get rid of "sticky" consumers...
if (isConsumer(pConsumer)) {
pConsumer.imageComplete(ImageConsumer.IMAGEERROR);
removeConsumer(pConsumer);
}
}
}
catch (Exception e) {
e.printStackTrace();
if (isConsumer(pConsumer)) {
pConsumer.imageComplete(ImageConsumer.IMAGEERROR);
}
}
}
public void removeConsumer(final ImageConsumer pConsumer) {
consumers.remove(pConsumer);
}
/**
* This implementation silently ignores this instruction. If pixel data is
* not in TDLR order by default, subclasses must override this method.
*
* @param pConsumer the consumer that requested the resend
*
* @see ImageProducer#requestTopDownLeftRightResend(java.awt.image.ImageConsumer)
*/
public void requestTopDownLeftRightResend(final ImageConsumer pConsumer) {
// ignore
}
public void startProduction(final ImageConsumer pConsumer) {
addConsumer(pConsumer);
}
public boolean isConsumer(final ImageConsumer pConsumer) {
return consumers.contains(pConsumer);
}
protected abstract void initConsumer(ImageConsumer pConsumer);
protected abstract void sendPixels(ImageConsumer pConsumer);
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.util.ArrayList;
import java.util.List;
/**
* AbstractImageSource
*
* @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/image/AbstractImageSource.java#1 $
*/
public abstract class AbstractImageSource implements ImageProducer {
private List<ImageConsumer> consumers = new ArrayList<ImageConsumer>();
protected int width;
protected int height;
protected int xOff;
protected int yOff;
// ImageProducer interface
public void addConsumer(final ImageConsumer pConsumer) {
if (consumers.contains(pConsumer)) {
return;
}
consumers.add(pConsumer);
try {
initConsumer(pConsumer);
sendPixels(pConsumer);
if (isConsumer(pConsumer)) {
pConsumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
// Get rid of "sticky" consumers...
if (isConsumer(pConsumer)) {
pConsumer.imageComplete(ImageConsumer.IMAGEERROR);
removeConsumer(pConsumer);
}
}
}
catch (Exception e) {
e.printStackTrace();
if (isConsumer(pConsumer)) {
pConsumer.imageComplete(ImageConsumer.IMAGEERROR);
}
}
}
public void removeConsumer(final ImageConsumer pConsumer) {
consumers.remove(pConsumer);
}
/**
* This implementation silently ignores this instruction. If pixel data is
* not in TDLR order by default, subclasses must override this method.
*
* @param pConsumer the consumer that requested the resend
*
* @see ImageProducer#requestTopDownLeftRightResend(java.awt.image.ImageConsumer)
*/
public void requestTopDownLeftRightResend(final ImageConsumer pConsumer) {
// ignore
}
public void startProduction(final ImageConsumer pConsumer) {
addConsumer(pConsumer);
}
public boolean isConsumer(final ImageConsumer pConsumer) {
return consumers.contains(pConsumer);
}
protected abstract void initConsumer(ImageConsumer pConsumer);
protected abstract void sendPixels(ImageConsumer pConsumer);
}
@@ -34,7 +34,13 @@ import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorModel;
import java.awt.image.ImagingOpException;
import java.awt.image.Raster;
import java.awt.image.RasterOp;
import java.awt.image.WritableRaster;
/**
* This is a drop-in replacement for {@link java.awt.image.AffineTransformOp}.
@@ -70,6 +76,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp {
delegate = new java.awt.image.AffineTransformOp(xform, interpolationType);
}
@SuppressWarnings("ConstantConditions")
@Override
public BufferedImage filter(final BufferedImage src, BufferedImage dst) {
try {
@@ -80,10 +87,9 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp {
dst = createCompatibleDestImage(src, src.getColorModel());
}
Graphics2D g2d = null;
Graphics2D g2d = dst.createGraphics();
try {
g2d = dst.createGraphics();
int interpolationType = delegate.getInterpolationType();
if (interpolationType > 0) {
@@ -109,9 +115,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp {
return dst;
}
finally {
if (g2d != null) {
g2d.dispose();
}
g2d.dispose();
}
}
}
@@ -1,170 +1,173 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.image.RGBImageFilter;
/**
* Adjusts the contrast and brightness of an image.
* <p/>
* For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}.
* A value of {@code 0.0} means no change.
* Negative values will make the pixels darker.
* Maximum negative value ({@code -2}) will make all filtered pixels black.
* Positive values will make the pixels brighter.
* Maximum positive value ({@code 2}) will make all filtered pixels white.
* <p/>
* For contrast, the valid range is {@code -1.0,..,0.0,..,1.0}.
* A value of {@code 0.0} means no change.
* Negative values will reduce contrast.
* Maximum negative value ({@code -1}) will make all filtered pixels grey
* (no contrast).
* Positive values will increase contrast.
* Maximum positive value ({@code 1}) will make all filtered pixels primary
* colors (either black, white, cyan, magenta, yellow, red, blue or green).
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
*
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/BrightnessContrastFilter.java#1 $
*
* @todo consider doing something similar to http://archives.java.sun.com/cgi-bin/wa?A2=ind0302&L=jai-interest&F=&S=&P=15947
*/
public class BrightnessContrastFilter extends RGBImageFilter {
// TODO: Replace with RescaleOp?
// This filter can filter IndexColorModel, as it is does not depend on
// the pixels' location
{
canFilterIndexColorModel = true;
}
// Use a pre-calculated lookup table for performance
private final int[] LUT;
/**
* Creates a BrightnessContrastFilter with default values
* ({@code brightness=0.3, contrast=0.3}).
* <p/>
* This will slightly increase both brightness and contrast.
*/
public BrightnessContrastFilter() {
this(0.3f, 0.3f);
}
/**
* Creates a BrightnessContrastFilter with the given values for brightness
* and contrast.
* <p/>
* For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}.
* A value of {@code 0.0} means no change.
* Negative values will make the pixels darker.
* Maximum negative value ({@code -2}) will make all filtered pixels black.
* Positive values will make the pixels brighter.
* Maximum positive value ({@code 2}) will make all filtered pixels white.
* <p/>
* For contrast, the valid range is {@code -1.0,..,0.0,..,1.0}.
* A value of {@code 0.0} means no change.
* Negative values will reduce contrast.
* Maximum negative value ({@code -1}) will make all filtered pixels grey
* (no contrast).
* Positive values will increase contrast.
* Maximum positive value ({@code 1}) will make all filtered pixels primary
* colors (either black, white, cyan, magenta, yellow, red, blue or green).
*
* @param pBrightness adjust the brightness of the image, in the range
* {@code -2.0,..,0.0,..,2.0}.
* @param pContrast adjust the contrast of the image, in the range
* {@code -1.0,..,0.0,..,1.0}.
*/
public BrightnessContrastFilter(float pBrightness, float pContrast) {
LUT = createLUT(pBrightness, pContrast);
}
private static int[] createLUT(float pBrightness, float pContrast) {
int[] lut = new int[256];
// Hmmm.. This approximates Photoshop values.. Not good though..
double contrast = pContrast > 0 ? Math.pow(pContrast, 7.0) * 127.0 : pContrast;
// Convert range [-1,..,0,..,1] -> [0,..,1,..,2]
double brightness = pBrightness + 1.0;
for (int i = 0; i < 256; i++) {
lut[i] = clamp((int) (127.5 * brightness + (i - 127) * (contrast + 1.0)));
}
// Special case, to ensure only primary colors for max contrast
if (pContrast == 1f) {
lut[127] = lut[126];
}
return lut;
}
private static int clamp(int i) {
if (i < 0) {
return 0;
}
if (i > 255) {
return 255;
}
return i;
}
/**
* Filters one pixel, adjusting brightness and contrast according to this
* filter.
*
* @param pX x
* @param pY y
* @param pARGB pixel value in default color space
*
* @return the filtered pixel value in the default color space
*/
public int filterRGB(int pX, int pY, int pARGB) {
// Get color components
int r = pARGB >> 16 & 0xFF;
int g = pARGB >> 8 & 0xFF;
int b = pARGB & 0xFF;
// Scale to new contrast
r = LUT[r];
g = LUT[g];
b = LUT[b];
// Return ARGB pixel, leave transparency as is
return (pARGB & 0xFF000000) | (r << 16) | (g << 8) | b;
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.image.RGBImageFilter;
/**
* Adjusts the contrast and brightness of an image.
* <p>
* For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}.
* A value of {@code 0.0} means no change.
* Negative values will make the pixels darker.
* Maximum negative value ({@code -2}) will make all filtered pixels black.
* Positive values will make the pixels brighter.
* Maximum positive value ({@code 2}) will make all filtered pixels white.
* </p>
* <p>
* For contrast, the valid range is {@code -1.0,..,0.0,..,1.0}.
* A value of {@code 0.0} means no change.
* Negative values will reduce contrast.
* Maximum negative value ({@code -1}) will make all filtered pixels grey
* (no contrast).
* Positive values will increase contrast.
* Maximum positive value ({@code 1}) will make all filtered pixels primary
* colors (either black, white, cyan, magenta, yellow, red, blue or green).
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
*
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/BrightnessContrastFilter.java#1 $
*/
// TODO: consider doing something similar to http://archives.java.sun.com/cgi-bin/wa?A2=ind0302&L=jai-interest&F=&S=&P=15947
public class BrightnessContrastFilter extends RGBImageFilter {
// TODO: Replace with RescaleOp?
// This filter can filter IndexColorModel, as it is does not depend on
// the pixels' location
{
canFilterIndexColorModel = true;
}
// Use a pre-calculated lookup table for performance
private final int[] LUT;
/**
* Creates a BrightnessContrastFilter with default values
* ({@code brightness=0.3, contrast=0.3}).
* <p>
* This will slightly increase both brightness and contrast.
* </p>
*/
public BrightnessContrastFilter() {
this(0.3f, 0.3f);
}
/**
* Creates a BrightnessContrastFilter with the given values for brightness
* and contrast.
* <p>
* For brightness, the valid range is {@code -2.0,..,0.0,..,2.0}.
* A value of {@code 0.0} means no change.
* Negative values will make the pixels darker.
* Maximum negative value ({@code -2}) will make all filtered pixels black.
* Positive values will make the pixels brighter.
* Maximum positive value ({@code 2}) will make all filtered pixels white.
* </p>
* <p>
* For contrast, the valid range is {@code -1.0,..,0.0,..,1.0}.
* A value of {@code 0.0} means no change.
* Negative values will reduce contrast.
* Maximum negative value ({@code -1}) will make all filtered pixels grey
* (no contrast).
* Positive values will increase contrast.
* Maximum positive value ({@code 1}) will make all filtered pixels primary
* colors (either black, white, cyan, magenta, yellow, red, blue or green).
* </p>
*
* @param pBrightness adjust the brightness of the image, in the range
* {@code -2.0,..,0.0,..,2.0}.
* @param pContrast adjust the contrast of the image, in the range
* {@code -1.0,..,0.0,..,1.0}.
*/
public BrightnessContrastFilter(float pBrightness, float pContrast) {
LUT = createLUT(pBrightness, pContrast);
}
private static int[] createLUT(float pBrightness, float pContrast) {
int[] lut = new int[256];
// Hmmm.. This approximates Photoshop values.. Not good though..
double contrast = pContrast > 0 ? Math.pow(pContrast, 7.0) * 127.0 : pContrast;
// Convert range [-1,..,0,..,1] -> [0,..,1,..,2]
double brightness = pBrightness + 1.0;
for (int i = 0; i < 256; i++) {
lut[i] = clamp((int) (127.5 * brightness + (i - 127) * (contrast + 1.0)));
}
// Special case, to ensure only primary colors for max contrast
if (pContrast == 1f) {
lut[127] = lut[126];
}
return lut;
}
private static int clamp(int i) {
if (i < 0) {
return 0;
}
if (i > 255) {
return 255;
}
return i;
}
/**
* Filters one pixel, adjusting brightness and contrast according to this
* filter.
*
* @param pX x
* @param pY y
* @param pARGB pixel value in default color space
*
* @return the filtered pixel value in the default color space
*/
public int filterRGB(int pX, int pY, int pARGB) {
// Get color components
int r = pARGB >> 16 & 0xFF;
int g = pARGB >> 8 & 0xFF;
int b = pARGB & 0xFF;
// Scale to new contrast
r = LUT[r];
g = LUT[g];
b = LUT[b];
// Return ARGB pixel, leave transparency as is
return (pARGB & 0xFF000000) | (r << 16) | (g << 8) | b;
}
}
@@ -44,14 +44,16 @@ import java.util.concurrent.CopyOnWriteArrayList;
* A faster, lighter and easier way to convert an {@code Image} to a
* {@code BufferedImage} than using a {@code PixelGrabber}.
* Clients may provide progress listeners to monitor conversion progress.
* <p/>
* <p>
* Supports source image subsampling and source region extraction.
* Supports source images with 16 bit {@link ColorModel} and
* {@link DataBuffer#TYPE_USHORT} transfer type, without converting to
* 32 bit/TYPE_INT.
* <p/>
* </p>
* <p>
* NOTE: Does not support images with more than one {@code ColorModel} or
* different types of pixel data. This is not very common.
* </p>
*
* @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/image/BufferedImageFactory.java#1 $
@@ -77,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;
@@ -89,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;
}
/**
@@ -153,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;
@@ -205,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() {
@@ -251,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() {
@@ -278,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;
}
@@ -306,7 +312,7 @@ public final class BufferedImageFactory {
return;
}
listeners.remove(pListener);
listeners.remove(listener);
}
/**
@@ -322,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;
@@ -349,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 {
@@ -444,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");
@@ -468,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) {
@@ -486,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?
@@ -504,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;
}
}
@@ -1,92 +1,90 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import com.twelvemonkeys.lang.Validate;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
/**
* An {@code Icon} implementation backed by a {@code BufferedImage}.
* <p/>
*
* @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/image/BufferedImageIcon.java#2 $
*/
public class BufferedImageIcon implements Icon {
private final BufferedImage image;
private int width;
private int height;
private final boolean fast;
public BufferedImageIcon(BufferedImage pImage) {
this(pImage, pImage != null ? pImage.getWidth() : 0, pImage != null ? pImage.getHeight() : 0);
}
public BufferedImageIcon(BufferedImage pImage, int pWidth, int pHeight) {
this(pImage, pWidth, pHeight, pImage.getWidth() == pWidth && pImage.getHeight() == pHeight);
}
public BufferedImageIcon(BufferedImage pImage, int pWidth, int pHeight, boolean useFastRendering) {
image = Validate.notNull(pImage, "image");
width = Validate.isTrue(pWidth > 0, pWidth, "width must be positive: %d");
height = Validate.isTrue(pHeight > 0, pHeight, "height must be positive: %d");
fast = useFastRendering;
}
public int getIconHeight() {
return height;
}
public int getIconWidth() {
return width;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
if (fast || !(g instanceof Graphics2D)) {
//System.out.println("Scaling fast");
g.drawImage(image, x, y, width, height, null);
}
else {
//System.out.println("Scaling using interpolation");
Graphics2D g2 = (Graphics2D) g;
AffineTransform xform = AffineTransform.getTranslateInstance(x, y);
xform.scale(width / (double) image.getWidth(), height / (double) image.getHeight());
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(image, xform, null);
}
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import com.twelvemonkeys.lang.Validate;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
/**
* An {@code Icon} implementation backed by a {@code BufferedImage}.
*
* @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/image/BufferedImageIcon.java#2 $
*/
public class BufferedImageIcon implements Icon {
private final BufferedImage image;
private final int width;
private final int height;
private final boolean fast;
public BufferedImageIcon(BufferedImage pImage) {
this(pImage, pImage != null ? pImage.getWidth() : 0, pImage != null ? pImage.getHeight() : 0);
}
public BufferedImageIcon(BufferedImage pImage, int pWidth, int pHeight) {
this(pImage, pWidth, pHeight, pImage.getWidth() == pWidth && pImage.getHeight() == pHeight);
}
public BufferedImageIcon(BufferedImage pImage, int pWidth, int pHeight, boolean useFastRendering) {
image = Validate.notNull(pImage, "image");
width = Validate.isTrue(pWidth > 0, pWidth, "width must be positive: %d");
height = Validate.isTrue(pHeight > 0, pHeight, "height must be positive: %d");
fast = useFastRendering;
}
public int getIconHeight() {
return height;
}
public int getIconWidth() {
return width;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
if (fast || !(g instanceof Graphics2D)) {
//System.out.println("Scaling fast");
g.drawImage(image, x, y, width, height, null);
}
else {
//System.out.println("Scaling using interpolation");
Graphics2D g2 = (Graphics2D) g;
AffineTransform transform = AffineTransform.getTranslateInstance(x, y);
transform.scale(width / (double) image.getWidth(), height / (double) image.getHeight());
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(image, transform, null);
}
}
}
@@ -1,483 +1,485 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import java.util.Random;
/**
* This {@code BufferedImageOp/RasterOp} implements basic
* Floyd-Steinberg error-diffusion algorithm for dithering.
* <P/>
* The weights used are 7/16, 3/16, 5/16 and 1/16, distributed like this:
* <!-- - -
* | |x|7|
* - - - -
* |3|5|1|
* - - -->
* <P/>
* <TABLE border="1" cellpadding="4" cellspacing="0">
* <TR><TD bgcolor="#000000">&nbsp;</TD><TD class="TableHeadingColor"
* align="center">X</TD><TD>7/16</TD></TR>
* <TR><TD>3/16</TD><TD>5/16</TD><TD>1/16</TD></TR>
* </TABLE>
* <P/>
* See <A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201848406&rl=1">Computer Graphics (Foley et al.)</a>
* for more information.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
*
* @version $Id: DiffusionDither.java#1 $
*/
public class DiffusionDither implements BufferedImageOp, RasterOp {
private static final int FS_SCALE = 1 << 8;
private static final Random RANDOM = new Random();
protected final IndexColorModel indexColorModel;
private boolean alternateScans = true;
/**
* Creates a {@code DiffusionDither}, using the given
* {@code IndexColorModel} for dithering into.
*
* @param pICM an IndexColorModel.
*/
public DiffusionDither(final IndexColorModel pICM) {
// Store color model
indexColorModel = pICM;
}
/**
* Creates a {@code DiffusionDither}, with no fixed
* {@code IndexColorModel}. The color model will be generated for each
* filtering, unless the destination image already has an
* {@code IndexColorModel}.
*/
public DiffusionDither() {
this(null);
}
/**
* Sets the scan mode. If the parameter is true, error distribution for
* every even line will be left-to-right, while odd lines will be
* right-to-left.
* The default is {@code true}.
*
* @param pUse {@code true} if scan mode should be alternating left/right
*/
public void setAlternateScans(boolean pUse) {
alternateScans = pUse;
}
/**
* Creates a compatible {@code BufferedImage} to dither into.
* Only {@code IndexColorModel} allowed.
*
* @return a compatible {@code BufferedImage}
*
* @throws ImageFilterException if {@code pDestCM} is not {@code null} or
* an instance of {@code IndexColorModel}.
*/
public final BufferedImage createCompatibleDestImage(BufferedImage pSource, ColorModel pDestCM) {
if (pDestCM == null) {
return new BufferedImage(pSource.getWidth(), pSource.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED,
getICM(pSource));
}
else if (pDestCM instanceof IndexColorModel) {
return new BufferedImage(pSource.getWidth(), pSource.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED,
(IndexColorModel) pDestCM);
}
else {
throw new ImageFilterException("Only IndexColorModel allowed.");
}
}
/**
* Creates a compatible {@code Raster} to dither into.
* Only {@code IndexColorModel} allowed.
*
* @param pSrc the source raster
*
* @return a {@code WritableRaster}
*/
public final WritableRaster createCompatibleDestRaster(Raster pSrc) {
return createCompatibleDestRaster(pSrc, getICM(pSrc));
}
/**
* Creates a compatible {@code Raster} to dither into.
*
* @param pSrc the source raster.
* @param pIndexColorModel the index color model used to create a {@code Raster}.
*
* @return a {@code WritableRaster}
*/
public final WritableRaster createCompatibleDestRaster(Raster pSrc, IndexColorModel pIndexColorModel) {
return pIndexColorModel.createCompatibleWritableRaster(pSrc.getWidth(), pSrc.getHeight());
}
/**
* Returns the bounding box of the filtered destination image. Since
* this is not a geometric operation, the bounding box does not
* change.
* @param pSrc the {@code BufferedImage} to be filtered
* @return the bounds of the filtered definition image.
*/
public final Rectangle2D getBounds2D(BufferedImage pSrc) {
return getBounds2D(pSrc.getRaster());
}
/**
* Returns the bounding box of the filtered destination Raster. Since
* this is not a geometric operation, the bounding box does not
* change.
* @param pSrc the {@code Raster} to be filtered
* @return the bounds of the filtered definition {@code Raster}.
*/
public final Rectangle2D getBounds2D(Raster pSrc) {
return pSrc.getBounds();
}
/**
* Returns the location of the destination point given a
* point in the source. If {@code dstPt} is not
* {@code null}, it will be used to hold the return value.
* Since this is not a geometric operation, the {@code srcPt}
* will equal the {@code dstPt}.
* @param pSrcPt a {@code Point2D} that represents a point
* in the source image
* @param pDstPt a {@code Point2D}that represents the location
* in the destination
* @return the {@code Point2D} in the destination that
* corresponds to the specified point in the source.
*/
public final Point2D getPoint2D(Point2D pSrcPt, Point2D pDstPt) {
// Create new Point, if needed
if (pDstPt == null) {
pDstPt = new Point2D.Float();
}
// Copy location
pDstPt.setLocation(pSrcPt.getX(), pSrcPt.getY());
// Return dest
return pDstPt;
}
/**
* Returns the rendering mHints for this op.
* @return the {@code RenderingHints} object associated
* with this op.
*/
public final RenderingHints getRenderingHints() {
return null;
}
/**
* Converts an int ARGB to int triplet.
*/
private static int[] toRGBArray(int pARGB, int[] pBuffer) {
pBuffer[0] = ((pARGB & 0x00ff0000) >> 16);
pBuffer[1] = ((pARGB & 0x0000ff00) >> 8);
pBuffer[2] = ((pARGB & 0x000000ff));
//pBuffer[3] = ((pARGB & 0xff000000) >> 24); // alpha
return pBuffer;
}
/**
* Converts a int triplet to int ARGB.
*/
private static int toIntARGB(int[] pRGB) {
return 0xff000000 // All opaque
| (pRGB[0] << 16)
| (pRGB[1] << 8)
| (pRGB[2]);
/*
| ((int) (pRGB[0] << 16) & 0x00ff0000)
| ((int) (pRGB[1] << 8) & 0x0000ff00)
| ((int) (pRGB[2] ) & 0x000000ff);
*/
}
/**
* Performs a single-input/single-output dither operation, applying basic
* Floyd-Steinberg error-diffusion to the image.
*
* @param pSource the source image
* @param pDest the destination image
*
* @return the destination image, or a new image, if {@code pDest} was
* {@code null}.
*/
public final BufferedImage filter(BufferedImage pSource, BufferedImage pDest) {
// Create destination image, if none provided
if (pDest == null) {
pDest = createCompatibleDestImage(pSource, getICM(pSource));
}
else if (!(pDest.getColorModel() instanceof IndexColorModel)) {
throw new ImageFilterException("Only IndexColorModel allowed.");
}
// Filter rasters
filter(pSource.getRaster(), pDest.getRaster(), (IndexColorModel) pDest.getColorModel());
return pDest;
}
/**
* Performs a single-input/single-output dither operation, applying basic
* Floyd-Steinberg error-diffusion to the image.
*
* @param pSource the source raster, assumed to be in sRGB
* @param pDest the destination raster, may be {@code null}
*
* @return the destination raster, or a new raster, if {@code pDest} was
* {@code null}.
*/
public final WritableRaster filter(final Raster pSource, WritableRaster pDest) {
return filter(pSource, pDest, getICM(pSource));
}
private IndexColorModel getICM(BufferedImage pSource) {
return (indexColorModel != null ? indexColorModel : IndexImage.getIndexColorModel(pSource, 256, IndexImage.TRANSPARENCY_BITMASK));
}
private IndexColorModel getICM(Raster pSource) {
return (indexColorModel != null ? indexColorModel : createIndexColorModel(pSource));
}
private IndexColorModel createIndexColorModel(Raster pSource) {
BufferedImage image = new BufferedImage(pSource.getWidth(), pSource.getHeight(),
BufferedImage.TYPE_INT_ARGB);
image.setData(pSource);
return IndexImage.getIndexColorModel(image, 256, IndexImage.TRANSPARENCY_BITMASK);
}
/**
* Performs a single-input/single-output dither operation, applying basic
* Floyd-Steinberg error-diffusion to the image.
*
* @param pSource the source raster, assumed to be in sRGB
* @param pDest the destination raster, may be {@code null}
* @param pColorModel the indexed color model to use
*
* @return the destination raster, or a new raster, if {@code pDest} was
* {@code null}.
*/
public final WritableRaster filter(final Raster pSource, WritableRaster pDest, IndexColorModel pColorModel) {
int width = pSource.getWidth();
int height = pSource.getHeight();
// Create destination raster if needed
if (pDest == null) {
pDest = createCompatibleDestRaster(pSource, pColorModel);
}
// Initialize Floyd-Steinberg error vectors.
// +2 to handle the previous pixel and next pixel case minimally
// When reference for column, add 1 to reference as this buffer is
// offset from actual column position by one to allow FS to not check
// left/right edge conditions
int[][] currErr = new int[width + 2][3];
int[][] nextErr = new int[width + 2][3];
// Random errors in [-1 .. 1] - for first row
for (int i = 0; i < width + 2; i++) {
// Note: This is broken for the strange cases where nextInt returns Integer.MIN_VALUE
currErr[i][0] = RANDOM.nextInt(FS_SCALE * 2) - FS_SCALE;
currErr[i][1] = RANDOM.nextInt(FS_SCALE * 2) - FS_SCALE;
currErr[i][2] = RANDOM.nextInt(FS_SCALE * 2) - FS_SCALE;
}
// Temp buffers
final int[] diff = new int[3]; // No alpha
final int[] inRGB = new int[4];
final int[] outRGB = new int[4];
Object pixel = null;
boolean forward = true;
// Loop through image data
for (int y = 0; y < height; y++) {
// Clear out next error rows for colour errors
for (int i = nextErr.length; --i >= 0;) {
nextErr[i][0] = 0;
nextErr[i][1] = 0;
nextErr[i][2] = 0;
}
// Set up start column and limit
int x;
int limit;
if (forward) {
x = 0;
limit = width;
}
else {
x = width - 1;
limit = -1;
}
// TODO: Use getPixels instead of getPixel for better performance?
// Loop over row
while (true) {
// Get RGB from original raster
// DON'T KNOW IF THIS WILL WORK FOR ALL TYPES.
pSource.getPixel(x, y, inRGB);
// Get error for this pixel & add error to rgb
for (int i = 0; i < 3; i++) {
// Make a 28.4 FP number, add Error (with fraction),
// rounding and truncate to int
inRGB[i] = ((inRGB[i] << 4) + currErr[x + 1][i] + 0x08) >> 4;
// Clamp
if (inRGB[i] > 255) {
inRGB[i] = 255;
}
else if (inRGB[i] < 0) {
inRGB[i] = 0;
}
}
// Get pixel value...
// It is VERY important that we are using a IndexColorModel that
// support reverse color lookup for speed.
pixel = pColorModel.getDataElements(toIntARGB(inRGB), pixel);
// ...set it...
pDest.setDataElements(x, y, pixel);
// ..and get back the closet match
pDest.getPixel(x, y, outRGB);
// Convert the value to default sRGB
// Should work for all transfertypes supported by IndexColorModel
toRGBArray(pColorModel.getRGB(outRGB[0]), outRGB);
// Find diff
diff[0] = inRGB[0] - outRGB[0];
diff[1] = inRGB[1] - outRGB[1];
diff[2] = inRGB[2] - outRGB[2];
// Apply F-S error diffusion
// Serpentine scan: left-right
if (forward) {
// Row 1 (y)
// Update error in this pixel (x + 1)
currErr[x + 2][0] += diff[0] * 7;
currErr[x + 2][1] += diff[1] * 7;
currErr[x + 2][2] += diff[2] * 7;
// Row 2 (y + 1)
// Update error in this pixel (x - 1)
nextErr[x][0] += diff[0] * 3;
nextErr[x][1] += diff[1] * 3;
nextErr[x][2] += diff[2] * 3;
// Update error in this pixel (x)
nextErr[x + 1][0] += diff[0] * 5;
nextErr[x + 1][1] += diff[1] * 5;
nextErr[x + 1][2] += diff[2] * 5;
// Update error in this pixel (x + 1)
// TODO: Consider calculating this using
// error term = error - sum(error terms 1, 2 and 3)
// See Computer Graphics (Foley et al.), p. 573
nextErr[x + 2][0] += diff[0]; // * 1;
nextErr[x + 2][1] += diff[1]; // * 1;
nextErr[x + 2][2] += diff[2]; // * 1;
// Next
x++;
// Done?
if (x >= limit) {
break;
}
}
else {
// Row 1 (y)
// Update error in this pixel (x - 1)
currErr[x][0] += diff[0] * 7;
currErr[x][1] += diff[1] * 7;
currErr[x][2] += diff[2] * 7;
// Row 2 (y + 1)
// Update error in this pixel (x + 1)
nextErr[x + 2][0] += diff[0] * 3;
nextErr[x + 2][1] += diff[1] * 3;
nextErr[x + 2][2] += diff[2] * 3;
// Update error in this pixel (x)
nextErr[x + 1][0] += diff[0] * 5;
nextErr[x + 1][1] += diff[1] * 5;
nextErr[x + 1][2] += diff[2] * 5;
// Update error in this pixel (x - 1)
// TODO: Consider calculating this using
// error term = error - sum(error terms 1, 2 and 3)
// See Computer Graphics (Foley et al.), p. 573
nextErr[x][0] += diff[0]; // * 1;
nextErr[x][1] += diff[1]; // * 1;
nextErr[x][2] += diff[2]; // * 1;
// Previous
x--;
// Done?
if (x <= limit) {
break;
}
}
}
// Make next error info current for next iteration
int[][] temperr;
temperr = currErr;
currErr = nextErr;
nextErr = temperr;
// Toggle direction
if (alternateScans) {
forward = !forward;
}
}
return pDest;
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import java.util.Random;
/**
* This {@code BufferedImageOp/RasterOp} implements basic
* Floyd-Steinberg error-diffusion algorithm for dithering.
* <p>
* The weights used are 7/16, 3/16, 5/16 and 1/16, distributed like this:
* <!-- - -
* | |x|7|
* - - - -
* |3|5|1|
* - - -->
* </p>
* <table border="1">
* <caption>Floyd-Steinberg error-diffusion weights</caption>
* <tr><td style="background:#000000">&nbsp;</td><td class="TableHeadingColor"
* style="text-align:center">x</td><td>7/16</td></tr>
* <tr><td>3/16</td><td>5/16</td><td>1/16</td></tr>
* </table>
* <p>
* See <A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201848406&rl=1">Computer Graphics (Foley et al.)</a>
* for more information.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
*
* @version $Id: DiffusionDither.java#1 $
*/
public class DiffusionDither implements BufferedImageOp, RasterOp {
private static final int FS_SCALE = 1 << 8;
private static final Random RANDOM = new Random();
protected final IndexColorModel indexColorModel;
private boolean alternateScans = true;
/**
* Creates a {@code DiffusionDither}, using the given
* {@code IndexColorModel} for dithering into.
*
* @param pICM an IndexColorModel.
*/
public DiffusionDither(final IndexColorModel pICM) {
// Store color model
indexColorModel = pICM;
}
/**
* Creates a {@code DiffusionDither}, with no fixed
* {@code IndexColorModel}. The color model will be generated for each
* filtering, unless the destination image already has an
* {@code IndexColorModel}.
*/
public DiffusionDither() {
this(null);
}
/**
* Sets the scan mode. If the parameter is true, error distribution for
* every even line will be left-to-right, while odd lines will be
* right-to-left.
* The default is {@code true}.
*
* @param pUse {@code true} if scan mode should be alternating left/right
*/
public void setAlternateScans(boolean pUse) {
alternateScans = pUse;
}
/**
* Creates a compatible {@code BufferedImage} to dither into.
* Only {@code IndexColorModel} allowed.
*
* @return a compatible {@code BufferedImage}
*
* @throws ImageFilterException if {@code pDestCM} is not {@code null} or
* an instance of {@code IndexColorModel}.
*/
public final BufferedImage createCompatibleDestImage(BufferedImage pSource, ColorModel pDestCM) {
if (pDestCM == null) {
return new BufferedImage(pSource.getWidth(), pSource.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED,
getICM(pSource));
}
else if (pDestCM instanceof IndexColorModel) {
return new BufferedImage(pSource.getWidth(), pSource.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED,
(IndexColorModel) pDestCM);
}
else {
throw new ImageFilterException("Only IndexColorModel allowed.");
}
}
/**
* Creates a compatible {@code Raster} to dither into.
* Only {@code IndexColorModel} allowed.
*
* @param pSrc the source raster
*
* @return a {@code WritableRaster}
*/
public final WritableRaster createCompatibleDestRaster(Raster pSrc) {
return createCompatibleDestRaster(pSrc, getICM(pSrc));
}
/**
* Creates a compatible {@code Raster} to dither into.
*
* @param pSrc the source raster.
* @param pIndexColorModel the index color model used to create a {@code Raster}.
*
* @return a {@code WritableRaster}
*/
public final WritableRaster createCompatibleDestRaster(Raster pSrc, IndexColorModel pIndexColorModel) {
return pIndexColorModel.createCompatibleWritableRaster(pSrc.getWidth(), pSrc.getHeight());
}
/**
* Returns the bounding box of the filtered destination image. Since
* this is not a geometric operation, the bounding box does not
* change.
* @param pSrc the {@code BufferedImage} to be filtered
* @return the bounds of the filtered definition image.
*/
public final Rectangle2D getBounds2D(BufferedImage pSrc) {
return getBounds2D(pSrc.getRaster());
}
/**
* Returns the bounding box of the filtered destination Raster. Since
* this is not a geometric operation, the bounding box does not
* change.
* @param pSrc the {@code Raster} to be filtered
* @return the bounds of the filtered definition {@code Raster}.
*/
public final Rectangle2D getBounds2D(Raster pSrc) {
return pSrc.getBounds();
}
/**
* Returns the location of the destination point given a
* point in the source. If {@code dstPt} is not
* {@code null}, it will be used to hold the return value.
* Since this is not a geometric operation, the {@code srcPt}
* will equal the {@code dstPt}.
* @param pSrcPt a {@code Point2D} that represents a point
* in the source image
* @param pDstPt a {@code Point2D}that represents the location
* in the destination
* @return the {@code Point2D} in the destination that
* corresponds to the specified point in the source.
*/
public final Point2D getPoint2D(Point2D pSrcPt, Point2D pDstPt) {
// Create new Point, if needed
if (pDstPt == null) {
pDstPt = new Point2D.Float();
}
// Copy location
pDstPt.setLocation(pSrcPt.getX(), pSrcPt.getY());
// Return dest
return pDstPt;
}
/**
* Returns the rendering mHints for this op.
* @return the {@code RenderingHints} object associated
* with this op.
*/
public final RenderingHints getRenderingHints() {
return null;
}
/**
* Converts an int ARGB to int triplet.
*/
private static int[] toRGBArray(int pARGB, int[] pBuffer) {
pBuffer[0] = ((pARGB & 0x00ff0000) >> 16);
pBuffer[1] = ((pARGB & 0x0000ff00) >> 8);
pBuffer[2] = ((pARGB & 0x000000ff));
//pBuffer[3] = ((pARGB & 0xff000000) >> 24); // alpha
return pBuffer;
}
/**
* Converts a int triplet to int ARGB.
*/
private static int toIntARGB(int[] pRGB) {
return 0xff000000 // All opaque
| (pRGB[0] << 16)
| (pRGB[1] << 8)
| (pRGB[2]);
/*
| ((int) (pRGB[0] << 16) & 0x00ff0000)
| ((int) (pRGB[1] << 8) & 0x0000ff00)
| ((int) (pRGB[2] ) & 0x000000ff);
*/
}
/**
* Performs a single-input/single-output dither operation, applying basic
* Floyd-Steinberg error-diffusion to the image.
*
* @param pSource the source image
* @param pDest the destination image
*
* @return the destination image, or a new image, if {@code pDest} was
* {@code null}.
*/
public final BufferedImage filter(BufferedImage pSource, BufferedImage pDest) {
// Create destination image, if none provided
if (pDest == null) {
pDest = createCompatibleDestImage(pSource, getICM(pSource));
}
else if (!(pDest.getColorModel() instanceof IndexColorModel)) {
throw new ImageFilterException("Only IndexColorModel allowed.");
}
// Filter rasters
filter(pSource.getRaster(), pDest.getRaster(), (IndexColorModel) pDest.getColorModel());
return pDest;
}
/**
* Performs a single-input/single-output dither operation, applying basic
* Floyd-Steinberg error-diffusion to the image.
*
* @param pSource the source raster, assumed to be in sRGB
* @param pDest the destination raster, may be {@code null}
*
* @return the destination raster, or a new raster, if {@code pDest} was
* {@code null}.
*/
public final WritableRaster filter(final Raster pSource, WritableRaster pDest) {
return filter(pSource, pDest, getICM(pSource));
}
private IndexColorModel getICM(BufferedImage pSource) {
return (indexColorModel != null ? indexColorModel : IndexImage.getIndexColorModel(pSource, 256, IndexImage.TRANSPARENCY_BITMASK));
}
private IndexColorModel getICM(Raster pSource) {
return (indexColorModel != null ? indexColorModel : createIndexColorModel(pSource));
}
private IndexColorModel createIndexColorModel(Raster pSource) {
BufferedImage image = new BufferedImage(pSource.getWidth(), pSource.getHeight(),
BufferedImage.TYPE_INT_ARGB);
image.setData(pSource);
return IndexImage.getIndexColorModel(image, 256, IndexImage.TRANSPARENCY_BITMASK);
}
/**
* Performs a single-input/single-output dither operation, applying basic
* Floyd-Steinberg error-diffusion to the image.
*
* @param pSource the source raster, assumed to be in sRGB
* @param pDest the destination raster, may be {@code null}
* @param pColorModel the indexed color model to use
*
* @return the destination raster, or a new raster, if {@code pDest} was
* {@code null}.
*/
public final WritableRaster filter(final Raster pSource, WritableRaster pDest, IndexColorModel pColorModel) {
int width = pSource.getWidth();
int height = pSource.getHeight();
// Create destination raster if needed
if (pDest == null) {
pDest = createCompatibleDestRaster(pSource, pColorModel);
}
// Initialize Floyd-Steinberg error vectors.
// +2 to handle the previous pixel and next pixel case minimally
// When reference for column, add 1 to reference as this buffer is
// offset from actual column position by one to allow FS to not check
// left/right edge conditions
int[][] currErr = new int[width + 2][3];
int[][] nextErr = new int[width + 2][3];
// Random errors in [-1 .. 1] - for first row
for (int i = 0; i < width + 2; i++) {
// Note: This is broken for the strange cases where nextInt returns Integer.MIN_VALUE
currErr[i][0] = RANDOM.nextInt(FS_SCALE * 2) - FS_SCALE;
currErr[i][1] = RANDOM.nextInt(FS_SCALE * 2) - FS_SCALE;
currErr[i][2] = RANDOM.nextInt(FS_SCALE * 2) - FS_SCALE;
}
// Temp buffers
final int[] diff = new int[3]; // No alpha
final int[] inRGB = new int[4];
final int[] outRGB = new int[4];
Object pixel = null;
boolean forward = true;
// Loop through image data
for (int y = 0; y < height; y++) {
// Clear out next error rows for colour errors
for (int i = nextErr.length; --i >= 0;) {
nextErr[i][0] = 0;
nextErr[i][1] = 0;
nextErr[i][2] = 0;
}
// Set up start column and limit
int x;
int limit;
if (forward) {
x = 0;
limit = width;
}
else {
x = width - 1;
limit = -1;
}
// TODO: Use getPixels instead of getPixel for better performance?
// Loop over row
while (true) {
// Get RGB from original raster
// DON'T KNOW IF THIS WILL WORK FOR ALL TYPES.
pSource.getPixel(x, y, inRGB);
// Get error for this pixel & add error to rgb
for (int i = 0; i < 3; i++) {
// Make a 28.4 FP number, add Error (with fraction),
// rounding and truncate to int
inRGB[i] = ((inRGB[i] << 4) + currErr[x + 1][i] + 0x08) >> 4;
// Clamp
if (inRGB[i] > 255) {
inRGB[i] = 255;
}
else if (inRGB[i] < 0) {
inRGB[i] = 0;
}
}
// Get pixel value...
// It is VERY important that we are using a IndexColorModel that
// support reverse color lookup for speed.
pixel = pColorModel.getDataElements(toIntARGB(inRGB), pixel);
// ...set it...
pDest.setDataElements(x, y, pixel);
// ..and get back the closet match
pDest.getPixel(x, y, outRGB);
// Convert the value to default sRGB
// Should work for all transfertypes supported by IndexColorModel
toRGBArray(pColorModel.getRGB(outRGB[0]), outRGB);
// Find diff
diff[0] = inRGB[0] - outRGB[0];
diff[1] = inRGB[1] - outRGB[1];
diff[2] = inRGB[2] - outRGB[2];
// Apply F-S error diffusion
// Serpentine scan: left-right
if (forward) {
// Row 1 (y)
// Update error in this pixel (x + 1)
currErr[x + 2][0] += diff[0] * 7;
currErr[x + 2][1] += diff[1] * 7;
currErr[x + 2][2] += diff[2] * 7;
// Row 2 (y + 1)
// Update error in this pixel (x - 1)
nextErr[x][0] += diff[0] * 3;
nextErr[x][1] += diff[1] * 3;
nextErr[x][2] += diff[2] * 3;
// Update error in this pixel (x)
nextErr[x + 1][0] += diff[0] * 5;
nextErr[x + 1][1] += diff[1] * 5;
nextErr[x + 1][2] += diff[2] * 5;
// Update error in this pixel (x + 1)
// TODO: Consider calculating this using
// error term = error - sum(error terms 1, 2 and 3)
// See Computer Graphics (Foley et al.), p. 573
nextErr[x + 2][0] += diff[0]; // * 1;
nextErr[x + 2][1] += diff[1]; // * 1;
nextErr[x + 2][2] += diff[2]; // * 1;
// Next
x++;
// Done?
if (x >= limit) {
break;
}
}
else {
// Row 1 (y)
// Update error in this pixel (x - 1)
currErr[x][0] += diff[0] * 7;
currErr[x][1] += diff[1] * 7;
currErr[x][2] += diff[2] * 7;
// Row 2 (y + 1)
// Update error in this pixel (x + 1)
nextErr[x + 2][0] += diff[0] * 3;
nextErr[x + 2][1] += diff[1] * 3;
nextErr[x + 2][2] += diff[2] * 3;
// Update error in this pixel (x)
nextErr[x + 1][0] += diff[0] * 5;
nextErr[x + 1][1] += diff[1] * 5;
nextErr[x + 1][2] += diff[2] * 5;
// Update error in this pixel (x - 1)
// TODO: Consider calculating this using
// error term = error - sum(error terms 1, 2 and 3)
// See Computer Graphics (Foley et al.), p. 573
nextErr[x][0] += diff[0]; // * 1;
nextErr[x][1] += diff[1]; // * 1;
nextErr[x][2] += diff[2]; // * 1;
// Previous
x--;
// Done?
if (x <= limit) {
break;
}
}
}
// Make next error info current for next iteration
int[][] temperr;
temperr = currErr;
currErr = nextErr;
nextErr = temperr;
// Toggle direction
if (alternateScans) {
forward = !forward;
}
}
return pDest;
}
}
@@ -1,84 +1,86 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.*;
/**
* GraphicsUtil
*
* @author <a href="mailto:harald.kuhr@gmail.no">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/GraphicsUtil.java#1 $
*/
public final class GraphicsUtil {
/**
* Enables anti-aliasing in the {@code Graphics} object.
* <p/>
* Anti-aliasing is enabled by casting to {@code Graphics2D} and setting
* the rendering hint {@code RenderingHints.KEY_ANTIALIASING} to
* {@code RenderingHints.VALUE_ANTIALIAS_ON}.
*
* @param pGraphics the graphics object
* @throws ClassCastException if {@code pGraphics} is not an instance of
* {@code Graphics2D}.
*
* @see java.awt.RenderingHints#KEY_ANTIALIASING
*/
public static void enableAA(final Graphics pGraphics) {
((Graphics2D) pGraphics).setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
}
/**
* Sets the alpha in the {@code Graphics} object.
* <p/>
* Alpha is set by casting to {@code Graphics2D} and setting the composite
* to the rule {@code AlphaComposite.SRC_OVER} multiplied by the given
* alpha.
*
* @param pGraphics the graphics object
* @param pAlpha the alpha level, {@code alpha} must be a floating point
* number in the inclusive range [0.0,&nbsp;1.0].
* @throws ClassCastException if {@code pGraphics} is not an instance of
* {@code Graphics2D}.
*
* @see java.awt.AlphaComposite#SRC_OVER
* @see java.awt.AlphaComposite#getInstance(int, float)
*/
public static void setAlpha(final Graphics pGraphics, final float pAlpha) {
((Graphics2D) pGraphics).setComposite(
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, pAlpha)
);
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.*;
/**
* GraphicsUtil
*
* @author <a href="mailto:harald.kuhr@gmail.no">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/GraphicsUtil.java#1 $
*/
public final class GraphicsUtil {
/**
* Enables anti-aliasing in the {@code Graphics} object.
* <p>
* Anti-aliasing is enabled by casting to {@code Graphics2D} and setting
* the rendering hint {@code RenderingHints.KEY_ANTIALIASING} to
* {@code RenderingHints.VALUE_ANTIALIAS_ON}.
* </p>
*
* @param pGraphics the graphics object
* @throws ClassCastException if {@code pGraphics} is not an instance of
* {@code Graphics2D}.
*
* @see java.awt.RenderingHints#KEY_ANTIALIASING
*/
public static void enableAA(final Graphics pGraphics) {
((Graphics2D) pGraphics).setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
}
/**
* Sets the alpha in the {@code Graphics} object.
* <p>
* Alpha is set by casting to {@code Graphics2D} and setting the composite
* to the rule {@code AlphaComposite.SRC_OVER} multiplied by the given
* alpha.
* </p>
*
* @param pGraphics the graphics object
* @param pAlpha the alpha level, {@code alpha} must be a floating point
* number in the inclusive range [0.0,&nbsp;1.0].
* @throws ClassCastException if {@code pGraphics} is not an instance of
* {@code Graphics2D}.
*
* @see java.awt.AlphaComposite#SRC_OVER
* @see java.awt.AlphaComposite#getInstance(int, float)
*/
public static void setAlpha(final Graphics pGraphics, final float pAlpha) {
((Graphics2D) pGraphics).setComposite(
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, pAlpha)
);
}
}
@@ -1,131 +1,132 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.image.RGBImageFilter;
/**
* This class can convert a color image to grayscale.
* <P/>
* Uses ITU standard conversion: (222 * Red + 707 * Green + 71 * Blue) / 1000.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
*
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/GrayFilter.java#1 $
*
*/
public class GrayFilter extends RGBImageFilter {
// This filter can filter IndexColorModel
{
canFilterIndexColorModel = true;
}
private int low = 0;
private float range = 1.0f;
/**
* Constructs a GrayFilter using ITU color-conversion.
*/
public GrayFilter() {
}
/**
* Constructs a GrayFilter using ITU color-conversion, and a dynamic range between
* pLow and pHigh.
*
* @param pLow float in the range 0..1
* @param pHigh float in the range 0..1 and >= pLow
*/
public GrayFilter(float pLow, float pHigh) {
if (pLow > pHigh) {
pLow = 0f;
}
// Make sure high and low are inside range
if (pLow < 0f) {
pLow = 0f;
}
else if (pLow > 1f) {
pLow = 1f;
}
if (pHigh < 0f) {
pHigh = 0f;
}
else if (pHigh > 1f) {
pHigh = 1f;
}
low = (int) (pLow * 255f);
range = pHigh - pLow;
}
/**
* Constructs a GrayFilter using ITU color-conversion, and a dynamic
* range between pLow and pHigh.
*
* @param pLow integer in the range 0..255
* @param pHigh inteeger in the range 0..255 and >= pLow
*/
public GrayFilter(int pLow, int pHigh) {
this(pLow / 255f, pHigh / 255f);
}
/**
* Filters one pixel using ITU color-conversion.
*
* @param pX x
* @param pY y
* @param pARGB pixel value in default color space
*
* @return the filtered pixel value in the default color space
*/
public int filterRGB(int pX, int pY, int pARGB) {
// Get color components
int r = pARGB >> 16 & 0xFF;
int g = pARGB >> 8 & 0xFF;
int b = pARGB & 0xFF;
// ITU standard: Gray scale=(222*Red+707*Green+71*Blue)/1000
int gray = (222 * r + 707 * g + 71 * b) / 1000;
//int gray = (int) ((float) (r + g + b) / 3.0f);
if (range != 1.0f) {
// Apply range
gray = low + (int) (gray * range);
}
// Return ARGB pixel
return (pARGB & 0xFF000000) | (gray << 16) | (gray << 8) | gray;
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.image.RGBImageFilter;
/**
* This class can convert a color image to grayscale.
* <p>
* Uses ITU standard conversion: (222 * Red + 707 * Green + 71 * Blue) / 1000.
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
*
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/GrayFilter.java#1 $
*
*/
public class GrayFilter extends RGBImageFilter {
// This filter can filter IndexColorModel
{
canFilterIndexColorModel = true;
}
private int low = 0;
private float range = 1.0f;
/**
* Constructs a GrayFilter using ITU color-conversion.
*/
public GrayFilter() {
}
/**
* Constructs a GrayFilter using ITU color-conversion, and a dynamic range between
* pLow and pHigh.
*
* @param pLow float in the range 0..1
* @param pHigh float in the range 0..1 and &gt;= pLow
*/
public GrayFilter(float pLow, float pHigh) {
if (pLow > pHigh) {
pLow = 0f;
}
// Make sure high and low are inside range
if (pLow < 0f) {
pLow = 0f;
}
else if (pLow > 1f) {
pLow = 1f;
}
if (pHigh < 0f) {
pHigh = 0f;
}
else if (pHigh > 1f) {
pHigh = 1f;
}
low = (int) (pLow * 255f);
range = pHigh - pLow;
}
/**
* Constructs a GrayFilter using ITU color-conversion, and a dynamic
* range between pLow and pHigh.
*
* @param pLow integer in the range 0..255
* @param pHigh integer in the range 0..255 and &gt;= pLow
*/
public GrayFilter(int pLow, int pHigh) {
this(pLow / 255f, pHigh / 255f);
}
/**
* Filters one pixel using ITU color-conversion.
*
* @param pX x
* @param pY y
* @param pARGB pixel value in default color space
*
* @return the filtered pixel value in the default color space
*/
public int filterRGB(int pX, int pY, int pARGB) {
// Get color components
int r = pARGB >> 16 & 0xFF;
int g = pARGB >> 8 & 0xFF;
int b = pARGB & 0xFF;
// ITU standard: Gray scale=(222*Red+707*Green+71*Blue)/1000
int gray = (222 * r + 707 * g + 71 * b) / 1000;
//int gray = (int) ((float) (r + g + b) / 3.0f);
if (range != 1.0f) {
// Apply range
gray = low + (int) (gray * range);
}
// Return ARGB pixel
return (pARGB & 0xFF000000) | (gray << 16) | (gray << 8) | gray;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,213 +1,214 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
/**
* Inverse Colormap to provide efficient lookup of any given input color
* to the closest match to the given color map.
* <p/>
* Based on "Efficient Inverse Color Map Computation" by Spencer W. Thomas
* in "Graphics Gems Volume II"
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author Robin Luiten (Java port)
* @author Spencer W. Thomas (original c version).
*
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/InverseColorMap.java#1 $
*/
class InverseColorMap {
/**
* Number of high bits of each color channel to use to lookup near match
*/
final static int QUANTBITS = 5;
/**
* Truncated bits of each color channel
*/
final static int TRUNCBITS = 8 - QUANTBITS;
/**
* BITMASK representing the bits for blue in the color lookup
*/
final static int QUANTMASK_BLUE = (1 << 5) - 1;
/**
* BITMASK representing the bits for green in the color lookup
*/
final static int QUANTMASK_GREEN = (QUANTMASK_BLUE << QUANTBITS);
/**
* BITMASK representing the bits for red in the color lookup
*/
final static int QUANTMASK_RED = (QUANTMASK_GREEN << QUANTBITS);
/**
* Maximum value a quantised color channel can have
*/
final static int MAXQUANTVAL = 1 << 5;
byte[] rgbMapByte;
int[] rgbMapInt;
int numColors;
int maxColor;
byte[] inverseRGB; // inverse rgb color map
int transparentIndex = -1;
/**
* @param pRGBColorMap the rgb color map to create inverse color map for.
*/
InverseColorMap(byte[] pRGBColorMap) {
this(pRGBColorMap, -1);
}
/**
* @param pRGBColorMap the rgb color map to create inverse color map for.
*/
// HaraldK 20040801: Added support for int[]
InverseColorMap(int[] pRGBColorMap) {
this(pRGBColorMap, -1);
}
/**
* @param pRGBColorMap the rgb color map to create inverse color map for.
* @param pTransparent the index of the transparent pixel in the map
*/
InverseColorMap(byte[] pRGBColorMap, int pTransparent) {
rgbMapByte = pRGBColorMap;
numColors = rgbMapByte.length / 4;
transparentIndex = pTransparent;
inverseRGB = new byte[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL];
initIRGB(new int[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL]);
}
/**
* @param pRGBColorMap the rgb color map to create inverse color map for.
* @param pTransparent the index of the transparent pixel in the map
*/
InverseColorMap(int[] pRGBColorMap, int pTransparent) {
rgbMapInt = pRGBColorMap;
numColors = rgbMapInt.length;
transparentIndex = pTransparent;
inverseRGB = new byte[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL];
initIRGB(new int[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL]);
}
/**
* Simple inverse color table creation method.
* @param pTemp temp array
*/
void initIRGB(int[] pTemp) {
final int x = (1 << TRUNCBITS); // 8 the size of 1 Dimension of each quantized cell
final int xsqr = 1 << (TRUNCBITS * 2); // 64 - twice the smallest step size vale of quantized colors
final int xsqr2 = xsqr + xsqr;
for (int i = 0; i < numColors; ++i) {
if (i == transparentIndex) {
// Skip the transparent pixel
continue;
}
int red, r, rdist, rinc, rxx;
int green, g, gdist, ginc, gxx;
int blue, b, bdist, binc, bxx;
// HaraldK 20040801: Added support for int[]
if (rgbMapByte != null) {
red = rgbMapByte[i * 4] & 0xFF;
green = rgbMapByte[i * 4 + 1] & 0xFF;
blue = rgbMapByte[i * 4 + 2] & 0xFF;
}
else if (rgbMapInt != null) {
red = (rgbMapInt[i] >> 16) & 0xFF;
green = (rgbMapInt[i] >> 8) & 0xFF;
blue = rgbMapInt[i] & 0xFF;
}
else {
throw new IllegalStateException("colormap == null");
}
rdist = red - x / 2; // distance of red to center of current cell
gdist = green - x / 2; // green
bdist = blue - x / 2; // blue
rdist = rdist * rdist + gdist * gdist + bdist * bdist;
rinc = 2 * (xsqr - (red << TRUNCBITS));
ginc = 2 * (xsqr - (green << TRUNCBITS));
binc = 2 * (xsqr - (blue << TRUNCBITS));
int rgbI = 0;
for (r = 0, rxx = rinc; r < MAXQUANTVAL; rdist += rxx, ++r, rxx += xsqr2) {
for (g = 0, gdist = rdist, gxx = ginc; g < MAXQUANTVAL; gdist += gxx, ++g, gxx += xsqr2) {
for (b = 0, bdist = gdist, bxx = binc; b < MAXQUANTVAL; bdist += bxx, ++b, ++rgbI, bxx += xsqr2) {
if (i == 0 || pTemp[rgbI] > bdist) {
pTemp[rgbI] = bdist;
inverseRGB[rgbI] = (byte) i;
}
}
}
}
}
}
/**
* Gets the index of the nearest color to from the color map.
*
* @param pColor the color to get the nearest color to from color map
* color must be of format {@code 0x00RRGGBB} - standard default RGB
* @return index of color which closest matches input color by using the
* created inverse color map.
*/
public final int getIndexNearest(int pColor) {
return inverseRGB[((pColor >> (3 * TRUNCBITS)) & QUANTMASK_RED) +
((pColor >> (2 * TRUNCBITS)) & QUANTMASK_GREEN) +
((pColor >> (/* 1 * */ TRUNCBITS)) & QUANTMASK_BLUE)] & 0xFF;
}
/**
* Gets the index of the nearest color to from the color map.
*
* @param pRed red component of the color to get the nearest color to from color map
* @param pGreen green component of the color to get the nearest color to from color map
* @param pBlue blue component of the color to get the nearest color to from color map
* @return index of color which closest matches input color by using the
* created inverse color map.
*/
public final int getIndexNearest(int pRed, int pGreen, int pBlue) {
// NOTE: the third line in expression for blue is shifting DOWN not UP.
return inverseRGB[((pRed << (2 * QUANTBITS - TRUNCBITS)) & QUANTMASK_RED) +
((pGreen << (/* 1 * */ QUANTBITS - TRUNCBITS)) & QUANTMASK_GREEN) +
((pBlue >> (TRUNCBITS)) & QUANTMASK_BLUE)] & 0xFF;
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
/**
* Inverse Colormap to provide efficient lookup of any given input color
* to the closest match to the given color map.
* <p>
* Based on "Efficient Inverse Color Map Computation" by Spencer W. Thomas
* in "Graphics Gems Volume II".
* </p>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author Robin Luiten (Java port)
* @author Spencer W. Thomas (original c version).
*
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/InverseColorMap.java#1 $
*/
class InverseColorMap {
/**
* Number of high bits of each color channel to use to lookup near match
*/
final static int QUANTBITS = 5;
/**
* Truncated bits of each color channel
*/
final static int TRUNCBITS = 8 - QUANTBITS;
/**
* BITMASK representing the bits for blue in the color lookup
*/
final static int QUANTMASK_BLUE = (1 << 5) - 1;
/**
* BITMASK representing the bits for green in the color lookup
*/
final static int QUANTMASK_GREEN = (QUANTMASK_BLUE << QUANTBITS);
/**
* BITMASK representing the bits for red in the color lookup
*/
final static int QUANTMASK_RED = (QUANTMASK_GREEN << QUANTBITS);
/**
* Maximum value a quantised color channel can have
*/
final static int MAXQUANTVAL = 1 << 5;
byte[] rgbMapByte;
int[] rgbMapInt;
int numColors;
int maxColor;
byte[] inverseRGB; // inverse rgb color map
int transparentIndex = -1;
/**
* @param pRGBColorMap the rgb color map to create inverse color map for.
*/
InverseColorMap(byte[] pRGBColorMap) {
this(pRGBColorMap, -1);
}
/**
* @param pRGBColorMap the rgb color map to create inverse color map for.
*/
// HaraldK 20040801: Added support for int[]
InverseColorMap(int[] pRGBColorMap) {
this(pRGBColorMap, -1);
}
/**
* @param pRGBColorMap the rgb color map to create inverse color map for.
* @param pTransparent the index of the transparent pixel in the map
*/
InverseColorMap(byte[] pRGBColorMap, int pTransparent) {
rgbMapByte = pRGBColorMap;
numColors = rgbMapByte.length / 4;
transparentIndex = pTransparent;
inverseRGB = new byte[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL];
initIRGB(new int[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL]);
}
/**
* @param pRGBColorMap the rgb color map to create inverse color map for.
* @param pTransparent the index of the transparent pixel in the map
*/
InverseColorMap(int[] pRGBColorMap, int pTransparent) {
rgbMapInt = pRGBColorMap;
numColors = rgbMapInt.length;
transparentIndex = pTransparent;
inverseRGB = new byte[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL];
initIRGB(new int[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL]);
}
/**
* Simple inverse color table creation method.
* @param pTemp temp array
*/
void initIRGB(int[] pTemp) {
final int x = (1 << TRUNCBITS); // 8 the size of 1 Dimension of each quantized cell
final int xsqr = 1 << (TRUNCBITS * 2); // 64 - twice the smallest step size vale of quantized colors
final int xsqr2 = xsqr + xsqr;
for (int i = 0; i < numColors; ++i) {
if (i == transparentIndex) {
// Skip the transparent pixel
continue;
}
int red, r, rdist, rinc, rxx;
int green, g, gdist, ginc, gxx;
int blue, b, bdist, binc, bxx;
// HaraldK 20040801: Added support for int[]
if (rgbMapByte != null) {
red = rgbMapByte[i * 4] & 0xFF;
green = rgbMapByte[i * 4 + 1] & 0xFF;
blue = rgbMapByte[i * 4 + 2] & 0xFF;
}
else if (rgbMapInt != null) {
red = (rgbMapInt[i] >> 16) & 0xFF;
green = (rgbMapInt[i] >> 8) & 0xFF;
blue = rgbMapInt[i] & 0xFF;
}
else {
throw new IllegalStateException("colormap == null");
}
rdist = red - x / 2; // distance of red to center of current cell
gdist = green - x / 2; // green
bdist = blue - x / 2; // blue
rdist = rdist * rdist + gdist * gdist + bdist * bdist;
rinc = 2 * (xsqr - (red << TRUNCBITS));
ginc = 2 * (xsqr - (green << TRUNCBITS));
binc = 2 * (xsqr - (blue << TRUNCBITS));
int rgbI = 0;
for (r = 0, rxx = rinc; r < MAXQUANTVAL; rdist += rxx, ++r, rxx += xsqr2) {
for (g = 0, gdist = rdist, gxx = ginc; g < MAXQUANTVAL; gdist += gxx, ++g, gxx += xsqr2) {
for (b = 0, bdist = gdist, bxx = binc; b < MAXQUANTVAL; bdist += bxx, ++b, ++rgbI, bxx += xsqr2) {
if (i == 0 || pTemp[rgbI] > bdist) {
pTemp[rgbI] = bdist;
inverseRGB[rgbI] = (byte) i;
}
}
}
}
}
}
/**
* Gets the index of the nearest color to from the color map.
*
* @param pColor the color to get the nearest color to from color map
* color must be of format {@code 0x00RRGGBB} - standard default RGB
* @return index of color which closest matches input color by using the
* created inverse color map.
*/
public final int getIndexNearest(int pColor) {
return inverseRGB[((pColor >> (3 * TRUNCBITS)) & QUANTMASK_RED) +
((pColor >> (2 * TRUNCBITS)) & QUANTMASK_GREEN) +
((pColor >> (/* 1 * */ TRUNCBITS)) & QUANTMASK_BLUE)] & 0xFF;
}
/**
* Gets the index of the nearest color to from the color map.
*
* @param pRed red component of the color to get the nearest color to from color map
* @param pGreen green component of the color to get the nearest color to from color map
* @param pBlue blue component of the color to get the nearest color to from color map
* @return index of color which closest matches input color by using the
* created inverse color map.
*/
public final int getIndexNearest(int pRed, int pGreen, int pBlue) {
// NOTE: the third line in expression for blue is shifting DOWN not UP.
return inverseRGB[((pRed << (2 * QUANTBITS - TRUNCBITS)) & QUANTMASK_RED) +
((pGreen << (/* 1 * */ QUANTBITS - TRUNCBITS)) & QUANTMASK_GREEN) +
((pBlue >> (TRUNCBITS)) & QUANTMASK_BLUE)] & 0xFF;
}
}
@@ -1,187 +0,0 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import com.twelvemonkeys.lang.SystemUtil;
import magick.MagickImage;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
/**
* This class accelerates certain graphics operations, using
* JMagick and ImageMagick, if available.
* If those libraries are not installed, this class silently does nothing.
* <p/>
* Set the system property {@code "com.twelvemonkeys.image.accel"} to
* {@code false}, to disable, even if JMagick is installed.
* Set the system property {@code "com.twelvemonkeys.image.magick.debug"} to
* <p/>
*
* @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/image/MagickAccelerator.java#3 $
*/
final class MagickAccelerator {
private static final boolean DEBUG = Magick.DEBUG;
private static final boolean USE_MAGICK = useMagick();
private static final int RESAMPLE_OP = 0;
private static Class[] nativeOp = new Class[1];
static {
try {
nativeOp[RESAMPLE_OP] = Class.forName("com.twelvemonkeys.image.ResampleOp");
}
catch (ClassNotFoundException e) {
System.err.println("Could not find class: " + e);
}
}
private static boolean useMagick() {
try {
boolean available = SystemUtil.isClassAvailable("magick.MagickImage");
if (DEBUG && !available) {
System.err.print("ImageMagick bindings not available.");
}
boolean useMagick =
available && !"FALSE".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.image.accel"));
if (DEBUG) {
System.err.println(
useMagick
? "Will use ImageMagick bindings to accelerate image resampling operations."
: "Will not use ImageMagick to accelerate image resampling operations."
);
}
return useMagick;
}
catch (Throwable t) {
// Most probably in case of a SecurityManager
System.err.println("Could not enable ImageMagick bindings: " + t);
return false;
}
}
private static int getNativeOpIndex(Class pOpClass) {
for (int i = 0; i < nativeOp.length; i++) {
if (pOpClass == nativeOp[i]) {
return i;
}
}
return -1;
}
public static BufferedImage filter(BufferedImageOp pOperation, BufferedImage pInput, BufferedImage pOutput) {
if (!USE_MAGICK) {
return null;
}
BufferedImage result = null;
switch (getNativeOpIndex(pOperation.getClass())) {
case RESAMPLE_OP:
ResampleOp resample = (ResampleOp) pOperation;
result = resampleMagick(pInput, resample.width, resample.height, resample.filterType);
// NOTE: If output parameter is non-null, we have to return that
// image, instead of result
if (pOutput != null) {
//pOutput.setData(result.getRaster()); // Fast, but less compatible
// NOTE: For some reason, this is sometimes super-slow...?
ImageUtil.drawOnto(pOutput, result);
result = pOutput;
}
break;
default:
// Simply fall through, allowing acceleration to be added later
break;
}
return result;
}
private static BufferedImage resampleMagick(BufferedImage pSrc, int pWidth, int pHeight, int pFilterType) {
// Convert to Magick, scale and convert back
MagickImage image = null;
MagickImage scaled = null;
try {
image = MagickUtil.toMagick(pSrc);
long start = 0;
if (DEBUG) {
start = System.currentTimeMillis();
}
// NOTE: setFilter affects zoomImage, NOT scaleImage
image.setFilter(pFilterType);
scaled = image.zoomImage(pWidth, pHeight);
//scaled = image.scaleImage(pWidth, pHeight); // AREA_AVERAGING
if (DEBUG) {
long time = System.currentTimeMillis() - start;
System.out.println("Filtered: " + time + " ms");
}
return MagickUtil.toBuffered(scaled);
}
//catch (MagickException e) {
catch (Exception e) {
// NOTE: Stupid workaround: If MagickException is caught, a
// NoClassDefFoundError is thrown, when MagickException class is
// unavailable...
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new ImageConversionException(e.getMessage(), e);
}
finally {
// NOTE: ImageMagick might be unstable after a while, if image data
// is not deallocated. The GC/finalize method handles this, but in
// special circumstances, it's not triggered often enough.
if (image != null) {
image.destroyImages();
}
if (scaled != null) {
scaled.destroyImages();
}
}
}
}
@@ -1,616 +0,0 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import magick.ImageType;
import magick.MagickException;
import magick.MagickImage;
import magick.PixelPacket;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.*;
/**
* Utility for converting JMagick {@code MagickImage}s to standard Java
* {@code BufferedImage}s and back.
* <p/>
* <em>NOTE: This class is considered an implementation detail and not part of
* the public API. This class is subject to change without further notice.
* You have been warned. :-)</em>
*
* @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/image/MagickUtil.java#4 $
*/
public final class MagickUtil {
// IMPORTANT NOTE: Disaster happens if any of these constants are used outside this class
// because you then have a dependency on MagickException (this is due to Java class loading
// and initialization magic).
// Do not use outside this class. If the constants need to be shared, move to Magick or ImageUtil.
/** Color Model usesd for bilevel (B/W) */
private static final IndexColorModel CM_MONOCHROME = MonochromeColorModel.getInstance();
/** Color Model usesd for raw ABGR */
private static final ColorModel CM_COLOR_ALPHA =
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8, 8, 8, 8},
true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
/** Color Model usesd for raw BGR */
private static final ColorModel CM_COLOR_OPAQUE =
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8, 8, 8},
false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
/** Color Model usesd for raw RGB */
//private static final ColorModel CM_COLOR_RGB = new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x0);
/** Color Model usesd for raw GRAY + ALPHA */
private static final ColorModel CM_GRAY_ALPHA =
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
/** Color Model usesd for raw GRAY */
private static final ColorModel CM_GRAY_OPAQUE =
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
/** Band offsets for raw ABGR */
private static final int[] BAND_OFF_TRANS = new int[] {3, 2, 1, 0};
/** Band offsets for raw BGR */
private static final int[] BAND_OFF_OPAQUE = new int[] {2, 1, 0};
/** The point at {@code 0, 0} */
private static final Point LOCATION_UPPER_LEFT = new Point(0, 0);
private static final boolean DEBUG = Magick.DEBUG;
// Only static members and methods
private MagickUtil() {}
/**
* Converts a {@code MagickImage} to a {@code BufferedImage}.
* <p/>
* The conversion depends on {@code pImage}'s {@code ImageType}:
* <dl>
* <dt>{@code ImageType.BilevelType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY}</dd>
*
* <dt>{@code ImageType.GrayscaleType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_GRAY}</dd>
* <dt>{@code ImageType.GrayscaleMatteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_USHORT_GRAY}</dd>
*
* <dt>{@code ImageType.PaletteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY} (for images
* with a palette of <= 16 colors) or {@code TYPE_BYTE_INDEXED}</dd>
* <dt>{@code ImageType.PaletteMatteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY} (for images
* with a palette of <= 16 colors) or {@code TYPE_BYTE_INDEXED}</dd>
*
* <dt>{@code ImageType.TrueColorType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_3BYTE_BGR}</dd>
* <dt>{@code ImageType.TrueColorPaletteType}</dt>
* <dd>{@code BufferedImage} of type {@code TYPE_4BYTE_ABGR}</dd>
*
* @param pImage the original {@code MagickImage}
* @return a new {@code BufferedImage}
*
* @throws IllegalArgumentException if {@code pImage} is {@code null}
* or if the {@code ImageType} is not one mentioned above.
* @throws MagickException if an exception occurs during conversion
*
* @see BufferedImage
*/
public static BufferedImage toBuffered(MagickImage pImage) throws MagickException {
if (pImage == null) {
throw new IllegalArgumentException("image == null");
}
long start = 0L;
if (DEBUG) {
start = System.currentTimeMillis();
}
BufferedImage image = null;
try {
switch (pImage.getImageType()) {
case ImageType.BilevelType:
image = bilevelToBuffered(pImage);
break;
case ImageType.GrayscaleType:
image = grayToBuffered(pImage, false);
break;
case ImageType.GrayscaleMatteType:
image = grayToBuffered(pImage, true);
break;
case ImageType.PaletteType:
image = paletteToBuffered(pImage, false);
break;
case ImageType.PaletteMatteType:
image = paletteToBuffered(pImage, true);
break;
case ImageType.TrueColorType:
image = rgbToBuffered(pImage, false);
break;
case ImageType.TrueColorMatteType:
image = rgbToBuffered(pImage, true);
break;
case ImageType.ColorSeparationType:
image = cmykToBuffered(pImage, false);
break;
case ImageType.ColorSeparationMatteType:
image = cmykToBuffered(pImage, true);
break;
case ImageType.OptimizeType:
default:
throw new IllegalArgumentException("Unknown JMagick image type: " + pImage.getImageType());
}
}
finally {
if (DEBUG) {
long time = System.currentTimeMillis() - start;
System.out.println("Converted JMagick image type: " + pImage.getImageType() + " to BufferedImage: " + image);
System.out.println("Conversion to BufferedImage: " + time + " ms");
}
}
return image;
}
/**
* Converts a {@code BufferedImage} to a {@code MagickImage}.
* <p/>
* The conversion depends on {@code pImage}'s {@code ColorModel}:
* <dl>
* <dt>{@code IndexColorModel} with 1 bit b/w</dt>
* <dd>{@code MagickImage} of type {@code ImageType.BilevelType}</dd>
* <dt>{@code IndexColorModel} &gt; 1 bit,</dt>
* <dd>{@code MagickImage} of type {@code ImageType.PaletteType}
* or {@code MagickImage} of type {@code ImageType.PaletteMatteType}
* depending on <tt>ColorModel.getAlpha()</dd>
*
* <dt>{@code ColorModel.getColorSpace().getType() == ColorSpace.TYPE_GRAY}</dt>
* <dd>{@code MagickImage} of type {@code ImageType.GrayscaleType}
* or {@code MagickImage} of type {@code ImageType.GrayscaleMatteType}
* depending on <tt>ColorModel.getAlpha()</dd>
*
* <dt>{@code ColorModel.getColorSpace().getType() == ColorSpace.TYPE_RGB}</dt>
* <dd>{@code MagickImage} of type {@code ImageType.TrueColorType}
* or {@code MagickImage} of type {@code ImageType.TrueColorPaletteType}</dd>
*
* @param pImage the original {@code BufferedImage}
* @return a new {@code MagickImage}
*
* @throws IllegalArgumentException if {@code pImage} is {@code null}
* or if the {@code ColorModel} is not one mentioned above.
* @throws MagickException if an exception occurs during conversion
*
* @see BufferedImage
*/
public static MagickImage toMagick(BufferedImage pImage) throws MagickException {
if (pImage == null) {
throw new IllegalArgumentException("image == null");
}
long start = 0L;
if (DEBUG) {
start = System.currentTimeMillis();
}
try {
ColorModel cm = pImage.getColorModel();
if (cm instanceof IndexColorModel) {
// Handles both BilevelType, PaletteType and PaletteMatteType
return indexedToMagick(pImage, (IndexColorModel) cm, cm.hasAlpha());
}
switch (cm.getColorSpace().getType()) {
case ColorSpace.TYPE_GRAY:
// Handles GrayType and GrayMatteType
return grayToMagick(pImage, cm.hasAlpha());
case ColorSpace.TYPE_RGB:
// Handles TrueColorType and TrueColorMatteType
return rgbToMagic(pImage, cm.hasAlpha());
case ColorSpace.TYPE_CMY:
case ColorSpace.TYPE_CMYK:
case ColorSpace.TYPE_HLS:
case ColorSpace.TYPE_HSV:
// Other types not supported yet
default:
throw new IllegalArgumentException("Unknown buffered image type: " + pImage);
}
}
finally {
if (DEBUG) {
long time = System.currentTimeMillis() - start;
System.out.println("Conversion to MagickImage: " + time + " ms");
}
}
}
private static MagickImage rgbToMagic(BufferedImage pImage, boolean pAlpha) throws MagickException {
MagickImage image = new MagickImage();
BufferedImage buffered = ImageUtil.toBuffered(pImage, pAlpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR);
// Need to get data of sub raster, not the full data array, this is
// just a convenient way
Raster raster;
if (buffered.getRaster().getParent() != null) {
raster = buffered.getData(new Rectangle(buffered.getWidth(), buffered.getHeight()));
}
else {
raster = buffered.getRaster();
}
image.constituteImage(buffered.getWidth(), buffered.getHeight(), pAlpha ? "ABGR" : "BGR",
((DataBufferByte) raster.getDataBuffer()).getData());
return image;
}
private static MagickImage grayToMagick(BufferedImage pImage, boolean pAlpha) throws MagickException {
MagickImage image = new MagickImage();
// TODO: Make a fix for TYPE_USHORT_GRAY
// The code below does not seem to work (JMagick issues?)...
/*
if (pImage.getType() == BufferedImage.TYPE_USHORT_GRAY) {
short[] data = ((DataBufferUShort) pImage.getRaster().getDataBuffer()).getData();
int[] intData = new int[data.length];
for (int i = 0; i < data.length; i++) {
intData[i] = (data[i] & 0xffff) * 0xffff;
}
image.constituteImage(pImage.getWidth(), pImage.getHeight(), "I", intData);
System.out.println("storageClass: " + image.getStorageClass());
System.out.println("depth: " + image.getDepth());
System.out.println("imageType: " + image.getImageType());
}
else {
*/
BufferedImage buffered = ImageUtil.toBuffered(pImage, pAlpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_BYTE_GRAY);
// Need to get data of sub raster, not the full data array, this is
// just a convenient way
Raster raster;
if (buffered.getRaster().getParent() != null) {
raster = buffered.getData(new Rectangle(buffered.getWidth(), buffered.getHeight()));
}
else {
raster = buffered.getRaster();
}
image.constituteImage(buffered.getWidth(), buffered.getHeight(), pAlpha ? "ABGR" : "I", ((DataBufferByte) raster.getDataBuffer()).getData());
//}
return image;
}
private static MagickImage indexedToMagick(BufferedImage pImage, IndexColorModel pColorModel, boolean pAlpha) throws MagickException {
MagickImage image = rgbToMagic(pImage, pAlpha);
int mapSize = pColorModel.getMapSize();
image.setNumberColors(mapSize);
return image;
}
/*
public static MagickImage toMagick(BufferedImage pImage) throws MagickException {
if (pImage == null) {
throw new IllegalArgumentException("image == null");
}
final int width = pImage.getWidth();
final int height = pImage.getHeight();
// int ARGB -> byte RGBA conversion
// NOTE: This is ImageMagick Q16 compatible raw RGBA format with 16 bits/sample...
// For a Q8 build, we could probably go with half the space...
// NOTE: This is close to insanity, as it wastes extreme ammounts of memory
final int[] argb = new int[width];
final byte[] raw16 = new byte[width * height * 8];
for (int y = 0; y < height; y++) {
// Fetch one line of ARGB data
pImage.getRGB(0, y, width, 1, argb, 0, width);
for (int x = 0; x < width; x++) {
int pixel = (x + (y * width)) * 8;
raw16[pixel ] = (byte) ((argb[x] >> 16) & 0xff); // R
raw16[pixel + 2] = (byte) ((argb[x] >> 8) & 0xff); // G
raw16[pixel + 4] = (byte) ((argb[x] ) & 0xff); // B
raw16[pixel + 6] = (byte) ((argb[x] >> 24) & 0xff); // A
}
}
// Create magick image
ImageInfo info = new ImageInfo();
info.setMagick("RGBA"); // Raw RGBA samples
info.setSize(width + "x" + height); // String?!?
MagickImage image = new MagickImage(info);
image.setImageAttribute("depth", "8");
// Set pixel data in 16 bit raw RGBA format
image.blobToImage(info, raw16);
return image;
}
*/
/**
* Converts a bi-level {@code MagickImage} to a {@code BufferedImage}, of
* type {@code TYPE_BYTE_BINARY}.
*
* @param pImage the original {@code MagickImage}
* @return a new {@code BufferedImage}
*
* @throws MagickException if an exception occurs during conversion
*
* @see BufferedImage
*/
private static BufferedImage bilevelToBuffered(MagickImage pImage) throws MagickException {
// As there is no way to get the binary representation of the image,
// convert to gray, and the create a binary image from it
BufferedImage temp = grayToBuffered(pImage, false);
BufferedImage image = new BufferedImage(temp.getWidth(), temp.getHeight(), BufferedImage.TYPE_BYTE_BINARY, CM_MONOCHROME);
ImageUtil.drawOnto(image, temp);
return image;
}
/**
* Converts a gray {@code MagickImage} to a {@code BufferedImage}, of
* type {@code TYPE_USHORT_GRAY} or {@code TYPE_BYTE_GRAY}.
*
* @param pImage the original {@code MagickImage}
* @param pAlpha keep alpha channel
* @return a new {@code BufferedImage}
*
* @throws MagickException if an exception occurs during conversion
*
* @see BufferedImage
*/
private static BufferedImage grayToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
Dimension size = pImage.getDimension();
int length = size.width * size.height;
int bands = pAlpha ? 2 : 1;
byte[] pixels = new byte[length * bands];
// TODO: Make a fix for 16 bit TYPE_USHORT_GRAY?!
// Note: The ordering AI or I corresponds to BufferedImage
// TYPE_CUSTOM and TYPE_BYTE_GRAY respectively
pImage.dispatchImage(0, 0, size.width, size.height, pAlpha ? "AI" : "I", pixels);
// Init databuffer with array, to avoid allocation of empty array
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
int[] bandOffsets = pAlpha ? new int[] {1, 0} : new int[] {0};
WritableRaster raster =
Raster.createInterleavedRaster(buffer, size.width, size.height,
size.width * bands, bands, bandOffsets, LOCATION_UPPER_LEFT);
return new BufferedImage(pAlpha ? CM_GRAY_ALPHA : CM_GRAY_OPAQUE, raster, pAlpha, null);
}
/**
* Converts a palette-based {@code MagickImage} to a
* {@code BufferedImage}, of type {@code TYPE_BYTE_BINARY} (for images
* with a palette of <= 16 colors) or {@code TYPE_BYTE_INDEXED}.
*
* @param pImage the original {@code MagickImage}
* @param pAlpha keep alpha channel
* @return a new {@code BufferedImage}
*
* @throws MagickException if an exception occurs during conversion
*
* @see BufferedImage
*/
private static BufferedImage paletteToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
// Create indexcolormodel for the image
IndexColorModel cm;
try {
cm = createIndexColorModel(pImage.getColormap(), pAlpha);
}
catch (MagickException e) {
// NOTE: Some MagickImages incorrecly (?) reports to be paletteType,
// but does not have a colormap, this is a workaround.
return rgbToBuffered(pImage, pAlpha);
}
// As there is no way to get the indexes of an indexed image, convert to
// RGB, and the create an indexed image from it
BufferedImage temp = rgbToBuffered(pImage, pAlpha);
BufferedImage image;
if (cm.getMapSize() <= 16) {
image = new BufferedImage(temp.getWidth(), temp.getHeight(), BufferedImage.TYPE_BYTE_BINARY, cm);
}
else {
image = new BufferedImage(temp.getWidth(), temp.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, cm);
}
// Create transparent background for images containing alpha
if (pAlpha) {
Graphics2D g = image.createGraphics();
try {
g.setComposite(AlphaComposite.Clear);
g.fillRect(0, 0, temp.getWidth(), temp.getHeight());
}
finally {
g.dispose();
}
}
// NOTE: This is (surprisingly) much faster than using g2d.drawImage()..
// (Tests shows 20-30ms, vs. 600-700ms on the same image)
BufferedImageOp op = new CopyDither(cm);
op.filter(temp, image);
return image;
}
/**
* Creates an {@code IndexColorModel} from an array of
* {@code PixelPacket}s.
*
* @param pColormap the original colormap as a {@code PixelPacket} array
* @param pAlpha keep alpha channel
*
* @return a new {@code IndexColorModel}
*/
public static IndexColorModel createIndexColorModel(PixelPacket[] pColormap, boolean pAlpha) {
int[] colors = new int[pColormap.length];
// TODO: Verify if this is correct for alpha...?
int trans = pAlpha ? colors.length - 1 : -1;
//for (int i = 0; i < pColormap.length; i++) {
for (int i = pColormap.length - 1; i != 0; i--) {
PixelPacket color = pColormap[i];
if (pAlpha) {
colors[i] = (0xff - (color.getOpacity() & 0xff)) << 24 |
(color.getRed() & 0xff) << 16 |
(color.getGreen() & 0xff) << 8 |
(color.getBlue() & 0xff);
}
else {
colors[i] = (color.getRed() & 0xff) << 16 |
(color.getGreen() & 0xff) << 8 |
(color.getBlue() & 0xff);
}
}
return new InverseColorMapIndexColorModel(8, colors.length, colors, 0, pAlpha, trans, DataBuffer.TYPE_BYTE);
}
/**
* Converts an (A)RGB {@code MagickImage} to a {@code BufferedImage}, of
* type {@code TYPE_4BYTE_ABGR} or {@code TYPE_3BYTE_BGR}.
*
* @param pImage the original {@code MagickImage}
* @param pAlpha keep alpha channel
* @return a new {@code BufferedImage}
*
* @throws MagickException if an exception occurs during conversion
*
* @see BufferedImage
*/
private static BufferedImage rgbToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
Dimension size = pImage.getDimension();
int length = size.width * size.height;
int bands = pAlpha ? 4 : 3;
byte[] pixels = new byte[length * bands];
// TODO: If we do multiple dispatches (one per line, typically), we could provide listener
// feedback. But it's currently a lot slower than fetching all the pixels in one go.
// Note: The ordering ABGR or BGR corresponds to BufferedImage
// TYPE_4BYTE_ABGR and TYPE_3BYTE_BGR respectively
pImage.dispatchImage(0, 0, size.width, size.height, pAlpha ? "ABGR" : "BGR", pixels);
// Init databuffer with array, to avoid allocation of empty array
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
int[] bandOffsets = pAlpha ? BAND_OFF_TRANS : BAND_OFF_OPAQUE;
WritableRaster raster =
Raster.createInterleavedRaster(buffer, size.width, size.height,
size.width * bands, bands, bandOffsets, LOCATION_UPPER_LEFT);
return new BufferedImage(pAlpha ? CM_COLOR_ALPHA : CM_COLOR_OPAQUE, raster, pAlpha, null);
}
/**
* Converts an {@code MagickImage} to a {@code BufferedImage} which holds an CMYK ICC profile
*
* @param pImage the original {@code MagickImage}
* @param pAlpha keep alpha channel
* @return a new {@code BufferedImage}
*
* @throws MagickException if an exception occurs during conversion
*
* @see BufferedImage
*/
private static BufferedImage cmykToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
Dimension size = pImage.getDimension();
int length = size.width * size.height;
// Retreive the ICC profile
ICC_Profile profile = ICC_Profile.getInstance(pImage.getColorProfile().getInfo());
ColorSpace cs = new ICC_ColorSpace(profile);
int bands = cs.getNumComponents() + (pAlpha ? 1 : 0);
int[] bits = new int[bands];
for (int i = 0; i < bands; i++) {
bits[i] = 8;
}
ColorModel cm = pAlpha ?
new ComponentColorModel(cs, bits, true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE) :
new ComponentColorModel(cs, bits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
byte[] pixels = new byte[length * bands];
// TODO: If we do multiple dispatches (one per line, typically), we could provide listener
// feedback. But it's currently a lot slower than fetching all the pixels in one go.
// TODO: handle more generic cases if profile is not CMYK
// TODO: Test "ACMYK"
pImage.dispatchImage(0, 0, size.width, size.height, pAlpha ? "ACMYK" : "CMYK", pixels);
// Init databuffer with array, to avoid allocation of empty array
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
// TODO: build array from bands variable, here it just works for CMYK
// The values has not been tested with an alpha picture actually...
int[] bandOffsets = pAlpha ? new int[] {0, 1, 2, 3, 4} : new int[] {0, 1, 2, 3};
WritableRaster raster =
Raster.createInterleavedRaster(buffer, size.width, size.height,
size.width * bands, bands, bandOffsets, LOCATION_UPPER_LEFT);
return new BufferedImage(cm, raster, pAlpha, null);
}
}
File diff suppressed because it is too large Load Diff
@@ -1,79 +1,80 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.image.ReplicateScaleFilter;
/**
* An {@code ImageFilter} class for subsampling images.
* <p/>
* It is meant to be used in conjunction with a {@code FilteredImageSource}
* object to produce subsampled versions of existing images.
*
* @see java.awt.image.FilteredImageSource
*
* @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/image/SubsamplingFilter.java#1 $
*/
public class SubsamplingFilter extends ReplicateScaleFilter {
private int xSub;
private int ySub;
/**
* Creates a {@code SubsamplingFilter}.
*
* @param pXSub
* @param pYSub
*
* @throws IllegalArgumentException if {@code pXSub} or {@code pYSub} is
* less than 1.
*/
public SubsamplingFilter(int pXSub, int pYSub) {
super(1, 1); // These are NOT REAL values, but we have to defer setting
// until w/h is available, in setDimensions below
if (pXSub < 1 || pYSub < 1) {
throw new IllegalArgumentException("Subsampling factors must be positive.");
}
xSub = pXSub;
ySub = pYSub;
}
/** {@code ImageFilter} implementation, do not invoke. */
public void setDimensions(int pWidth, int pHeight) {
destWidth = (pWidth + xSub - 1) / xSub;
destHeight = (pHeight + ySub - 1) / ySub;
//System.out.println("Subsampling: " + xSub + "," + ySub + "-> " + destWidth + ", " + destHeight);
super.setDimensions(pWidth, pHeight);
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.image;
import java.awt.image.ReplicateScaleFilter;
/**
* An {@code ImageFilter} class for subsampling images.
* <p>
* It is meant to be used in conjunction with a {@code FilteredImageSource}
* object to produce subsampled versions of existing images.
* </p>
*
* @see java.awt.image.FilteredImageSource
*
* @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/image/SubsamplingFilter.java#1 $
*/
public class SubsamplingFilter extends ReplicateScaleFilter {
private int xSub;
private int ySub;
/**
* Creates a {@code SubsamplingFilter}.
*
* @param pXSub
* @param pYSub
*
* @throws IllegalArgumentException if {@code pXSub} or {@code pYSub} is
* less than 1.
*/
public SubsamplingFilter(int pXSub, int pYSub) {
super(1, 1); // These are NOT REAL values, but we have to defer setting
// until w/h is available, in setDimensions below
if (pXSub < 1 || pYSub < 1) {
throw new IllegalArgumentException("Subsampling factors must be positive.");
}
xSub = pXSub;
ySub = pYSub;
}
/** {@code ImageFilter} implementation, do not invoke. */
public void setDimensions(int pWidth, int pHeight) {
destWidth = (pWidth + xSub - 1) / xSub;
destHeight = (pHeight + ySub - 1) / ySub;
//System.out.println("Subsampling: " + xSub + "," + ySub + "-> " + destWidth + ", " + destHeight);
super.setDimensions(pWidth, pHeight);
}
}
@@ -30,8 +30,9 @@
/**
* Classes for image manipulation.
* <p/>
* <p>
* See the class {@link com.twelvemonkeys.image.ImageUtil}.
* </p>
*
* @version 1.0
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
@@ -30,17 +30,24 @@
package com.twelvemonkeys.image;
import org.junit.Test;
import static java.lang.Math.min;
import static org.junit.jupiter.api.Assertions.*;
import javax.imageio.ImageTypeSpecifier;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.DataBuffer;
import java.awt.image.ImagingOpException;
import java.awt.image.Raster;
import java.awt.image.RasterOp;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
import javax.imageio.ImageTypeSpecifier;
import org.junit.jupiter.api.Test;
/**
* AffineTransformOpTest.
@@ -101,6 +108,7 @@ public class AffineTransformOpTest {
private final int width = 30;
private final int height = 20;
private final double anchor = min(width, height) / 2.0;
@Test
public void testGetPoint2D() {
@@ -128,33 +136,33 @@ public class AffineTransformOpTest {
@Test
public void testFilterRotateBIStandard() {
BufferedImageOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
BufferedImageOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
BufferedImageOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
BufferedImageOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
for (Integer type : TYPES) {
BufferedImage image = new BufferedImage(width, height, type);
BufferedImage jreResult = jreOp.filter(image, null);
BufferedImage tmResult = tmOp.filter(image, null);
assertNotNull("No result!", tmResult);
assertEquals("Bad type", jreResult.getType(), tmResult.getType());
assertEquals("Incorrect color model", jreResult.getColorModel(), tmResult.getColorModel());
assertNotNull(tmResult, "No result!");
assertEquals(jreResult.getType(), tmResult.getType(), "Bad type");
assertEquals(jreResult.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
}
}
@Test
public void testFilterRotateBICustom() {
BufferedImageOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
BufferedImageOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
BufferedImageOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
BufferedImageOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
for (ImageTypeSpecifier spec : SPECS) {
BufferedImage image = spec.createBufferedImage(width, height);
BufferedImage tmResult = tmOp.filter(image, null);
assertNotNull("No result!", tmResult);
assertNotNull(tmResult, "No result!");
BufferedImage jreResult = null;
@@ -166,18 +174,18 @@ public class AffineTransformOpTest {
}
if (jreResult != null) {
assertEquals("Bad type", jreResult.getType(), tmResult.getType());
assertEquals("Incorrect color model", jreResult.getColorModel(), tmResult.getColorModel());
assertEquals(jreResult.getType(), tmResult.getType(), "Bad type");
assertEquals(jreResult.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
}
else {
assertEquals("Bad type", spec.getBufferedImageType(), tmResult.getType());
assertEquals("Incorrect color model", spec.getColorModel(), tmResult.getColorModel());
assertEquals(spec.getBufferedImageType(), tmResult.getType(), "Bad type");
assertEquals(spec.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
assertEquals("Incorrect width", height, tmResult.getWidth());
assertEquals("Incorrect height", width, tmResult.getHeight());
assertEquals(height, tmResult.getWidth(), "Incorrect width");
assertEquals(width, tmResult.getHeight(), "Incorrect height");
}
}
}
@@ -197,8 +205,8 @@ public class AffineTransformOpTest {
@Test
public void testFilterRotateRasterStandard() {
RasterOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
RasterOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
RasterOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
RasterOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
for (Integer type : TYPES) {
Raster raster = new BufferedImage(width, height, type).getRaster();
@@ -221,27 +229,25 @@ public class AffineTransformOpTest {
fail("No result!");
}
else {
System.err.println("AffineTransformOpTest.testFilterRotateRasterStandard");
System.err.println("type: " + type);
continue;
}
}
if (jreResult != null) {
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
}
else {
assertEquals("Incorrect width", height, tmResult.getWidth());
assertEquals("Incorrect height", width, tmResult.getHeight());
assertEquals(height, tmResult.getWidth(), "Incorrect width");
assertEquals(width, tmResult.getHeight(), "Incorrect height");
}
}
}
@Test
public void testFilterRotateRasterCustom() {
RasterOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
RasterOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
RasterOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
RasterOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
for (ImageTypeSpecifier spec : SPECS) {
Raster raster = spec.createBufferedImage(width, height).getRaster();
@@ -264,19 +270,17 @@ public class AffineTransformOpTest {
fail("No result!");
}
else {
System.err.println("AffineTransformOpTest.testFilterRotateRasterCustom");
System.err.println("spec: " + spec);
continue;
}
}
if (jreResult != null) {
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
}
else {
assertEquals("Incorrect width", height, tmResult.getWidth());
assertEquals("Incorrect height", width, tmResult.getHeight());
assertEquals(height, tmResult.getWidth(), "Incorrect width");
assertEquals(width, tmResult.getHeight(), "Incorrect height");
}
}
}
@@ -30,18 +30,16 @@
package com.twelvemonkeys.image;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.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 java.time.Duration;
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* BufferedImageFactoryTestCase
@@ -51,50 +49,58 @@ import static org.junit.Assert.*;
* @version $Id: BufferedImageFactoryTestCase.java,v 1.0 May 7, 2010 12:40:08 PM haraldk Exp$
*/
public class BufferedImageFactoryTest {
@Test(expected = IllegalArgumentException.class)
@Test
public void testCreateNullImage() {
new BufferedImageFactory((Image) null);
assertThrows(IllegalArgumentException.class, () -> {
new BufferedImageFactory((Image) null);
});
}
@Test(expected = IllegalArgumentException.class)
@Test
public void testCreateNullProducer() {
new BufferedImageFactory((ImageProducer) null);
assertThrows(IllegalArgumentException.class, () -> {
new BufferedImageFactory((ImageProducer) null);
});
}
// NPE in Toolkit, ok
@Test(expected = RuntimeException.class)
@Test
public void testGetBufferedImageErrorSourceByteArray() {
Image source = Toolkit.getDefaultToolkit().createImage((byte[]) null);
new BufferedImageFactory(source);
assertThrows(RuntimeException.class, () -> {
Image source = Toolkit.getDefaultToolkit().createImage((byte[]) null);
new BufferedImageFactory(source);
});
}
@Test(expected = IllegalArgumentException.class)
@Test
public void testGetBufferedImageErrorSourceImageProducer() {
Image source = Toolkit.getDefaultToolkit().createImage((ImageProducer) null);
new BufferedImageFactory(source);
assertThrows(IllegalArgumentException.class, () -> {
new BufferedImageFactory(source);
});
}
// TODO: This is a quite serious bug, however, the bug is in the Toolkit, allowing such images in the first place...
// In any case, there's not much we can do, except until someone is bored and kills the app/thread... :-P
@Ignore("Bug in Toolkit")
@Test(timeout = 1000, expected = ImageConversionException.class)
@Disabled("Bug in Toolkit")
@Test
public void testGetBufferedImageErrorSourceString() {
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
BufferedImageFactory factory = new BufferedImageFactory(source);
factory.getBufferedImage();
assertTimeoutPreemptively(Duration.ofMillis(1000), () -> {
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
BufferedImageFactory factory = new BufferedImageFactory(source);
assertThrows(ImageConversionException.class, factory::getBufferedImage);
});
}
// This is a little random, and it would be nicer if we could throw an IllegalArgumentException on create.
// Unfortunately, the API doesn't allow this...
@Test(timeout = 1000, expected = ImageConversionException.class)
@Test
public void testGetBufferedImageErrorSourceURL() {
Image source = Toolkit.getDefaultToolkit().createImage(getClass().getResource("/META-INF/MANIFEST.MF"));
BufferedImageFactory factory = new BufferedImageFactory(source);
factory.getBufferedImage();
assertTimeoutPreemptively(Duration.ofMillis(1000), () -> {
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
BufferedImageFactory factory = new BufferedImageFactory(source);
assertThrows(ImageConversionException.class, factory::getBufferedImage);
});
}
@Test
@@ -166,7 +172,7 @@ public class BufferedImageFactoryTest {
assertEquals(3, colorModel.getNumColorComponents());
assertEquals(ColorSpace.getInstance(ColorSpace.CS_sRGB), colorModel.getColorSpace());
assertTrue(colorModel instanceof IndexColorModel);
assertInstanceOf(IndexColorModel.class, colorModel);
assertTrue(colorModel.hasAlpha());
assertEquals(4, colorModel.getNumComponents());
@@ -197,7 +203,7 @@ public class BufferedImageFactoryTest {
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(x * 2, y * 2), image.getRGB(x, y));
assertEquals(original.getRGB(x * 2, y * 2), image.getRGB(x, y), "RGB[" + x + ", " + y + "]");
}
}
}
@@ -220,7 +226,7 @@ public class BufferedImageFactoryTest {
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(40 + x, 40 + y), image.getRGB(x, y));
assertEquals(original.getRGB(40 + x, 40 + y), image.getRGB(x, y), "RGB[" + x + ", " + y + "]");
}
}
}
@@ -244,7 +250,7 @@ public class BufferedImageFactoryTest {
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(40 + x * 2, 40 + y * 2), image.getRGB(x, y));
assertEquals(original.getRGB(40 + x * 2, 40 + y * 2), image.getRGB(x, y), "RGB[" + x + ", " + y + "]");
}
}
}
@@ -260,9 +266,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 +349,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 +386,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;
}
@@ -30,7 +30,7 @@
package com.twelvemonkeys.image;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import javax.imageio.ImageIO;
import java.awt.*;
@@ -39,7 +39,7 @@ import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
import java.io.InputStream;
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.*;
public class ImageUtilTest {
@@ -116,8 +116,8 @@ public class ImageUtilTest {
public void testImageIsNotBufferedImage() {
// Should not be a buffered image
assertFalse(
"FOR SOME IMPLEMENTATIONS THIS MIGHT FAIL!\nIn that case, testToBufferedImage() will fail too.",
scaled instanceof BufferedImage
scaled instanceof BufferedImage,
"FOR SOME IMPLEMENTATIONS THIS MIGHT FAIL!\nIn that case, testToBufferedImage() will fail too."
);
}
@@ -247,7 +247,7 @@ public class ImageUtilTest {
if (original != notContrasted) { // Don't care to test if images are same
for (int y = 0; y < original.getHeight(); y++) {
for (int x = 0; x < original.getWidth(); x++) {
assertEquals("0 constrast should not change image", original.getRGB(x, y), notContrasted.getRGB(x, y));
assertEquals(original.getRGB(x, y), notContrasted.getRGB(x, y), "0 constrast should not change image");
}
}
}
@@ -275,24 +275,24 @@ public class ImageUtilTest {
// RED
if (oR < 127) {
assertTrue("Contrast should be decreased or same", oR >= cR && cR >= dR);
assertTrue(oR >= cR && cR >= dR, "Contrast should be decreased or same");
}
else {
assertTrue("Contrast should be increased or same", oR <= cR && cR <= dR);
assertTrue(oR <= cR && cR <= dR, "Contrast should be increased or same");
}
// GREEN
if (oG < 127) {
assertTrue("Contrast should be decreased or same", oG >= cG && cG >= dG);
assertTrue(oG >= cG && cG >= dG, "Contrast should be decreased or same");
}
else {
assertTrue("Contrast should be increased or same", oG <= cG && cG <= dG);
assertTrue(oG <= cG && cG <= dG, "Contrast should be increased or same");
}
// BLUE
if (oB < 127) {
assertTrue("Contrast should be decreased or same", oB >= cB && cB >= dB);
assertTrue(oB >= cB && cB >= dB, "Contrast should be decreased or same");
}
else {
assertTrue("Contrast should be increased or same", oB <= cB && cB <= dB);
assertTrue(oB <= cB && cB <= dB, "Contrast should be increased or same");
}
}
}
@@ -304,9 +304,9 @@ public class ImageUtilTest {
int r = rgb >> 16 & 0xFF;
int g = rgb >> 8 & 0xFF;
int b = rgb & 0xFF;
assertTrue("Max contrast should only produce primary colors", r == 0 || r == 255);
assertTrue("Max contrast should only produce primary colors", g == 0 || g == 255);
assertTrue("Max contrast should only produce primary colors", b == 0 || b == 255);
assertTrue(r == 0 || r == 255, "Max contrast should only produce primary colors");
assertTrue(g == 0 || g == 255, "Max contrast should only produce primary colors");
assertTrue(b == 0 || b == 255, "Max contrast should only produce primary colors");
}
}
@@ -327,24 +327,24 @@ public class ImageUtilTest {
// RED
if (oR >= 127) {
assertTrue("Contrast should be decreased or same", oR >= cR);
assertTrue(oR >= cR, "Contrast should be decreased or same");
}
else {
assertTrue("Contrast should be increased or same", oR <= cR);
assertTrue(oR <= cR, "Contrast should be increased or same");
}
// GREEN
if (oG >= 127) {
assertTrue("Contrast should be decreased or same", oG >= cG);
assertTrue(oG >= cG, "Contrast should be decreased or same");
}
else {
assertTrue("Contrast should be increased or same", oG <= cG);
assertTrue(oG <= cG, "Contrast should be increased or same");
}
// BLUE
if (oB >= 127) {
assertTrue("Contrast should be decreased or same", oB >= cB);
assertTrue(oB >= cB, "Contrast should be decreased or same");
}
else {
assertTrue("Contrast should be increased or same", oB <= cB);
assertTrue(oB <= cB, "Contrast should be increased or same");
}
}
}
@@ -357,7 +357,7 @@ public class ImageUtilTest {
int r = rgb >> 16 & 0xFF;
int g = rgb >> 8 & 0xFF;
int b = rgb & 0xFF;
assertTrue("Minimum contrast should be all gray", r == 127 && g == 127 && b == 127);
assertTrue(r == 127 && g == 127 && b == 127, "Minimum contrast should be all gray");
}
}
@@ -400,7 +400,7 @@ public class ImageUtilTest {
if (original != notSharpened) { // Don't care to test if images are same
for (int y = 0; y < original.getHeight(); y++) {
for (int x = 0; x < original.getWidth(); x++) {
assertEquals("0 sharpen should not change image", original.getRGB(x, y), notSharpened.getRGB(x, y));
assertEquals(original.getRGB(x, y), notSharpened.getRGB(x, y), "0 sharpen should not change image");
}
}
}
@@ -446,13 +446,13 @@ public class ImageUtilTest {
}
// assertEquals("Difference should not change", diffOriginal, diffSharpened);
assertTrue("Abs difference should increase", absDiffOriginal < absDiffSharpened);
assertTrue(absDiffOriginal < absDiffSharpened, "Abs difference should increase");
// assertEquals("Difference should not change", diffOriginal, diffDefault);
assertTrue("Abs difference should increase", absDiffOriginal < absDiffDefault);
assertTrue(absDiffOriginal < absDiffDefault, "Abs difference should increase");
// assertEquals("Difference should not change", diffOriginal, diffMore);
assertTrue("Abs difference should increase", absDiffOriginal < absDiffMore);
assertTrue(absDiffOriginal < absDiffMore, "Abs difference should increase");
// assertEquals("Difference should not change", diffSharpened, diffMore);
assertTrue("Abs difference should increase", absDiffSharpened < absDiffMore);
assertTrue(absDiffSharpened < absDiffMore, "Abs difference should increase");
}
@Test
@@ -466,7 +466,7 @@ public class ImageUtilTest {
if (original != notBlurred) { // Don't care to test if images are same
for (int y = 0; y < original.getHeight(); y++) {
for (int x = 0; x < original.getWidth(); x++) {
assertEquals("0 blur should not change image", original.getRGB(x, y), notBlurred.getRGB(x, y));
assertEquals(original.getRGB(x, y), notBlurred.getRGB(x, y), "0 blur should not change image");
}
}
}
@@ -512,13 +512,13 @@ public class ImageUtilTest {
}
// assertEquals("Difference should not change", diffOriginal, diffBlurred);
assertTrue(String.format("Abs difference should decrease: %s <= %s", absDiffOriginal, absDiffBlurred), absDiffOriginal > absDiffBlurred);
assertTrue(absDiffOriginal > absDiffBlurred, String.format("Abs difference should decrease: %s <= %s", absDiffOriginal, absDiffBlurred));
// assertEquals("Difference should not change", diffOriginal, diffDefault);
assertTrue("Abs difference should decrease", absDiffOriginal > absDiffDefault);
assertTrue(absDiffOriginal > absDiffDefault, "Abs difference should decrease");
// assertEquals("Difference should not change", diffOriginal, diffMore);
assertTrue("Abs difference should decrease", absDiffOriginal > absDiffMore);
assertTrue(absDiffOriginal > absDiffMore, "Abs difference should decrease");
// assertEquals("Difference should not change", diffBlurred, diffMore);
assertTrue("Abs difference should decrease", absDiffBlurred > absDiffMore);
assertTrue(absDiffBlurred > absDiffMore, "Abs difference should decrease");
}
@Test
@@ -528,7 +528,7 @@ public class ImageUtilTest {
assertNotNull(sunflower);
BufferedImage image = ImageUtil.createIndexed(sunflower);
assertNotNull("Image was null", image);
assertTrue(image.getColorModel() instanceof IndexColorModel);
assertNotNull(image, "Image was null");
assertInstanceOf(IndexColorModel.class, image.getColorModel());
}
}
@@ -30,8 +30,8 @@
package com.twelvemonkeys.image;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.awt.*;
import java.awt.image.BufferedImage;
@@ -40,7 +40,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.*;
/**
* ResampleOpTestCase
@@ -124,7 +124,7 @@ public class ResampleOpTest {
}
}
assertEquals("Filter threw exceptions: ", Collections.EMPTY_LIST, exceptions);
assertEquals(Collections.EMPTY_LIST, exceptions, "Filter threw exceptions: ");
}
// 1x1
@@ -358,7 +358,7 @@ public class ResampleOpTest {
}
}
@Ignore("Not for general unit testing")
@Disabled("Not for general unit testing")
@Test
public void testTime() {
int iterations = 1000;
-6
View File
@@ -1,6 +0,0 @@
TODO:
Remove compile-time dependency on JMagick:
- Extract interface for MagickAccelerator
- Move implementation to separate module
- Instantiate impl via reflection
DONE:
+14 -2
View File
@@ -4,15 +4,19 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.4</version>
<version>3.13.2-SNAPSHOT</version>
</parent>
<artifactId>common-io</artifactId>
<packaging>jar</packaging>
<name>TwelveMonkeys :: Common :: IO</name>
<description>
The TwelveMonkeys Common IO support
TwelveMonkeys Common I/O support classes.
</description>
<properties>
<project.jpms.module.name>com.twelvemonkeys.common.io</project.jpms.module.name>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
@@ -27,4 +31,12 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@@ -186,7 +186,7 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
}
protected void closeImpl() throws IOException {
cache.flush(position);
cache.close();
cache = null;
stream.close();
}
@@ -198,12 +198,12 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/AbstractCachedSeekableStream.java#2 $
*/
public static abstract class StreamCache {
static abstract class StreamCache {
/**
* Creates a {@code StreamCache}.
*/
protected StreamCache() {
StreamCache() {
}
/**
@@ -218,9 +218,10 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
/**
* Writes a series of bytes at the current read/write position. The read/write position will be increased by
* {@code pLength}.
* <p/>
* <p>
* This implementation invokes {@link #write(int)} {@code pLength} times.
* Subclasses may override this method for performance.
* </p>
*
* @param pBuffer the bytes to write.
* @param pOffset the starting offset into the buffer.
@@ -246,9 +247,10 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
/**
* Writes a series of bytes at the current read/write position. The read/write position will be increased by
* {@code pLength}.
* <p/>
* <p>
* This implementation invokes {@link #read()} {@code pLength} times.
* Subclasses may override this method for performance.
* </p>
*
* @param pBuffer the bytes to write
* @param pOffset the starting offset into the buffer.
@@ -283,12 +285,14 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
/**
* Optionally flushes any data prior to the given position.
* <p/>
* <p>
* Attempting to perform a seek operation, and/or a read or write operation to a position equal to or before
* the flushed position may result in exceptions or undefined behaviour.
* <p/>
* </p>
* <p>
* Subclasses should override this method for performance reasons, to avoid holding on to unnecessary resources.
* This implementation does nothing.
* </p>
*
* @param pPosition the last position to flush.
*/
@@ -303,5 +307,7 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
* @throws IOException if the position can't be determined because of a problem in the cache backing mechanism.
*/
abstract long getPosition() throws IOException;
abstract void close() throws IOException;
}
}
@@ -1,222 +1,221 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A Reader implementation that can read from multiple sources.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/CompoundReader.java#2 $
*/
public class CompoundReader extends Reader {
private Reader current;
private List<Reader> readers;
protected final Object finalLock;
protected final boolean markSupported;
private int currentReader;
private int markedReader;
private int mark;
private int mNext;
/**
* Create a new compound reader.
*
* @param pReaders {@code Iterator} containting {@code Reader}s,
* providing the character stream.
*
* @throws NullPointerException if {@code pReaders} is {@code null}, or
* any of the elements in the iterator is {@code null}.
* @throws ClassCastException if any element of the iterator is not a
* {@code java.io.Reader}
*/
public CompoundReader(final Iterator<Reader> pReaders) {
super(Validate.notNull(pReaders, "readers"));
finalLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
// reference can't change, only it's elements
readers = new ArrayList<Reader>();
boolean markSupported = true;
while (pReaders.hasNext()) {
Reader reader = pReaders.next();
if (reader == null) {
throw new NullPointerException("readers cannot contain null-elements");
}
readers.add(reader);
markSupported = markSupported && reader.markSupported();
}
this.markSupported = markSupported;
current = nextReader();
}
protected final Reader nextReader() {
if (currentReader >= readers.size()) {
current = new EmptyReader();
}
else {
current = readers.get(currentReader++);
}
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
mNext = 0;
return current;
}
/**
* Check to make sure that the stream has not been closed
*
* @throws IOException if the stream is closed
*/
protected final void ensureOpen() throws IOException {
if (readers == null) {
throw new IOException("Stream closed");
}
}
public void close() throws IOException {
// Close all readers
for (Reader reader : readers) {
reader.close();
}
readers = null;
}
@Override
public void mark(int pReadLimit) throws IOException {
if (pReadLimit < 0) {
throw new IllegalArgumentException("Read limit < 0");
}
// TODO: It would be nice if we could actually close some readers now
synchronized (finalLock) {
ensureOpen();
mark = mNext;
markedReader = currentReader;
current.mark(pReadLimit);
}
}
@Override
public void reset() throws IOException {
synchronized (finalLock) {
ensureOpen();
if (currentReader != markedReader) {
// Reset any reader before this
for (int i = currentReader; i >= markedReader; i--) {
readers.get(i).reset();
}
currentReader = markedReader - 1;
nextReader();
}
current.reset();
mNext = mark;
}
}
@Override
public boolean markSupported() {
return markSupported;
}
@Override
public int read() throws IOException {
synchronized (finalLock) {
int read = current.read();
if (read < 0 && currentReader < readers.size()) {
nextReader();
return read(); // In case of 0-length readers
}
mNext++;
return read;
}
}
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
if (read < 0 && currentReader < readers.size()) {
nextReader();
return read(pBuffer, pOffset, pLength); // In case of 0-length readers
}
mNext += read;
return read;
}
}
@Override
public boolean ready() throws IOException {
return current.ready();
}
@Override
public long skip(long pChars) throws IOException {
synchronized (finalLock) {
long skipped = current.skip(pChars);
if (skipped == 0 && currentReader < readers.size()) {
nextReader();
return skip(pChars); // In case of 0-length readers
}
mNext += skipped;
return skipped;
}
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A Reader implementation that can read from multiple sources.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/CompoundReader.java#2 $
*/
public class CompoundReader extends Reader {
private Reader current;
private List<Reader> readers;
protected final Object finalLock;
protected final boolean markSupported;
private int currentReader;
private int markedReader;
private long mark;
private long next;
/**
* Create a new compound reader.
*
* @param pReaders {@code Iterator} containting {@code Reader}s,
* providing the character stream.
*
* @throws NullPointerException if {@code pReaders} is {@code null}, or
* any of the elements in the iterator is {@code null}.
* @throws ClassCastException if any element of the iterator is not a
* {@code java.io.Reader}
*/
public CompoundReader(final Iterator<Reader> pReaders) {
super(Validate.notNull(pReaders, "readers"));
finalLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
// reference can't change, only it's elements
readers = new ArrayList<>();
boolean markSupported = true;
while (pReaders.hasNext()) {
Reader reader = pReaders.next();
if (reader == null) {
throw new NullPointerException("readers cannot contain null-elements");
}
readers.add(reader);
markSupported = markSupported && reader.markSupported();
}
this.markSupported = markSupported;
current = nextReader();
}
protected final Reader nextReader() {
if (currentReader >= readers.size()) {
current = new EmptyReader();
}
else {
current = readers.get(currentReader++);
}
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
next = 0;
return current;
}
/**
* Check to make sure that the stream has not been closed
*
* @throws IOException if the stream is closed
*/
protected final void ensureOpen() throws IOException {
if (readers == null) {
throw new IOException("Stream closed");
}
}
public void close() throws IOException {
// Close all readers
for (Reader reader : readers) {
reader.close();
}
readers = null;
}
@Override
public void mark(int pReadLimit) throws IOException {
if (pReadLimit < 0) {
throw new IllegalArgumentException("Read limit < 0");
}
// TODO: It would be nice if we could actually close some readers now
synchronized (finalLock) {
ensureOpen();
mark = next;
markedReader = currentReader;
current.mark(pReadLimit);
}
}
@Override
public void reset() throws IOException {
synchronized (finalLock) {
ensureOpen();
if (currentReader != markedReader) {
// Reset any reader before this
for (int i = currentReader; i >= markedReader; i--) {
readers.get(i).reset();
}
currentReader = markedReader - 1;
nextReader();
}
current.reset();
next = mark;
}
}
@Override
public boolean markSupported() {
return markSupported;
}
@Override
public int read() throws IOException {
synchronized (finalLock) {
int read = current.read();
if (read < 0 && currentReader < readers.size()) {
nextReader();
return read(); // In case of 0-length readers
}
next++;
return read;
}
}
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
if (read < 0 && currentReader < readers.size()) {
nextReader();
return read(pBuffer, pOffset, pLength); // In case of 0-length readers
}
next += read;
return read;
}
}
@Override
public boolean ready() throws IOException {
return current.ready();
}
@Override
public long skip(long pChars) throws IOException {
synchronized (finalLock) {
long skipped = current.skip(pChars);
if (skipped == 0 && currentReader < readers.size()) {
nextReader();
return skip(pChars); // In case of 0-length readers
}
next += skipped;
return skipped;
}
}
}
@@ -1,47 +1,46 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.StringReader;
/**
* EmptyReader
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/EmptyReader.java#1 $
*/
final class EmptyReader extends StringReader {
public EmptyReader() {
super("");
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.StringReader;
/**
* EmptyReader
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/EmptyReader.java#1 $
*/
final class EmptyReader extends StringReader {
public EmptyReader() {
super("");
}
}
@@ -1,136 +1,130 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* An unsynchronized {@code ByteArrayOutputStream} implementation. This version
* also has a constructor that lets you create a stream with initial content.
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: FastByteArrayOutputStream.java#2 $
*/
// TODO: Performance test of a stream impl that uses list of fixed size blocks, rather than contiguous block
public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
/** Max grow size (unless if writing more than this amount of bytes) */
protected int maxGrowSize = 1024 * 1024; // 1 MB
/**
* Creates a {@code ByteArrayOutputStream} with the given initial buffer
* size.
*
* @param pSize initial buffer size
*/
public FastByteArrayOutputStream(int pSize) {
super(pSize);
}
/**
* Creates a {@code ByteArrayOutputStream} with the given initial content.
* <p/>
* Note that the buffer is not cloned, for maximum performance.
*
* @param pBuffer initial buffer
*/
public FastByteArrayOutputStream(byte[] pBuffer) {
super(0); // Don't allocate array
buf = pBuffer;
count = pBuffer.length;
}
@Override
public void write(byte pBytes[], int pOffset, int pLength) {
if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
throw new IndexOutOfBoundsException();
}
else if (pLength == 0) {
return;
}
int newCount = count + pLength;
growIfNeeded(newCount);
System.arraycopy(pBytes, pOffset, buf, count, pLength);
count = newCount;
}
@Override
public void write(int pByte) {
int newCount = count + 1;
growIfNeeded(newCount);
buf[count] = (byte) pByte;
count = newCount;
}
private void growIfNeeded(int pNewCount) {
if (pNewCount > buf.length) {
int newSize = Math.max(Math.min(buf.length << 1, buf.length + maxGrowSize), pNewCount);
byte newBuf[] = new byte[newSize];
System.arraycopy(buf, 0, newBuf, 0, count);
buf = newBuf;
}
}
// Non-synchronized version of writeTo
@Override
public void writeTo(OutputStream pOut) throws IOException {
pOut.write(buf, 0, count);
}
// Non-synchronized version of toByteArray
@Override
public byte[] toByteArray() {
byte newBuf[] = new byte[count];
System.arraycopy(buf, 0, newBuf, 0, count);
return newBuf;
}
/**
* Creates a {@code ByteArrayInputStream} that reads directly from this
* {@code FastByteArrayOutputStream}'s byte buffer.
* The buffer is not cloned, for maximum performance.
* <p/>
* Note that care needs to be taken to avoid writes to
* this output stream after the input stream is created.
* Failing to do so, may result in unpredictable behaviour.
*
* @return a new {@code ByteArrayInputStream}, reading from this stream's buffer.
*/
public ByteArrayInputStream createInputStream() {
return new ByteArrayInputStream(buf, 0, count);
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
/**
* An unsynchronized {@code ByteArrayOutputStream} implementation. This version
* also has a constructor that lets you create a stream with initial content.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: FastByteArrayOutputStream.java#2 $
*/
// TODO: Performance test of a stream impl that uses list of fixed size blocks, rather than contiguous block
public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
/**
* Creates a {@code ByteArrayOutputStream} with the given initial buffer
* size.
*
* @param pSize initial buffer size
*/
public FastByteArrayOutputStream(int pSize) {
super(pSize);
}
/**
* Creates a {@code ByteArrayOutputStream} with the given initial content.
* <p>
* Note that the buffer is not cloned, for maximum performance.
* </p>
*
* @param pBuffer initial buffer
*/
public FastByteArrayOutputStream(byte[] pBuffer) {
super(0); // Don't allocate array
buf = pBuffer;
count = pBuffer.length;
}
@Override
public void write(byte[] pBytes, int pOffset, int pLength) {
if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
throw new IndexOutOfBoundsException();
}
else if (pLength == 0) {
return;
}
int newCount = count + pLength;
growIfNeeded(newCount);
System.arraycopy(pBytes, pOffset, buf, count, pLength);
count = newCount;
}
@Override
public void write(int pByte) {
int newCount = count + 1;
growIfNeeded(newCount);
buf[count] = (byte) pByte;
count = newCount;
}
private void growIfNeeded(int pNewCount) {
if (pNewCount > buf.length) {
int newSize = Math.max(buf.length << 1, pNewCount);
buf = Arrays.copyOf(buf, newSize);
}
}
// Non-synchronized version of writeTo
@Override
public void writeTo(OutputStream pOut) throws IOException {
pOut.write(buf, 0, count);
}
// Non-synchronized version of toByteArray
@Override
public byte[] toByteArray() {
return Arrays.copyOf(buf, count);
}
/**
* Creates a {@code ByteArrayInputStream} that reads directly from this
* {@code FastByteArrayOutputStream}'s byte buffer.
* The buffer is not cloned, for maximum performance.
* <p>
* Note that care needs to be taken to avoid writes to
* this output stream after the input stream is created.
* Failing to do so, may result in unpredictable behaviour.
* </p>
*
* @return a new {@code ByteArrayInputStream}, reading from this stream's buffer.
*/
public ByteArrayInputStream createInputStream() {
return new ByteArrayInputStream(buf, 0, count);
}
}
@@ -1,232 +1,241 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.*;
/**
* A {@code SeekableInputStream} implementation that caches data in a temporary {@code File}.
* <p/>
* Temporary files are created as specified in {@link File#createTempFile(String, String, java.io.File)}.
*
* @see MemoryCacheSeekableStream
* @see FileSeekableStream
*
* @see File#createTempFile(String, String)
* @see RandomAccessFile
*
* @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/FileCacheSeekableStream.java#5 $
*/
public final class FileCacheSeekableStream extends AbstractCachedSeekableStream {
private byte[] buffer;
/**
* Creates a {@code FileCacheSeekableStream} reading from the given
* {@code InputStream}. Data will be cached in a temporary file.
*
* @param pStream the {@code InputStream} to read from
*
* @throws IOException if the temporary file cannot be created,
* or cannot be opened for random access.
*/
public FileCacheSeekableStream(final InputStream pStream) throws IOException {
this(pStream, "iocache", null);
}
/**
* Creates a {@code FileCacheSeekableStream} reading from the given
* {@code InputStream}. Data will be cached in a temporary file, with
* the given base name.
*
* @param pStream the {@code InputStream} to read from
* @param pTempBaseName optional base name for the temporary file
*
* @throws IOException if the temporary file cannot be created,
* or cannot be opened for random access.
*/
public FileCacheSeekableStream(final InputStream pStream, final String pTempBaseName) throws IOException {
this(pStream, pTempBaseName, null);
}
/**
* Creates a {@code FileCacheSeekableStream} reading from the given
* {@code InputStream}. Data will be cached in a temporary file, with
* the given base name, in the given directory
*
* @param pStream the {@code InputStream} to read from
* @param pTempBaseName optional base name for the temporary file
* @param pTempDir optional temp directory
*
* @throws IOException if the temporary file cannot be created,
* or cannot be opened for random access.
*/
public FileCacheSeekableStream(final InputStream pStream, final String pTempBaseName, final File pTempDir) throws IOException {
// NOTE: We do validation BEFORE we create temp file, to avoid orphan files
this(Validate.notNull(pStream, "stream"), createTempFile(pTempBaseName, pTempDir));
}
/*protected*/ static File createTempFile(String pTempBaseName, File pTempDir) throws IOException {
Validate.notNull(pTempBaseName, "tempBaseName");
File file = File.createTempFile(pTempBaseName, null, pTempDir);
file.deleteOnExit();
return file;
}
// TODO: Consider exposing this for external use
/*protected*/ FileCacheSeekableStream(final InputStream pStream, final File pFile) throws FileNotFoundException {
super(pStream, new FileCache(pFile));
// TODO: Allow for custom buffer sizes?
buffer = new byte[1024];
}
public final boolean isCachedMemory() {
return false;
}
public final boolean isCachedFile() {
return true;
}
@Override
protected void closeImpl() throws IOException {
super.closeImpl();
buffer = null;
}
@Override
public int read() throws IOException {
checkOpen();
int read;
if (position == streamPosition) {
// Read ahead into buffer, for performance
read = readAhead(buffer, 0, buffer.length);
if (read >= 0) {
read = buffer[0] & 0xff;
}
//System.out.println("Read 1 byte from stream: " + Integer.toHexString(read & 0xff));
}
else {
// ..or read byte from the cache
syncPosition();
read = getCache().read();
//System.out.println("Read 1 byte from cache: " + Integer.toHexString(read & 0xff));
}
// TODO: This field is not REALLY considered accessible.. :-P
if (read != -1) {
position++;
}
return read;
}
@Override
public int read(byte[] pBytes, int pOffset, int pLength) throws IOException {
checkOpen();
int length;
if (position == streamPosition) {
// Read bytes from the stream
length = readAhead(pBytes, pOffset, pLength);
//System.out.println("Read " + length + " byte from stream");
}
else {
// ...or read bytes from the cache
syncPosition();
length = getCache().read(pBytes, pOffset, (int) Math.min(pLength, streamPosition - position));
//System.out.println("Read " + length + " byte from cache");
}
// TODO: This field is not REALLY considered accessible.. :-P
if (length > 0) {
position += length;
}
return length;
}
private int readAhead(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
int length;
length = stream.read(pBytes, pOffset, pLength);
if (length > 0) {
streamPosition += length;
getCache().write(pBytes, pOffset, length);
}
return length;
}
final static class FileCache extends StreamCache {
private RandomAccessFile mCacheFile;
public FileCache(final File pFile) throws FileNotFoundException {
Validate.notNull(pFile, "file");
mCacheFile = new RandomAccessFile(pFile, "rw");
}
public void write(final int pByte) throws IOException {
mCacheFile.write(pByte);
}
@Override
public void write(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
mCacheFile.write(pBuffer, pOffset, pLength);
}
public int read() throws IOException {
return mCacheFile.read();
}
@Override
public int read(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
return mCacheFile.read(pBuffer, pOffset, pLength);
}
public void seek(final long pPosition) throws IOException {
mCacheFile.seek(pPosition);
}
public long getPosition() throws IOException {
return mCacheFile.getFilePointer();
}
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.*;
/**
* A {@code SeekableInputStream} implementation that caches data in a temporary {@code File}.
* <p>
* Temporary files are created as specified in {@link File#createTempFile(String, String, java.io.File)}.
* </p>
*
* @see MemoryCacheSeekableStream
* @see FileSeekableStream
*
* @see File#createTempFile(String, String)
* @see RandomAccessFile
*
* @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/FileCacheSeekableStream.java#5 $
*/
public final class FileCacheSeekableStream extends AbstractCachedSeekableStream {
private byte[] buffer;
/**
* Creates a {@code FileCacheSeekableStream} reading from the given
* {@code InputStream}. Data will be cached in a temporary file.
*
* @param pStream the {@code InputStream} to read from
*
* @throws IOException if the temporary file cannot be created,
* or cannot be opened for random access.
*/
public FileCacheSeekableStream(final InputStream pStream) throws IOException {
this(pStream, "iocache", null);
}
/**
* Creates a {@code FileCacheSeekableStream} reading from the given
* {@code InputStream}. Data will be cached in a temporary file, with
* the given base name.
*
* @param pStream the {@code InputStream} to read from
* @param pTempBaseName optional base name for the temporary file
*
* @throws IOException if the temporary file cannot be created,
* or cannot be opened for random access.
*/
public FileCacheSeekableStream(final InputStream pStream, final String pTempBaseName) throws IOException {
this(pStream, pTempBaseName, null);
}
/**
* Creates a {@code FileCacheSeekableStream} reading from the given
* {@code InputStream}. Data will be cached in a temporary file, with
* the given base name, in the given directory
*
* @param pStream the {@code InputStream} to read from
* @param pTempBaseName optional base name for the temporary file
* @param pTempDir optional temp directory
*
* @throws IOException if the temporary file cannot be created,
* or cannot be opened for random access.
*/
public FileCacheSeekableStream(final InputStream pStream, final String pTempBaseName, final File pTempDir) throws IOException {
// NOTE: We do validation BEFORE we create temp file, to avoid orphan files
this(Validate.notNull(pStream, "stream"), createTempFile(pTempBaseName, pTempDir));
}
/*protected*/ static File createTempFile(String pTempBaseName, File pTempDir) throws IOException {
Validate.notNull(pTempBaseName, "tempBaseName");
File file = File.createTempFile(pTempBaseName, null, pTempDir);
file.deleteOnExit();
return file;
}
// TODO: Consider exposing this for external use
/*protected*/ FileCacheSeekableStream(final InputStream pStream, final File pFile) throws FileNotFoundException {
super(pStream, new FileCache(pFile));
// TODO: Allow for custom buffer sizes?
buffer = new byte[1024];
}
public final boolean isCachedMemory() {
return false;
}
public final boolean isCachedFile() {
return true;
}
@Override
protected void closeImpl() throws IOException {
// TODO: Close cache file
super.closeImpl();
buffer = null;
}
@Override
public int read() throws IOException {
checkOpen();
int read;
if (position == streamPosition) {
// Read ahead into buffer, for performance
read = readAhead(buffer, 0, buffer.length);
if (read >= 0) {
read = buffer[0] & 0xff;
}
//System.out.println("Read 1 byte from stream: " + Integer.toHexString(read & 0xff));
}
else {
// ..or read byte from the cache
syncPosition();
read = getCache().read();
//System.out.println("Read 1 byte from cache: " + Integer.toHexString(read & 0xff));
}
// TODO: This field is not REALLY considered accessible.. :-P
if (read != -1) {
position++;
}
return read;
}
@Override
public int read(byte[] pBytes, int pOffset, int pLength) throws IOException {
checkOpen();
int length;
if (position == streamPosition) {
// Read bytes from the stream
length = readAhead(pBytes, pOffset, pLength);
//System.out.println("Read " + length + " byte from stream");
}
else {
// ...or read bytes from the cache
syncPosition();
length = getCache().read(pBytes, pOffset, (int) Math.min(pLength, streamPosition - position));
//System.out.println("Read " + length + " byte from cache");
}
// TODO: This field is not REALLY considered accessible.. :-P
if (length > 0) {
position += length;
}
return length;
}
private int readAhead(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
int length;
length = stream.read(pBytes, pOffset, pLength);
if (length > 0) {
streamPosition += length;
getCache().write(pBytes, pOffset, length);
}
return length;
}
// TODO: We need to close the cache file!!! Otherwise we are leaking file descriptors
final static class FileCache extends StreamCache {
private RandomAccessFile cacheFile;
public FileCache(final File pFile) throws FileNotFoundException {
Validate.notNull(pFile, "file");
cacheFile = new RandomAccessFile(pFile, "rw");
}
public void write(final int pByte) throws IOException {
cacheFile.write(pByte);
}
@Override
public void write(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
cacheFile.write(pBuffer, pOffset, pLength);
}
public int read() throws IOException {
return cacheFile.read();
}
@Override
public int read(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
return cacheFile.read(pBuffer, pOffset, pLength);
}
public void seek(final long pPosition) throws IOException {
cacheFile.seek(pPosition);
}
public long getPosition() throws IOException {
return cacheFile.getFilePointer();
}
@Override
void close() throws IOException {
cacheFile.close();
}
}
}
@@ -1,135 +1,135 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* A {@code SeekableInputStream} implementation that uses random access directly to a {@code File}.
* <p/>
* @see FileCacheSeekableStream
* @see MemoryCacheSeekableStream
* @see RandomAccessFile
*
* @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/FileSeekableStream.java#4 $
*/
public final class FileSeekableStream extends SeekableInputStream {
// TODO: Figure out why this class is SLOWER than FileCacheSeekableStream in
// my tests..?
final RandomAccessFile mRandomAccess;
/**
* Creates a {@code FileSeekableStream} that reads from the given
* {@code File}.
*
* @param pInput file to read from
* @throws FileNotFoundException if {@code pInput} does not exist
*/
public FileSeekableStream(final File pInput) throws FileNotFoundException {
this(new RandomAccessFile(pInput, "r"));
}
/**
* Creates a {@code FileSeekableStream} that reads from the given file.
* The {@code RandomAccessFile} needs only to be open in read
* ({@code "r"}) mode.
*
* @param pInput file to read from
*/
public FileSeekableStream(final RandomAccessFile pInput) {
mRandomAccess = pInput;
}
/// Seekable
public boolean isCached() {
return false;
}
public boolean isCachedFile() {
return false;
}
public boolean isCachedMemory() {
return false;
}
/// InputStream
@Override
public int available() throws IOException {
long length = mRandomAccess.length() - position;
return length > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) length;
}
public void closeImpl() throws IOException {
mRandomAccess.close();
}
public int read() throws IOException {
checkOpen();
int read = mRandomAccess.read();
if (read >= 0) {
position++;
}
return read;
}
@Override
public int read(byte pBytes[], int pOffset, int pLength) throws IOException {
checkOpen();
int read = mRandomAccess.read(pBytes, pOffset, pLength);
if (read > 0) {
position += read;
}
return read;
}
/**
* Does nothing, as we don't really do any caching here.
*
* @param pPosition the position to flush to
*/
protected void flushBeforeImpl(long pPosition) {
}
protected void seekImpl(long pPosition) throws IOException {
mRandomAccess.seek(pPosition);
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* A {@code SeekableInputStream} implementation that uses random access directly to a {@code File}.
* @see FileCacheSeekableStream
* @see MemoryCacheSeekableStream
* @see RandomAccessFile
*
* @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/FileSeekableStream.java#4 $
*/
public final class FileSeekableStream extends SeekableInputStream {
// TODO: Figure out why this class is SLOWER than FileCacheSeekableStream in
// my tests..?
final RandomAccessFile mRandomAccess;
/**
* Creates a {@code FileSeekableStream} that reads from the given
* {@code File}.
*
* @param pInput file to read from
* @throws FileNotFoundException if {@code pInput} does not exist
*/
public FileSeekableStream(final File pInput) throws FileNotFoundException {
this(new RandomAccessFile(pInput, "r"));
}
/**
* Creates a {@code FileSeekableStream} that reads from the given file.
* The {@code RandomAccessFile} needs only to be open in read
* ({@code "r"}) mode.
*
* @param pInput file to read from
*/
public FileSeekableStream(final RandomAccessFile pInput) {
mRandomAccess = pInput;
}
/// Seekable
public boolean isCached() {
return false;
}
public boolean isCachedFile() {
return false;
}
public boolean isCachedMemory() {
return false;
}
/// InputStream
@Override
public int available() throws IOException {
long length = mRandomAccess.length() - position;
return length > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) length;
}
public void closeImpl() throws IOException {
mRandomAccess.close();
}
public int read() throws IOException {
checkOpen();
int read = mRandomAccess.read();
if (read >= 0) {
position++;
}
return read;
}
@Override
public int read(byte pBytes[], int pOffset, int pLength) throws IOException {
checkOpen();
int read = mRandomAccess.read(pBytes, pOffset, pLength);
if (read > 0) {
position += read;
}
return read;
}
/**
* Does nothing, as we don't really do any caching here.
*
* @param pPosition the position to flush to
*/
protected void flushBeforeImpl(long pPosition) {
}
protected void seekImpl(long pPosition) throws IOException {
mRandomAccess.seek(pPosition);
}
}
@@ -1,103 +1,102 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* FileSystem
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: FileSystem.java#1 $
*/
abstract class FileSystem {
abstract long getFreeSpace(File pPath);
abstract long getTotalSpace(File pPath);
abstract String getName();
static BufferedReader exec(String[] pArgs) throws IOException {
Process cmd = Runtime.getRuntime().exec(pArgs);
return new BufferedReader(new InputStreamReader(cmd.getInputStream()));
}
static FileSystem get() {
String os = System.getProperty("os.name");
//System.out.println("os = " + os);
os = os.toLowerCase();
if (os.contains("windows")) {
return new Win32FileSystem();
}
else if (os.contains("linux") ||
os.contains("sun os") ||
os.contains("sunos") ||
os.contains("solaris") ||
os.contains("mpe/ix") ||
os.contains("hp-ux") ||
os.contains("aix") ||
os.contains("freebsd") ||
os.contains("irix") ||
os.contains("digital unix") ||
os.contains("unix") ||
os.contains("mac os x")) {
return new UnixFileSystem();
}
else {
return new UnknownFileSystem(os);
}
}
private static class UnknownFileSystem extends FileSystem {
private final String osName;
UnknownFileSystem(String pOSName) {
osName = pOSName;
}
long getFreeSpace(File pPath) {
return 0l;
}
long getTotalSpace(File pPath) {
return 0l;
}
String getName() {
return "Unknown (" + osName + ")";
}
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* FileSystem
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: FileSystem.java#1 $
*/
abstract class FileSystem {
abstract long getFreeSpace(File pPath);
abstract long getTotalSpace(File pPath);
abstract String getName();
static BufferedReader exec(String[] pArgs) throws IOException {
Process cmd = Runtime.getRuntime().exec(pArgs);
return new BufferedReader(new InputStreamReader(cmd.getInputStream()));
}
static FileSystem get() {
String os = System.getProperty("os.name");
//System.out.println("os = " + os);
os = os.toLowerCase();
if (os.contains("windows")) {
return new Win32FileSystem();
}
else if (os.contains("linux") ||
os.contains("sun os") ||
os.contains("sunos") ||
os.contains("solaris") ||
os.contains("mpe/ix") ||
os.contains("hp-ux") ||
os.contains("aix") ||
os.contains("freebsd") ||
os.contains("irix") ||
os.contains("digital unix") ||
os.contains("unix") ||
os.contains("mac os x")) {
return new UnixFileSystem();
}
else {
return new UnknownFileSystem(os);
}
}
private static class UnknownFileSystem extends FileSystem {
private final String osName;
UnknownFileSystem(String pOSName) {
osName = pOSName;
}
long getFreeSpace(File pPath) {
return 0l;
}
long getTotalSpace(File pPath) {
return 0l;
}
String getName() {
return "Unknown (" + osName + ")";
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,244 +1,250 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.util.regex.WildcardStringParser;
import java.io.File;
import java.io.FilenameFilter;
/**
* A Java Bean used for approving file names which are to be included in a
* {@code java.io.File} listing.
* The mask is given as a well-known DOS filename format, with '*' and '?' as
* wildcards.
* All other characters counts as ordinary characters.
* <p/>
* The file name masks are used as a filter input and is given to the class via
* the string array property:<br>
* <dd>{@code filenameMasksForInclusion} - Filename mask for exclusion of
* files (default if both properties are defined)
* <dd>{@code filenameMasksForExclusion} - Filename mask for exclusion of
* files.
* <p/>
* A recommended way of doing this is by referencing to the component which uses
* this class for file listing. In this way all properties are set in the same
* component and this utility component is kept in the background with only
* initial configuration necessary.
*
* @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a>
* @see File#list(java.io.FilenameFilter) java.io.File.list
* @see FilenameFilter java.io.FilenameFilter
* @see WildcardStringParser
* @deprecated
*/
public class FilenameMaskFilter implements FilenameFilter {
// TODO: Rewrite to use regexp, or create new class
// Members
private String[] filenameMasksForInclusion;
private String[] filenameMasksForExclusion;
private boolean inclusion = true;
/**
* Creates a {@code FilenameMaskFilter}
*/
public FilenameMaskFilter() {
}
/**
* Creates a {@code FilenameMaskFilter}
*
* @param pFilenameMask the filename mask
*/
public FilenameMaskFilter(final String pFilenameMask) {
String[] filenameMask = {pFilenameMask};
setFilenameMasksForInclusion(filenameMask);
}
/**
* Creates a {@code FilenameMaskFilter}
*
* @param pFilenameMasks the filename masks
*/
public FilenameMaskFilter(final String[] pFilenameMasks) {
this(pFilenameMasks, false);
}
/**
* Creates a {@code FilenameMaskFilter}
*
* @param pFilenameMask the filename masks
* @param pExclusion if {@code true}, the masks will be excluded
*/
public FilenameMaskFilter(final String pFilenameMask, final boolean pExclusion) {
String[] filenameMask = {pFilenameMask};
if (pExclusion) {
setFilenameMasksForExclusion(filenameMask);
}
else {
setFilenameMasksForInclusion(filenameMask);
}
}
/**
* Creates a {@code FilenameMaskFilter}
*
* @param pFilenameMasks the filename masks
* @param pExclusion if {@code true}, the masks will be excluded
*/
public FilenameMaskFilter(final String[] pFilenameMasks, final boolean pExclusion) {
if (pExclusion) {
setFilenameMasksForExclusion(pFilenameMasks);
}
else {
setFilenameMasksForInclusion(pFilenameMasks);
}
}
/**
*
* @param pFilenameMasksForInclusion the filename masks to include
*/
public void setFilenameMasksForInclusion(String[] pFilenameMasksForInclusion) {
filenameMasksForInclusion = pFilenameMasksForInclusion;
}
/**
* @return the current inclusion masks
*/
public String[] getFilenameMasksForInclusion() {
return filenameMasksForInclusion.clone();
}
/**
* @param pFilenameMasksForExclusion the filename masks to exclude
*/
public void setFilenameMasksForExclusion(String[] pFilenameMasksForExclusion) {
filenameMasksForExclusion = pFilenameMasksForExclusion;
inclusion = false;
}
/**
* @return the current exclusion masks
*/
public String[] getFilenameMasksForExclusion() {
return filenameMasksForExclusion.clone();
}
/**
* This method implements the {@code java.io.FilenameFilter} interface.
*
* @param pDir the directory in which the file was found.
* @param pName the name of the file.
* @return {@code true} if the file {@code pName} should be included in the file
* list; {@code false} otherwise.
*/
public boolean accept(File pDir, String pName) {
WildcardStringParser parser;
// Check each filename string mask whether the file is to be accepted
if (inclusion) { // Inclusion
for (String mask : filenameMasksForInclusion) {
parser = new WildcardStringParser(mask);
if (parser.parseString(pName)) {
// The filename was accepted by the filename masks provided
// - include it in filename list
return true;
}
}
// The filename not was accepted by any of the filename masks
// provided - NOT to be included in the filename list
return false;
}
else {
// Exclusion
for (String mask : filenameMasksForExclusion) {
parser = new WildcardStringParser(mask);
if (parser.parseString(pName)) {
// The filename was accepted by the filename masks provided
// - NOT to be included in the filename list
return false;
}
}
// The filename was not accepted by any of the filename masks
// provided - include it in filename list
return true;
}
}
/**
* @return a string representation for debug purposes
*/
public String toString() {
StringBuilder retVal = new StringBuilder();
int i;
if (inclusion) {
// Inclusion
if (filenameMasksForInclusion == null) {
retVal.append("No filename masks set - property filenameMasksForInclusion is null!");
}
else {
retVal.append(filenameMasksForInclusion.length);
retVal.append(" filename mask(s) - ");
for (i = 0; i < filenameMasksForInclusion.length; i++) {
retVal.append("\"");
retVal.append(filenameMasksForInclusion[i]);
retVal.append("\", \"");
}
}
}
else {
// Exclusion
if (filenameMasksForExclusion == null) {
retVal.append("No filename masks set - property filenameMasksForExclusion is null!");
}
else {
retVal.append(filenameMasksForExclusion.length);
retVal.append(" exclusion filename mask(s) - ");
for (i = 0; i < filenameMasksForExclusion.length; i++) {
retVal.append("\"");
retVal.append(filenameMasksForExclusion[i]);
retVal.append("\", \"");
}
}
}
return retVal.toString();
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.util.regex.WildcardStringParser;
import java.io.File;
import java.io.FilenameFilter;
/**
* A Java Bean used for approving file names which are to be included in a
* {@code java.io.File} listing.
* The mask is given as a well-known DOS filename format, with '*' and '?' as
* wildcards.
* All other characters counts as ordinary characters.
* <p>
* The file name masks are used as a filter input and is given to the class via
* the string array property:
* </p>
* <dl>
* <dt>{@code filenameMasksForInclusion}</dt>
* <dd>Filename mask for exclusion of
* files (default if both properties are defined).</dd>
* <dt>{@code filenameMasksForExclusion}</dt>
* <dd>Filename mask for exclusion of files.</dd>
* </dl>
* <p>
* A recommended way of doing this is by referencing to the component which uses
* this class for file listing. In this way all properties are set in the same
* component and this utility component is kept in the background with only
* initial configuration necessary.
* </p>
*
* @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a>
* @see File#list(java.io.FilenameFilter) java.io.File.list
* @see FilenameFilter java.io.FilenameFilter
* @see WildcardStringParser
* @deprecated
*/
@Deprecated
public class FilenameMaskFilter implements FilenameFilter {
// TODO: Rewrite to use regexp, or create new class
// Members
private String[] filenameMasksForInclusion;
private String[] filenameMasksForExclusion;
private boolean inclusion = true;
/**
* Creates a {@code FilenameMaskFilter}
*/
public FilenameMaskFilter() {
}
/**
* Creates a {@code FilenameMaskFilter}
*
* @param pFilenameMask the filename mask
*/
public FilenameMaskFilter(final String pFilenameMask) {
String[] filenameMask = {pFilenameMask};
setFilenameMasksForInclusion(filenameMask);
}
/**
* Creates a {@code FilenameMaskFilter}
*
* @param pFilenameMasks the filename masks
*/
public FilenameMaskFilter(final String[] pFilenameMasks) {
this(pFilenameMasks, false);
}
/**
* Creates a {@code FilenameMaskFilter}
*
* @param pFilenameMask the filename masks
* @param pExclusion if {@code true}, the masks will be excluded
*/
public FilenameMaskFilter(final String pFilenameMask, final boolean pExclusion) {
String[] filenameMask = {pFilenameMask};
if (pExclusion) {
setFilenameMasksForExclusion(filenameMask);
}
else {
setFilenameMasksForInclusion(filenameMask);
}
}
/**
* Creates a {@code FilenameMaskFilter}
*
* @param pFilenameMasks the filename masks
* @param pExclusion if {@code true}, the masks will be excluded
*/
public FilenameMaskFilter(final String[] pFilenameMasks, final boolean pExclusion) {
if (pExclusion) {
setFilenameMasksForExclusion(pFilenameMasks);
}
else {
setFilenameMasksForInclusion(pFilenameMasks);
}
}
/**
*
* @param pFilenameMasksForInclusion the filename masks to include
*/
public void setFilenameMasksForInclusion(String[] pFilenameMasksForInclusion) {
filenameMasksForInclusion = pFilenameMasksForInclusion;
}
/**
* @return the current inclusion masks
*/
public String[] getFilenameMasksForInclusion() {
return filenameMasksForInclusion.clone();
}
/**
* @param pFilenameMasksForExclusion the filename masks to exclude
*/
public void setFilenameMasksForExclusion(String[] pFilenameMasksForExclusion) {
filenameMasksForExclusion = pFilenameMasksForExclusion;
inclusion = false;
}
/**
* @return the current exclusion masks
*/
public String[] getFilenameMasksForExclusion() {
return filenameMasksForExclusion.clone();
}
/**
* This method implements the {@code java.io.FilenameFilter} interface.
*
* @param pDir the directory in which the file was found.
* @param pName the name of the file.
* @return {@code true} if the file {@code pName} should be included in the file
* list; {@code false} otherwise.
*/
public boolean accept(File pDir, String pName) {
WildcardStringParser parser;
// Check each filename string mask whether the file is to be accepted
if (inclusion) { // Inclusion
for (String mask : filenameMasksForInclusion) {
parser = new WildcardStringParser(mask);
if (parser.parseString(pName)) {
// The filename was accepted by the filename masks provided
// - include it in filename list
return true;
}
}
// The filename not was accepted by any of the filename masks
// provided - NOT to be included in the filename list
return false;
}
else {
// Exclusion
for (String mask : filenameMasksForExclusion) {
parser = new WildcardStringParser(mask);
if (parser.parseString(pName)) {
// The filename was accepted by the filename masks provided
// - NOT to be included in the filename list
return false;
}
}
// The filename was not accepted by any of the filename masks
// provided - include it in filename list
return true;
}
}
/**
* @return a string representation for debug purposes
*/
public String toString() {
StringBuilder retVal = new StringBuilder();
int i;
if (inclusion) {
// Inclusion
if (filenameMasksForInclusion == null) {
retVal.append("No filename masks set - property filenameMasksForInclusion is null!");
}
else {
retVal.append(filenameMasksForInclusion.length);
retVal.append(" filename mask(s) - ");
for (i = 0; i < filenameMasksForInclusion.length; i++) {
retVal.append("\"");
retVal.append(filenameMasksForInclusion[i]);
retVal.append("\", \"");
}
}
}
else {
// Exclusion
if (filenameMasksForExclusion == null) {
retVal.append("No filename masks set - property filenameMasksForExclusion is null!");
}
else {
retVal.append(filenameMasksForExclusion.length);
retVal.append(" exclusion filename mask(s) - ");
for (i = 0; i < filenameMasksForExclusion.length; i++) {
retVal.append("\"");
retVal.append(filenameMasksForExclusion[i]);
retVal.append("\", \"");
}
}
}
return retVal.toString();
}
}
@@ -1,453 +1,450 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* From http://www.cafeaulait.org/books/javaio/ioexamples/index.html:
*
* Please feel free to use any fragment of this code you need in your own work.
* As far as I am concerned, it's in the public domain. No permission is necessary
* or required. Credit is always appreciated if you use a large chunk or base a
* significant product on one of my examples, but that's not required either.
*
* Elliotte Rusty Harold
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.*;
/**
* A little endian input stream reads two's complement,
* little endian integers, floating point numbers, and characters
* and returns them as Java primitive types.
* <p/>
* The standard {@code java.io.DataInputStream} class
* which this class imitates reads big endian quantities.
* <p/>
* <em>Warning:
* <!-- Beware of little indians! -->
* The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations.
* </em>
*
* @see com.twelvemonkeys.io.LittleEndianRandomAccessFile
* @see java.io.DataInputStream
* @see java.io.DataInput
* @see java.io.DataOutput
*
* @author Elliotte Rusty Harold
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version 2
*/
public class LittleEndianDataInputStream extends FilterInputStream implements DataInput {
// TODO: Optimize by reading into a fixed size (8 bytes) buffer instead of individual read operations?
/**
* Creates a new little endian input stream and chains it to the
* input stream specified by the {@code pStream} argument.
*
* @param pStream the underlying input stream.
* @see java.io.FilterInputStream#in
*/
public LittleEndianDataInputStream(final InputStream pStream) {
super(Validate.notNull(pStream, "stream"));
}
/**
* Reads a {@code boolean} from the underlying input stream by
* reading a single byte. If the byte is zero, false is returned.
* If the byte is positive, true is returned.
*
* @return the {@code boolean} value read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public boolean readBoolean() throws IOException {
int b = in.read();
if (b < 0) {
throw new EOFException();
}
return b != 0;
}
/**
* Reads a signed {@code byte} from the underlying input stream
* with value between -128 and 127
*
* @return the {@code byte} value read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public byte readByte() throws IOException {
int b = in.read();
if (b < 0) {
throw new EOFException();
}
return (byte) b;
}
/**
* Reads an unsigned {@code byte} from the underlying
* input stream with value between 0 and 255
*
* @return the {@code byte} value read.
* @throws EOFException if the end of the underlying input
* stream has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public int readUnsignedByte() throws IOException {
int b = in.read();
if (b < 0) {
throw new EOFException();
}
return b;
}
/**
* Reads a two byte signed {@code short} from the underlying
* input stream in little endian order, low byte first.
*
* @return the {@code short} read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public short readShort() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
// only need to test last byte read
// if byte1 is -1 so is byte2
if (byte2 < 0) {
throw new EOFException();
}
return (short) (((byte2 << 24) >>> 16) | (byte1 << 24) >>> 24);
}
/**
* Reads a two byte unsigned {@code short} from the underlying
* input stream in little endian order, low byte first.
*
* @return the int value of the unsigned short read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public int readUnsignedShort() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
if (byte2 < 0) {
throw new EOFException();
}
return (byte2 << 8) + byte1;
}
/**
* Reads a two byte Unicode {@code char} from the underlying
* input stream in little endian order, low byte first.
*
* @return the int value of the unsigned short read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public char readChar() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
if (byte2 < 0) {
throw new EOFException();
}
return (char) (((byte2 << 24) >>> 16) | ((byte1 << 24) >>> 24));
}
/**
* Reads a four byte signed {@code int} from the underlying
* input stream in little endian order, low byte first.
*
* @return the {@code int} read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public int readInt() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
int byte3 = in.read();
int byte4 = in.read();
if (byte4 < 0) {
throw new EOFException();
}
return (byte4 << 24) | ((byte3 << 24) >>> 8)
| ((byte2 << 24) >>> 16) | ((byte1 << 24) >>> 24);
}
/**
* Reads an eight byte signed {@code int} from the underlying
* input stream in little endian order, low byte first.
*
* @return the {@code int} read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public long readLong() throws IOException {
long byte1 = in.read();
long byte2 = in.read();
long byte3 = in.read();
long byte4 = in.read();
long byte5 = in.read();
long byte6 = in.read();
long byte7 = in.read();
long byte8 = in.read();
if (byte8 < 0) {
throw new EOFException();
}
return (byte8 << 56) | ((byte7 << 56) >>> 8)
| ((byte6 << 56) >>> 16) | ((byte5 << 56) >>> 24)
| ((byte4 << 56) >>> 32) | ((byte3 << 56) >>> 40)
| ((byte2 << 56) >>> 48) | ((byte1 << 56) >>> 56);
}
/**
* Reads a string of no more than 65,535 characters
* from the underlying input stream using UTF-8
* encoding. This method first reads a two byte short
* in <b>big</b> endian order as required by the
* UTF-8 specification. This gives the number of bytes in
* the UTF-8 encoded version of the string.
* Next this many bytes are read and decoded as UTF-8
* encoded characters.
*
* @return the decoded string
* @throws UTFDataFormatException if the string cannot be decoded
* @throws IOException if the underlying stream throws an IOException.
*/
public String readUTF() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
if (byte2 < 0) {
throw new EOFException();
}
int numbytes = (byte1 << 8) + byte2;
char result[] = new char[numbytes];
int numread = 0;
int numchars = 0;
while (numread < numbytes) {
int c1 = readUnsignedByte();
int c2, c3;
// The first four bits of c1 determine how many bytes are in this char
int test = c1 >> 4;
if (test < 8) { // one byte
numread++;
result[numchars++] = (char) c1;
}
else if (test == 12 || test == 13) { // two bytes
numread += 2;
if (numread > numbytes) {
throw new UTFDataFormatException();
}
c2 = readUnsignedByte();
if ((c2 & 0xC0) != 0x80) {
throw new UTFDataFormatException();
}
result[numchars++] = (char) (((c1 & 0x1F) << 6) | (c2 & 0x3F));
}
else if (test == 14) { // three bytes
numread += 3;
if (numread > numbytes) {
throw new UTFDataFormatException();
}
c2 = readUnsignedByte();
c3 = readUnsignedByte();
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
throw new UTFDataFormatException();
}
result[numchars++] = (char) (((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
}
else { // malformed
throw new UTFDataFormatException();
}
} // end while
return new String(result, 0, numchars);
}
/**
* @return the next eight bytes of this input stream, interpreted as a
* little endian {@code double}.
* @throws EOFException if end of stream occurs before eight bytes
* have been read.
* @throws IOException if an I/O error occurs.
*/
public final double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
/**
* @return the next four bytes of this input stream, interpreted as a
* little endian {@code int}.
* @throws EOFException if end of stream occurs before four bytes
* have been read.
* @throws IOException if an I/O error occurs.
*/
public final float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
/**
* See the general contract of the {@code skipBytes}
* method of {@code DataInput}.
* <p>
* Bytes for this operation are read from the contained input stream.
*
* @param pLength the number of bytes to be skipped.
* @return the actual number of bytes skipped.
* @exception IOException if an I/O error occurs.
*/
public final int skipBytes(int pLength) throws IOException {
// NOTE: There was probably a bug in ERH's original code here, as skip
// never returns -1, but returns 0 if no more bytes can be skipped...
int total = 0;
int skipped;
while ((total < pLength) && ((skipped = (int) in.skip(pLength - total)) > 0)) {
total += skipped;
}
return total;
}
/**
* See the general contract of the {@code readFully}
* method of {@code DataInput}.
* <p/>
* Bytes
* for this operation are read from the contained
* input stream.
*
* @param pBytes the buffer into which the data is read.
* @throws EOFException if this input stream reaches the end before
* reading all the bytes.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterInputStream#in
*/
public final void readFully(byte pBytes[]) throws IOException {
readFully(pBytes, 0, pBytes.length);
}
/**
* See the general contract of the {@code readFully}
* method of {@code DataInput}.
* <p/>
* Bytes
* for this operation are read from the contained
* input stream.
*
* @param pBytes the buffer into which the data is read.
* @param pOffset the start offset of the data.
* @param pLength the number of bytes to read.
* @throws EOFException if this input stream reaches the end before
* reading all the bytes.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterInputStream#in
*/
public final void readFully(byte pBytes[], int pOffset, int pLength) throws IOException {
if (pLength < 0) {
throw new IndexOutOfBoundsException();
}
int count = 0;
while (count < pLength) {
int read = in.read(pBytes, pOffset + count, pLength - count);
if (read < 0) {
throw new EOFException();
}
count += read;
}
}
/**
* See the general contract of the {@code readLine}
* method of {@code DataInput}.
* <p>
* Bytes for this operation are read from the contained input stream.
*
* @deprecated This method does not properly convert bytes to characters.
*
* @return the next line of text from this input stream.
* @exception IOException if an I/O error occurs.
* @see java.io.BufferedReader#readLine()
* @see java.io.DataInputStream#readLine()
* @noinspection deprecation
*/
public String readLine() throws IOException {
DataInputStream ds = new DataInputStream(in);
return ds.readLine();
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* From http://www.cafeaulait.org/books/javaio/ioexamples/index.html:
*
* Please feel free to use any fragment of this code you need in your own work.
* As far as I am concerned, it's in the public domain. No permission is necessary
* or required. Credit is always appreciated if you use a large chunk or base a
* significant product on one of my examples, but that's not required either.
*
* Elliotte Rusty Harold
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.*;
/**
* A little endian input stream reads two's complement,
* little endian integers, floating point numbers, and characters
* and returns them as Java primitive types.
* <p>
* The standard {@code java.io.DataInputStream} class
* which this class imitates reads big endian quantities.
* </p>
* <p>
* <em>Warning:
* The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations.
* </em>
* </p>
*
* @see com.twelvemonkeys.io.LittleEndianRandomAccessFile
* @see java.io.DataInputStream
* @see java.io.DataInput
* @see java.io.DataOutput
*
* @author Elliotte Rusty Harold
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version 2
*/
public class LittleEndianDataInputStream extends FilterInputStream implements DataInput {
// TODO: Optimize by reading into a fixed size (8 bytes) buffer instead of individual read operations?
/**
* Creates a new little endian input stream and chains it to the
* input stream specified by the {@code pStream} argument.
*
* @param pStream the underlying input stream.
* @see java.io.FilterInputStream#in
*/
public LittleEndianDataInputStream(final InputStream pStream) {
super(Validate.notNull(pStream, "stream"));
}
/**
* Reads a {@code boolean} from the underlying input stream by
* reading a single byte. If the byte is zero, false is returned.
* If the byte is positive, true is returned.
*
* @return the {@code boolean} value read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public boolean readBoolean() throws IOException {
int b = in.read();
if (b < 0) {
throw new EOFException();
}
return b != 0;
}
/**
* Reads a signed {@code byte} from the underlying input stream
* with value between -128 and 127
*
* @return the {@code byte} value read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public byte readByte() throws IOException {
int b = in.read();
if (b < 0) {
throw new EOFException();
}
return (byte) b;
}
/**
* Reads an unsigned {@code byte} from the underlying
* input stream with value between 0 and 255
*
* @return the {@code byte} value read.
* @throws EOFException if the end of the underlying input
* stream has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public int readUnsignedByte() throws IOException {
int b = in.read();
if (b < 0) {
throw new EOFException();
}
return b;
}
/**
* Reads a two byte signed {@code short} from the underlying
* input stream in little endian order, low byte first.
*
* @return the {@code short} read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public short readShort() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
// only need to test last byte read
// if byte1 is -1 so is byte2
if (byte2 < 0) {
throw new EOFException();
}
return (short) (((byte2 << 24) >>> 16) | (byte1 << 24) >>> 24);
}
/**
* Reads a two byte unsigned {@code short} from the underlying
* input stream in little endian order, low byte first.
*
* @return the int value of the unsigned short read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public int readUnsignedShort() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
if (byte2 < 0) {
throw new EOFException();
}
return (byte2 << 8) + byte1;
}
/**
* Reads a two byte Unicode {@code char} from the underlying
* input stream in little endian order, low byte first.
*
* @return the int value of the unsigned short read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public char readChar() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
if (byte2 < 0) {
throw new EOFException();
}
return (char) (((byte2 << 24) >>> 16) | ((byte1 << 24) >>> 24));
}
/**
* Reads a four byte signed {@code int} from the underlying
* input stream in little endian order, low byte first.
*
* @return the {@code int} read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public int readInt() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
int byte3 = in.read();
int byte4 = in.read();
if (byte4 < 0) {
throw new EOFException();
}
return (byte4 << 24) | ((byte3 << 24) >>> 8)
| ((byte2 << 24) >>> 16) | ((byte1 << 24) >>> 24);
}
/**
* Reads an eight byte signed {@code int} from the underlying
* input stream in little endian order, low byte first.
*
* @return the {@code int} read.
* @throws EOFException if the end of the underlying input stream
* has been reached
* @throws IOException if the underlying stream throws an IOException.
*/
public long readLong() throws IOException {
long byte1 = in.read();
long byte2 = in.read();
long byte3 = in.read();
long byte4 = in.read();
long byte5 = in.read();
long byte6 = in.read();
long byte7 = in.read();
long byte8 = in.read();
if (byte8 < 0) {
throw new EOFException();
}
return (byte8 << 56) | ((byte7 << 56) >>> 8)
| ((byte6 << 56) >>> 16) | ((byte5 << 56) >>> 24)
| ((byte4 << 56) >>> 32) | ((byte3 << 56) >>> 40)
| ((byte2 << 56) >>> 48) | ((byte1 << 56) >>> 56);
}
/**
* Reads a string of no more than 65,535 characters
* from the underlying input stream using UTF-8
* encoding. This method first reads a two byte short
* in <b>big</b> endian order as required by the
* UTF-8 specification. This gives the number of bytes in
* the UTF-8 encoded version of the string.
* Next this many bytes are read and decoded as UTF-8
* encoded characters.
*
* @return the decoded string
* @throws UTFDataFormatException if the string cannot be decoded
* @throws IOException if the underlying stream throws an IOException.
*/
public String readUTF() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
if (byte2 < 0) {
throw new EOFException();
}
int numbytes = (byte1 << 8) + byte2;
char result[] = new char[numbytes];
int numread = 0;
int numchars = 0;
while (numread < numbytes) {
int c1 = readUnsignedByte();
int c2, c3;
// The first four bits of c1 determine how many bytes are in this char
int test = c1 >> 4;
if (test < 8) { // one byte
numread++;
result[numchars++] = (char) c1;
}
else if (test == 12 || test == 13) { // two bytes
numread += 2;
if (numread > numbytes) {
throw new UTFDataFormatException();
}
c2 = readUnsignedByte();
if ((c2 & 0xC0) != 0x80) {
throw new UTFDataFormatException();
}
result[numchars++] = (char) (((c1 & 0x1F) << 6) | (c2 & 0x3F));
}
else if (test == 14) { // three bytes
numread += 3;
if (numread > numbytes) {
throw new UTFDataFormatException();
}
c2 = readUnsignedByte();
c3 = readUnsignedByte();
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
throw new UTFDataFormatException();
}
result[numchars++] = (char) (((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
}
else { // malformed
throw new UTFDataFormatException();
}
} // end while
return new String(result, 0, numchars);
}
/**
* @return the next eight bytes of this input stream, interpreted as a
* little endian {@code double}.
* @throws EOFException if end of stream occurs before eight bytes
* have been read.
* @throws IOException if an I/O error occurs.
*/
public final double readDouble() throws IOException {
return Double.longBitsToDouble(readLong());
}
/**
* @return the next four bytes of this input stream, interpreted as a
* little endian {@code int}.
* @throws EOFException if end of stream occurs before four bytes
* have been read.
* @throws IOException if an I/O error occurs.
*/
public final float readFloat() throws IOException {
return Float.intBitsToFloat(readInt());
}
/**
* See the general contract of the {@code skipBytes}
* method of {@code DataInput}.
* <p>
* Bytes for this operation are read from the contained input stream.
*
* @param pLength the number of bytes to be skipped.
* @return the actual number of bytes skipped.
* @exception IOException if an I/O error occurs.
*/
public final int skipBytes(int pLength) throws IOException {
// NOTE: There was probably a bug in ERH's original code here, as skip
// never returns -1, but returns 0 if no more bytes can be skipped...
int total = 0;
int skipped;
while ((total < pLength) && ((skipped = (int) in.skip(pLength - total)) > 0)) {
total += skipped;
}
return total;
}
/**
* See the general contract of the {@code readFully} method of {@code DataInput}.
* <p>
* Bytes for this operation are read from the contained input stream.
* </p>
*
* @param pBytes the buffer into which the data is read.
* @throws EOFException if this input stream reaches the end before
* reading all the bytes.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterInputStream#in
*/
public final void readFully(byte pBytes[]) throws IOException {
readFully(pBytes, 0, pBytes.length);
}
/**
* See the general contract of the {@code readFully} method of {@code DataInput}.
* <p>
* Bytes for this operation are read from the contained input stream.
* </p>
*
* @param pBytes the buffer into which the data is read.
* @param pOffset the start offset of the data.
* @param pLength the number of bytes to read.
* @throws EOFException if this input stream reaches the end before
* reading all the bytes.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterInputStream#in
*/
public final void readFully(byte pBytes[], int pOffset, int pLength) throws IOException {
if (pLength < 0) {
throw new IndexOutOfBoundsException();
}
int count = 0;
while (count < pLength) {
int read = in.read(pBytes, pOffset + count, pLength - count);
if (read < 0) {
throw new EOFException();
}
count += read;
}
}
/**
* See the general contract of the {@code readLine}
* method of {@code DataInput}.
* <p>
* Bytes for this operation are read from the contained input stream.
*
* @deprecated This method does not properly convert bytes to characters.
*
* @return the next line of text from this input stream.
* @exception IOException if an I/O error occurs.
* @see java.io.BufferedReader#readLine()
* @see java.io.DataInputStream#readLine()
*/
@Deprecated
public String readLine() throws IOException {
DataInputStream ds = new DataInputStream(in);
return ds.readLine();
}
}
@@ -1,341 +1,342 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* From http://www.cafeaulait.org/books/javaio/ioexamples/index.html:
*
* Please feel free to use any fragment of this code you need in your own work.
* As far as I am concerned, it's in the public domain. No permission is necessary
* or required. Credit is always appreciated if you use a large chunk or base a
* significant product on one of my examples, but that's not required either.
*
* Elliotte Rusty Harold
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.*;
/**
* A little endian output stream writes primitive Java numbers
* and characters to an output stream in a little endian format.
* <p/>
* The standard {@code java.io.DataOutputStream} class which this class
* imitates uses big endian integers.
* <p/>
* <em>Warning:
* <!-- Beware of little indians! -->
* The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations.
* </em>
*
* @see com.twelvemonkeys.io.LittleEndianRandomAccessFile
* @see java.io.DataOutputStream
* @see java.io.DataInput
* @see java.io.DataOutput
*
* @author Elliotte Rusty Harold
* @version 1.0.1, 19 May 1999
*/
public class LittleEndianDataOutputStream extends FilterOutputStream implements DataOutput {
/**
* The number of bytes written so far to the little endian output stream.
*/
protected int bytesWritten;
/**
* Creates a new little endian output stream and chains it to the
* output stream specified by the {@code pStream} argument.
*
* @param pStream the underlying output stream.
* @see java.io.FilterOutputStream#out
*/
public LittleEndianDataOutputStream(OutputStream pStream) {
super(Validate.notNull(pStream, "stream"));
}
/**
* Writes the specified byte value to the underlying output stream.
*
* @param pByte the {@code byte} value to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public synchronized void write(int pByte) throws IOException {
out.write(pByte);
bytesWritten++;
}
/**
* Writes {@code pLength} bytes from the specified byte array
* starting at {@code pOffset} to the underlying output stream.
*
* @param pBytes the data.
* @param pOffset the start offset in the data.
* @param pLength the number of bytes to write.
* @throws IOException if the underlying stream throws an IOException.
*/
public synchronized void write(byte[] pBytes, int pOffset, int pLength) throws IOException {
out.write(pBytes, pOffset, pLength);
bytesWritten += pLength;
}
/**
* Writes a {@code boolean} to the underlying output stream as
* a single byte. If the argument is true, the byte value 1 is written.
* If the argument is false, the byte value {@code 0} in written.
*
* @param pBoolean the {@code boolean} value to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeBoolean(boolean pBoolean) throws IOException {
if (pBoolean) {
write(1);
}
else {
write(0);
}
}
/**
* Writes out a {@code byte} to the underlying output stream
*
* @param pByte the {@code byte} value to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeByte(int pByte) throws IOException {
out.write(pByte);
bytesWritten++;
}
/**
* Writes a two byte {@code short} to the underlying output stream in
* little endian order, low byte first.
*
* @param pShort the {@code short} to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeShort(int pShort) throws IOException {
out.write(pShort & 0xFF);
out.write((pShort >>> 8) & 0xFF);
bytesWritten += 2;
}
/**
* Writes a two byte {@code char} to the underlying output stream
* in little endian order, low byte first.
*
* @param pChar the {@code char} value to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeChar(int pChar) throws IOException {
out.write(pChar & 0xFF);
out.write((pChar >>> 8) & 0xFF);
bytesWritten += 2;
}
/**
* Writes a four-byte {@code int} to the underlying output stream
* in little endian order, low byte first, high byte last
*
* @param pInt the {@code int} to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeInt(int pInt) throws IOException {
out.write(pInt & 0xFF);
out.write((pInt >>> 8) & 0xFF);
out.write((pInt >>> 16) & 0xFF);
out.write((pInt >>> 24) & 0xFF);
bytesWritten += 4;
}
/**
* Writes an eight-byte {@code long} to the underlying output stream
* in little endian order, low byte first, high byte last
*
* @param pLong the {@code long} to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeLong(long pLong) throws IOException {
out.write((int) pLong & 0xFF);
out.write((int) (pLong >>> 8) & 0xFF);
out.write((int) (pLong >>> 16) & 0xFF);
out.write((int) (pLong >>> 24) & 0xFF);
out.write((int) (pLong >>> 32) & 0xFF);
out.write((int) (pLong >>> 40) & 0xFF);
out.write((int) (pLong >>> 48) & 0xFF);
out.write((int) (pLong >>> 56) & 0xFF);
bytesWritten += 8;
}
/**
* Writes a 4 byte Java float to the underlying output stream in
* little endian order.
*
* @param f the {@code float} value to be written.
* @throws IOException if an I/O error occurs.
*/
public final void writeFloat(float f) throws IOException {
writeInt(Float.floatToIntBits(f));
}
/**
* Writes an 8 byte Java double to the underlying output stream in
* little endian order.
*
* @param d the {@code double} value to be written.
* @throws IOException if an I/O error occurs.
*/
public final void writeDouble(double d) throws IOException {
writeLong(Double.doubleToLongBits(d));
}
/**
* Writes a string to the underlying output stream as a sequence of
* bytes. Each character is written to the data output stream as
* if by the {@link #writeByte(int)} method.
*
* @param pString the {@code String} value to be written.
* @throws IOException if the underlying stream throws an IOException.
* @see #writeByte(int)
* @see #out
*/
public void writeBytes(String pString) throws IOException {
int length = pString.length();
for (int i = 0; i < length; i++) {
out.write((byte) pString.charAt(i));
}
bytesWritten += length;
}
/**
* Writes a string to the underlying output stream as a sequence of
* characters. Each character is written to the data output stream as
* if by the {@code writeChar} method.
*
* @param pString a {@code String} value to be written.
* @throws IOException if the underlying stream throws an IOException.
* @see #writeChar(int)
* @see #out
*/
public void writeChars(String pString) throws IOException {
int length = pString.length();
for (int i = 0; i < length; i++) {
int c = pString.charAt(i);
out.write(c & 0xFF);
out.write((c >>> 8) & 0xFF);
}
bytesWritten += length * 2;
}
/**
* Writes a string of no more than 65,535 characters
* to the underlying output stream using UTF-8
* encoding. This method first writes a two byte short
* in <b>big</b> endian order as required by the
* UTF-8 specification. This gives the number of bytes in the
* UTF-8 encoded version of the string, not the number of characters
* in the string. Next each character of the string is written
* using the UTF-8 encoding for the character.
*
* @param pString the string to be written.
* @throws UTFDataFormatException if the string is longer than
* 65,535 characters.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeUTF(String pString) throws IOException {
int numchars = pString.length();
int numbytes = 0;
for (int i = 0; i < numchars; i++) {
int c = pString.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
numbytes++;
}
else if (c > 0x07FF) {
numbytes += 3;
}
else {
numbytes += 2;
}
}
if (numbytes > 65535) {
throw new UTFDataFormatException();
}
out.write((numbytes >>> 8) & 0xFF);
out.write(numbytes & 0xFF);
for (int i = 0; i < numchars; i++) {
int c = pString.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out.write(c);
}
else if (c > 0x07FF) {
out.write(0xE0 | ((c >> 12) & 0x0F));
out.write(0x80 | ((c >> 6) & 0x3F));
out.write(0x80 | (c & 0x3F));
bytesWritten += 2;
}
else {
out.write(0xC0 | ((c >> 6) & 0x1F));
out.write(0x80 | (c & 0x3F));
bytesWritten += 1;
}
}
bytesWritten += numchars + 2;
}
/**
* Returns the number of bytes written to this little endian output stream.
* (This class is not thread-safe with respect to this method. It is
* possible that this number is temporarily less than the actual
* number of bytes written.)
* @return the value of the {@code written} field.
* @see #bytesWritten
*/
public int size() {
return bytesWritten;
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* From http://www.cafeaulait.org/books/javaio/ioexamples/index.html:
*
* Please feel free to use any fragment of this code you need in your own work.
* As far as I am concerned, it's in the public domain. No permission is necessary
* or required. Credit is always appreciated if you use a large chunk or base a
* significant product on one of my examples, but that's not required either.
*
* Elliotte Rusty Harold
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.*;
/**
* A little endian output stream writes primitive Java numbers
* and characters to an output stream in a little endian format.
* <p>
* The standard {@code java.io.DataOutputStream} class which this class
* imitates uses big endian integers.
* </p>
* <p>
* <em>Warning:
* The {@code DataInput} and {@code DataOutput} interfaces
* specifies big endian byte order in their documentation.
* This means that this class is, strictly speaking, not a proper
* implementation. However, I don't see a reason for the these interfaces to
* specify the byte order of their underlying representations.
* </em>
* <p>
*
* @see com.twelvemonkeys.io.LittleEndianRandomAccessFile
* @see java.io.DataOutputStream
* @see java.io.DataInput
* @see java.io.DataOutput
*
* @author Elliotte Rusty Harold
* @version 1.0.1, 19 May 1999
*/
public class LittleEndianDataOutputStream extends FilterOutputStream implements DataOutput {
/**
* The number of bytes written so far to the little endian output stream.
*/
protected int bytesWritten;
/**
* Creates a new little endian output stream and chains it to the
* output stream specified by the {@code pStream} argument.
*
* @param pStream the underlying output stream.
* @see java.io.FilterOutputStream#out
*/
public LittleEndianDataOutputStream(OutputStream pStream) {
super(Validate.notNull(pStream, "stream"));
}
/**
* Writes the specified byte value to the underlying output stream.
*
* @param pByte the {@code byte} value to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public synchronized void write(int pByte) throws IOException {
out.write(pByte);
bytesWritten++;
}
/**
* Writes {@code pLength} bytes from the specified byte array
* starting at {@code pOffset} to the underlying output stream.
*
* @param pBytes the data.
* @param pOffset the start offset in the data.
* @param pLength the number of bytes to write.
* @throws IOException if the underlying stream throws an IOException.
*/
public synchronized void write(byte[] pBytes, int pOffset, int pLength) throws IOException {
out.write(pBytes, pOffset, pLength);
bytesWritten += pLength;
}
/**
* Writes a {@code boolean} to the underlying output stream as
* a single byte. If the argument is true, the byte value 1 is written.
* If the argument is false, the byte value {@code 0} in written.
*
* @param pBoolean the {@code boolean} value to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeBoolean(boolean pBoolean) throws IOException {
if (pBoolean) {
write(1);
}
else {
write(0);
}
}
/**
* Writes out a {@code byte} to the underlying output stream
*
* @param pByte the {@code byte} value to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeByte(int pByte) throws IOException {
out.write(pByte);
bytesWritten++;
}
/**
* Writes a two byte {@code short} to the underlying output stream in
* little endian order, low byte first.
*
* @param pShort the {@code short} to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeShort(int pShort) throws IOException {
out.write(pShort & 0xFF);
out.write((pShort >>> 8) & 0xFF);
bytesWritten += 2;
}
/**
* Writes a two byte {@code char} to the underlying output stream
* in little endian order, low byte first.
*
* @param pChar the {@code char} value to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeChar(int pChar) throws IOException {
out.write(pChar & 0xFF);
out.write((pChar >>> 8) & 0xFF);
bytesWritten += 2;
}
/**
* Writes a four-byte {@code int} to the underlying output stream
* in little endian order, low byte first, high byte last
*
* @param pInt the {@code int} to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeInt(int pInt) throws IOException {
out.write(pInt & 0xFF);
out.write((pInt >>> 8) & 0xFF);
out.write((pInt >>> 16) & 0xFF);
out.write((pInt >>> 24) & 0xFF);
bytesWritten += 4;
}
/**
* Writes an eight-byte {@code long} to the underlying output stream
* in little endian order, low byte first, high byte last
*
* @param pLong the {@code long} to be written.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeLong(long pLong) throws IOException {
out.write((int) pLong & 0xFF);
out.write((int) (pLong >>> 8) & 0xFF);
out.write((int) (pLong >>> 16) & 0xFF);
out.write((int) (pLong >>> 24) & 0xFF);
out.write((int) (pLong >>> 32) & 0xFF);
out.write((int) (pLong >>> 40) & 0xFF);
out.write((int) (pLong >>> 48) & 0xFF);
out.write((int) (pLong >>> 56) & 0xFF);
bytesWritten += 8;
}
/**
* Writes a 4 byte Java float to the underlying output stream in
* little endian order.
*
* @param f the {@code float} value to be written.
* @throws IOException if an I/O error occurs.
*/
public final void writeFloat(float f) throws IOException {
writeInt(Float.floatToIntBits(f));
}
/**
* Writes an 8 byte Java double to the underlying output stream in
* little endian order.
*
* @param d the {@code double} value to be written.
* @throws IOException if an I/O error occurs.
*/
public final void writeDouble(double d) throws IOException {
writeLong(Double.doubleToLongBits(d));
}
/**
* Writes a string to the underlying output stream as a sequence of
* bytes. Each character is written to the data output stream as
* if by the {@link #writeByte(int)} method.
*
* @param pString the {@code String} value to be written.
* @throws IOException if the underlying stream throws an IOException.
* @see #writeByte(int)
* @see #out
*/
public void writeBytes(String pString) throws IOException {
int length = pString.length();
for (int i = 0; i < length; i++) {
out.write((byte) pString.charAt(i));
}
bytesWritten += length;
}
/**
* Writes a string to the underlying output stream as a sequence of
* characters. Each character is written to the data output stream as
* if by the {@code writeChar} method.
*
* @param pString a {@code String} value to be written.
* @throws IOException if the underlying stream throws an IOException.
* @see #writeChar(int)
* @see #out
*/
public void writeChars(String pString) throws IOException {
int length = pString.length();
for (int i = 0; i < length; i++) {
int c = pString.charAt(i);
out.write(c & 0xFF);
out.write((c >>> 8) & 0xFF);
}
bytesWritten += length * 2;
}
/**
* Writes a string of no more than 65,535 characters
* to the underlying output stream using UTF-8
* encoding. This method first writes a two byte short
* in <b>big</b> endian order as required by the
* UTF-8 specification. This gives the number of bytes in the
* UTF-8 encoded version of the string, not the number of characters
* in the string. Next each character of the string is written
* using the UTF-8 encoding for the character.
*
* @param pString the string to be written.
* @throws UTFDataFormatException if the string is longer than
* 65,535 characters.
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeUTF(String pString) throws IOException {
int numchars = pString.length();
int numbytes = 0;
for (int i = 0; i < numchars; i++) {
int c = pString.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
numbytes++;
}
else if (c > 0x07FF) {
numbytes += 3;
}
else {
numbytes += 2;
}
}
if (numbytes > 65535) {
throw new UTFDataFormatException();
}
out.write((numbytes >>> 8) & 0xFF);
out.write(numbytes & 0xFF);
for (int i = 0; i < numchars; i++) {
int c = pString.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out.write(c);
}
else if (c > 0x07FF) {
out.write(0xE0 | ((c >> 12) & 0x0F));
out.write(0x80 | ((c >> 6) & 0x3F));
out.write(0x80 | (c & 0x3F));
bytesWritten += 2;
}
else {
out.write(0xC0 | ((c >> 6) & 0x1F));
out.write(0x80 | (c & 0x3F));
bytesWritten += 1;
}
}
bytesWritten += numchars + 2;
}
/**
* Returns the number of bytes written to this little endian output stream.
* (This class is not thread-safe with respect to this method. It is
* possible that this number is temporarily less than the actual
* number of bytes written.)
* @return the value of the {@code written} field.
* @see #bytesWritten
*/
public int size() {
return bytesWritten;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,193 +1,197 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* A {@code SeekableInputStream} implementation that caches data in memory.
* <p/>
*
* @see FileCacheSeekableStream
*
* @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/MemoryCacheSeekableStream.java#3 $
*/
public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStream {
/**
* Creates a {@code MemoryCacheSeekableStream}, reading from the given
* {@code InputStream}. Data will be cached in memory.
*
* @param pStream the {@code InputStream} to read from.
*/
public MemoryCacheSeekableStream(final InputStream pStream) {
super(pStream, new MemoryCache());
}
public final boolean isCachedMemory() {
return true;
}
public final boolean isCachedFile() {
return false;
}
final static class MemoryCache extends StreamCache {
final static int BLOCK_SIZE = 1 << 13;
private final List<byte[]> cache = new ArrayList<byte[]>();
private long length;
private long position;
private long start;
private byte[] getBlock() throws IOException {
final long currPos = position - start;
if (currPos < 0) {
throw new IOException("StreamCache flushed before read position");
}
long index = currPos / BLOCK_SIZE;
if (index >= Integer.MAX_VALUE) {
throw new IOException("Memory cache max size exceeded");
}
if (index >= cache.size()) {
try {
cache.add(new byte[BLOCK_SIZE]);
// System.out.println("Allocating new block, size: " + BLOCK_SIZE);
// System.out.println("New total size: " + cache.size() * BLOCK_SIZE + " (" + cache.size() + " blocks)");
}
catch (OutOfMemoryError e) {
throw new IOException("No more memory for cache: " + cache.size() * BLOCK_SIZE);
}
}
//System.out.println("index: " + index);
return cache.get((int) index);
}
public void write(final int pByte) throws IOException {
byte[] buffer = getBlock();
int idx = (int) (position % BLOCK_SIZE);
buffer[idx] = (byte) pByte;
position++;
if (position > length) {
length = position;
}
}
// TODO: OptimizeMe!!!
@Override
public void write(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
byte[] buffer = getBlock();
for (int i = 0; i < pLength; i++) {
int index = (int) position % BLOCK_SIZE;
if (index == 0) {
buffer = getBlock();
}
buffer[index] = pBuffer[pOffset + i];
position++;
}
if (position > length) {
length = position;
}
}
public int read() throws IOException {
if (position >= length) {
return -1;
}
byte[] buffer = getBlock();
int idx = (int) (position % BLOCK_SIZE);
position++;
return buffer[idx] & 0xff;
}
// TODO: OptimizeMe!!!
@Override
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (position >= length) {
return -1;
}
byte[] buffer = getBlock();
int bufferPos = (int) (position % BLOCK_SIZE);
// Find maxIdx and simplify test in for-loop
int maxLen = (int) Math.min(Math.min(pLength, buffer.length - bufferPos), length - position);
int i;
//for (i = 0; i < pLength && i < buffer.length - idx && i < length - position; i++) {
for (i = 0; i < maxLen; i++) {
pBytes[pOffset + i] = buffer[bufferPos + i];
}
position += i;
return i;
}
public void seek(final long pPosition) throws IOException {
if (pPosition < start) {
throw new IOException("Seek before flush position");
}
position = pPosition;
}
@Override
public void flush(final long pPosition) {
int firstPos = (int) (pPosition / BLOCK_SIZE) - 1;
for (int i = 0; i < firstPos; i++) {
cache.remove(0);
}
start = pPosition;
}
public long getPosition() {
return position;
}
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* A {@code SeekableInputStream} implementation that caches data in memory.
*
* @see FileCacheSeekableStream
*
* @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/MemoryCacheSeekableStream.java#3 $
*/
public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStream {
/**
* Creates a {@code MemoryCacheSeekableStream}, reading from the given
* {@code InputStream}. Data will be cached in memory.
*
* @param pStream the {@code InputStream} to read from.
*/
public MemoryCacheSeekableStream(final InputStream pStream) {
super(pStream, new MemoryCache());
}
public final boolean isCachedMemory() {
return true;
}
public final boolean isCachedFile() {
return false;
}
final static class MemoryCache extends StreamCache {
final static int BLOCK_SIZE = 1 << 13;
private final List<byte[]> cache = new ArrayList<>();
private long length;
private long position;
private long start;
private byte[] getBlock() throws IOException {
final long currPos = position - start;
if (currPos < 0) {
throw new IOException("StreamCache flushed before read position");
}
long index = currPos / BLOCK_SIZE;
if (index >= Integer.MAX_VALUE) {
throw new IOException("Memory cache max size exceeded");
}
if (index >= cache.size()) {
try {
cache.add(new byte[BLOCK_SIZE]);
// System.out.println("Allocating new block, size: " + BLOCK_SIZE);
// System.out.println("New total size: " + cache.size() * BLOCK_SIZE + " (" + cache.size() + " blocks)");
}
catch (OutOfMemoryError e) {
throw new IOException("No more memory for cache: " + cache.size() * BLOCK_SIZE);
}
}
//System.out.println("index: " + index);
return cache.get((int) index);
}
public void write(final int pByte) throws IOException {
byte[] buffer = getBlock();
int idx = (int) (position % BLOCK_SIZE);
buffer[idx] = (byte) pByte;
position++;
if (position > length) {
length = position;
}
}
// TODO: OptimizeMe!!!
@Override
public void write(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
byte[] buffer = getBlock();
for (int i = 0; i < pLength; i++) {
int index = (int) position % BLOCK_SIZE;
if (index == 0) {
buffer = getBlock();
}
buffer[index] = pBuffer[pOffset + i];
position++;
}
if (position > length) {
length = position;
}
}
public int read() throws IOException {
if (position >= length) {
return -1;
}
byte[] buffer = getBlock();
int idx = (int) (position % BLOCK_SIZE);
position++;
return buffer[idx] & 0xff;
}
// TODO: OptimizeMe!!!
@Override
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (position >= length) {
return -1;
}
byte[] buffer = getBlock();
int bufferPos = (int) (position % BLOCK_SIZE);
// Find maxIdx and simplify test in for-loop
int maxLen = (int) Math.min(Math.min(pLength, buffer.length - bufferPos), length - position);
int i;
//for (i = 0; i < pLength && i < buffer.length - idx && i < length - position; i++) {
for (i = 0; i < maxLen; i++) {
pBytes[pOffset + i] = buffer[bufferPos + i];
}
position += i;
return i;
}
public void seek(final long pPosition) throws IOException {
if (pPosition < start) {
throw new IOException("Seek before flush position");
}
position = pPosition;
}
@Override
public void flush(final long pPosition) {
int firstPos = (int) (pPosition / BLOCK_SIZE) - 1;
for (int i = 0; i < firstPos; i++) {
cache.remove(0);
}
start = pPosition;
}
@Override
void close() throws IOException {
cache.clear();
}
public long getPosition() {
return position;
}
}
}
@@ -1,82 +1,81 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.InputStream;
/**
* An {@code InputStream} that contains no bytes.
* <p/>
*
* @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/NullInputStream.java#2 $
*/
public class NullInputStream extends InputStream {
/**
* Creates a {@code NullInputStream}.
*/
public NullInputStream() {
}
/**
* This implementation returns {@code -1} (EOF), always.
*
* @return {@code -1}
* @throws IOException
*/
public int read() throws IOException {
return -1;
}
/**
* This implementation returns {@code 0}, always.
*
* @return {@code 0}
* @throws IOException
*/
@Override
public int available() throws IOException {
return 0;
}
/**
* This implementation returns {@code 0}, always.
*
* @return {@code 0}
* @throws IOException
*/
@Override
public long skip(long pOffset) throws IOException {
return 0l;
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.InputStream;
/**
* An {@code InputStream} that contains no bytes.
*
* @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/NullInputStream.java#2 $
*/
public class NullInputStream extends InputStream {
/**
* Creates a {@code NullInputStream}.
*/
public NullInputStream() {
}
/**
* This implementation returns {@code -1} (EOF), always.
*
* @return {@code -1}
* @throws IOException
*/
public int read() throws IOException {
return -1;
}
/**
* This implementation returns {@code 0}, always.
*
* @return {@code 0}
* @throws IOException
*/
@Override
public int available() throws IOException {
return 0;
}
/**
* This implementation returns {@code 0}, always.
*
* @return {@code 0}
* @throws IOException
*/
@Override
public long skip(long pOffset) throws IOException {
return 0l;
}
}
@@ -1,70 +1,69 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.OutputStream;
/**
* An {@code OutputStream} implementation that works as a sink.
* <p/>
*
* @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/NullOutputStream.java#2 $
*/
public class NullOutputStream extends OutputStream {
/**
* Creates a {@code NullOutputStream}.
*/
public NullOutputStream() {
}
/**
* This implementation does nothing.
*/
public void write(int pByte) throws IOException {
}
/**
* This implementation does nothing.
*/
@Override
public void write(byte pBytes[]) throws IOException {
}
/**
* This implementation does nothing.
*/
@Override
public void write(byte pBytes[], int pOffset, int pLength) throws IOException {
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.OutputStream;
/**
* An {@code OutputStream} implementation that works as a sink.
*
* @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/NullOutputStream.java#2 $
*/
public class NullOutputStream extends OutputStream {
/**
* Creates a {@code NullOutputStream}.
*/
public NullOutputStream() {
}
/**
* This implementation does nothing.
*/
public void write(int pByte) throws IOException {
}
/**
* This implementation does nothing.
*/
@Override
public void write(byte pBytes[]) throws IOException {
}
/**
* This implementation does nothing.
*/
@Override
public void write(byte pBytes[], int pOffset, int pLength) throws IOException {
}
}
@@ -1,241 +1,242 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.EOFException;
import java.io.IOException;
/**
* A data stream that is both readable and writable, much like a
* {@code RandomAccessFile}, except it may be backed by something other than a file.
* <p/>
*
* @see java.io.RandomAccessFile
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/RandomAccessStream.java#3 $
*/
public abstract class RandomAccessStream implements Seekable, DataInput, DataOutput {
// TODO: Use a RandomAcceessFile as backing in impl, probably
// TODO: Create an in-memory implementation too?
// TODO: Package private SeekableDelegate?
// TODO: Both read and write must update stream position
//private int position = -1;
/** This random access stream, wrapped in an {@code InputStream} */
SeekableInputStream inputView = null;
/** This random access stream, wrapped in an {@code OutputStream} */
SeekableOutputStream outputView = null;
// TODO: Create an Input and an Output interface matching InputStream and OutputStream?
public int read() throws IOException {
try {
return readByte() & 0xff;
}
catch (EOFException e) {
return -1;
}
}
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (pBytes == null) {
throw new NullPointerException("bytes == null");
}
else if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
throw new IndexOutOfBoundsException();
}
else if (pLength == 0) {
return 0;
}
// Special case, allready at EOF
int c = read();
if (c == -1) {
return -1;
}
// Otherwise, read as many as bytes as possible
pBytes[pOffset] = (byte) c;
int i = 1;
try {
for (; i < pLength; i++) {
c = read();
if (c == -1) {
break;
}
pBytes[pOffset + i] = (byte) c;
}
}
catch (IOException ignore) {
// Ignore exception, just return length
}
return i;
}
public final int read(byte[] pBytes) throws IOException {
return read(pBytes, 0, pBytes != null ? pBytes.length : 1);
}
/**
* Returns an input view of this {@code RandomAccessStream}.
* Invoking this method several times, will return the same object.
* <p/>
* <em>Note that read access is NOT synchronized.</em>
*
* @return a {@code SeekableInputStream} reading from this stream
*/
public final SeekableInputStream asInputStream() {
if (inputView == null) {
inputView = new InputStreamView(this);
}
return inputView;
}
/**
* Returns an output view of this {@code RandomAccessStream}.
* Invoking this method several times, will return the same object.
* <p/>
* <em>Note that write access is NOT synchronized.</em>
*
* @return a {@code SeekableOutputStream} writing to this stream
*/
public final SeekableOutputStream asOutputStream() {
if (outputView == null) {
outputView = new OutputStreamView(this);
}
return outputView;
}
static final class InputStreamView extends SeekableInputStream {
// TODO: Consider adding synchonization (on stream) for all operations
// TODO: Is is a good thing that close/flush etc works on stream?
// - Or should it rather just work on the views?
// - Allow multiple views?
final private RandomAccessStream mStream;
public InputStreamView(RandomAccessStream pStream) {
if (pStream == null) {
throw new IllegalArgumentException("stream == null");
}
mStream = pStream;
}
public boolean isCached() {
return mStream.isCached();
}
public boolean isCachedFile() {
return mStream.isCachedFile();
}
public boolean isCachedMemory() {
return mStream.isCachedMemory();
}
protected void closeImpl() throws IOException {
mStream.close();
}
protected void flushBeforeImpl(long pPosition) throws IOException {
mStream.flushBefore(pPosition);
}
protected void seekImpl(long pPosition) throws IOException {
mStream.seek(pPosition);
}
public int read() throws IOException {
return mStream.read();
}
@Override
public int read(byte pBytes[], int pOffset, int pLength) throws IOException {
return mStream.read(pBytes, pOffset, pLength);
}
}
static final class OutputStreamView extends SeekableOutputStream {
// TODO: Consider adding synchonization (on stream) for all operations
// TODO: Is is a good thing that close/flush etc works on stream?
// - Or should it rather just work on the views?
// - Allow multiple views?
final private RandomAccessStream mStream;
public OutputStreamView(RandomAccessStream pStream) {
if (pStream == null) {
throw new IllegalArgumentException("stream == null");
}
mStream = pStream;
}
public boolean isCached() {
return mStream.isCached();
}
public boolean isCachedFile() {
return mStream.isCachedFile();
}
public boolean isCachedMemory() {
return mStream.isCachedMemory();
}
protected void closeImpl() throws IOException {
mStream.close();
}
protected void flushBeforeImpl(long pPosition) throws IOException {
mStream.flushBefore(pPosition);
}
protected void seekImpl(long pPosition) throws IOException {
mStream.seek(pPosition);
}
public void write(int pByte) throws IOException {
mStream.write(pByte);
}
@Override
public void write(byte pBytes[], int pOffset, int pLength) throws IOException {
mStream.write(pBytes, pOffset, pLength);
}
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.EOFException;
import java.io.IOException;
/**
* A data stream that is both readable and writable, much like a
* {@code RandomAccessFile}, except it may be backed by something other than a file.
*
* @see java.io.RandomAccessFile
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/RandomAccessStream.java#3 $
*/
public abstract class RandomAccessStream implements Seekable, DataInput, DataOutput {
// TODO: Use a RandomAcceessFile as backing in impl, probably
// TODO: Create an in-memory implementation too?
// TODO: Package private SeekableDelegate?
// TODO: Both read and write must update stream position
//private int position = -1;
/** This random access stream, wrapped in an {@code InputStream} */
SeekableInputStream inputView = null;
/** This random access stream, wrapped in an {@code OutputStream} */
SeekableOutputStream outputView = null;
// TODO: Create an Input and an Output interface matching InputStream and OutputStream?
public int read() throws IOException {
try {
return readByte() & 0xff;
}
catch (EOFException e) {
return -1;
}
}
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (pBytes == null) {
throw new NullPointerException("bytes == null");
}
else if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
throw new IndexOutOfBoundsException();
}
else if (pLength == 0) {
return 0;
}
// Special case, allready at EOF
int c = read();
if (c == -1) {
return -1;
}
// Otherwise, read as many as bytes as possible
pBytes[pOffset] = (byte) c;
int i = 1;
try {
for (; i < pLength; i++) {
c = read();
if (c == -1) {
break;
}
pBytes[pOffset + i] = (byte) c;
}
}
catch (IOException ignore) {
// Ignore exception, just return length
}
return i;
}
public final int read(byte[] pBytes) throws IOException {
return read(pBytes, 0, pBytes != null ? pBytes.length : 1);
}
/**
* Returns an input view of this {@code RandomAccessStream}.
* Invoking this method several times, will return the same object.
* <p>
* <em>Note that read access is NOT synchronized.</em>
* </p>
*
* @return a {@code SeekableInputStream} reading from this stream
*/
public final SeekableInputStream asInputStream() {
if (inputView == null) {
inputView = new InputStreamView(this);
}
return inputView;
}
/**
* Returns an output view of this {@code RandomAccessStream}.
* Invoking this method several times, will return the same object.
* <p>
* <em>Note that write access is NOT synchronized.</em>
* </p>
*
* @return a {@code SeekableOutputStream} writing to this stream
*/
public final SeekableOutputStream asOutputStream() {
if (outputView == null) {
outputView = new OutputStreamView(this);
}
return outputView;
}
static final class InputStreamView extends SeekableInputStream {
// TODO: Consider adding synchonization (on stream) for all operations
// TODO: Is is a good thing that close/flush etc works on stream?
// - Or should it rather just work on the views?
// - Allow multiple views?
final private RandomAccessStream mStream;
public InputStreamView(RandomAccessStream pStream) {
if (pStream == null) {
throw new IllegalArgumentException("stream == null");
}
mStream = pStream;
}
public boolean isCached() {
return mStream.isCached();
}
public boolean isCachedFile() {
return mStream.isCachedFile();
}
public boolean isCachedMemory() {
return mStream.isCachedMemory();
}
protected void closeImpl() throws IOException {
mStream.close();
}
protected void flushBeforeImpl(long pPosition) throws IOException {
mStream.flushBefore(pPosition);
}
protected void seekImpl(long pPosition) throws IOException {
mStream.seek(pPosition);
}
public int read() throws IOException {
return mStream.read();
}
@Override
public int read(byte pBytes[], int pOffset, int pLength) throws IOException {
return mStream.read(pBytes, pOffset, pLength);
}
}
static final class OutputStreamView extends SeekableOutputStream {
// TODO: Consider adding synchonization (on stream) for all operations
// TODO: Is is a good thing that close/flush etc works on stream?
// - Or should it rather just work on the views?
// - Allow multiple views?
final private RandomAccessStream mStream;
public OutputStreamView(RandomAccessStream pStream) {
if (pStream == null) {
throw new IllegalArgumentException("stream == null");
}
mStream = pStream;
}
public boolean isCached() {
return mStream.isCached();
}
public boolean isCachedFile() {
return mStream.isCachedFile();
}
public boolean isCachedMemory() {
return mStream.isCachedMemory();
}
protected void closeImpl() throws IOException {
mStream.close();
}
protected void flushBeforeImpl(long pPosition) throws IOException {
mStream.flushBefore(pPosition);
}
protected void seekImpl(long pPosition) throws IOException {
mStream.seek(pPosition);
}
public void write(int pByte) throws IOException {
mStream.write(pByte);
}
@Override
public void write(byte pBytes[], int pOffset, int pLength) throws IOException {
mStream.write(pBytes, pOffset, pLength);
}
}
}
@@ -1,186 +1,193 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
/**
* Interface for seekable streams.
* <p/>
* @see SeekableInputStream
* @see SeekableOutputStream
*
* @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/Seekable.java#1 $
*/
public interface Seekable {
/**
* Returns the current byte position of the stream. The next read will take
* place starting at this offset.
*
* @return a {@code long} containing the position of the stream.
* @throws IOException if an I/O error occurs.
*/
long getStreamPosition() throws IOException;
/**
* Sets the current stream position to the desired location.
* The next read will occur at this location.
* <p/>
* An {@code IndexOutOfBoundsException} will be thrown if pPosition is smaller
* than the flushed position (as returned by {@link #getFlushedPosition()}).
* <p/>
* It is legal to seek past the end of the file; an {@code EOFException}
* will be thrown only if a read is performed.
*
* @param pPosition a long containing the desired file pointer position.
*
* @throws IndexOutOfBoundsException if {@code pPosition} is smaller than
* the flushed position.
* @throws IOException if any other I/O error occurs.
*/
void seek(long pPosition) throws IOException;
/**
* Marks a position in the stream to be returned to by a subsequent call to
* reset.
* Unlike a standard {@code InputStream}, all {@code Seekable}
* streams upport marking. Additionally, calls to {@code mark} and
* {@code reset} may be nested arbitrarily.
* <p/>
* Unlike the {@code mark} methods declared by the {@code Reader} or
* {@code InputStream}
* interfaces, no {@code readLimit} parameter is used. An arbitrary amount
* of data may be read following the call to {@code mark}.
*/
void mark();
/**
* Returns the file pointer to its previous position,
* at the time of the most recent unmatched call to mark.
* <p/>
* Calls to reset without a corresponding call to mark will either:
* <ul>
* <li>throw an {@code IOException}</li>
* <li>or, reset to the beginning of the stream.</li>
* </ul>
* An {@code IOException} will be thrown if the previous marked position
* lies in the discarded portion of the stream.
*
* @throws IOException if an I/O error occurs.
* @see java.io.InputStream#reset()
*/
void reset() throws IOException;
/**
* Discards the initial portion of the stream prior to the indicated
* postion. Attempting to seek to an offset within the flushed portion of
* the stream will result in an {@code IndexOutOfBoundsException}.
* <p/>
* Calling {@code flushBefore} may allow classes implementing this
* interface to free up resources such as memory or disk space that are
* being used to store data from the stream.
*
* @param pPosition a long containing the length of the file prefix that
* may be flushed.
*
* @throws IndexOutOfBoundsException if {@code pPosition} lies in the
* flushed portion of the stream or past the current stream position.
* @throws IOException if an I/O error occurs.
*/
void flushBefore(long pPosition) throws IOException;
/**
* Discards the initial position of the stream prior to the current stream
* position. Equivalent to {@code flushBefore(getStreamPosition())}.
*
* @throws IOException if an I/O error occurs.
*/
void flush() throws IOException;
/**
* Returns the earliest position in the stream to which seeking may be
* performed. The returned value will be the maximum of all values passed
* into previous calls to {@code flushBefore}.
*
* @return the earliest legal position for seeking, as a {@code long}.
*
* @throws IOException if an I/O error occurs.
*/
long getFlushedPosition() throws IOException;
/**
* Returns true if this {@code Seekable} stream caches data itself in order
* to allow seeking backwards. Applications may consult this in order to
* decide how frequently, or whether, to flush in order to conserve cache
* resources.
*
* @return {@code true} if this {@code Seekable} caches data.
* @see #isCachedMemory()
* @see #isCachedFile()
*/
boolean isCached();
/**
* Returns true if this {@code Seekable} stream caches data itself in order
* to allow seeking backwards, and the cache is kept in main memory.
* Applications may consult this in order to decide how frequently, or
* whether, to flush in order to conserve cache resources.
*
* @return {@code true} if this {@code Seekable} caches data in main
* memory.
* @see #isCached()
* @see #isCachedFile()
*/
boolean isCachedMemory();
/**
* Returns true if this {@code Seekable} stream caches data itself in
* order to allow seeking backwards, and the cache is kept in a
* temporary file.
* Applications may consult this in order to decide how frequently,
* or whether, to flush in order to conserve cache resources.
*
* @return {@code true} if this {@code Seekable} caches data in a
* temporary file.
* @see #isCached
* @see #isCachedMemory
*/
boolean isCachedFile();
/**
* Closes the stream.
*
* @throws java.io.IOException if the stream can't be closed.
*/
void close() throws IOException;
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
/**
* Interface for seekable streams.
*
* @see SeekableInputStream
* @see SeekableOutputStream
*
* @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/Seekable.java#1 $
*/
public interface Seekable {
/**
* Returns the current byte position of the stream. The next read will take
* place starting at this offset.
*
* @return a {@code long} containing the position of the stream.
* @throws IOException if an I/O error occurs.
*/
long getStreamPosition() throws IOException;
/**
* Sets the current stream position to the desired location.
* The next read will occur at this location.
* <p>
* An {@code IndexOutOfBoundsException} will be thrown if pPosition is smaller
* than the flushed position (as returned by {@link #getFlushedPosition()}).
* </p>
* <p>
* It is legal to seek past the end of the file; an {@code EOFException}
* will be thrown only if a read is performed.
* </p>
*
* @param pPosition a long containing the desired file pointer position.
*
* @throws IndexOutOfBoundsException if {@code pPosition} is smaller than
* the flushed position.
* @throws IOException if any other I/O error occurs.
*/
void seek(long pPosition) throws IOException;
/**
* Marks a position in the stream to be returned to by a subsequent call to
* reset.
* Unlike a standard {@code InputStream}, all {@code Seekable}
* streams upport marking. Additionally, calls to {@code mark} and
* {@code reset} may be nested arbitrarily.
* <p>
* Unlike the {@code mark} methods declared by the {@code Reader} or
* {@code InputStream}
* interfaces, no {@code readLimit} parameter is used. An arbitrary amount
* of data may be read following the call to {@code mark}.
* </p>
*/
void mark();
/**
* Returns the file pointer to its previous position,
* at the time of the most recent unmatched call to mark.
* <p>
* Calls to reset without a corresponding call to mark will either:
* </p>
* <ul>
* <li>throw an {@code IOException}</li>
* <li>or, reset to the beginning of the stream.</li>
* </ul>
* <p>
* An {@code IOException} will be thrown if the previous marked position
* lies in the discarded portion of the stream.
* </p>
*
* @throws IOException if an I/O error occurs.
* @see java.io.InputStream#reset()
*/
void reset() throws IOException;
/**
* Discards the initial portion of the stream prior to the indicated
* postion. Attempting to seek to an offset within the flushed portion of
* the stream will result in an {@code IndexOutOfBoundsException}.
* <p>
* Calling {@code flushBefore} may allow classes implementing this
* interface to free up resources such as memory or disk space that are
* being used to store data from the stream.
* </p>
*
* @param pPosition a long containing the length of the file prefix that
* may be flushed.
*
* @throws IndexOutOfBoundsException if {@code pPosition} lies in the
* flushed portion of the stream or past the current stream position.
* @throws IOException if an I/O error occurs.
*/
void flushBefore(long pPosition) throws IOException;
/**
* Discards the initial position of the stream prior to the current stream
* position. Equivalent to {@code flushBefore(getStreamPosition())}.
*
* @throws IOException if an I/O error occurs.
*/
void flush() throws IOException;
/**
* Returns the earliest position in the stream to which seeking may be
* performed. The returned value will be the maximum of all values passed
* into previous calls to {@code flushBefore}.
*
* @return the earliest legal position for seeking, as a {@code long}.
*
* @throws IOException if an I/O error occurs.
*/
long getFlushedPosition() throws IOException;
/**
* Returns true if this {@code Seekable} stream caches data itself in order
* to allow seeking backwards. Applications may consult this in order to
* decide how frequently, or whether, to flush in order to conserve cache
* resources.
*
* @return {@code true} if this {@code Seekable} caches data.
* @see #isCachedMemory()
* @see #isCachedFile()
*/
boolean isCached();
/**
* Returns true if this {@code Seekable} stream caches data itself in order
* to allow seeking backwards, and the cache is kept in main memory.
* Applications may consult this in order to decide how frequently, or
* whether, to flush in order to conserve cache resources.
*
* @return {@code true} if this {@code Seekable} caches data in main
* memory.
* @see #isCached()
* @see #isCachedFile()
*/
boolean isCachedMemory();
/**
* Returns true if this {@code Seekable} stream caches data itself in
* order to allow seeking backwards, and the cache is kept in a
* temporary file.
* Applications may consult this in order to decide how frequently,
* or whether, to flush in order to conserve cache resources.
*
* @return {@code true} if this {@code Seekable} caches data in a
* temporary file.
* @see #isCached
* @see #isCachedMemory
*/
boolean isCachedFile();
/**
* Closes the stream.
*
* @throws java.io.IOException if the stream can't be closed.
*/
void close() throws IOException;
}
@@ -1,238 +1,238 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;
/**
* Abstract base class for {@code InputStream}s implementing the {@code Seekable} interface.
* <p/>
* @see SeekableOutputStream
*
* @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/SeekableInputStream.java#4 $
*/
public abstract class SeekableInputStream extends InputStream implements Seekable {
// TODO: It's at the moment not possible to create subclasses outside this
// package, as there's no access to position. position needs to be
// updated from the read/read/read methods...
/** The stream position in this stream */
long position;
long flushedPosition;
boolean closed;
protected Stack<Long> markedPositions = new Stack<Long>();
/// InputStream overrides
@Override
public final int read(byte[] pBytes) throws IOException {
return read(pBytes, 0, pBytes != null ? pBytes.length : 1);
}
/**
* Implemented using {@code seek(currentPos + pLength)}.
*
* @param pLength the number of bytes to skip
* @return the actual number of bytes skipped (may be equal to or less
* than {@code pLength})
*
* @throws IOException if an I/O exception occurs during skip
*/
@Override
public final long skip(final long pLength) throws IOException {
long pos = position;
long wantedPosition = pos + pLength;
if (wantedPosition < flushedPosition) {
throw new IOException("position < flushedPosition");
}
// Stop at stream length for compatibility, even though it might be allowed
// to seek past end of stream
int available = available();
if (available > 0) {
seek(Math.min(wantedPosition, pos + available));
}
// TODO: Add optimization for streams with known length!
else {
// Slow mode...
int toSkip = (int) Math.max(Math.min(pLength, 512), -512);
while (toSkip > 0 && read() >= 0) {
toSkip--;
}
}
return position - pos;
}
@Override
public final void mark(int pLimit) {
mark();
// TODO: We don't really need to do this.. Is it a good idea?
try {
flushBefore(Math.max(position - pLimit, flushedPosition));
}
catch (IOException ignore) {
// Ignore, as it's not really critical
}
}
/**
* Returns {@code true}, as marking is always supported.
*
* @return {@code true}.
*/
@Override
public final boolean markSupported() {
return true;
}
/// Seekable implementation
public final void seek(long pPosition) throws IOException {
checkOpen();
// NOTE: This is correct according to javax.imageio (IndexOutOfBoundsException),
// but it's kind of inconsistent with reset that throws IOException...
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition");
}
seekImpl(pPosition);
position = pPosition;
}
protected abstract void seekImpl(long pPosition) throws IOException;
public final void mark() {
markedPositions.push(position);
}
@Override
public final void reset() throws IOException {
checkOpen();
if (!markedPositions.isEmpty()) {
long newPos = markedPositions.pop();
// NOTE: This is correct according to javax.imageio (IOException),
// but it's kind of inconsistent with seek that throws IndexOutOfBoundsException...
if (newPos < flushedPosition) {
throw new IOException("Previous marked position has been discarded");
}
seek(newPos);
}
else {
// TODO: To iron out some wrinkles due to conflicting contracts
// (InputStream and Seekable both declare reset),
// we might need to reset to the last marked position instead..
// However, that becomes REALLY confusing if that position is after
// the current position...
seek(0);
}
}
public final void flushBefore(long pPosition) throws IOException {
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition");
}
if (pPosition > getStreamPosition()) {
throw new IndexOutOfBoundsException("position > stream position");
}
checkOpen();
flushBeforeImpl(pPosition);
flushedPosition = pPosition;
}
/**
* Discards the initial portion of the stream prior to the indicated postion.
*
* @param pPosition the position to flush to
* @throws IOException if an I/O exception occurs during the flush operation
*
* @see #flushBefore(long)
*/
protected abstract void flushBeforeImpl(long pPosition) throws IOException;
public final void flush() throws IOException {
flushBefore(flushedPosition);
}
public final long getFlushedPosition() throws IOException {
checkOpen();
return flushedPosition;
}
public final long getStreamPosition() throws IOException {
checkOpen();
return position;
}
protected final void checkOpen() throws IOException {
if (closed) {
throw new IOException("closed");
}
}
@Override
public final void close() throws IOException {
checkOpen();
closed = true;
closeImpl();
}
protected abstract void closeImpl() throws IOException;
/**
* Finalizes this object prior to garbage collection. The
* {@code close} method is called to close any open input
* source. This method should not be called from application
* code.
*
* @exception Throwable if an error occurs during superclass
* finalization.
*/
@Override
protected void finalize() throws Throwable {
if (!closed) {
try {
close();
}
catch (IOException ignore) {
// Ignroe
}
}
super.finalize();
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;
/**
* Abstract base class for {@code InputStream}s implementing the {@code Seekable} interface.
*
* @see SeekableOutputStream
*
* @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/SeekableInputStream.java#4 $
*/
public abstract class SeekableInputStream extends InputStream implements Seekable {
// TODO: It's at the moment not possible to create subclasses outside this
// package, as there's no access to position. position needs to be
// updated from the read/read/read methods...
/** The stream position in this stream */
long position;
long flushedPosition;
boolean closed;
protected Stack<Long> markedPositions = new Stack<Long>();
/// InputStream overrides
@Override
public final int read(byte[] pBytes) throws IOException {
return read(pBytes, 0, pBytes != null ? pBytes.length : 1);
}
/**
* Implemented using {@code seek(currentPos + pLength)}.
*
* @param pLength the number of bytes to skip
* @return the actual number of bytes skipped (may be equal to or less
* than {@code pLength})
*
* @throws IOException if an I/O exception occurs during skip
*/
@Override
public final long skip(final long pLength) throws IOException {
long pos = position;
long wantedPosition = pos + pLength;
if (wantedPosition < flushedPosition) {
throw new IOException("position < flushedPosition");
}
// Stop at stream length for compatibility, even though it might be allowed
// to seek past end of stream
int available = available();
if (available > 0) {
seek(Math.min(wantedPosition, pos + available));
}
// TODO: Add optimization for streams with known length!
else {
// Slow mode...
int toSkip = (int) Math.max(Math.min(pLength, 512), -512);
while (toSkip > 0 && read() >= 0) {
toSkip--;
}
}
return position - pos;
}
@Override
public final void mark(int pLimit) {
mark();
// TODO: We don't really need to do this.. Is it a good idea?
try {
flushBefore(Math.max(position - pLimit, flushedPosition));
}
catch (IOException ignore) {
// Ignore, as it's not really critical
}
}
/**
* Returns {@code true}, as marking is always supported.
*
* @return {@code true}.
*/
@Override
public final boolean markSupported() {
return true;
}
/// Seekable implementation
public final void seek(long pPosition) throws IOException {
checkOpen();
// NOTE: This is correct according to javax.imageio (IndexOutOfBoundsException),
// but it's kind of inconsistent with reset that throws IOException...
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition");
}
seekImpl(pPosition);
position = pPosition;
}
protected abstract void seekImpl(long pPosition) throws IOException;
public final void mark() {
markedPositions.push(position);
}
@Override
public final void reset() throws IOException {
checkOpen();
if (!markedPositions.isEmpty()) {
long newPos = markedPositions.pop();
// NOTE: This is correct according to javax.imageio (IOException),
// but it's kind of inconsistent with seek that throws IndexOutOfBoundsException...
if (newPos < flushedPosition) {
throw new IOException("Previous marked position has been discarded");
}
seek(newPos);
}
else {
// TODO: To iron out some wrinkles due to conflicting contracts
// (InputStream and Seekable both declare reset),
// we might need to reset to the last marked position instead..
// However, that becomes REALLY confusing if that position is after
// the current position...
seek(0);
}
}
public final void flushBefore(long pPosition) throws IOException {
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition");
}
if (pPosition > getStreamPosition()) {
throw new IndexOutOfBoundsException("position > stream position");
}
checkOpen();
flushBeforeImpl(pPosition);
flushedPosition = pPosition;
}
/**
* Discards the initial portion of the stream prior to the indicated postion.
*
* @param pPosition the position to flush to
* @throws IOException if an I/O exception occurs during the flush operation
*
* @see #flushBefore(long)
*/
protected abstract void flushBeforeImpl(long pPosition) throws IOException;
public final void flush() throws IOException {
flushBefore(flushedPosition);
}
public final long getFlushedPosition() throws IOException {
checkOpen();
return flushedPosition;
}
public final long getStreamPosition() throws IOException {
checkOpen();
return position;
}
protected final void checkOpen() throws IOException {
if (closed) {
throw new IOException("closed");
}
}
@Override
public final void close() throws IOException {
checkOpen();
closed = true;
closeImpl();
}
protected abstract void closeImpl() throws IOException;
/**
* Finalizes this object prior to garbage collection. The
* {@code close} method is called to close any open input
* source. This method should not be called from application
* code.
*
* @exception Throwable if an error occurs during superclass
* finalization.
*/
@Override
protected void finalize() throws Throwable {
if (!closed) {
try {
close();
}
catch (IOException ignore) {
// Ignroe
}
}
super.finalize();
}
}
@@ -1,140 +1,140 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Stack;
/**
* Abstract base class for {@code OutputStream}s implementing the
* {@code Seekable} interface.
* <p/>
* @see SeekableInputStream
*
* @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/SeekableOutputStream.java#2 $
*/
public abstract class SeekableOutputStream extends OutputStream implements Seekable {
// TODO: Implement
long position;
long flushedPosition;
boolean closed;
protected Stack<Long> markedPositions = new Stack<Long>();
/// Outputstream overrides
@Override
public final void write(byte pBytes[]) throws IOException {
write(pBytes, 0, pBytes != null ? pBytes.length : 1);
}
/// Seekable implementation
// TODO: This is common behaviour/implementation with SeekableInputStream,
// probably a good idea to extract a delegate..?
public final void seek(long pPosition) throws IOException {
checkOpen();
// TODO: This is correct according to javax.imageio (IndexOutOfBoundsException),
// but it's inconsistent with reset that throws IOException...
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition!");
}
seekImpl(pPosition);
position = pPosition;
}
protected abstract void seekImpl(long pPosition) throws IOException;
public final void mark() {
markedPositions.push(position);
}
public final void reset() throws IOException {
checkOpen();
if (!markedPositions.isEmpty()) {
long newPos = markedPositions.pop();
// TODO: This is correct according to javax.imageio (IOException),
// but it's inconsistent with seek that throws IndexOutOfBoundsException...
if (newPos < flushedPosition) {
throw new IOException("Previous marked position has been discarded!");
}
seek(newPos);
}
}
public final void flushBefore(long pPosition) throws IOException {
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition!");
}
if (pPosition > getStreamPosition()) {
throw new IndexOutOfBoundsException("position > getStreamPosition()!");
}
checkOpen();
flushBeforeImpl(pPosition);
flushedPosition = pPosition;
}
protected abstract void flushBeforeImpl(long pPosition) throws IOException;
@Override
public final void flush() throws IOException {
flushBefore(flushedPosition);
}
public final long getFlushedPosition() throws IOException {
checkOpen();
return flushedPosition;
}
public final long getStreamPosition() throws IOException {
checkOpen();
return position;
}
protected final void checkOpen() throws IOException {
if (closed) {
throw new IOException("closed");
}
}
@Override
public final void close() throws IOException {
checkOpen();
closed = true;
closeImpl();
}
protected abstract void closeImpl() throws IOException;
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Stack;
/**
* Abstract base class for {@code OutputStream}s implementing the
* {@code Seekable} interface.
*
* @see SeekableInputStream
*
* @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/SeekableOutputStream.java#2 $
*/
public abstract class SeekableOutputStream extends OutputStream implements Seekable {
// TODO: Implement
long position;
long flushedPosition;
boolean closed;
protected Stack<Long> markedPositions = new Stack<Long>();
/// Outputstream overrides
@Override
public final void write(byte pBytes[]) throws IOException {
write(pBytes, 0, pBytes != null ? pBytes.length : 1);
}
/// Seekable implementation
// TODO: This is common behaviour/implementation with SeekableInputStream,
// probably a good idea to extract a delegate..?
public final void seek(long pPosition) throws IOException {
checkOpen();
// TODO: This is correct according to javax.imageio (IndexOutOfBoundsException),
// but it's inconsistent with reset that throws IOException...
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition!");
}
seekImpl(pPosition);
position = pPosition;
}
protected abstract void seekImpl(long pPosition) throws IOException;
public final void mark() {
markedPositions.push(position);
}
public final void reset() throws IOException {
checkOpen();
if (!markedPositions.isEmpty()) {
long newPos = markedPositions.pop();
// TODO: This is correct according to javax.imageio (IOException),
// but it's inconsistent with seek that throws IndexOutOfBoundsException...
if (newPos < flushedPosition) {
throw new IOException("Previous marked position has been discarded!");
}
seek(newPos);
}
}
public final void flushBefore(long pPosition) throws IOException {
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition!");
}
if (pPosition > getStreamPosition()) {
throw new IndexOutOfBoundsException("position > getStreamPosition()!");
}
checkOpen();
flushBeforeImpl(pPosition);
flushedPosition = pPosition;
}
protected abstract void flushBeforeImpl(long pPosition) throws IOException;
@Override
public final void flush() throws IOException {
flushBefore(flushedPosition);
}
public final long getFlushedPosition() throws IOException {
checkOpen();
return flushedPosition;
}
public final long getStreamPosition() throws IOException {
checkOpen();
return position;
}
protected final void checkOpen() throws IOException {
if (closed) {
throw new IOException("closed");
}
}
@Override
public final void close() throws IOException {
checkOpen();
closed = true;
closeImpl();
}
protected abstract void closeImpl() throws IOException;
}
@@ -1,189 +1,188 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
/**
* StringArrayReader
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/StringArrayReader.java#2 $
*/
public class StringArrayReader extends StringReader {
private StringReader current;
private String[] strings;
protected final Object finalLock;
private int currentSting;
private int markedString;
private int mark;
private int next;
/**
* Create a new string array reader.
*
* @param pStrings {@code String}s providing the character stream.
*/
public StringArrayReader(final String[] pStrings) {
super("");
Validate.notNull(pStrings, "strings");
finalLock = lock = pStrings; // NOTE: It's ok to sync on pStrings, as the
// reference can't change, only it's elements
strings = pStrings.clone(); // Defensive copy for content
nextReader();
}
protected final Reader nextReader() {
if (currentSting >= strings.length) {
current = new EmptyReader();
}
else {
current = new StringReader(strings[currentSting++]);
}
// NOTE: Reset next for every reader, and record marked reader in mark/reset methods!
next = 0;
return current;
}
/**
* Check to make sure that the stream has not been closed
*
* @throws IOException if the stream is closed
*/
protected final void ensureOpen() throws IOException {
if (strings == null) {
throw new IOException("Stream closed");
}
}
public void close() {
super.close();
strings = null;
current.close();
}
public void mark(int pReadLimit) throws IOException {
if (pReadLimit < 0){
throw new IllegalArgumentException("Read limit < 0");
}
synchronized (finalLock) {
ensureOpen();
mark = next;
markedString = currentSting;
current.mark(pReadLimit);
}
}
public void reset() throws IOException {
synchronized (finalLock) {
ensureOpen();
if (currentSting != markedString) {
currentSting = markedString - 1;
nextReader();
current.skip(mark);
}
else {
current.reset();
}
next = mark;
}
}
public boolean markSupported() {
return true;
}
public int read() throws IOException {
synchronized (finalLock) {
int read = current.read();
if (read < 0 && currentSting < strings.length) {
nextReader();
return read(); // In case of empty strings
}
next++;
return read;
}
}
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
if (read < 0 && currentSting < strings.length) {
nextReader();
return read(pBuffer, pOffset, pLength); // In case of empty strings
}
next += read;
return read;
}
}
public boolean ready() throws IOException {
return current.ready();
}
public long skip(long pChars) throws IOException {
synchronized (finalLock) {
long skipped = current.skip(pChars);
if (skipped == 0 && currentSting < strings.length) {
nextReader();
return skip(pChars);
}
next += skipped;
return skipped;
}
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
/**
* StringArrayReader
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/StringArrayReader.java#2 $
*/
public class StringArrayReader extends StringReader {
private StringReader current;
private String[] strings;
protected final Object finalLock;
private int currentSting;
private int markedString;
private long mark;
private long next;
/**
* Create a new string array reader.
*
* @param pStrings {@code String}s providing the character stream.
*/
public StringArrayReader(final String[] pStrings) {
super("");
Validate.notNull(pStrings, "strings");
finalLock = lock = pStrings; // NOTE: It's ok to sync on pStrings, as the
// reference can't change, only it's elements
strings = pStrings.clone(); // Defensive copy for content
nextReader();
}
protected final Reader nextReader() {
if (currentSting >= strings.length) {
current = new EmptyReader();
}
else {
current = new StringReader(strings[currentSting++]);
}
// NOTE: Reset next for every reader, and record marked reader in mark/reset methods!
next = 0;
return current;
}
/**
* Check to make sure that the stream has not been closed
*
* @throws IOException if the stream is closed
*/
protected final void ensureOpen() throws IOException {
if (strings == null) {
throw new IOException("Stream closed");
}
}
public void close() {
super.close();
strings = null;
current.close();
}
public void mark(int pReadLimit) throws IOException {
if (pReadLimit < 0){
throw new IllegalArgumentException("Read limit < 0");
}
synchronized (finalLock) {
ensureOpen();
mark = next;
markedString = currentSting;
current.mark(pReadLimit);
}
}
public void reset() throws IOException {
synchronized (finalLock) {
ensureOpen();
if (currentSting != markedString) {
currentSting = markedString - 1;
nextReader();
current.skip(mark);
}
else {
current.reset();
}
next = mark;
}
}
public boolean markSupported() {
return true;
}
public int read() throws IOException {
synchronized (finalLock) {
int read = current.read();
if (read < 0 && currentSting < strings.length) {
nextReader();
return read(); // In case of empty strings
}
next++;
return read;
}
}
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
if (read < 0 && currentSting < strings.length) {
nextReader();
return read(pBuffer, pOffset, pLength); // In case of empty strings
}
next += read;
return read;
}
}
public boolean ready() throws IOException {
return current.ready();
}
public long skip(long pChars) throws IOException {
synchronized (finalLock) {
long skipped = current.skip(pChars);
if (skipped == 0 && currentSting < strings.length) {
nextReader();
return skip(pChars);
}
next += skipped;
return skipped;
}
}
}
@@ -1,137 +1,134 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* An {@code InputStream} reading up to a specified number of bytes from an
* underlying stream.
* <p/>
*
* @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}.
*
* @param pStream the underlying input stream
* @param pLength maximum number of bytes to read drom this stream
*/
public SubStream(final InputStream pStream, final long pLength) {
super(Validate.notNull(pStream, "stream"));
bytesLeft = pLength;
}
/**
* Marks this stream as closed.
* This implementation does <em>not</em> close the underlying stream.
*/
@Override
public void close() throws IOException {
// NOTE: Do not close the underlying stream
while (bytesLeft > 0) {
//noinspection ResultOfMethodCallIgnored
skip(bytesLeft);
}
}
@Override
public int available() throws IOException {
return (int) Math.min(super.available(), bytesLeft);
}
@Override
public void mark(int pReadLimit) {
super.mark(pReadLimit);// This either succeeds or does nothing...
markLimit = pReadLimit;
}
@Override
public void reset() throws IOException {
super.reset();// This either succeeds or throws IOException
bytesLeft += markLimit;
}
@Override
public int read() throws IOException {
if (bytesLeft-- <= 0) {
return -1;
}
return super.read();
}
@Override
public final int read(byte[] pBytes) throws IOException {
return read(pBytes, 0, pBytes.length);
}
@Override
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (bytesLeft <= 0) {
return -1;
}
int read = super.read(pBytes, pOffset, (int) findMaxLen(pLength));
bytesLeft = read < 0 ? 0 : bytesLeft - read;
return read;
}
/**
* Finds the maximum number of bytes we can read or skip, from this stream.
*
* @param pLength 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;
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* An {@code InputStream} reading up to a specified number of bytes from an
* underlying stream.
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
*/
public final class SubStream extends FilterInputStream {
private long bytesLeft;
private int markLimit;
/**
* Creates a {@code SubStream} of the given {@code stream}.
*
* @param stream the underlying input stream
* @param length maximum number of bytes to read from this stream
*/
public SubStream(final InputStream stream, final long length) {
super(Validate.notNull(stream, "stream"));
bytesLeft = Validate.isTrue(length >= 0, length, "length < 0: %s");
}
/**
* Marks this stream as closed.
* This implementation does <em>not</em> close the underlying stream.
*/
@Override
public void close() throws IOException {
// NOTE: Do not close the underlying stream, but consume it
while (bytesLeft > 0) {
if (skip(bytesLeft) <= 0 && read() < 0) {
break;
}
}
}
@Override
public int available() throws IOException {
return (int) findMaxLen(super.available());
}
@Override
public void mark(int readLimit) {
super.mark(readLimit);// This either succeeds or does nothing...
markLimit = readLimit;
}
@Override
public void reset() throws IOException {
super.reset();// This either succeeds or throws IOException
bytesLeft += markLimit;
}
@Override
public int read() throws IOException {
if (bytesLeft-- <= 0) {
return -1;
}
return super.read();
}
@Override
public int read(byte[] bytes) throws IOException {
return read(bytes, 0, bytes.length);
}
@Override
public int read(final byte[] bytes, final int off, final int len) throws IOException {
if (bytesLeft <= 0) {
return -1;
}
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 length the requested length
* @return the maximum number of bytes to read
*/
private long findMaxLen(long length) {
return bytesLeft < length ? Math.max(bytesLeft, 0) : length;
}
}
@@ -1,107 +1,106 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.util.StringTokenIterator;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
/**
* UnixFileSystem
* <p/>
*
* @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/UnixFileSystem.java#1 $
*/
final class UnixFileSystem extends FileSystem {
long getFreeSpace(File pPath) {
try {
return getNumber(pPath, 3);
}
catch (IOException e) {
return 0l;
}
}
long getTotalSpace(File pPath) {
try {
return getNumber(pPath, 5);
}
catch (IOException e) {
return 0l;
}
}
private long getNumber(File pPath, int pIndex) throws IOException {
// TODO: Test on other platforms
// Tested on Mac OS X, CygWin
BufferedReader reader = exec(new String[] {"df", "-k", pPath.getAbsolutePath()});
String last = null;
String line;
try {
while ((line = reader.readLine()) != null) {
last = line;
}
}
finally {
FileUtil.close(reader);
}
if (last != null) {
String blocks = null;
StringTokenIterator tokens = new StringTokenIterator(last, " ", StringTokenIterator.REVERSE);
int count = 0;
// We want the 3rd last token
while (count < pIndex && tokens.hasNext()) {
blocks = tokens.nextToken();
count++;
}
if (blocks != null) {
try {
return Long.parseLong(blocks) * 1024L;
}
catch (NumberFormatException ignore) {
// Ignore
}
}
}
return 0l;
}
String getName() {
return "Unix";
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.util.StringTokenIterator;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
/**
* UnixFileSystem
*
* @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/UnixFileSystem.java#1 $
*/
final class UnixFileSystem extends FileSystem {
long getFreeSpace(File pPath) {
try {
return getNumber(pPath, 3);
}
catch (IOException e) {
return 0l;
}
}
long getTotalSpace(File pPath) {
try {
return getNumber(pPath, 5);
}
catch (IOException e) {
return 0l;
}
}
private long getNumber(File pPath, int pIndex) throws IOException {
// TODO: Test on other platforms
// Tested on Mac OS X, CygWin
BufferedReader reader = exec(new String[] {"df", "-k", pPath.getAbsolutePath()});
String last = null;
String line;
try {
while ((line = reader.readLine()) != null) {
last = line;
}
}
finally {
FileUtil.close(reader);
}
if (last != null) {
String blocks = null;
StringTokenIterator tokens = new StringTokenIterator(last, " ", StringTokenIterator.REVERSE);
int count = 0;
// We want the 3rd last token
while (count < pIndex && tokens.hasNext()) {
blocks = tokens.nextToken();
count++;
}
if (blocks != null) {
try {
return Long.parseLong(blocks) * 1024L;
}
catch (NumberFormatException ignore) {
// Ignore
}
}
}
return 0l;
}
String getName() {
return "Unix";
}
}
@@ -1,195 +1,194 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
/**
* Win32File
* <p/>
*
* @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/Win32File.java#2 $
*/
final class Win32File extends File {
private final static boolean IS_WINDOWS = isWindows();
private static boolean isWindows() {
try {
String os = System.getProperty("os.name");
return os.toLowerCase().indexOf("windows") >= 0;
}
catch (Throwable t) {
// Ignore
}
return false;
}
private Win32File(File pPath) {
super(pPath.getPath());
}
public static void main(String[] pArgs) {
int argIdx = 0;
boolean recursive = false;
while (pArgs.length > argIdx + 1 && pArgs[argIdx].charAt(0) == '-' && pArgs[argIdx].length() > 1) {
if (pArgs[argIdx].charAt(1) == 'R' || pArgs[argIdx].equals("--recursive")) {
recursive = true;
}
else {
System.err.println("Unknown option: " + pArgs[argIdx]);
}
argIdx++;
}
File file = wrap(new File(pArgs[argIdx]));
System.out.println("file: " + file);
System.out.println("file.getClass(): " + file.getClass());
listFiles(file, 0, recursive);
}
private static void listFiles(File pFile, int pLevel, boolean pRecursive) {
if (pFile.isDirectory()) {
File[] files = pFile.listFiles();
for (int l = 0; l < pLevel; l++) {
System.out.print(" ");
}
System.out.println("Contents of " + pFile + ": ");
for (File file : files) {
for (int l = 0; l < pLevel; l++) {
System.out.print(" ");
}
System.out.println(" " + file);
if (pRecursive) {
listFiles(file, pLevel + 1, pLevel < 4);
}
}
}
}
/**
* Wraps a {@code File} object pointing to a Windows symbolic link
* ({@code .lnk} file) in a {@code Win32Lnk}.
* If the operating system is not Windows, the
* {@code pPath} parameter is returned unwrapped.
*
* @param pPath any path, possibly pointing to a Windows symbolic link file.
* May be {@code null}, in which case {@code null} is returned.
*
* @return a new {@code Win32Lnk} object if the current os is Windows, and
* the file is a Windows symbolic link ({@code .lnk} file), otherwise
* {@code pPath}
*/
public static File wrap(final File pPath) {
if (pPath == null) {
return null;
}
if (IS_WINDOWS) {
// Don't wrap if allready wrapped
if (pPath instanceof Win32File || pPath instanceof Win32Lnk) {
return pPath;
}
if (pPath.exists() && pPath.getName().endsWith(".lnk")) {
// If Win32 .lnk, let's wrap
try {
return new Win32Lnk(pPath);
}
catch (IOException e) {
// TODO: FixMe!
e.printStackTrace();
}
}
// Wwrap even if not a .lnk, as the listFiles() methods etc,
// could potentially return .lnk's, that we want to wrap later...
return new Win32File(pPath);
}
return pPath;
}
/**
* Wraps a {@code File} array, possibly pointing to Windows symbolic links
* ({@code .lnk} files) in {@code Win32Lnk}s.
*
* @param pPaths an array of {@code File}s, possibly pointing to Windows
* symbolic link files.
* May be {@code null}, in which case {@code null} is returned.
*
* @return {@code pPaths}, with any {@code File} representing a Windows
* symbolic link ({@code .lnk} file) wrapped in a {@code Win32Lnk}.
*/
public static File[] wrap(File[] pPaths) {
if (IS_WINDOWS) {
for (int i = 0; pPaths != null && i < pPaths.length; i++) {
pPaths[i] = wrap(pPaths[i]);
}
}
return pPaths;
}
// File overrides
@Override
public File getAbsoluteFile() {
return wrap(super.getAbsoluteFile());
}
@Override
public File getCanonicalFile() throws IOException {
return wrap(super.getCanonicalFile());
}
@Override
public File getParentFile() {
return wrap(super.getParentFile());
}
@Override
public File[] listFiles() {
return wrap(super.listFiles());
}
@Override
public File[] listFiles(FileFilter filter) {
return wrap(super.listFiles(filter));
}
@Override
public File[] listFiles(FilenameFilter filter) {
return wrap(super.listFiles(filter));
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
/**
* Win32File
*
* @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/Win32File.java#2 $
*/
final class Win32File extends File {
private final static boolean IS_WINDOWS = isWindows();
private static boolean isWindows() {
try {
String os = System.getProperty("os.name");
return os.toLowerCase().indexOf("windows") >= 0;
}
catch (Throwable t) {
// Ignore
}
return false;
}
private Win32File(File pPath) {
super(pPath.getPath());
}
public static void main(String[] pArgs) {
int argIdx = 0;
boolean recursive = false;
while (pArgs.length > argIdx + 1 && pArgs[argIdx].charAt(0) == '-' && pArgs[argIdx].length() > 1) {
if (pArgs[argIdx].charAt(1) == 'R' || pArgs[argIdx].equals("--recursive")) {
recursive = true;
}
else {
System.err.println("Unknown option: " + pArgs[argIdx]);
}
argIdx++;
}
File file = wrap(new File(pArgs[argIdx]));
System.out.println("file: " + file);
System.out.println("file.getClass(): " + file.getClass());
listFiles(file, 0, recursive);
}
private static void listFiles(File pFile, int pLevel, boolean pRecursive) {
if (pFile.isDirectory()) {
File[] files = pFile.listFiles();
for (int l = 0; l < pLevel; l++) {
System.out.print(" ");
}
System.out.println("Contents of " + pFile + ": ");
for (File file : files) {
for (int l = 0; l < pLevel; l++) {
System.out.print(" ");
}
System.out.println(" " + file);
if (pRecursive) {
listFiles(file, pLevel + 1, pLevel < 4);
}
}
}
}
/**
* Wraps a {@code File} object pointing to a Windows symbolic link
* ({@code .lnk} file) in a {@code Win32Lnk}.
* If the operating system is not Windows, the
* {@code pPath} parameter is returned unwrapped.
*
* @param pPath any path, possibly pointing to a Windows symbolic link file.
* May be {@code null}, in which case {@code null} is returned.
*
* @return a new {@code Win32Lnk} object if the current os is Windows, and
* the file is a Windows symbolic link ({@code .lnk} file), otherwise
* {@code pPath}
*/
public static File wrap(final File pPath) {
if (pPath == null) {
return null;
}
if (IS_WINDOWS) {
// Don't wrap if allready wrapped
if (pPath instanceof Win32File || pPath instanceof Win32Lnk) {
return pPath;
}
if (pPath.exists() && pPath.getName().endsWith(".lnk")) {
// If Win32 .lnk, let's wrap
try {
return new Win32Lnk(pPath);
}
catch (IOException e) {
// TODO: FixMe!
e.printStackTrace();
}
}
// Wwrap even if not a .lnk, as the listFiles() methods etc,
// could potentially return .lnk's, that we want to wrap later...
return new Win32File(pPath);
}
return pPath;
}
/**
* Wraps a {@code File} array, possibly pointing to Windows symbolic links
* ({@code .lnk} files) in {@code Win32Lnk}s.
*
* @param pPaths an array of {@code File}s, possibly pointing to Windows
* symbolic link files.
* May be {@code null}, in which case {@code null} is returned.
*
* @return {@code pPaths}, with any {@code File} representing a Windows
* symbolic link ({@code .lnk} file) wrapped in a {@code Win32Lnk}.
*/
public static File[] wrap(File[] pPaths) {
if (IS_WINDOWS) {
for (int i = 0; pPaths != null && i < pPaths.length; i++) {
pPaths[i] = wrap(pPaths[i]);
}
}
return pPaths;
}
// File overrides
@Override
public File getAbsoluteFile() {
return wrap(super.getAbsoluteFile());
}
@Override
public File getCanonicalFile() throws IOException {
return wrap(super.getCanonicalFile());
}
@Override
public File getParentFile() {
return wrap(super.getParentFile());
}
@Override
public File[] listFiles() {
return wrap(super.listFiles());
}
@Override
public File[] listFiles(FileFilter filter) {
return wrap(super.listFiles(filter));
}
@Override
public File[] listFiles(FilenameFilter filter) {
return wrap(super.listFiles(filter));
}
}
@@ -1,92 +1,91 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
/**
* WindowsFileSystem
* <p/>
*
* @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/Win32FileSystem.java#2 $
*/
final class Win32FileSystem extends FileSystem {
public long getFreeSpace(File pPath) {
try {
// Windows version
// TODO: Test on W2K/95/98/etc... (tested on XP)
BufferedReader reader = exec(new String[] {"CMD.EXE", "/C", "DIR", "/-C", pPath.getAbsolutePath()});
String last = null;
String line;
try {
while ((line = reader.readLine()) != null) {
last = line;
}
}
finally {
FileUtil.close(reader);
}
if (last != null) {
int end = last.lastIndexOf(" bytes free");
int start = last.lastIndexOf(' ', end - 1);
if (start >= 0 && end >= 0) {
try {
return Long.parseLong(last.substring(start + 1, end));
}
catch (NumberFormatException ignore) {
// Ignore
}
}
}
}
catch (IOException ignore) {
// Ignore
}
return 0l;
}
long getTotalSpace(File pPath) {
// TODO: Implement, probably need some JNI stuff...
// Distribute df.exe and execute from temp!? ;-)
return getFreeSpace(pPath);
}
String getName() {
return "Win32";
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
/**
* WindowsFileSystem
*
* @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/Win32FileSystem.java#2 $
*/
final class Win32FileSystem extends FileSystem {
public long getFreeSpace(File pPath) {
try {
// Windows version
// TODO: Test on W2K/95/98/etc... (tested on XP)
BufferedReader reader = exec(new String[] {"CMD.EXE", "/C", "DIR", "/-C", pPath.getAbsolutePath()});
String last = null;
String line;
try {
while ((line = reader.readLine()) != null) {
last = line;
}
}
finally {
FileUtil.close(reader);
}
if (last != null) {
int end = last.lastIndexOf(" bytes free");
int start = last.lastIndexOf(' ', end - 1);
if (start >= 0 && end >= 0) {
try {
return Long.parseLong(last.substring(start + 1, end));
}
catch (NumberFormatException ignore) {
// Ignore
}
}
}
}
catch (IOException ignore) {
// Ignore
}
return 0l;
}
long getTotalSpace(File pPath) {
// TODO: Implement, probably need some JNI stuff...
// Distribute df.exe and execute from temp!? ;-)
return getFreeSpace(pPath);
}
String getName() {
return "Win32";
}
}
@@ -1,475 +1,477 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.*;
import java.util.Arrays;
/**
* A {@code File} implementation that resolves the Windows {@code .lnk} files as symbolic links.
* <p/>
* This class is based on example code from
* <a href="http://www.oreilly.com/catalog/swinghks/index.html">Swing Hacks</a>,
* By Joshua Marinacci, Chris Adamson (O'Reilly, ISBN: 0-596-00907-0), Hack 30.
*
* @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/Win32Lnk.java#2 $
*/
final class Win32Lnk extends File {
private final static byte[] LNK_MAGIC = {
'L', 0x00, 0x00, 0x00, // Magic
};
private final static byte[] LNK_GUID = {
0x01, 0x14, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Shell Link GUID
(byte) 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'F'
};
private final File target;
private static final int FLAG_ITEM_ID_LIST = 0x01;
private static final int FLAG_FILE_LOC_INFO = 0x02;
private static final int FLAG_DESC_STRING = 0x04;
private static final int FLAG_REL_PATH_STRING = 0x08;
private static final int FLAG_WORKING_DIRECTORY = 0x10;
private static final int FLAG_COMMAND_LINE_ARGS = 0x20;
private static final int FLAG_ICON_FILENAME = 0x40;
private static final int FLAG_ADDITIONAL_INFO = 0x80;
private Win32Lnk(final String pPath) throws IOException {
super(pPath);
File target = parse(this);
if (target == this) {
// NOTE: This is a workaround
// target = this causes infinite loops in some methods
target = new File(pPath);
}
this.target = target;
}
Win32Lnk(final File pPath) throws IOException {
this(pPath.getPath());
}
/**
* Parses a {@code .lnk} file to find the real file.
*
* @param pPath the path to the {@code .lnk} file
* @return a new file object that
* @throws java.io.IOException if the {@code .lnk} cannot be parsed
*/
static File parse(final File pPath) throws IOException {
if (!pPath.getName().endsWith(".lnk")) {
return pPath;
}
File result = pPath;
LittleEndianDataInputStream in = new LittleEndianDataInputStream(new BufferedInputStream(new FileInputStream(pPath)));
try {
byte[] magic = new byte[4];
in.readFully(magic);
byte[] guid = new byte[16];
in.readFully(guid);
if (!(Arrays.equals(LNK_MAGIC, magic) && Arrays.equals(LNK_GUID, guid))) {
//System.out.println("Not a symlink");
// Not a symlink
return pPath;
}
// Get the flags
int flags = in.readInt();
//System.out.println("flags: " + Integer.toBinaryString(flags & 0xff));
// Get to the file settings
/*int attributes = */in.readInt();
// File attributes
// 0 Target is read only.
// 1 Target is hidden.
// 2 Target is a system file.
// 3 Target is a volume label. (Not possible)
// 4 Target is a directory.
// 5 Target has been modified since last backup. (archive)
// 6 Target is encrypted (NTFS EFS)
// 7 Target is Normal??
// 8 Target is temporary.
// 9 Target is a sparse file.
// 10 Target has reparse point data.
// 11 Target is compressed.
// 12 Target is offline.
//System.out.println("attributes: " + Integer.toBinaryString(attributes));
// NOTE: Cygwin .lnks are not directory links, can't rely on this.. :-/
in.skipBytes(48); // TODO: Make sense of this data...
// Skipped data:
// long time 1 (creation)
// long time 2 (modification)
// long time 3 (last access)
// int file length
// int icon number
// int ShowVnd value
// int hotkey
// int, int - unknown: 0,0
// If the shell settings are present, skip them
if ((flags & FLAG_ITEM_ID_LIST) != 0) {
// Shell Item Id List present
//System.out.println("Shell Item Id List present");
int shellLen = in.readShort(); // Short
//System.out.println("shellLen: " + shellLen);
// TODO: Probably need to parse this data, to determine
// Cygwin folders...
/*
int read = 2;
int itemLen = in.readShort();
while (itemLen > 0) {
System.out.println("--> ITEM: " + itemLen);
BufferedReader reader = new BufferedReader(new InputStreamReader(new SubStream(in, itemLen - 2)));
//byte[] itemBytes = new byte[itemLen - 2]; // NOTE: Lenght included
//in.readFully(itemBytes);
String item = reader.readLine();
System.out.println("item: \"" + item + "\"");
itemLen = in.readShort();
read += itemLen;
}
System.out.println("read: " + read);
*/
in.skipBytes(shellLen);
}
if ((flags & FLAG_FILE_LOC_INFO) != 0) {
// File Location Info Table present
//System.out.println("File Location Info Table present");
// 0h 1 dword This is the total length of this structure and all following data
// 4h 1 dword This is a pointer to first offset after this structure. 1Ch
// 8h 1 dword Flags
// Ch 1 dword Offset of local volume info
// 10h 1 dword Offset of base pathname on local system
// 14h 1 dword Offset of network volume info
// 18h 1 dword Offset of remaining pathname
// Flags:
// Bit Meaning
// 0 Available on a local volume
// 1 Available on a network share
// TODO: Make sure the path is on a local disk, etc..
int tableLen = in.readInt(); // Int
//System.out.println("tableLen: " + tableLen);
in.readInt(); // Skip
int locFlags = in.readInt();
//System.out.println("locFlags: " + Integer.toBinaryString(locFlags));
if ((locFlags & 0x01) != 0) {
//System.out.println("Available local");
}
if ((locFlags & 0x02) != 0) {
//System.err.println("Available on network path");
}
// Get the local volume and local system values
in.skipBytes(4); // TODO: see above for structure
int localSysOff = in.readInt();
//System.out.println("localSysOff: " + localSysOff);
in.skipBytes(localSysOff - 20); // Relative to start of chunk
byte[] pathBytes = new byte[tableLen - localSysOff - 1];
in.readFully(pathBytes, 0, pathBytes.length);
String path = new String(pathBytes, 0, pathBytes.length - 1);
/*
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
byte read;
// Read bytes until the null (0) character
while (true) {
read = in.readByte();
if (read == 0) {
break;
}
bytes.write(read & 0xff);
}
String path = new String(bytes.toByteArray(), 0, bytes.size());
//*/
// Recurse to end of link chain
// TODO: This may cause endless loop if cyclic chain...
//System.out.println("path: \"" + path + "\"");
try {
result = parse(new File(path));
}
catch (StackOverflowError e) {
throw new IOException("Cannot resolve cyclic link: " + e.getMessage());
}
}
if ((flags & FLAG_DESC_STRING) != 0) {
// Description String present, skip it.
//System.out.println("Description String present");
// The string length is the first word which must also be skipped.
int descLen = in.readShort();
//System.out.println("descLen: " + descLen);
byte[] descBytes = new byte[descLen];
in.readFully(descBytes, 0, descLen);
//String desc = new String(descBytes, 0, descLen);
//System.out.println("desc: " + desc);
}
if ((flags & FLAG_REL_PATH_STRING) != 0) {
// Relative Path String present
//System.out.println("Relative Path String present");
// The string length is the first word which must also be skipped.
int pathLen = in.readShort();
//System.out.println("pathLen: " + pathLen);
byte[] pathBytes = new byte[pathLen];
in.readFully(pathBytes, 0, pathLen);
String path = new String(pathBytes, 0, pathLen);
// TODO: This may cause endless loop if cyclic chain...
//System.out.println("path: \"" + path + "\"");
if (result == pPath) {
try {
result = parse(new File(pPath.getParentFile(), path));
}
catch (StackOverflowError e) {
throw new IOException("Cannot resolve cyclic link: " + e.getMessage());
}
}
}
if ((flags & FLAG_WORKING_DIRECTORY) != 0) {
//System.out.println("Working Directory present");
}
if ((flags & FLAG_COMMAND_LINE_ARGS) != 0) {
//System.out.println("Command Line Arguments present");
// NOTE: This means this .lnk is not a folder, don't follow
result = pPath;
}
if ((flags & FLAG_ICON_FILENAME) != 0) {
//System.out.println("Icon Filename present");
}
if ((flags & FLAG_ADDITIONAL_INFO) != 0) {
//System.out.println("Additional Info present");
}
}
finally {
in.close();
}
return result;
}
/*
private static String getNullDelimitedString(byte[] bytes, int off) {
int len = 0;
// Count bytes until the null (0) character
while (true) {
if (bytes[off + len] == 0) {
break;
}
len++;
}
System.err.println("--> " + len);
return new String(bytes, off, len);
}
*/
/**
* Converts two bytes into a short.
* <p/>
* NOTE: this is little endian because it's for an
* Intel only OS
*
* @ param bytes
* @ param off
* @return the bytes as a short.
*/
/*
private static int bytes2short(byte[] bytes, int off) {
return ((bytes[off + 1] & 0xff) << 8) | (bytes[off] & 0xff);
}
*/
public File getTarget() {
return target;
}
// java.io.File overrides below
@Override
public boolean isDirectory() {
return target.isDirectory();
}
@Override
public boolean canRead() {
return target.canRead();
}
@Override
public boolean canWrite() {
return target.canWrite();
}
// NOTE: equals is implemented using compareto == 0
/*
public int compareTo(File pathname) {
// TODO: Verify this
// Probably not a good idea, as it IS NOT THE SAME file
// It's probably better to not override
return target.compareTo(pathname);
}
*/
// Should probably never allow creating a new .lnk
// public boolean createNewFile() throws IOException
// Deletes only the .lnk
// public boolean delete() {
//public void deleteOnExit() {
@Override
public boolean exists() {
return target.exists();
}
// A .lnk may be absolute
//public File getAbsoluteFile() {
//public String getAbsolutePath() {
// Theses should be resolved according to the API (for Unix).
@Override
public File getCanonicalFile() throws IOException {
return target.getCanonicalFile();
}
@Override
public String getCanonicalPath() throws IOException {
return target.getCanonicalPath();
}
//public String getName() {
// I guess the parent should be the parent of the .lnk, not the target
//public String getParent() {
//public File getParentFile() {
// public boolean isAbsolute() {
@Override
public boolean isFile() {
return target.isFile();
}
@Override
public boolean isHidden() {
return target.isHidden();
}
@Override
public long lastModified() {
return target.lastModified();
}
@Override
public long length() {
return target.length();
}
@Override
public String[] list() {
return target.list();
}
@Override
public String[] list(final FilenameFilter filter) {
return target.list(filter);
}
@Override
public File[] listFiles() {
return Win32File.wrap(target.listFiles());
}
@Override
public File[] listFiles(final FileFilter filter) {
return Win32File.wrap(target.listFiles(filter));
}
@Override
public File[] listFiles(final FilenameFilter filter) {
return Win32File.wrap(target.listFiles(filter));
}
// Makes no sense, does it?
//public boolean mkdir() {
//public boolean mkdirs() {
// Only rename the lnk
//public boolean renameTo(File dest) {
@Override
public boolean setLastModified(long time) {
return target.setLastModified(time);
}
@Override
public boolean setReadOnly() {
return target.setReadOnly();
}
@Override
public String toString() {
if (target.equals(this)) {
return super.toString();
}
return super.toString() + " -> " + target.toString();
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import java.io.*;
import java.util.Arrays;
/**
* A {@code File} implementation that resolves the Windows {@code .lnk} files as symbolic links.
* <p>
* This class is based on example code from
* <a href="http://www.oreilly.com/catalog/swinghks/index.html">Swing Hacks</a>,
* By Joshua Marinacci, Chris Adamson (O'Reilly, ISBN: 0-596-00907-0), Hack 30.
* </p>
*
* @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/Win32Lnk.java#2 $
*/
final class Win32Lnk extends File {
private final static byte[] LNK_MAGIC = {
'L', 0x00, 0x00, 0x00, // Magic
};
private final static byte[] LNK_GUID = {
0x01, 0x14, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, // Shell Link GUID
(byte) 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'F'
};
private final File target;
private static final int FLAG_ITEM_ID_LIST = 0x01;
private static final int FLAG_FILE_LOC_INFO = 0x02;
private static final int FLAG_DESC_STRING = 0x04;
private static final int FLAG_REL_PATH_STRING = 0x08;
private static final int FLAG_WORKING_DIRECTORY = 0x10;
private static final int FLAG_COMMAND_LINE_ARGS = 0x20;
private static final int FLAG_ICON_FILENAME = 0x40;
private static final int FLAG_ADDITIONAL_INFO = 0x80;
private Win32Lnk(final String pPath) throws IOException {
super(pPath);
File target = parse(this);
if (target == this) {
// NOTE: This is a workaround
// target = this causes infinite loops in some methods
target = new File(pPath);
}
this.target = target;
}
Win32Lnk(final File pPath) throws IOException {
this(pPath.getPath());
}
/**
* Parses a {@code .lnk} file to find the real file.
*
* @param pPath the path to the {@code .lnk} file
* @return a new file object that
* @throws java.io.IOException if the {@code .lnk} cannot be parsed
*/
static File parse(final File pPath) throws IOException {
if (!pPath.getName().endsWith(".lnk")) {
return pPath;
}
File result = pPath;
LittleEndianDataInputStream in = new LittleEndianDataInputStream(new BufferedInputStream(new FileInputStream(pPath)));
try {
byte[] magic = new byte[4];
in.readFully(magic);
byte[] guid = new byte[16];
in.readFully(guid);
if (!(Arrays.equals(LNK_MAGIC, magic) && Arrays.equals(LNK_GUID, guid))) {
//System.out.println("Not a symlink");
// Not a symlink
return pPath;
}
// Get the flags
int flags = in.readInt();
//System.out.println("flags: " + Integer.toBinaryString(flags & 0xff));
// Get to the file settings
/*int attributes = */in.readInt();
// File attributes
// 0 Target is read only.
// 1 Target is hidden.
// 2 Target is a system file.
// 3 Target is a volume label. (Not possible)
// 4 Target is a directory.
// 5 Target has been modified since last backup. (archive)
// 6 Target is encrypted (NTFS EFS)
// 7 Target is Normal??
// 8 Target is temporary.
// 9 Target is a sparse file.
// 10 Target has reparse point data.
// 11 Target is compressed.
// 12 Target is offline.
//System.out.println("attributes: " + Integer.toBinaryString(attributes));
// NOTE: Cygwin .lnks are not directory links, can't rely on this.. :-/
in.skipBytes(48); // TODO: Make sense of this data...
// Skipped data:
// long time 1 (creation)
// long time 2 (modification)
// long time 3 (last access)
// int file length
// int icon number
// int ShowVnd value
// int hotkey
// int, int - unknown: 0,0
// If the shell settings are present, skip them
if ((flags & FLAG_ITEM_ID_LIST) != 0) {
// Shell Item Id List present
//System.out.println("Shell Item Id List present");
int shellLen = in.readShort(); // Short
//System.out.println("shellLen: " + shellLen);
// TODO: Probably need to parse this data, to determine
// Cygwin folders...
/*
int read = 2;
int itemLen = in.readShort();
while (itemLen > 0) {
System.out.println("--> ITEM: " + itemLen);
BufferedReader reader = new BufferedReader(new InputStreamReader(new SubStream(in, itemLen - 2)));
//byte[] itemBytes = new byte[itemLen - 2]; // NOTE: Lenght included
//in.readFully(itemBytes);
String item = reader.readLine();
System.out.println("item: \"" + item + "\"");
itemLen = in.readShort();
read += itemLen;
}
System.out.println("read: " + read);
*/
in.skipBytes(shellLen);
}
if ((flags & FLAG_FILE_LOC_INFO) != 0) {
// File Location Info Table present
//System.out.println("File Location Info Table present");
// 0h 1 dword This is the total length of this structure and all following data
// 4h 1 dword This is a pointer to first offset after this structure. 1Ch
// 8h 1 dword Flags
// Ch 1 dword Offset of local volume info
// 10h 1 dword Offset of base pathname on local system
// 14h 1 dword Offset of network volume info
// 18h 1 dword Offset of remaining pathname
// Flags:
// Bit Meaning
// 0 Available on a local volume
// 1 Available on a network share
// TODO: Make sure the path is on a local disk, etc..
int tableLen = in.readInt(); // Int
//System.out.println("tableLen: " + tableLen);
in.readInt(); // Skip
int locFlags = in.readInt();
//System.out.println("locFlags: " + Integer.toBinaryString(locFlags));
if ((locFlags & 0x01) != 0) {
//System.out.println("Available local");
}
if ((locFlags & 0x02) != 0) {
//System.err.println("Available on network path");
}
// Get the local volume and local system values
in.skipBytes(4); // TODO: see above for structure
int localSysOff = in.readInt();
//System.out.println("localSysOff: " + localSysOff);
in.skipBytes(localSysOff - 20); // Relative to start of chunk
byte[] pathBytes = new byte[tableLen - localSysOff - 1];
in.readFully(pathBytes, 0, pathBytes.length);
String path = new String(pathBytes, 0, pathBytes.length - 1);
/*
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
byte read;
// Read bytes until the null (0) character
while (true) {
read = in.readByte();
if (read == 0) {
break;
}
bytes.write(read & 0xff);
}
String path = new String(bytes.toByteArray(), 0, bytes.size());
//*/
// Recurse to end of link chain
// TODO: This may cause endless loop if cyclic chain...
//System.out.println("path: \"" + path + "\"");
try {
result = parse(new File(path));
}
catch (StackOverflowError e) {
throw new IOException("Cannot resolve cyclic link: " + e.getMessage());
}
}
if ((flags & FLAG_DESC_STRING) != 0) {
// Description String present, skip it.
//System.out.println("Description String present");
// The string length is the first word which must also be skipped.
int descLen = in.readShort();
//System.out.println("descLen: " + descLen);
byte[] descBytes = new byte[descLen];
in.readFully(descBytes, 0, descLen);
//String desc = new String(descBytes, 0, descLen);
//System.out.println("desc: " + desc);
}
if ((flags & FLAG_REL_PATH_STRING) != 0) {
// Relative Path String present
//System.out.println("Relative Path String present");
// The string length is the first word which must also be skipped.
int pathLen = in.readShort();
//System.out.println("pathLen: " + pathLen);
byte[] pathBytes = new byte[pathLen];
in.readFully(pathBytes, 0, pathLen);
String path = new String(pathBytes, 0, pathLen);
// TODO: This may cause endless loop if cyclic chain...
//System.out.println("path: \"" + path + "\"");
if (result == pPath) {
try {
result = parse(new File(pPath.getParentFile(), path));
}
catch (StackOverflowError e) {
throw new IOException("Cannot resolve cyclic link: " + e.getMessage());
}
}
}
if ((flags & FLAG_WORKING_DIRECTORY) != 0) {
//System.out.println("Working Directory present");
}
if ((flags & FLAG_COMMAND_LINE_ARGS) != 0) {
//System.out.println("Command Line Arguments present");
// NOTE: This means this .lnk is not a folder, don't follow
result = pPath;
}
if ((flags & FLAG_ICON_FILENAME) != 0) {
//System.out.println("Icon Filename present");
}
if ((flags & FLAG_ADDITIONAL_INFO) != 0) {
//System.out.println("Additional Info present");
}
}
finally {
in.close();
}
return result;
}
/*
private static String getNullDelimitedString(byte[] bytes, int off) {
int len = 0;
// Count bytes until the null (0) character
while (true) {
if (bytes[off + len] == 0) {
break;
}
len++;
}
System.err.println("--> " + len);
return new String(bytes, off, len);
}
*/
/**
* Converts two bytes into a short.
* <p>
* NOTE: this is little endian because it's for an
* Intel only OS
* </p>
*
* @ param bytes
* @ param off
* @return the bytes as a short.
*/
/*
private static int bytes2short(byte[] bytes, int off) {
return ((bytes[off + 1] & 0xff) << 8) | (bytes[off] & 0xff);
}
*/
public File getTarget() {
return target;
}
// java.io.File overrides below
@Override
public boolean isDirectory() {
return target.isDirectory();
}
@Override
public boolean canRead() {
return target.canRead();
}
@Override
public boolean canWrite() {
return target.canWrite();
}
// NOTE: equals is implemented using compareto == 0
/*
public int compareTo(File pathname) {
// TODO: Verify this
// Probably not a good idea, as it IS NOT THE SAME file
// It's probably better to not override
return target.compareTo(pathname);
}
*/
// Should probably never allow creating a new .lnk
// public boolean createNewFile() throws IOException
// Deletes only the .lnk
// public boolean delete() {
//public void deleteOnExit() {
@Override
public boolean exists() {
return target.exists();
}
// A .lnk may be absolute
//public File getAbsoluteFile() {
//public String getAbsolutePath() {
// Theses should be resolved according to the API (for Unix).
@Override
public File getCanonicalFile() throws IOException {
return target.getCanonicalFile();
}
@Override
public String getCanonicalPath() throws IOException {
return target.getCanonicalPath();
}
//public String getName() {
// I guess the parent should be the parent of the .lnk, not the target
//public String getParent() {
//public File getParentFile() {
// public boolean isAbsolute() {
@Override
public boolean isFile() {
return target.isFile();
}
@Override
public boolean isHidden() {
return target.isHidden();
}
@Override
public long lastModified() {
return target.lastModified();
}
@Override
public long length() {
return target.length();
}
@Override
public String[] list() {
return target.list();
}
@Override
public String[] list(final FilenameFilter filter) {
return target.list(filter);
}
@Override
public File[] listFiles() {
return Win32File.wrap(target.listFiles());
}
@Override
public File[] listFiles(final FileFilter filter) {
return Win32File.wrap(target.listFiles(filter));
}
@Override
public File[] listFiles(final FilenameFilter filter) {
return Win32File.wrap(target.listFiles(filter));
}
// Makes no sense, does it?
//public boolean mkdir() {
//public boolean mkdirs() {
// Only rename the lnk
//public boolean renameTo(File dest) {
@Override
public boolean setLastModified(long time) {
return target.setLastModified(time);
}
@Override
public boolean setReadOnly() {
return target.setReadOnly();
}
@Override
public String toString() {
if (target.equals(this)) {
return super.toString();
}
return super.toString() + " -> " + target.toString();
}
}
@@ -1,239 +1,240 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.DateUtil;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
/**
* Wraps a {@code Writer} in an {@code OutputStream}.
* <p/>
* <em>Instances of this class are not thread-safe.</em>
* <p/>
* <em>NOTE: This class is probably not the right way of solving your problem,
* however it might prove useful in JSPs etc.
* If possible, it's always better to use the {@code Writer}'s underlying
* {@code OutputStream}, or wrap it's native backing.
* </em>
* <p/>
*
* @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/WriterOutputStream.java#2 $
*/
public class WriterOutputStream extends OutputStream {
protected Writer writer;
final protected Decoder decoder;
final ByteArrayOutputStream bufferStream = new FastByteArrayOutputStream(1024);
private volatile boolean isFlushing = false; // Ugly but critical...
private static final boolean NIO_AVAILABLE = isNIOAvailable();
private static boolean isNIOAvailable() {
try {
Class.forName("java.nio.charset.Charset");
return true;
}
catch (Throwable t) {
// Ignore
}
return false;
}
public WriterOutputStream(final Writer pWriter, final String pCharset) {
writer = pWriter;
decoder = getDecoder(pCharset);
}
public WriterOutputStream(final Writer pWriter) {
this(pWriter, null);
}
private static Decoder getDecoder(final String pCharset) {
// NOTE: The CharsetDecoder is typically 10-20% faster than
// StringDecoder according to my tests
// StringEncoder is horribly slow on 1.2 systems, but there's no
// alternative...
if (NIO_AVAILABLE) {
return new CharsetDecoder(pCharset);
}
return new StringDecoder(pCharset);
}
@Override
public void close() throws IOException {
flush();
writer.close();
writer = null;
}
@Override
public void flush() throws IOException {
flushBuffer();
writer.flush();
}
@Override
public final void write(byte[] pBytes) throws IOException {
if (pBytes == null) {
throw new NullPointerException("bytes == null");
}
write(pBytes, 0, pBytes.length);
}
@Override
public final void write(byte[] pBytes, int pOffset, int pLength) throws IOException {
flushBuffer();
decoder.decodeTo(writer, pBytes, pOffset, pLength);
}
@Override
public final void write(int pByte) {
// TODO: Is it possible to know if this is a good place in the stream to
// flush? It might be in the middle of a multi-byte encoded character..
bufferStream.write(pByte);
}
private void flushBuffer() throws IOException {
if (!isFlushing && bufferStream.size() > 0) {
isFlushing = true;
bufferStream.writeTo(this); // NOTE: Avoids cloning buffer array
bufferStream.reset();
isFlushing = false;
}
}
///////////////////////////////////////////////////////////////////////////
public static void main(String[] pArgs) throws IOException {
int iterations = 1000000;
byte[] bytes = " klashf lkash ljah lhaaklhghdfgu ksd".getBytes("UTF-8");
Decoder d;
long start;
long time;
Writer sink = new PrintWriter(new NullOutputStream());
StringWriter writer;
String str;
d = new StringDecoder("UTF-8");
for (int i = 0; i < 10000; i++) {
d.decodeTo(sink, bytes, 0, bytes.length);
}
start = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
d.decodeTo(sink, bytes, 0, bytes.length);
}
time = DateUtil.delta(start);
System.out.println("StringDecoder");
System.out.println("time: " + time);
writer = new StringWriter();
d.decodeTo(writer, bytes, 0, bytes.length);
str = writer.toString();
System.out.println("str: \"" + str + "\"");
System.out.println("chars.length: " + str.length());
System.out.println();
if (NIO_AVAILABLE) {
d = new CharsetDecoder("UTF-8");
for (int i = 0; i < 10000; i++) {
d.decodeTo(sink, bytes, 0, bytes.length);
}
start = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
d.decodeTo(sink, bytes, 0, bytes.length);
}
time = DateUtil.delta(start);
System.out.println("CharsetDecoder");
System.out.println("time: " + time);
writer = new StringWriter();
d.decodeTo(writer, bytes, 0, bytes.length);
str = writer.toString();
System.out.println("str: \"" + str + "\"");
System.out.println("chars.length: " + str.length());
System.out.println();
}
OutputStream os = new WriterOutputStream(new PrintWriter(System.out), "UTF-8");
os.write(bytes);
os.flush();
System.out.println();
for (byte b : bytes) {
os.write(b & 0xff);
}
os.flush();
}
///////////////////////////////////////////////////////////////////////////
private static interface Decoder {
void decodeTo(Writer pWriter, byte[] pBytes, int pOffset, int pLength) throws IOException;
}
private static final class CharsetDecoder implements Decoder {
final Charset mCharset;
CharsetDecoder(String pCharset) {
// Handle null-case, to get default charset
String charset = pCharset != null ? pCharset :
System.getProperty("file.encoding", "ISO-8859-1");
mCharset = Charset.forName(charset);
}
public void decodeTo(Writer pWriter, byte[] pBytes, int pOffset, int pLength) throws IOException {
CharBuffer cb = mCharset.decode(ByteBuffer.wrap(pBytes, pOffset, pLength));
pWriter.write(cb.array(), 0, cb.length());
}
}
private static final class StringDecoder implements Decoder {
final String mCharset;
StringDecoder(String pCharset) {
mCharset = pCharset;
}
public void decodeTo(Writer pWriter, byte[] pBytes, int pOffset, int pLength) throws IOException {
String str = mCharset == null ?
new String(pBytes, pOffset, pLength) :
new String(pBytes, pOffset, pLength, mCharset);
pWriter.write(str);
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.DateUtil;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
/**
* Wraps a {@code Writer} in an {@code OutputStream}.
* <p>
* <em>Instances of this class are not thread-safe.</em>
* </p>
* <p>
* <em>NOTE: This class is probably not the right way of solving your problem,
* however it might prove useful in JSPs etc.
* If possible, it's always better to use the {@code Writer}'s underlying
* {@code OutputStream}, or wrap it's native backing.
* </em>
* </p>
*
* @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/WriterOutputStream.java#2 $
*/
public class WriterOutputStream extends OutputStream {
protected Writer writer;
final protected Decoder decoder;
final ByteArrayOutputStream bufferStream = new FastByteArrayOutputStream(1024);
private volatile boolean isFlushing = false; // Ugly but critical...
private static final boolean NIO_AVAILABLE = isNIOAvailable();
private static boolean isNIOAvailable() {
try {
Class.forName("java.nio.charset.Charset");
return true;
}
catch (Throwable t) {
// Ignore
}
return false;
}
public WriterOutputStream(final Writer pWriter, final String pCharset) {
writer = pWriter;
decoder = getDecoder(pCharset);
}
public WriterOutputStream(final Writer pWriter) {
this(pWriter, null);
}
private static Decoder getDecoder(final String pCharset) {
// NOTE: The CharsetDecoder is typically 10-20% faster than
// StringDecoder according to my tests
// StringEncoder is horribly slow on 1.2 systems, but there's no
// alternative...
if (NIO_AVAILABLE) {
return new CharsetDecoder(pCharset);
}
return new StringDecoder(pCharset);
}
@Override
public void close() throws IOException {
flush();
writer.close();
writer = null;
}
@Override
public void flush() throws IOException {
flushBuffer();
writer.flush();
}
@Override
public final void write(byte[] pBytes) throws IOException {
if (pBytes == null) {
throw new NullPointerException("bytes == null");
}
write(pBytes, 0, pBytes.length);
}
@Override
public final void write(byte[] pBytes, int pOffset, int pLength) throws IOException {
flushBuffer();
decoder.decodeTo(writer, pBytes, pOffset, pLength);
}
@Override
public final void write(int pByte) {
// TODO: Is it possible to know if this is a good place in the stream to
// flush? It might be in the middle of a multi-byte encoded character..
bufferStream.write(pByte);
}
private void flushBuffer() throws IOException {
if (!isFlushing && bufferStream.size() > 0) {
isFlushing = true;
bufferStream.writeTo(this); // NOTE: Avoids cloning buffer array
bufferStream.reset();
isFlushing = false;
}
}
///////////////////////////////////////////////////////////////////////////
public static void main(String[] pArgs) throws IOException {
int iterations = 1000000;
byte[] bytes = " klashf lkash ljah lhaaklhghdfgu ksd".getBytes("UTF-8");
Decoder d;
long start;
long time;
Writer sink = new PrintWriter(new NullOutputStream());
StringWriter writer;
String str;
d = new StringDecoder("UTF-8");
for (int i = 0; i < 10000; i++) {
d.decodeTo(sink, bytes, 0, bytes.length);
}
start = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
d.decodeTo(sink, bytes, 0, bytes.length);
}
time = DateUtil.delta(start);
System.out.println("StringDecoder");
System.out.println("time: " + time);
writer = new StringWriter();
d.decodeTo(writer, bytes, 0, bytes.length);
str = writer.toString();
System.out.println("str: \"" + str + "\"");
System.out.println("chars.length: " + str.length());
System.out.println();
if (NIO_AVAILABLE) {
d = new CharsetDecoder("UTF-8");
for (int i = 0; i < 10000; i++) {
d.decodeTo(sink, bytes, 0, bytes.length);
}
start = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
d.decodeTo(sink, bytes, 0, bytes.length);
}
time = DateUtil.delta(start);
System.out.println("CharsetDecoder");
System.out.println("time: " + time);
writer = new StringWriter();
d.decodeTo(writer, bytes, 0, bytes.length);
str = writer.toString();
System.out.println("str: \"" + str + "\"");
System.out.println("chars.length: " + str.length());
System.out.println();
}
OutputStream os = new WriterOutputStream(new PrintWriter(System.out), "UTF-8");
os.write(bytes);
os.flush();
System.out.println();
for (byte b : bytes) {
os.write(b & 0xff);
}
os.flush();
}
///////////////////////////////////////////////////////////////////////////
private static interface Decoder {
void decodeTo(Writer pWriter, byte[] pBytes, int pOffset, int pLength) throws IOException;
}
private static final class CharsetDecoder implements Decoder {
final Charset mCharset;
CharsetDecoder(String pCharset) {
// Handle null-case, to get default charset
String charset = pCharset != null ? pCharset :
System.getProperty("file.encoding", "ISO-8859-1");
mCharset = Charset.forName(charset);
}
public void decodeTo(Writer pWriter, byte[] pBytes, int pOffset, int pLength) throws IOException {
CharBuffer cb = mCharset.decode(ByteBuffer.wrap(pBytes, pOffset, pLength));
pWriter.write(cb.array(), 0, cb.length());
}
}
private static final class StringDecoder implements Decoder {
final String mCharset;
StringDecoder(String pCharset) {
mCharset = pCharset;
}
public void decodeTo(Writer pWriter, byte[] pBytes, int pOffset, int pLength) throws IOException {
String str = mCharset == null ?
new String(pBytes, pOffset, pLength) :
new String(pBytes, pOffset, pLength, mCharset);
pWriter.write(str);
}
}
}
@@ -1,188 +1,188 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* {@code Decoder} implementation for standard base64 encoding.
* <p/>
* @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421</a>
* @see <a href="http://tools.ietf.org/html/rfc2045"RFC 2045</a>
*
* @see Base64Encoder
*
* @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/enc/Base64Decoder.java#2 $
*/
public final class Base64Decoder implements Decoder {
/**
* This array maps the characters to their 6 bit values
*/
final static byte[] PEM_ARRAY = {
//0 1 2 3 4 5 6 7
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 1
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 2
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 3
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 4
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 5
'w', 'x', 'y', 'z', '0', '1', '2', '3', // 6
'4', '5', '6', '7', '8', '9', '+', '/' // 7
};
final static byte[] PEM_CONVERT_ARRAY;
private byte[] decodeBuffer = new byte[4];
static {
PEM_CONVERT_ARRAY = new byte[256];
for (int i = 0; i < 255; i++) {
PEM_CONVERT_ARRAY[i] = -1;
}
for (int i = 0; i < PEM_ARRAY.length; i++) {
PEM_CONVERT_ARRAY[PEM_ARRAY[i]] = (byte) i;
}
}
protected static int readFully(final InputStream pStream, final byte pBytes[], final int pOffset, final int pLength)
throws IOException
{
for (int i = 0; i < pLength; i++) {
int read = pStream.read();
if (read == -1) {
return i != 0 ? i : -1;
}
pBytes[i + pOffset] = (byte) read;
}
return pLength;
}
protected boolean decodeAtom(final InputStream pInput, final ByteBuffer pOutput, final int pLength)
throws IOException {
byte byte0 = -1;
byte byte1 = -1;
byte byte2 = -1;
byte byte3 = -1;
if (pLength < 2) {
throw new IOException("BASE64Decoder: Not enough bytes for an atom.");
}
int read;
// Skip line feeds
do {
read = pInput.read();
if (read == -1) {
return false;
}
} while (read == 10 || read == 13);
decodeBuffer[0] = (byte) read;
read = readFully(pInput, decodeBuffer, 1, pLength - 1);
if (read == -1) {
return false;
}
int length = pLength;
if (length > 3 && decodeBuffer[3] == 61) {
length = 3;
}
if (length > 2 && decodeBuffer[2] == 61) {
length = 2;
}
switch (length) {
case 4:
byte3 = PEM_CONVERT_ARRAY[decodeBuffer[3] & 255];
// fall through
case 3:
byte2 = PEM_CONVERT_ARRAY[decodeBuffer[2] & 255];
// fall through
case 2:
byte1 = PEM_CONVERT_ARRAY[decodeBuffer[1] & 255];
byte0 = PEM_CONVERT_ARRAY[decodeBuffer[0] & 255];
// fall through
default:
switch (length) {
case 2:
pOutput.put((byte) (byte0 << 2 & 252 | byte1 >>> 4 & 3));
break;
case 3:
pOutput.put((byte) (byte0 << 2 & 252 | byte1 >>> 4 & 3));
pOutput.put((byte) (byte1 << 4 & 240 | byte2 >>> 2 & 15));
break;
case 4:
pOutput.put((byte) (byte0 << 2 & 252 | byte1 >>> 4 & 3));
pOutput.put((byte) (byte1 << 4 & 240 | byte2 >>> 2 & 15));
pOutput.put((byte) (byte2 << 6 & 192 | byte3 & 63));
break;
}
break;
}
return true;
}
public int decode(final InputStream stream, final ByteBuffer buffer) throws IOException {
do {
int k = 72;
int i;
for (i = 0; i + 4 < k; i += 4) {
if(!decodeAtom(stream, buffer, 4)) {
break;
}
}
if (!decodeAtom(stream, buffer, k - i)) {
break;
}
}
while (buffer.remaining() > 54); // 72 char lines should produce no more than 54 bytes
return buffer.position();
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* {@code Decoder} implementation for standard base64 encoding.
*
* @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421</a>
* @see <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a>
*
* @see Base64Encoder
*
* @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/enc/Base64Decoder.java#2 $
*/
public final class Base64Decoder implements Decoder {
/**
* This array maps the characters to their 6 bit values
*/
final static byte[] PEM_ARRAY = {
//0 1 2 3 4 5 6 7
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 1
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 2
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 3
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 4
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 5
'w', 'x', 'y', 'z', '0', '1', '2', '3', // 6
'4', '5', '6', '7', '8', '9', '+', '/' // 7
};
final static byte[] PEM_CONVERT_ARRAY;
private byte[] decodeBuffer = new byte[4];
static {
PEM_CONVERT_ARRAY = new byte[256];
for (int i = 0; i < 255; i++) {
PEM_CONVERT_ARRAY[i] = -1;
}
for (int i = 0; i < PEM_ARRAY.length; i++) {
PEM_CONVERT_ARRAY[PEM_ARRAY[i]] = (byte) i;
}
}
protected static int readFully(final InputStream pStream, final byte pBytes[], final int pOffset, final int pLength)
throws IOException
{
for (int i = 0; i < pLength; i++) {
int read = pStream.read();
if (read == -1) {
return i != 0 ? i : -1;
}
pBytes[i + pOffset] = (byte) read;
}
return pLength;
}
protected boolean decodeAtom(final InputStream pInput, final ByteBuffer pOutput, final int pLength)
throws IOException {
byte byte0 = -1;
byte byte1 = -1;
byte byte2 = -1;
byte byte3 = -1;
if (pLength < 2) {
throw new IOException("BASE64Decoder: Not enough bytes for an atom.");
}
int read;
// Skip line feeds
do {
read = pInput.read();
if (read == -1) {
return false;
}
} while (read == 10 || read == 13);
decodeBuffer[0] = (byte) read;
read = readFully(pInput, decodeBuffer, 1, pLength - 1);
if (read == -1) {
return false;
}
int length = pLength;
if (length > 3 && decodeBuffer[3] == 61) {
length = 3;
}
if (length > 2 && decodeBuffer[2] == 61) {
length = 2;
}
switch (length) {
case 4:
byte3 = PEM_CONVERT_ARRAY[decodeBuffer[3] & 255];
// fall through
case 3:
byte2 = PEM_CONVERT_ARRAY[decodeBuffer[2] & 255];
// fall through
case 2:
byte1 = PEM_CONVERT_ARRAY[decodeBuffer[1] & 255];
byte0 = PEM_CONVERT_ARRAY[decodeBuffer[0] & 255];
// fall through
default:
switch (length) {
case 2:
pOutput.put((byte) (byte0 << 2 & 252 | byte1 >>> 4 & 3));
break;
case 3:
pOutput.put((byte) (byte0 << 2 & 252 | byte1 >>> 4 & 3));
pOutput.put((byte) (byte1 << 4 & 240 | byte2 >>> 2 & 15));
break;
case 4:
pOutput.put((byte) (byte0 << 2 & 252 | byte1 >>> 4 & 3));
pOutput.put((byte) (byte1 << 4 & 240 | byte2 >>> 2 & 15));
pOutput.put((byte) (byte2 << 6 & 192 | byte3 & 63));
break;
}
break;
}
return true;
}
public int decode(final InputStream stream, final ByteBuffer buffer) throws IOException {
do {
int k = 72;
int i;
for (i = 0; i + 4 < k; i += 4) {
if(!decodeAtom(stream, buffer, 4)) {
break;
}
}
if (!decodeAtom(stream, buffer, k - i)) {
break;
}
}
while (buffer.remaining() > 54); // 72 char lines should produce no more than 54 bytes
return buffer.position();
}
}
@@ -1,106 +1,106 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* {@code Encoder} implementation for standard base64 encoding.
* <p/>
* @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421</a>
* @see <a href="http://tools.ietf.org/html/rfc2045"RFC 2045</a>
*
* @see Base64Decoder
*
* @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/enc/Base64Encoder.java#2 $
*/
public class Base64Encoder implements Encoder {
public void encode(final OutputStream stream, final ByteBuffer buffer)
throws IOException
{
// TODO: Implement
// NOTE: This is impossible, given the current spec, as we need to either:
// - buffer all data in the EncoderStream
// - or have flush/end method(s) in the Encoder
// to ensure proper end of stream handling
int length;
// TODO: Temp impl, will only work for single writes
while (buffer.hasRemaining()) {
byte a, b, c;
// if ((buffer.remaining()) > 2) {
// length = 3;
// }
// else {
// length = buffer.remaining();
// }
length = Math.min(3, buffer.remaining());
switch (length) {
case 1:
a = buffer.get();
b = 0;
stream.write(Base64Decoder.PEM_ARRAY[(a >>> 2) & 0x3F]);
stream.write(Base64Decoder.PEM_ARRAY[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
stream.write('=');
stream.write('=');
break;
case 2:
a = buffer.get();
b = buffer.get();
c = 0;
stream.write(Base64Decoder.PEM_ARRAY[(a >>> 2) & 0x3F]);
stream.write(Base64Decoder.PEM_ARRAY[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
stream.write(Base64Decoder.PEM_ARRAY[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
stream.write('=');
break;
default:
a = buffer.get();
b = buffer.get();
c = buffer.get();
stream.write(Base64Decoder.PEM_ARRAY[(a >>> 2) & 0x3F]);
stream.write(Base64Decoder.PEM_ARRAY[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
stream.write(Base64Decoder.PEM_ARRAY[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
stream.write(Base64Decoder.PEM_ARRAY[c & 0x3F]);
break;
}
}
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* {@code Encoder} implementation for standard base64 encoding.
*
* @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421</a>
* @see <a href="http://tools.ietf.org/html/rfc2045">RFC 2045</a>
*
* @see Base64Decoder
*
* @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/enc/Base64Encoder.java#2 $
*/
public class Base64Encoder implements Encoder {
public void encode(final OutputStream stream, final ByteBuffer buffer)
throws IOException
{
// TODO: Implement
// NOTE: This is impossible, given the current spec, as we need to either:
// - buffer all data in the EncoderStream
// - or have flush/end method(s) in the Encoder
// to ensure proper end of stream handling
int length;
// TODO: Temp impl, will only work for single writes
while (buffer.hasRemaining()) {
byte a, b, c;
// if ((buffer.remaining()) > 2) {
// length = 3;
// }
// else {
// length = buffer.remaining();
// }
length = Math.min(3, buffer.remaining());
switch (length) {
case 1:
a = buffer.get();
b = 0;
stream.write(Base64Decoder.PEM_ARRAY[(a >>> 2) & 0x3F]);
stream.write(Base64Decoder.PEM_ARRAY[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
stream.write('=');
stream.write('=');
break;
case 2:
a = buffer.get();
b = buffer.get();
c = 0;
stream.write(Base64Decoder.PEM_ARRAY[(a >>> 2) & 0x3F]);
stream.write(Base64Decoder.PEM_ARRAY[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
stream.write(Base64Decoder.PEM_ARRAY[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
stream.write('=');
break;
default:
a = buffer.get();
b = buffer.get();
c = buffer.get();
stream.write(Base64Decoder.PEM_ARRAY[(a >>> 2) & 0x3F]);
stream.write(Base64Decoder.PEM_ARRAY[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
stream.write(Base64Decoder.PEM_ARRAY[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
stream.write(Base64Decoder.PEM_ARRAY[c & 0x3F]);
break;
}
}
}
}
@@ -1,56 +1,55 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
/**
* Thrown by {@code Decoder}s when encoded data can not be decoded.
* <p/>
*
* @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/enc/DecodeException.java#2 $
*/
public class DecodeException extends IOException {
public DecodeException(final String pMessage) {
super(pMessage);
}
public DecodeException(final String pMessage, final Throwable pCause) {
super(pMessage);
initCause(pCause);
}
public DecodeException(final Throwable pCause) {
this(pCause.getMessage(), pCause);
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
/**
* Thrown by {@code Decoder}s when encoded data can not be decoded.
*
* @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/enc/DecodeException.java#2 $
*/
public class DecodeException extends IOException {
public DecodeException(final String pMessage) {
super(pMessage);
}
public DecodeException(final String pMessage, final Throwable pCause) {
super(pMessage);
initCause(pCause);
}
public DecodeException(final Throwable pCause) {
this(pCause.getMessage(), pCause);
}
}
@@ -1,68 +1,69 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* Interface for decoders.
* A {@code Decoder} may be used with a {@code DecoderStream}, to perform
* on-the-fly decoding from an {@code InputStream}.
* <p/>
* Important note: Decoder implementations are typically not synchronized.
* <p/>
* @see Encoder
* @see DecoderStream
*
* @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/enc/Decoder.java#2 $
*/
public interface Decoder {
/**
* Decodes up to {@code buffer.length} bytes from the given input stream,
* into the given buffer.
*
* @param stream the input stream to decode data from
* @param buffer buffer to store the read data
*
* @return the total number of bytes read into the buffer, or {@code 0}
* if there is no more data because the end of the stream has been reached.
*
* @throws DecodeException if encoded data is corrupt.
* @throws IOException if an I/O error occurs.
* @throws java.io.EOFException if a premature end-of-file is encountered.
* @throws java.lang.NullPointerException if either argument is {@code null}.
*/
int decode(InputStream stream, ByteBuffer buffer) throws IOException;
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* Interface for decoders.
* A {@code Decoder} may be used with a {@code DecoderStream}, to perform
* on-the-fly decoding from an {@code InputStream}.
* <p>
* Important note: Decoder implementations are typically not synchronized.
* </p>
*
* @see Encoder
* @see DecoderStream
*
* @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/enc/Decoder.java#2 $
*/
public interface Decoder {
/**
* Decodes up to {@code buffer.length} bytes from the given input stream,
* into the given buffer.
*
* @param stream the input stream to decode data from
* @param buffer buffer to store the read data
*
* @return the total number of bytes read into the buffer, or {@code 0}
* if there is no more data because the end of the stream has been reached.
*
* @throws DecodeException if encoded data is corrupt.
* @throws IOException if an I/O error occurs.
* @throws java.io.EOFException if a premature end-of-file is encountered.
* @throws java.lang.NullPointerException if either argument is {@code null}.
*/
int decode(InputStream stream, ByteBuffer buffer) throws IOException;
}
@@ -1,200 +1,199 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* An {@code InputStream} that provides on-the-fly decoding from an underlying
* stream.
* <p/>
* @see EncoderStream
* @see Decoder
*
* @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/enc/DecoderStream.java#2 $
*/
public final class DecoderStream extends FilterInputStream {
protected final ByteBuffer buffer;
protected final Decoder decoder;
/**
* Creates a new decoder stream and chains it to the
* input stream specified by the {@code pStream} argument.
* The stream will use a default decode buffer size.
*
* @param pStream the underlying input stream.
* @param pDecoder the decoder that will be used to decode the underlying stream
*
* @see java.io.FilterInputStream#in
*/
public DecoderStream(final InputStream pStream, final Decoder pDecoder) {
// TODO: Let the decoder decide preferred buffer size
this(pStream, pDecoder, 1024);
}
/**
* Creates a new decoder stream and chains it to the
* input stream specified by the {@code pStream} argument.
*
* @param pStream the underlying input stream.
* @param pDecoder the decoder that will be used to decode the underlying stream
* @param pBufferSize the size of the decode buffer
*
* @see java.io.FilterInputStream#in
*/
public DecoderStream(final InputStream pStream, final Decoder pDecoder, final int pBufferSize) {
super(pStream);
decoder = pDecoder;
buffer = ByteBuffer.allocate(pBufferSize);
buffer.flip();
}
public int available() throws IOException {
return buffer.remaining();
}
public int read() throws IOException {
if (!buffer.hasRemaining()) {
if (fill() < 0) {
return -1;
}
}
return buffer.get() & 0xff;
}
public int read(final byte pBytes[], final int pOffset, final int pLength) throws IOException {
if (pBytes == null) {
throw new NullPointerException();
}
else if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
throw new IndexOutOfBoundsException("bytes.length=" + pBytes.length + " offset=" + pOffset + " length=" + pLength);
}
else if (pLength == 0) {
return 0;
}
// End of file?
if (!buffer.hasRemaining()) {
if (fill() < 0) {
return -1;
}
}
// Read until we have read pLength bytes, or have reached EOF
int count = 0;
int off = pOffset;
while (pLength > count) {
if (!buffer.hasRemaining()) {
if (fill() < 0) {
break;
}
}
// Copy as many bytes as possible
int dstLen = Math.min(pLength - count, buffer.remaining());
buffer.get(pBytes, off, dstLen);
// Update offset (rest)
off += dstLen;
// Increase count
count += dstLen;
}
return count;
}
public long skip(final long pLength) throws IOException {
// End of file?
if (!buffer.hasRemaining()) {
if (fill() < 0) {
return 0; // Yes, 0, not -1
}
}
// Skip until we have skipped pLength bytes, or have reached EOF
long total = 0;
while (total < pLength) {
if (!buffer.hasRemaining()) {
if (fill() < 0) {
break;
}
}
// NOTE: Skipped can never be more than avail, which is an int, so the cast is safe
int skipped = (int) Math.min(pLength - total, buffer.remaining());
buffer.position(buffer.position() + skipped);
total += skipped;
}
return total;
}
/**
* Fills the buffer, by decoding data from the underlying input stream.
*
* @return the number of bytes decoded, or {@code -1} if the end of the
* file is reached
*
* @throws IOException if an I/O error occurs
*/
protected int fill() throws IOException {
buffer.clear();
int read = decoder.decode(in, buffer);
// TODO: Enforce this in test case, leave here to aid debugging
if (read > buffer.capacity()) {
throw new AssertionError(
String.format(
"Decode beyond buffer (%d): %d (using %s decoder)",
buffer.capacity(), read, decoder.getClass().getName()
)
);
}
buffer.flip();
if (read == 0) {
return -1;
}
return read;
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* An {@code InputStream} that provides on-the-fly decoding from an underlying stream.
*
* @see EncoderStream
* @see Decoder
*
* @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/enc/DecoderStream.java#2 $
*/
public final class DecoderStream extends FilterInputStream {
private final ByteBuffer buffer;
private final Decoder decoder;
/**
* Creates a new decoder stream and chains it to the
* input stream specified by the {@code stream} argument.
* The stream will use a default decode buffer size.
*
* @param stream the underlying input stream.
* @param decoder the decoder that will be used to decode the underlying stream
*
* @see java.io.FilterInputStream#in
*/
public DecoderStream(final InputStream stream, final Decoder decoder) {
// TODO: Let the decoder decide preferred buffer size
this(stream, decoder, 1024);
}
/**
* Creates a new decoder stream and chains it to the
* input stream specified by the {@code stream} argument.
*
* @param stream the underlying input stream.
* @param decoder the decoder that will be used to decode the underlying stream
* @param bufferSize the size of the decode buffer
*
* @see java.io.FilterInputStream#in
*/
public DecoderStream(final InputStream stream, final Decoder decoder, final int bufferSize) {
super(stream);
this.decoder = decoder;
buffer = ByteBuffer.allocate(bufferSize); // TODO: Allow decoder to specify minimum buffer size
buffer.flip();
}
public int available() throws IOException {
return buffer.remaining();
}
public int read() throws IOException {
if (!buffer.hasRemaining()) {
if (fill() < 0) {
return -1;
}
}
return buffer.get() & 0xff;
}
public int read(final byte[] bytes, final int offset, final int length) throws IOException {
if (bytes == null) {
throw new NullPointerException();
}
else if ((offset < 0) || (offset > bytes.length) || (length < 0) ||
((offset + length) > bytes.length) || ((offset + length) < 0)) {
throw new IndexOutOfBoundsException("bytes.length=" + bytes.length + " offset=" + offset + " length=" + length);
}
else if (length == 0) {
return 0;
}
// End of file?
if (!buffer.hasRemaining()) {
if (fill() < 0) {
return -1;
}
}
// Read until we have read length bytes, or have reached EOF
int count = 0;
int off = offset;
while (length > count) {
if (!buffer.hasRemaining()) {
if (fill() < 0) {
break;
}
}
// Copy as many bytes as possible
int dstLen = Math.min(length - count, buffer.remaining());
buffer.get(bytes, off, dstLen);
// Update offset (rest)
off += dstLen;
// Increase count
count += dstLen;
}
return count;
}
public long skip(final long length) throws IOException {
// End of file?
if (!buffer.hasRemaining()) {
if (fill() < 0) {
return 0; // Yes, 0, not -1
}
}
// Skip until we have skipped length bytes, or have reached EOF
long total = 0;
while (total < length) {
if (!buffer.hasRemaining()) {
if (fill() < 0) {
break;
}
}
// NOTE: Skipped can never be more than avail, which is an int, so the cast is safe
int skipped = (int) Math.min(length - total, buffer.remaining());
buffer.position(buffer.position() + skipped);
total += skipped;
}
return total;
}
/**
* Fills the buffer, by decoding data from the underlying input stream.
*
* @return the number of bytes decoded, or {@code -1} if the end of the
* file is reached
*
* @throws IOException if an I/O error occurs
*/
private int fill() throws IOException {
buffer.clear();
int read = decoder.decode(in, buffer);
// TODO: Enforce this in test case, leave here to aid debugging
if (read > buffer.capacity()) {
throw new AssertionError(
String.format(
"Decode beyond buffer (%d): %d (using %s decoder)",
buffer.capacity(), read, decoder.getClass().getName()
)
);
}
buffer.flip();
if (read == 0) {
return -1;
}
return read;
}
}
@@ -1,65 +1,66 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* Interface for encoders.
* An {@code Encoder} may be used with an {@code EncoderStream}, to perform
* on-the-fly encoding to an {@code OutputStream}.
* <p/>
* Important note: Encoder implementations are typically not synchronized.
*
* @see Decoder
* @see EncoderStream
*
* @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/enc/Encoder.java#2 $
*/
public interface Encoder {
/**
* Encodes up to {@code buffer.remaining()} bytes into the given input stream,
* from the given buffer.
*
* @param stream the output stream to encode data to
* @param buffer buffer to read data from
*
* @throws java.io.IOException if an I/O error occurs
*/
void encode(OutputStream stream, ByteBuffer buffer) throws IOException;
//TODO: int requiredBufferSize(): -1 == any, otherwise, use this buffer size
// void flush()?
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* Interface for encoders.
* An {@code Encoder} may be used with an {@code EncoderStream}, to perform
* on-the-fly encoding to an {@code OutputStream}.
* <p>
* Important note: Encoder implementations are typically not synchronized.
* </p>
*
* @see Decoder
* @see EncoderStream
*
* @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/enc/Encoder.java#2 $
*/
public interface Encoder {
/**
* Encodes up to {@code buffer.remaining()} bytes into the given input stream,
* from the given buffer.
*
* @param stream the output stream to encode data to
* @param buffer buffer to read data from
*
* @throws java.io.IOException if an I/O error occurs
*/
void encode(OutputStream stream, ByteBuffer buffer) throws IOException;
//TODO: int requiredBufferSize(): -1 == any, otherwise, use this buffer size
// void flush()?
}
@@ -1,137 +1,134 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* An {@code OutputStream} that provides on-the-fly encoding to an underlying
* stream.
* <p/>
* @see DecoderStream
* @see Encoder
*
* @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/enc/EncoderStream.java#2 $
*/
public final class EncoderStream extends FilterOutputStream {
// TODO: This class need a test case ASAP!!!
protected final Encoder encoder;
private final boolean flushOnWrite;
protected final ByteBuffer buffer;
/**
* Creates an output stream filter built on top of the specified
* underlying output stream.
*
* @param pStream the underlying output stream
* @param pEncoder the encoder to use
*/
public EncoderStream(final OutputStream pStream, final Encoder pEncoder) {
this(pStream, pEncoder, false);
}
/**
* Creates an output stream filter built on top of the specified
* underlying output stream.
*
* @param pStream the underlying output stream
* @param pEncoder the encoder to use
* @param pFlushOnWrite if {@code true}, calls to the byte-array
* {@code write} methods will automatically flush the buffer.
*/
public EncoderStream(final OutputStream pStream, final Encoder pEncoder, final boolean pFlushOnWrite) {
super(pStream);
encoder = pEncoder;
flushOnWrite = pFlushOnWrite;
buffer = ByteBuffer.allocate(1024);
buffer.flip();
}
public void close() throws IOException {
flush();
super.close();
}
public void flush() throws IOException {
encodeBuffer();
super.flush();
}
private void encodeBuffer() throws IOException {
if (buffer.position() != 0) {
buffer.flip();
// Make sure all remaining data in buffer is written to the stream
encoder.encode(out, buffer);
// Reset buffer
buffer.clear();
}
}
public final void write(final byte[] pBytes) throws IOException {
write(pBytes, 0, pBytes.length);
}
// TODO: Verify that this works for the general case (it probably won't)...
// TODO: We might need a way to explicitly flush the encoder, or specify
// that the encoder can't buffer. In that case, the encoder should probably
// tell the EncoderStream how large buffer it prefers...
public void write(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (!flushOnWrite && pLength < buffer.remaining()) {
// Buffer data
buffer.put(pBytes, pOffset, pLength);
}
else {
// Encode data already in the buffer
encodeBuffer();
// Encode rest without buffering
encoder.encode(out, ByteBuffer.wrap(pBytes, pOffset, pLength));
}
}
public void write(final int pByte) throws IOException {
if (!buffer.hasRemaining()) {
encodeBuffer(); // Resets bufferPos to 0
}
buffer.put((byte) pByte);
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* An {@code OutputStream} that provides on-the-fly encoding to an underlying stream.
*
* @see DecoderStream
* @see Encoder
*
* @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/enc/EncoderStream.java#2 $
*/
public final class EncoderStream extends FilterOutputStream {
private final Encoder encoder;
private final boolean flushOnWrite;
private final ByteBuffer buffer;
/**
* Creates an output stream filter built on top of the specified
* underlying output stream.
*
* @param stream the underlying output stream
* @param encoder the encoder to use
*/
public EncoderStream(final OutputStream stream, final Encoder encoder) {
this(stream, encoder, false);
}
/**
* Creates an output stream filter built on top of the specified
* underlying output stream.
*
* @param stream the underlying output stream
* @param encoder the encoder to use
* @param flushOnWrite if {@code true}, calls to the byte-array
* {@code write} methods will automatically flush the buffer.
*/
public EncoderStream(final OutputStream stream, final Encoder encoder, final boolean flushOnWrite) {
super(stream);
this.encoder = encoder;
this.flushOnWrite = flushOnWrite;
buffer = ByteBuffer.allocate(1024);
}
public void close() throws IOException {
flush();
super.close();
}
public void flush() throws IOException {
encodeBuffer();
super.flush();
}
private void encodeBuffer() throws IOException {
if (buffer.position() != 0) {
buffer.flip();
// Make sure all remaining data in buffer is written to the stream
encoder.encode(out, buffer);
// Reset buffer
buffer.clear();
}
}
public void write(final byte[] bytes) throws IOException {
write(bytes, 0, bytes.length);
}
// TODO: Verify that this works for the general case (it probably won't)...
// TODO: We might need a way to explicitly flush the encoder, or specify
// that the encoder can't buffer. In that case, the encoder should probably
// tell the EncoderStream how large buffer it prefers...
public void write(final byte[] values, final int offset, final int length) throws IOException {
if (!flushOnWrite && length < buffer.remaining()) {
// Buffer data
buffer.put(values, offset, length);
}
else {
// Encode data already in the buffer
encodeBuffer();
// Encode rest without buffering
encoder.encode(out, ByteBuffer.wrap(values, offset, length));
}
}
public void write(final int value) throws IOException {
if (!buffer.hasRemaining()) {
encodeBuffer(); // Resets bufferPos to 0
}
buffer.put((byte) value);
}
}
@@ -1,210 +1,194 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* Decoder implementation for Apple PackBits run-length encoding.
* <p/>
* <small>From Wikipedia, the free encyclopedia</small><br/>
* PackBits is a fast, simple compression scheme for run-length encoding of
* data.
* <p/>
* Apple introduced the PackBits format with the release of MacPaint on the
* Macintosh computer. This compression scheme is one of the types of
* compression that can be used in TIFF-files.
* <p/>
* A PackBits data stream consists of packets of one byte of header followed by
* data. The header is a signed byte; the data can be signed, unsigned, or
* packed (such as MacPaint pixels).
* <p/>
* <table><tr><th>Header byte</th><th>Data</th></tr>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in
* the decompressed output</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr></table>
* <p/>
* Note that interpreting 0 as positive or negative makes no difference in the
* output. Runs of two bytes adjacent to non-runs are typically written as
* literal data.
* <p/>
* See <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a>
*
* @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/enc/PackBitsDecoder.java#1 $
*/
public final class PackBitsDecoder implements Decoder {
// TODO: Look at ICNSImageReader#unpackbits... What is this weirdness?
private final boolean disableNoOp;
private final byte[] sample;
private int leftOfRun;
private boolean splitRun;
private boolean reachedEOF;
/** Creates a {@code PackBitsDecoder}. */
public PackBitsDecoder() {
this(1, false);
}
/**
* Creates a {@code PackBitsDecoder}, with optional compatibility mode.
* <p/>
* As some implementations of PackBits-like encoders treat {@code -128} as length of
* a compressed run, instead of a no-op, it's possible to disable no-ops for compatibility.
* Should be used with caution, even though, most known encoders never write no-ops in the compressed streams.
*
* @param disableNoOp {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
public PackBitsDecoder(final boolean disableNoOp) {
this(1, disableNoOp);
}
/**
* Creates a {@code PackBitsDecoder}, with optional compatibility mode.
* <p/>
* As some implementations of PackBits-like encoders treat {@code -128} as length of
* a compressed run, instead of a no-op, it's possible to disable no-ops for compatibility.
* Should be used with caution, even though, most known encoders never write no-ops in the compressed streams.
*
* @param disableNoOp {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
public PackBitsDecoder(int sampleSize, final boolean disableNoOp) {
this.sample = new byte[sampleSize];
this.disableNoOp = disableNoOp;
}
/**
* Decodes bytes from the given input stream, to the given buffer.
*
* @param stream the stream to decode from
* @param buffer a byte array, minimum 128 (or 129 if no-op is disabled) bytes long
* @return The number of bytes decoded
*
* @throws java.io.IOException
*/
public int decode(final InputStream stream, final ByteBuffer buffer) throws IOException {
if (reachedEOF) {
return -1;
}
// TODO: Don't decode more than single runs, because some writers add pad bytes inside the stream...
while (buffer.hasRemaining()) {
int n;
if (splitRun) {
// Continue run
n = leftOfRun;
splitRun = false;
}
else {
// Start new run
int b = stream.read();
if (b < 0) {
reachedEOF = true;
break;
}
n = (byte) b;
}
// Split run at or before max
if (n >= 0 && n + 1 > buffer.remaining()) {
leftOfRun = n;
splitRun = true;
break;
}
else if (n < 0 && -n + 1 > buffer.remaining()) {
leftOfRun = n;
splitRun = true;
break;
}
try {
if (n >= 0) {
// Copy next n + 1 bytes literally
readFully(stream, buffer, sample.length * (n + 1));
}
// Allow -128 for compatibility, see above
else if (disableNoOp || n != -128) {
// Replicate the next byte -n + 1 times
for (int s = 0; s < sample.length; s++) {
sample[s] = readByte(stream);
}
for (int i = -n + 1; i > 0; i--) {
buffer.put(sample);
}
}
// else NOOP (-128)
}
catch (IndexOutOfBoundsException e) {
throw new DecodeException("Error in PackBits decompression, data seems corrupt", e);
}
}
return buffer.position();
}
static byte readByte(final InputStream pStream) throws IOException {
int read = pStream.read();
if (read < 0) {
throw new EOFException("Unexpected end of PackBits stream");
}
return (byte) read;
}
static void readFully(final InputStream pStream, final ByteBuffer pBuffer, final int pLength) throws IOException {
if (pLength < 0) {
throw new IndexOutOfBoundsException(String.format("Negative length: %d", pLength));
}
int total = 0;
while (total < pLength) {
int count = pStream.read(pBuffer.array(), pBuffer.arrayOffset() + pBuffer.position() + total, pLength - total);
if (count < 0) {
throw new EOFException("Unexpected end of PackBits stream");
}
total += count;
}
pBuffer.position(pBuffer.position() + total);
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
/**
* Decoder implementation for Apple PackBits run-length encoding.
* <p>
* <small>From Wikipedia, the free encyclopedia</small>
* <br>
* PackBits is a fast, simple compression scheme for run-length encoding of
* data.
* </p>
* <p>
* Apple introduced the PackBits format with the release of MacPaint on the
* Macintosh computer. This compression scheme is one of the types of
* compression that can be used in TIFF-files.
* </p>
* <p>
* A PackBits data stream consists of packets of one byte of header followed by
* data. The header is a signed byte; the data can be signed, unsigned, or
* packed (such as MacPaint pixels).
* </p>
* <table>
* <caption>PackBits</caption>
* <tr><th>Header byte</th><th>Data</th></tr>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in the decompressed output</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr>
* </table>
* <p>
* Note that interpreting 0 as positive or negative makes no difference in the
* output. Runs of two bytes adjacent to non-runs are typically written as
* literal data.
* </p>
*
* @see <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a>
*
* @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/enc/PackBitsDecoder.java#1 $
*/
public final class PackBitsDecoder implements Decoder {
// TODO: Look at ICNSImageReader#unpackbits... What is this weirdness?
private final boolean disableNoOp;
private final byte[] sample;
private boolean reachedEOF;
/** Creates a {@code PackBitsDecoder}. */
public PackBitsDecoder() {
this(1, false);
}
/**
* Creates a {@code PackBitsDecoder}, with optional compatibility mode.
* <p>
* As some implementations of PackBits-like encoders treat {@code -128} as length of
* a compressed run, instead of a no-op, it's possible to disable no-ops for compatibility.
* Should be used with caution, even though, most known encoders never write no-ops in the compressed streams.
* </p>
*
* @param disableNoOp {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
public PackBitsDecoder(final boolean disableNoOp) {
this(1, disableNoOp);
}
/**
* Creates a {@code PackBitsDecoder}, with optional compatibility mode.
* <p>
* As some implementations of PackBits-like encoders treat {@code -128} as length of
* a compressed run, instead of a no-op, it's possible to disable no-ops for compatibility.
* Should be used with caution, even though, most known encoders never write no-ops in the compressed streams.
* </p>
*
* @param disableNoOp {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
public PackBitsDecoder(int sampleSize, final boolean disableNoOp) {
this.sample = new byte[sampleSize];
this.disableNoOp = disableNoOp;
}
/**
* Decodes bytes from the given input stream, to the given buffer.
*
* @param stream the stream to decode from
* @param buffer a byte array, minimum 128 (or 129 if no-op is disabled) bytes long
* @return The number of bytes decoded
*
* @throws java.io.IOException if a problem occurs during decoding.
*/
public int decode(final InputStream stream, final ByteBuffer buffer) throws IOException {
if (reachedEOF) {
return -1;
}
// NOTE: We don't decode more than single runs, because some writers add pad bytes inside the stream...
// Start new run
int b = stream.read();
if (b < 0) {
reachedEOF = true;
return 0;
}
int n = (byte) b;
try {
if (n >= 0) {
// Copy next n + 1 bytes literally
readFully(stream, buffer, sample.length * (n + 1));
}
// Allow -128 for compatibility, see above
else if (disableNoOp || n != -128) {
// Replicate the next byte -n + 1 times
for (int s = 0; s < sample.length; s++) {
sample[s] = readByte(stream);
}
for (int i = -n + 1; i > 0; i--) {
buffer.put(sample);
}
}
// else NOOP (-128)
}
catch (IndexOutOfBoundsException e) {
throw new DecodeException("Error in PackBits decompression, data seems corrupt", e);
}
return buffer.position();
}
static byte readByte(final InputStream pStream) throws IOException {
int read = pStream.read();
if (read < 0) {
throw new EOFException("Unexpected end of PackBits stream");
}
return (byte) read;
}
static void readFully(final InputStream pStream, final ByteBuffer pBuffer, final int pLength) throws IOException {
if (pLength < 0) {
throw new IndexOutOfBoundsException(String.format("Negative length: %d", pLength));
}
int total = 0;
while (total < pLength) {
int count = pStream.read(pBuffer.array(), pBuffer.arrayOffset() + pBuffer.position() + total, pLength - total);
if (count < 0) {
throw new EOFException("Unexpected end of PackBits stream");
}
total += count;
}
pBuffer.position(pBuffer.position() + total);
}
}
@@ -1,132 +1,138 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* Encoder implementation for Apple PackBits run-length encoding.
* <p/>
* From Wikipedia, the free encyclopedia<br/>
* PackBits is a fast, simple compression scheme for run-length encoding of
* data.
* <p/>
* Apple introduced the PackBits format with the release of MacPaint on the
* Macintosh computer. This compression scheme is one of the types of
* compression that can be used in TIFF-files.
* <p/>
* A PackBits data stream consists of packets of one byte of header followed by
* data. The header is a signed byte; the data can be signed, unsigned, or
* packed (such as MacPaint pixels).
* <p/>
* <table><tr><th>Header byte</th><th>Data</th></tr>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in
* the decompressed output</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr></table>
* <p/>
* Note that interpreting 0 as positive or negative makes no difference in the
* output. Runs of two bytes adjacent to non-runs are typically written as
* literal data.
* <p/>
* See <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a>
*
* @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/enc/PackBitsEncoder.java#1 $
*/
public final class PackBitsEncoder implements Encoder {
final private byte[] buffer = new byte[128];
/**
* Creates a {@code PackBitsEncoder}.
*/
public PackBitsEncoder() {
}
public void encode(final OutputStream stream, final ByteBuffer buffer) throws IOException {
encode(stream, buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
buffer.position(buffer.remaining());
}
private void encode(OutputStream pStream, byte[] pBuffer, int pOffset, int pLength) throws IOException {
// NOTE: It's best to encode a 2 byte repeat
// run as a replicate run except when preceded and followed by a
// literal run, in which case it's best to merge the three into one
// literal run. Always encode 3 byte repeats as replicate runs.
// NOTE: Worst case: output = input + (input + 127) / 128
int offset = pOffset;
final int max = pOffset + pLength - 1;
final int maxMinus1 = max - 1;
while (offset <= max) {
// Compressed run
int run = 1;
byte replicate = pBuffer[offset];
while (run < 127 && offset < max && pBuffer[offset] == pBuffer[offset + 1]) {
offset++;
run++;
}
if (run > 1) {
offset++;
pStream.write(-(run - 1));
pStream.write(replicate);
}
// Literal run
run = 0;
while ((run < 128 && ((offset < max && pBuffer[offset] != pBuffer[offset + 1])
|| (offset < maxMinus1 && pBuffer[offset] != pBuffer[offset + 2])))) {
buffer[run++] = pBuffer[offset++];
}
// If last byte, include it in literal run, if space
if (offset == max && run > 0 && run < 128) {
buffer[run++] = pBuffer[offset++];
}
if (run > 0) {
pStream.write(run - 1);
pStream.write(buffer, 0, run);
}
// If last byte, and not space, start new literal run
if (offset == max && (run <= 0 || run >= 128)) {
pStream.write(0);
pStream.write(pBuffer[offset++]);
}
}
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* Encoder implementation for Apple PackBits run-length encoding.
* <p>
* From Wikipedia, the free encyclopedia
* <br>
* PackBits is a fast, simple compression scheme for run-length encoding of
* data.
* </p>
* <p>
* Apple introduced the PackBits format with the release of MacPaint on the
* Macintosh computer. This compression scheme is one of the types of
* compression that can be used in TIFF-files.
* </p>
* <p>
* A PackBits data stream consists of packets of one byte of header followed by
* data. The header is a signed byte; the data can be signed, unsigned, or
* packed (such as MacPaint pixels).
* </p>
* <table>
* <caption>PackBits</caption>
* <tr><th>Header byte</th><th>Data</th></tr>
* <tr><td>0 to 127</td> <td>1 + <i>n</i> literal bytes of data</td></tr>
* <tr><td>0 to -127</td> <td>One byte of data, repeated 1 - <i>n</i> times in the decompressed output</td></tr>
* <tr><td>-128</td> <td>No operation</td></tr>
* </table>
* <p>
* Note that interpreting 0 as positive or negative makes no difference in the
* output. Runs of two bytes adjacent to non-runs are typically written as
* literal data.
* </p>
*
* @see <a href="http://developer.apple.com/technotes/tn/tn1023.html">Understanding PackBits</a>
*
* @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/enc/PackBitsEncoder.java#1 $
*/
public final class PackBitsEncoder implements Encoder {
final private byte[] buffer = new byte[128];
/**
* Creates a {@code PackBitsEncoder}.
*/
public PackBitsEncoder() {
}
public void encode(final OutputStream stream, final ByteBuffer buffer) throws IOException {
encode(stream, buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
buffer.position(buffer.remaining());
}
private void encode(OutputStream pStream, byte[] pBuffer, int pOffset, int pLength) throws IOException {
// NOTE: It's best to encode a 2 byte repeat
// run as a replicate run except when preceded and followed by a
// literal run, in which case it's best to merge the three into one
// literal run. Always encode 3 byte repeats as replicate runs.
// NOTE: Worst case: output = input + (input + 127) / 128
int offset = pOffset;
final int max = pOffset + pLength - 1;
final int maxMinus1 = max - 1;
while (offset <= max) {
// Compressed run
int run = 1;
byte replicate = pBuffer[offset];
while (run < 127 && offset < max && pBuffer[offset] == pBuffer[offset + 1]) {
offset++;
run++;
}
if (run > 1) {
offset++;
pStream.write(-(run - 1));
pStream.write(replicate);
}
// Literal run
run = 0;
while ((run < 128 && ((offset < max && pBuffer[offset] != pBuffer[offset + 1])
|| (offset < maxMinus1 && pBuffer[offset] != pBuffer[offset + 2])))) {
buffer[run++] = pBuffer[offset++];
}
// If last byte, include it in literal run, if space
if (offset == max && run > 0 && run < 128) {
buffer[run++] = pBuffer[offset++];
}
if (run > 0) {
pStream.write(run - 1);
pStream.write(buffer, 0, run);
}
// If last byte, and not space, start new literal run
if (offset == max && (run <= 0 || run >= 128)) {
pStream.write(0);
pStream.write(pBuffer[offset++]);
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,342 +1,344 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.ole2;
import com.twelvemonkeys.io.SeekableInputStream;
import java.io.DataInput;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* Represents an OLE 2 compound document entry.
* This is similar to a file in a file system, or an entry in a ZIP or JAR file.
*
* @author <a href="mailto:harald.kuhr@gmail.no">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/ole2/Entry.java#4 $
* @see com.twelvemonkeys.io.ole2.CompoundDocument
*/
// TODO: Consider extending java.io.File...
public final class Entry implements Comparable<Entry> {
String name;
byte type;
byte nodeColor;
int prevDId;
int nextDId;
int rootNodeDId;
long createdTimestamp;
long modifiedTimestamp;
int startSId;
int streamSize;
CompoundDocument document;
Entry parent;
SortedSet<Entry> children;
public final static int LENGTH = 128;
static final int EMPTY = 0;
static final int USER_STORAGE = 1;
static final int USER_STREAM = 2;
static final int LOCK_BYTES = 3;
static final int PROPERTY = 4;
static final int ROOT_STORAGE = 5;
private static final SortedSet<Entry> NO_CHILDREN = Collections.unmodifiableSortedSet(new TreeSet<Entry>());
private Entry() {
}
/**
* Reads an entry from the input.
*
* @param pInput the input data
* @return the {@code Entry} read from the input data
* @throws IOException if an i/o exception occurs during reading
*/
static Entry readEntry(final DataInput pInput) throws IOException {
Entry p = new Entry();
p.read(pInput);
return p;
}
/**
* Reads this entry
*
* @param pInput the input data
* @throws IOException if an i/o exception occurs during reading
*/
private void read(final DataInput pInput) throws IOException {
byte[] bytes = new byte[64];
pInput.readFully(bytes);
// NOTE: Length is in bytes, including the null-terminator...
int nameLength = pInput.readShort();
name = new String(bytes, 0, nameLength - 2, Charset.forName("UTF-16LE"));
// System.out.println("name: " + name);
type = pInput.readByte();
// System.out.println("type: " + type);
nodeColor = pInput.readByte();
// System.out.println("nodeColor: " + nodeColor);
prevDId = pInput.readInt();
// System.out.println("prevDId: " + prevDId);
nextDId = pInput.readInt();
// System.out.println("nextDId: " + nextDId);
rootNodeDId = pInput.readInt();
// System.out.println("rootNodeDId: " + rootNodeDId);
// UID (16) + user flags (4), ignored
if (pInput.skipBytes(20) != 20) {
throw new CorruptDocumentException();
}
createdTimestamp = CompoundDocument.toJavaTimeInMillis(pInput.readLong());
modifiedTimestamp = CompoundDocument.toJavaTimeInMillis(pInput.readLong());
startSId = pInput.readInt();
// System.out.println("startSId: " + startSId);
streamSize = pInput.readInt();
// System.out.println("streamSize: " + streamSize);
// Reserved
pInput.readInt();
}
/**
* If {@code true} this {@code Entry} is the root {@code Entry}.
*
* @return {@code true} if this is the root {@code Entry}
*/
public boolean isRoot() {
return type == ROOT_STORAGE;
}
/**
* If {@code true} this {@code Entry} is a directory
* {@code Entry}.
*
* @return {@code true} if this is a directory {@code Entry}
*/
public boolean isDirectory() {
return type == USER_STORAGE;
}
/**
* If {@code true} this {@code Entry} is a file (document)
* {@code Entry}.
*
* @return {@code true} if this is a document {@code Entry}
*/
public boolean isFile() {
return type == USER_STREAM;
}
/**
* Returns the name of this {@code Entry}
*
* @return the name of this {@code Entry}
*/
public String getName() {
return name;
}
/**
* Returns the {@code InputStream} for this {@code Entry}
*
* @return an {@code InputStream} containing the data for this
* {@code Entry} or {@code null} if this is a directory {@code Entry}
* @throws java.io.IOException if an I/O exception occurs
* @see #length()
*/
public SeekableInputStream getInputStream() throws IOException {
if (!isFile()) {
return null;
}
return document.getInputStreamForSId(startSId, streamSize);
}
/**
* Returns the length of this entry
*
* @return the length of the stream for this entry, or {@code 0} if this is
* a directory {@code Entry}
* @see #getInputStream()
*/
public long length() {
if (!isFile()) {
return 0L;
}
return streamSize;
}
/**
* Returns the time that this entry was created.
* The time is converted from its internal representation to standard Java
* representation, milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970).
* <p/>
* Note that most applications leaves this value empty ({@code 0L}).
*
* @return A {@code long} value representing the time this entry was
* created, measured in milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970), or {@code 0L} if no
* creation time stamp exists for this entry.
*/
public long created() {
return createdTimestamp;
}
/**
* Returns the time that this entry was last modified.
* The time is converted from its internal representation to standard Java
* representation, milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970).
* <p/>
* Note that many applications leaves this value empty ({@code 0L}).
*
* @return A {@code long} value representing the time this entry was
* last modified, measured in milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970), or {@code 0L} if no
* modification time stamp exists for this entry.
*/
public long lastModified() {
return modifiedTimestamp;
}
/**
* Return the parent of this {@code Entry}
*
* @return the parent of this {@code Entry}, or {@code null} if this is
* the root {@code Entry}
*/
public Entry getParentEntry() {
return parent;
}
/**
* Returns the child of this {@code Entry} with the given name.
*
* @param pName the name of the child {@code Entry}
* @return the child {@code Entry} or {@code null} if thee is no such
* child
* @throws java.io.IOException if an I/O exception occurs
*/
public Entry getChildEntry(final String pName) throws IOException {
if (isFile() || rootNodeDId == -1) {
return null;
}
Entry dummy = new Entry();
dummy.name = pName;
dummy.parent = this;
SortedSet child = getChildEntries().tailSet(dummy);
return (Entry) child.first();
}
/**
* Returns the children of this {@code Entry}.
*
* @return a {@code SortedSet} of {@code Entry} objects
* @throws java.io.IOException if an I/O exception occurs
*/
public SortedSet<Entry> getChildEntries() throws IOException {
if (children == null) {
if (isFile() || rootNodeDId == -1) {
children = NO_CHILDREN;
}
else {
// Start at root node in R/B tree, and read to the left and right,
// re-build tree, according to the docs
children = Collections.unmodifiableSortedSet(document.getEntries(rootNodeDId, this));
}
}
return children;
}
@Override
public String toString() {
return "\"" + name + "\""
+ " (" + (isFile() ? "Document" : (isDirectory() ? "Directory" : "Root"))
+ (parent != null ? ", parent: \"" + parent.getName() + "\"" : "")
+ (isFile() ? "" : ", children: " + (children != null ? String.valueOf(children.size()) : "(unknown)"))
+ ", SId=" + startSId + ", length=" + streamSize + ")";
}
@Override
public boolean equals(final Object pOther) {
if (pOther == this) {
return true;
}
if (!(pOther instanceof Entry)) {
return false;
}
Entry other = (Entry) pOther;
return name.equals(other.name) && (parent == other.parent
|| (parent != null && parent.equals(other.parent)));
}
@Override
public int hashCode() {
return name.hashCode() ^ startSId;
}
public int compareTo(final Entry pOther) {
if (this == pOther) {
return 0;
}
// NOTE: This is the sorting algorthm defined by the Compound Document:
// - first sort by name length
// - if lengths are equal, sort by comparing strings, case sensitive
int diff = name.length() - pOther.name.length();
if (diff != 0) {
return diff;
}
return name.compareTo(pOther.name);
}
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.ole2;
import com.twelvemonkeys.io.SeekableInputStream;
import java.io.DataInput;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* Represents an OLE 2 compound document entry.
* This is similar to a file in a file system, or an entry in a ZIP or JAR file.
*
* @author <a href="mailto:harald.kuhr@gmail.no">Harald Kuhr</a>
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/ole2/Entry.java#4 $
* @see com.twelvemonkeys.io.ole2.CompoundDocument
*/
// TODO: Consider extending java.io.File...
public final class Entry implements Comparable<Entry> {
String name;
byte type;
byte nodeColor;
int prevDId;
int nextDId;
int rootNodeDId;
long createdTimestamp;
long modifiedTimestamp;
int startSId;
int streamSize;
CompoundDocument document;
Entry parent;
SortedSet<Entry> children;
public final static int LENGTH = 128;
static final int EMPTY = 0;
static final int USER_STORAGE = 1;
static final int USER_STREAM = 2;
static final int LOCK_BYTES = 3;
static final int PROPERTY = 4;
static final int ROOT_STORAGE = 5;
private static final SortedSet<Entry> NO_CHILDREN = Collections.unmodifiableSortedSet(new TreeSet<Entry>());
private Entry() {
}
/**
* Reads an entry from the input.
*
* @param pInput the input data
* @return the {@code Entry} read from the input data
* @throws IOException if an i/o exception occurs during reading
*/
static Entry readEntry(final DataInput pInput) throws IOException {
Entry p = new Entry();
p.read(pInput);
return p;
}
/**
* Reads this entry
*
* @param pInput the input data
* @throws IOException if an i/o exception occurs during reading
*/
private void read(final DataInput pInput) throws IOException {
byte[] bytes = new byte[64];
pInput.readFully(bytes);
// NOTE: Length is in bytes, including the null-terminator...
int nameLength = pInput.readShort();
name = new String(bytes, 0, nameLength - 2, Charset.forName("UTF-16LE"));
// System.out.println("name: " + name);
type = pInput.readByte();
// System.out.println("type: " + type);
nodeColor = pInput.readByte();
// System.out.println("nodeColor: " + nodeColor);
prevDId = pInput.readInt();
// System.out.println("prevDId: " + prevDId);
nextDId = pInput.readInt();
// System.out.println("nextDId: " + nextDId);
rootNodeDId = pInput.readInt();
// System.out.println("rootNodeDId: " + rootNodeDId);
// UID (16) + user flags (4), ignored
if (pInput.skipBytes(20) != 20) {
throw new CorruptDocumentException();
}
createdTimestamp = CompoundDocument.toJavaTimeInMillis(pInput.readLong());
modifiedTimestamp = CompoundDocument.toJavaTimeInMillis(pInput.readLong());
startSId = pInput.readInt();
// System.out.println("startSId: " + startSId);
streamSize = pInput.readInt();
// System.out.println("streamSize: " + streamSize);
// Reserved
pInput.readInt();
}
/**
* If {@code true} this {@code Entry} is the root {@code Entry}.
*
* @return {@code true} if this is the root {@code Entry}
*/
public boolean isRoot() {
return type == ROOT_STORAGE;
}
/**
* If {@code true} this {@code Entry} is a directory
* {@code Entry}.
*
* @return {@code true} if this is a directory {@code Entry}
*/
public boolean isDirectory() {
return type == USER_STORAGE;
}
/**
* If {@code true} this {@code Entry} is a file (document)
* {@code Entry}.
*
* @return {@code true} if this is a document {@code Entry}
*/
public boolean isFile() {
return type == USER_STREAM;
}
/**
* Returns the name of this {@code Entry}
*
* @return the name of this {@code Entry}
*/
public String getName() {
return name;
}
/**
* Returns the {@code InputStream} for this {@code Entry}
*
* @return an {@code InputStream} containing the data for this
* {@code Entry} or {@code null} if this is a directory {@code Entry}
* @throws java.io.IOException if an I/O exception occurs
* @see #length()
*/
public SeekableInputStream getInputStream() throws IOException {
if (!isFile()) {
return null;
}
return document.getInputStreamForSId(startSId, streamSize);
}
/**
* Returns the length of this entry
*
* @return the length of the stream for this entry, or {@code 0} if this is
* a directory {@code Entry}
* @see #getInputStream()
*/
public long length() {
if (!isFile()) {
return 0L;
}
return streamSize;
}
/**
* Returns the time that this entry was created.
* The time is converted from its internal representation to standard Java
* representation, milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970).
* <p>
* Note that most applications leaves this value empty ({@code 0L}).
* </p>
*
* @return A {@code long} value representing the time this entry was
* created, measured in milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970), or {@code 0L} if no
* creation time stamp exists for this entry.
*/
public long created() {
return createdTimestamp;
}
/**
* Returns the time that this entry was last modified.
* The time is converted from its internal representation to standard Java
* representation, milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970).
* <p>
* Note that many applications leaves this value empty ({@code 0L}).
* </p>
*
* @return A {@code long} value representing the time this entry was
* last modified, measured in milliseconds since the epoch
* (00:00:00 GMT, January 1, 1970), or {@code 0L} if no
* modification time stamp exists for this entry.
*/
public long lastModified() {
return modifiedTimestamp;
}
/**
* Return the parent of this {@code Entry}
*
* @return the parent of this {@code Entry}, or {@code null} if this is
* the root {@code Entry}
*/
public Entry getParentEntry() {
return parent;
}
/**
* Returns the child of this {@code Entry} with the given name.
*
* @param pName the name of the child {@code Entry}
* @return the child {@code Entry} or {@code null} if thee is no such
* child
* @throws java.io.IOException if an I/O exception occurs
*/
public Entry getChildEntry(final String pName) throws IOException {
if (isFile() || rootNodeDId == -1) {
return null;
}
Entry dummy = new Entry();
dummy.name = pName;
dummy.parent = this;
SortedSet child = getChildEntries().tailSet(dummy);
return (Entry) child.first();
}
/**
* Returns the children of this {@code Entry}.
*
* @return a {@code SortedSet} of {@code Entry} objects
* @throws java.io.IOException if an I/O exception occurs
*/
public SortedSet<Entry> getChildEntries() throws IOException {
if (children == null) {
if (isFile() || rootNodeDId == -1) {
children = NO_CHILDREN;
}
else {
// Start at root node in R/B tree, and read to the left and right,
// re-build tree, according to the docs
children = Collections.unmodifiableSortedSet(document.getEntries(rootNodeDId, this));
}
}
return children;
}
@Override
public String toString() {
return "\"" + name + "\""
+ " (" + (isFile() ? "Document" : (isDirectory() ? "Directory" : "Root"))
+ (parent != null ? ", parent: \"" + parent.getName() + "\"" : "")
+ (isFile() ? "" : ", children: " + (children != null ? String.valueOf(children.size()) : "(unknown)"))
+ ", SId=" + startSId + ", length=" + streamSize + ")";
}
@Override
public boolean equals(final Object pOther) {
if (pOther == this) {
return true;
}
if (!(pOther instanceof Entry)) {
return false;
}
Entry other = (Entry) pOther;
return name.equals(other.name) && (parent == other.parent
|| (parent != null && parent.equals(other.parent)));
}
@Override
public int hashCode() {
return name.hashCode() ^ startSId;
}
public int compareTo(final Entry pOther) {
if (this == pOther) {
return 0;
}
// NOTE: This is the sorting algorthm defined by the Compound Document:
// - first sort by name length
// - if lengths are equal, sort by comparing strings, case sensitive
int diff = name.length() - pOther.name.length();
if (diff != 0) {
return diff;
}
return name.compareTo(pOther.name);
}
}
@@ -1,314 +1,313 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.net;
import com.twelvemonkeys.lang.StringUtil;
import com.twelvemonkeys.lang.SystemUtil;
import java.io.IOException;
import java.util.*;
/**
* Contains mappings from file extension to mime-types and from mime-type to file-types.
* <p/>
*
* @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/net/MIMEUtil.java#5 $
*
* @see <A href="http://www.iana.org/assignments/media-types/">MIME Media Types</A>
*/
public final class MIMEUtil {
// TODO: Piggy-back on the mappings form the JRE? (1.6 comes with javax.activation)
// TODO: Piggy-back on mappings from javax.activation?
// See: http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/activation/MimetypesFileTypeMap.html
// See: http://java.sun.com/javase/6/docs/api/javax/activation/MimetypesFileTypeMap.html
// TODO: Use the format (and lookup) specified by the above URLs
// TODO: Allow 3rd party to add mappings? Will need application context support to do it safe.. :-P
private static Map<String, List<String>> sExtToMIME = new HashMap<String, List<String>>();
private static Map<String, List<String>> sUnmodifiableExtToMIME = Collections.unmodifiableMap(sExtToMIME);
private static Map<String, List<String>> sMIMEToExt = new HashMap<String, List<String>>();
private static Map<String, List<String>> sUnmodifiableMIMEToExt = Collections.unmodifiableMap(sMIMEToExt);
static {
// Load mapping for MIMEUtil
try {
Properties mappings = SystemUtil.loadProperties(MIMEUtil.class);
for (Map.Entry entry : mappings.entrySet()) {
// Convert and break up extensions and mimeTypes
String extStr = StringUtil.toLowerCase((String) entry.getKey());
List<String> extensions =
Collections.unmodifiableList(Arrays.asList(StringUtil.toStringArray(extStr, ";, ")));
String typeStr = StringUtil.toLowerCase((String) entry.getValue());
List<String> mimeTypes =
Collections.unmodifiableList(Arrays.asList(StringUtil.toStringArray(typeStr, ";, ")));
// TODO: Handle duplicates in MIME to extension mapping, like
// xhtml=application/xhtml+xml;application/xml
// xml=text/xml;application/xml
// Populate normal and reverse MIME-mappings
for (String extension : extensions) {
sExtToMIME.put(extension, mimeTypes);
}
for (String mimeType : mimeTypes) {
sMIMEToExt.put(mimeType, extensions);
}
}
}
catch (IOException e) {
System.err.println("Could not read properties for MIMEUtil: " + e.getMessage());
e.printStackTrace();
}
}
// Disallow construction
private MIMEUtil() {
}
/**
* Returns the default MIME type for the given file extension.
*
* @param pFileExt the file extension
*
* @return a {@code String} containing the MIME type, or {@code null} if
* there are no known MIME types for the given file extension.
*/
public static String getMIMEType(final String pFileExt) {
List<String> types = sExtToMIME.get(StringUtil.toLowerCase(pFileExt));
return (types == null || types.isEmpty()) ? null : types.get(0);
}
/**
* Returns all MIME types for the given file extension.
*
* @param pFileExt the file extension
*
* @return a {@link List} of {@code String}s containing the MIME types, or an empty
* list, if there are no known MIME types for the given file extension.
*/
public static List<String> getMIMETypes(final String pFileExt) {
List<String> types = sExtToMIME.get(StringUtil.toLowerCase(pFileExt));
return maskNull(types);
}
/**
* Returns an unmodifiabale {@link Map} view of the extension to
* MIME mapping, to use as the default mapping in client applications.
*
* @return an unmodifiabale {@code Map} view of the extension to
* MIME mapping.
*/
public static Map<String, List<String>> getMIMETypeMappings() {
return sUnmodifiableExtToMIME;
}
/**
* Returns the default file extension for the given MIME type.
* Specifying a wildcard type will return {@code null}.
*
* @param pMIME the MIME type
*
* @return a {@code String} containing the file extension, or {@code null}
* if there are no known file extensions for the given MIME type.
*/
public static String getExtension(final String pMIME) {
String mime = bareMIME(StringUtil.toLowerCase(pMIME));
List<String> extensions = sMIMEToExt.get(mime);
return (extensions == null || extensions.isEmpty()) ? null : extensions.get(0);
}
/**
* Returns all file extension for the given MIME type.
* The default extension will be the first in the list.
* Note that no specific order is given for wildcard types (image/*, *&#47;* etc).
*
* @param pMIME the MIME type
*
* @return a {@link List} of {@code String}s containing the MIME types, or an empty
* list, if there are no known file extensions for the given MIME type.
*/
public static List<String> getExtensions(final String pMIME) {
String mime = bareMIME(StringUtil.toLowerCase(pMIME));
if (mime.endsWith("/*")) {
return getExtensionForWildcard(mime);
}
List<String> extensions = sMIMEToExt.get(mime);
return maskNull(extensions);
}
// Gets all extensions for a wildcard MIME type
private static List<String> getExtensionForWildcard(final String pMIME) {
final String family = pMIME.substring(0, pMIME.length() - 1);
Set<String> extensions = new LinkedHashSet<String>();
for (Map.Entry<String, List<String>> mimeToExt : sMIMEToExt.entrySet()) {
if ("*/".equals(family) || mimeToExt.getKey().startsWith(family)) {
extensions.addAll(mimeToExt.getValue());
}
}
return Collections.unmodifiableList(new ArrayList<String>(extensions));
}
/**
* Returns an unmodifiabale {@link Map} view of the MIME to
* extension mapping, to use as the default mapping in client applications.
*
* @return an unmodifiabale {@code Map} view of the MIME to
* extension mapping.
*/
public static Map<String, List<String>> getExtensionMappings() {
return sUnmodifiableMIMEToExt;
}
/**
* Tests wehter the type is a subtype of the type family.
*
* @param pTypeFamily the MIME type family ({@code image/*, *&#47;*}, etc)
* @param pType the MIME type
* @return {@code true} if {@code pType} is a subtype of {@code pTypeFamily}, otherwise {@code false}
*/
// TODO: Rename? isSubtype?
// TODO: Make public
static boolean includes(final String pTypeFamily, final String pType) {
// TODO: Handle null in a well-defined way
// - Is null family same as */*?
// - Is null subtype of any family? Subtype of no family?
String type = bareMIME(pType);
return type.equals(pTypeFamily)
|| "*/*".equals(pTypeFamily)
|| pTypeFamily.endsWith("/*") && pTypeFamily.startsWith(type.substring(0, type.indexOf('/')));
}
/**
* Removes any charset or extra info from the mime-type string (anything after a semicolon, {@code ;}, inclusive).
*
* @param pMIME the mime-type string
* @return the bare mime-type
*/
public static String bareMIME(final String pMIME) {
int idx;
if (pMIME != null && (idx = pMIME.indexOf(';')) >= 0) {
return pMIME.substring(0, idx);
}
return pMIME;
}
// Returns the list or empty list if list is null
private static List<String> maskNull(List<String> pTypes) {
return (pTypes == null) ? Collections.<String>emptyList() : pTypes;
}
/**
* For debugging. Prints all known MIME types and file extensions.
*
* @param pArgs command line arguments
*/
public static void main(String[] pArgs) {
if (pArgs.length > 1) {
String type = pArgs[0];
String family = pArgs[1];
boolean incuded = includes(family, type);
System.out.println(
"Mime type family " + family
+ (incuded ? " includes " : " does not include ")
+ "type " + type
);
}
if (pArgs.length > 0) {
String str = pArgs[0];
if (str.indexOf('/') >= 0) {
// MIME
String extension = getExtension(str);
System.out.println("Default extension for MIME type '" + str + "' is "
+ (extension != null ? ": '" + extension + "'" : "unknown") + ".");
System.out.println("All possible: " + getExtensions(str));
}
else {
// EXT
String mimeType = getMIMEType(str);
System.out.println("Default MIME type for extension '" + str + "' is "
+ (mimeType != null ? ": '" + mimeType + "'" : "unknown") + ".");
System.out.println("All possible: " + getMIMETypes(str));
}
return;
}
Set set = sMIMEToExt.keySet();
String[] mimeTypes = new String[set.size()];
int i = 0;
for (Iterator iterator = set.iterator(); iterator.hasNext(); i++) {
String mime = (String) iterator.next();
mimeTypes[i] = mime;
}
Arrays.sort(mimeTypes);
System.out.println("Known MIME types (" + mimeTypes.length + "):");
for (int j = 0; j < mimeTypes.length; j++) {
String mimeType = mimeTypes[j];
if (j != 0) {
System.out.print(", ");
}
System.out.print(mimeType);
}
System.out.println("\n");
set = sExtToMIME.keySet();
String[] extensions = new String[set.size()];
i = 0;
for (Iterator iterator = set.iterator(); iterator.hasNext(); i++) {
String ext = (String) iterator.next();
extensions[i] = ext;
}
Arrays.sort(extensions);
System.out.println("Known file types (" + extensions.length + "):");
for (int j = 0; j < extensions.length; j++) {
String extension = extensions[j];
if (j != 0) {
System.out.print(", ");
}
System.out.print(extension);
}
System.out.println();
}
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.net;
import com.twelvemonkeys.lang.StringUtil;
import com.twelvemonkeys.lang.SystemUtil;
import java.io.IOException;
import java.util.*;
/**
* Contains mappings from file extension to mime-types and from mime-type to file-types.
*
* @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/net/MIMEUtil.java#5 $
*
* @see <A href="http://www.iana.org/assignments/media-types/">MIME Media Types</A>
*/
public final class MIMEUtil {
// TODO: Piggy-back on the mappings form the JRE? (1.6 comes with javax.activation)
// TODO: Piggy-back on mappings from javax.activation?
// See: http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/activation/MimetypesFileTypeMap.html
// See: http://java.sun.com/javase/6/docs/api/javax/activation/MimetypesFileTypeMap.html
// TODO: Use the format (and lookup) specified by the above URLs
// TODO: Allow 3rd party to add mappings? Will need application context support to do it safe.. :-P
private static Map<String, List<String>> sExtToMIME = new HashMap<String, List<String>>();
private static Map<String, List<String>> sUnmodifiableExtToMIME = Collections.unmodifiableMap(sExtToMIME);
private static Map<String, List<String>> sMIMEToExt = new HashMap<String, List<String>>();
private static Map<String, List<String>> sUnmodifiableMIMEToExt = Collections.unmodifiableMap(sMIMEToExt);
static {
// Load mapping for MIMEUtil
try {
Properties mappings = SystemUtil.loadProperties(MIMEUtil.class);
for (Map.Entry entry : mappings.entrySet()) {
// Convert and break up extensions and mimeTypes
String extStr = StringUtil.toLowerCase((String) entry.getKey());
List<String> extensions =
Collections.unmodifiableList(Arrays.asList(StringUtil.toStringArray(extStr, ";, ")));
String typeStr = StringUtil.toLowerCase((String) entry.getValue());
List<String> mimeTypes =
Collections.unmodifiableList(Arrays.asList(StringUtil.toStringArray(typeStr, ";, ")));
// TODO: Handle duplicates in MIME to extension mapping, like
// xhtml=application/xhtml+xml;application/xml
// xml=text/xml;application/xml
// Populate normal and reverse MIME-mappings
for (String extension : extensions) {
sExtToMIME.put(extension, mimeTypes);
}
for (String mimeType : mimeTypes) {
sMIMEToExt.put(mimeType, extensions);
}
}
}
catch (IOException e) {
System.err.println("Could not read properties for MIMEUtil: " + e.getMessage());
e.printStackTrace();
}
}
// Disallow construction
private MIMEUtil() {
}
/**
* Returns the default MIME type for the given file extension.
*
* @param pFileExt the file extension
*
* @return a {@code String} containing the MIME type, or {@code null} if
* there are no known MIME types for the given file extension.
*/
public static String getMIMEType(final String pFileExt) {
List<String> types = sExtToMIME.get(StringUtil.toLowerCase(pFileExt));
return (types == null || types.isEmpty()) ? null : types.get(0);
}
/**
* Returns all MIME types for the given file extension.
*
* @param pFileExt the file extension
*
* @return a {@link List} of {@code String}s containing the MIME types, or an empty
* list, if there are no known MIME types for the given file extension.
*/
public static List<String> getMIMETypes(final String pFileExt) {
List<String> types = sExtToMIME.get(StringUtil.toLowerCase(pFileExt));
return maskNull(types);
}
/**
* Returns an unmodifiabale {@link Map} view of the extension to
* MIME mapping, to use as the default mapping in client applications.
*
* @return an unmodifiabale {@code Map} view of the extension to
* MIME mapping.
*/
public static Map<String, List<String>> getMIMETypeMappings() {
return sUnmodifiableExtToMIME;
}
/**
* Returns the default file extension for the given MIME type.
* Specifying a wildcard type will return {@code null}.
*
* @param pMIME the MIME type
*
* @return a {@code String} containing the file extension, or {@code null}
* if there are no known file extensions for the given MIME type.
*/
public static String getExtension(final String pMIME) {
String mime = bareMIME(StringUtil.toLowerCase(pMIME));
List<String> extensions = sMIMEToExt.get(mime);
return (extensions == null || extensions.isEmpty()) ? null : extensions.get(0);
}
/**
* Returns all file extension for the given MIME type.
* The default extension will be the first in the list.
* Note that no specific order is given for wildcard types (image/*, *&#47;* etc).
*
* @param pMIME the MIME type
*
* @return a {@link List} of {@code String}s containing the MIME types, or an empty
* list, if there are no known file extensions for the given MIME type.
*/
public static List<String> getExtensions(final String pMIME) {
String mime = bareMIME(StringUtil.toLowerCase(pMIME));
if (mime.endsWith("/*")) {
return getExtensionForWildcard(mime);
}
List<String> extensions = sMIMEToExt.get(mime);
return maskNull(extensions);
}
// Gets all extensions for a wildcard MIME type
private static List<String> getExtensionForWildcard(final String pMIME) {
final String family = pMIME.substring(0, pMIME.length() - 1);
Set<String> extensions = new LinkedHashSet<String>();
for (Map.Entry<String, List<String>> mimeToExt : sMIMEToExt.entrySet()) {
if ("*/".equals(family) || mimeToExt.getKey().startsWith(family)) {
extensions.addAll(mimeToExt.getValue());
}
}
return Collections.unmodifiableList(new ArrayList<String>(extensions));
}
/**
* Returns an unmodifiabale {@link Map} view of the MIME to
* extension mapping, to use as the default mapping in client applications.
*
* @return an unmodifiabale {@code Map} view of the MIME to
* extension mapping.
*/
public static Map<String, List<String>> getExtensionMappings() {
return sUnmodifiableMIMEToExt;
}
/**
* Tests wehter the type is a subtype of the type family.
*
* @param pTypeFamily the MIME type family ({@code image/*, *&#47;*}, etc)
* @param pType the MIME type
* @return {@code true} if {@code pType} is a subtype of {@code pTypeFamily}, otherwise {@code false}
*/
// TODO: Rename? isSubtype?
// TODO: Make public
static boolean includes(final String pTypeFamily, final String pType) {
// TODO: Handle null in a well-defined way
// - Is null family same as */*?
// - Is null subtype of any family? Subtype of no family?
String type = bareMIME(pType);
return type.equals(pTypeFamily)
|| "*/*".equals(pTypeFamily)
|| pTypeFamily.endsWith("/*") && pTypeFamily.startsWith(type.substring(0, type.indexOf('/')));
}
/**
* Removes any charset or extra info from the mime-type string (anything after a semicolon, {@code ;}, inclusive).
*
* @param pMIME the mime-type string
* @return the bare mime-type
*/
public static String bareMIME(final String pMIME) {
int idx;
if (pMIME != null && (idx = pMIME.indexOf(';')) >= 0) {
return pMIME.substring(0, idx);
}
return pMIME;
}
// Returns the list or empty list if list is null
private static List<String> maskNull(List<String> pTypes) {
return (pTypes == null) ? Collections.<String>emptyList() : pTypes;
}
/**
* For debugging. Prints all known MIME types and file extensions.
*
* @param pArgs command line arguments
*/
public static void main(String[] pArgs) {
if (pArgs.length > 1) {
String type = pArgs[0];
String family = pArgs[1];
boolean incuded = includes(family, type);
System.out.println(
"Mime type family " + family
+ (incuded ? " includes " : " does not include ")
+ "type " + type
);
}
if (pArgs.length > 0) {
String str = pArgs[0];
if (str.indexOf('/') >= 0) {
// MIME
String extension = getExtension(str);
System.out.println("Default extension for MIME type '" + str + "' is "
+ (extension != null ? ": '" + extension + "'" : "unknown") + ".");
System.out.println("All possible: " + getExtensions(str));
}
else {
// EXT
String mimeType = getMIMEType(str);
System.out.println("Default MIME type for extension '" + str + "' is "
+ (mimeType != null ? ": '" + mimeType + "'" : "unknown") + ".");
System.out.println("All possible: " + getMIMETypes(str));
}
return;
}
Set set = sMIMEToExt.keySet();
String[] mimeTypes = new String[set.size()];
int i = 0;
for (Iterator iterator = set.iterator(); iterator.hasNext(); i++) {
String mime = (String) iterator.next();
mimeTypes[i] = mime;
}
Arrays.sort(mimeTypes);
System.out.println("Known MIME types (" + mimeTypes.length + "):");
for (int j = 0; j < mimeTypes.length; j++) {
String mimeType = mimeTypes[j];
if (j != 0) {
System.out.print(", ");
}
System.out.print(mimeType);
}
System.out.println("\n");
set = sExtToMIME.keySet();
String[] extensions = new String[set.size()];
i = 0;
for (Iterator iterator = set.iterator(); iterator.hasNext(); i++) {
String ext = (String) iterator.next();
extensions[i] = ext;
}
Arrays.sort(extensions);
System.out.println("Known file types (" + extensions.length + "):");
for (int j = 0; j < extensions.length; j++) {
String extension = extensions[j];
if (j != 0) {
System.out.print(", ");
}
System.out.print(extension);
}
System.out.println();
}
}
@@ -29,6 +29,9 @@
package com.twelvemonkeys.xml;
import java.io.OutputStream;
import java.io.Writer;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMImplementationList;
import org.w3c.dom.Document;
@@ -38,9 +41,6 @@ import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import java.io.OutputStream;
import java.io.Writer;
/**
* {@code DOMImplementationLS} backed implementation.
*
@@ -88,22 +88,12 @@ public final class DOMSerializer {
output.setCharacterStream(pStream);
}
/*
// TODO: Is it useful?
public void setNewLine(final String pNewLine) {
serializer.setNewLine(pNewLine);
}
public String getNewLine() {
return serializer.getNewLine();
}
*/
/**
* Specifies wether the serializer should use indentation and optimize for
* readability.
* <p/>
* Note: This is a hint, and may be ignored by DOM implemenations.
* <p>
* Note: This is a hint, and may be ignored by DOM implementations.
* </p>
*
* @param pPrettyPrint {@code true} to enable pretty printing
*/
@@ -168,13 +158,7 @@ public final class DOMSerializer {
try {
return DOMImplementationRegistry.newInstance();
}
catch (ClassNotFoundException e) {
throw new IllegalStateException(e);
}
catch (InstantiationException e) {
throw new IllegalStateException(e);
}
catch (IllegalAccessException e) {
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
+23 -15
View File
@@ -30,16 +30,23 @@
package com.twelvemonkeys.xml;
import com.twelvemonkeys.lang.StringUtil;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.Date;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.nio.charset.Charset;
import java.util.Date;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import com.twelvemonkeys.lang.StringUtil;
/**
* XMLSerializer
@@ -290,7 +297,7 @@ public class XMLSerializer {
}
private static int appendAndEscape(final String pString, int pStart, final int pEnd, final StringBuilder pBuilder, final String pEntity) {
pBuilder.append(pString.substring(pStart, pEnd));
pBuilder.append(pString, pStart, pEnd);
pBuilder.append(pEntity);
return pEnd + 1;
}
@@ -389,9 +396,10 @@ public class XMLSerializer {
private void writeDocument(final PrintWriter pOut, final Node pNode, final SerializationContext pContext) {
// Document fragments might not have child nodes...
if (pNode.hasChildNodes()) {
NodeList nodes = pNode.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
writeNodeRecursive(pOut, nodes.item(i), pContext);
Node child = pNode.getFirstChild();
while (child != null) {
writeNodeRecursive(pOut, child, pContext);
child = child.getNextSibling();
}
}
}
@@ -448,9 +456,10 @@ public class XMLSerializer {
pOut.println();
}
NodeList children = pNode.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
writeNodeRecursive(pOut, children.item(i), pContext.push());
Node child = pNode.getFirstChild();
while (child != null) {
writeNodeRecursive(pOut, child, pContext.push());
child = child.getNextSibling();
}
if (!pContext.preserveSpace) {
@@ -525,8 +534,7 @@ public class XMLSerializer {
builder = factory.newDocumentBuilder();
}
catch (ParserConfigurationException e) {
//noinspection ThrowableInstanceNeverThrown BOGUS
throw (IOException) new IOException(e.getMessage()).initCause(e);
throw new IOException(e);
}
DOMImplementation dom = builder.getDOMImplementation();
@@ -32,7 +32,6 @@ package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.StringUtil;
import com.twelvemonkeys.util.CollectionUtil;
import org.junit.Test;
import java.io.IOException;
import java.io.Reader;
@@ -40,7 +39,8 @@ import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* CompoundReaderTestCase
@@ -30,12 +30,11 @@
package com.twelvemonkeys.io;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import static org.junit.Assert.assertEquals;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* FastByteArrayOutputStreamTestCase
@@ -30,11 +30,10 @@
package com.twelvemonkeys.io;
import org.junit.Test;
import java.io.*;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* MemoryCacheSeekableStreamTestCase
@@ -92,13 +91,13 @@ public class FileSeekableStreamTest extends SeekableInputStreamAbstractTest {
try {
FileUtil.read(stream); // Read until EOF
assertEquals("EOF not reached (test case broken)", -1, stream.read());
assertFalse("Underlying stream closed before close", closed[0]);
assertEquals(-1, stream.read(), "EOF not reached (test case broken)");
assertFalse(closed[0], "Underlying stream closed before close");
}
finally {
stream.close();
}
assertTrue("Underlying stream not closed", closed[0]);
assertTrue(closed[0], "Underlying stream not closed");
}
}
@@ -46,14 +46,14 @@
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.ObjectAbstractTest;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* InputStreamAbstractTestCase
@@ -104,15 +104,15 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
int size = 5;
InputStream input = makeInputStream(makeOrderedArray(size));
for (int i = 0; i < size; i++) {
assertTrue("Check Size [" + i + "]", (size - i) >= input.available());
assertEquals("Check Value [" + i + "]", i, input.read());
assertTrue((size - i) >= input.available(), "Check Size [" + i + "]");
assertEquals(i, input.read(), "Check Value [" + i + "]");
}
assertEquals("Available after contents all read", 0, input.available());
assertEquals(0, input.available(), "Available after contents all read");
// Test reading after the end of file
try {
int result = input.read();
assertEquals("Wrong value read after end of file", -1, result);
assertEquals( -1, result, "Wrong value read after end of file");
}
catch (IOException e) {
fail("Should not have thrown an IOException: " + e.getMessage());
@@ -122,12 +122,12 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
@Test
public void testAvailable() throws Exception {
InputStream input = makeInputStream(1);
assertFalse("Unexpected EOF", input.read() < 0);
assertEquals("Available after contents all read", 0, input.available());
assertFalse(input.read() < 0, "Unexpected EOF");
assertEquals(0, input.available(), "Available after contents all read");
// Check availbale is zero after End of file
assertEquals("End of File", -1, input.read());
assertEquals("Available after End of File", 0, input.available());
assertEquals(-1, input.read(), "End of File");
assertEquals( 0, input.available(), "Available after End of File");
}
@Test
@@ -138,26 +138,26 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
// Read into array
int count1 = input.read(bytes);
assertEquals("Read 1", bytes.length, count1);
assertEquals(bytes.length, count1, "Read 1");
for (int i = 0; i < count1; i++) {
assertEquals("Check Bytes 1", i, bytes[i]);
assertEquals(i, bytes[i], "Check Bytes 1");
}
// Read into array
int count2 = input.read(bytes);
assertEquals("Read 2", 5, count2);
assertEquals(5, count2, "Read 2");
for (int i = 0; i < count2; i++) {
assertEquals("Check Bytes 2", count1 + i, bytes[i]);
assertEquals(count1 + i, bytes[i], "Check Bytes 2");
}
// End of File
int count3 = input.read(bytes);
assertEquals("Read 3 (EOF)", -1, count3);
assertEquals(-1, count3, "Read 3 (EOF)");
// Test reading after the end of file
try {
int result = input.read(bytes);
assertEquals("Wrong value read after end of file", -1, result);
assertEquals(-1, result, "Wrong value read after end of file");
}
catch (IOException e) {
fail("Should not have thrown an IOException: " + e.getMessage());
@@ -170,20 +170,20 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
int offset = 2;
int lth = 4;
int count5 = input.read(bytes, offset, lth);
assertEquals("Read 5", lth, count5);
assertEquals(lth, count5, "Read 5");
for (int i = offset; i < lth; i++) {
assertEquals("Check Bytes 2", i - offset, bytes[i]);
assertEquals(i - offset, bytes[i], "Check Bytes 2");
}
}
@Test
public void testEOF() throws Exception {
InputStream input = makeInputStream(makeOrderedArray(2));
assertEquals("Read 1", 0, input.read());
assertEquals("Read 2", 1, input.read());
assertEquals("Read 3", -1, input.read());
assertEquals("Read 4", -1, input.read());
assertEquals("Read 5", -1, input.read());
assertEquals(0, input.read(), "Read 1");
assertEquals(1, input.read(), "Read 2");
assertEquals(-1, input.read(), "Read 3");
assertEquals(-1, input.read(), "Read 4");
assertEquals(-1, input.read(), "Read 5");
}
@Test
@@ -205,7 +205,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
fail("Should throw IOException");
}
catch (IOException e) {
assertTrue("Wrong messge: " + e.getMessage(), e.getMessage().contains("reset"));
assertTrue(e.getMessage().contains("reset"), "Wrong messge: " + e.getMessage());
}
}
@@ -223,10 +223,10 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
// No mark may either throw exception, or reset to beginning of stream.
try {
input.reset();
assertEquals("Re-read of reset data should be same", 0, input.read());
assertEquals(0, input.read(), "Re-read of reset data should be same");
}
catch (Exception e) {
assertTrue("Wrong no mark IOException message", e.getMessage().contains("mark"));
assertTrue(e.getMessage().contains("mark"), "Wrong no mark IOException message");
}
}
@@ -249,7 +249,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
// Read further
for (int i = 0; i < 3; i++) {
assertEquals("Read After Mark [" + i + "]", (position + i), input.read());
assertEquals((position + i), input.read(), "Read After Mark [" + i + "]");
}
// Reset
@@ -257,7 +257,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
// Read from marked position
for (int i = 0; i < readlimit + 1; i++) {
assertEquals("Read After Reset [" + i + "]", (position + i), input.read());
assertEquals((position + i), input.read(), "Read After Reset [" + i + "]");
}
}
@@ -280,16 +280,16 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
// Read past marked position
for (int i = 0; i < readlimit + 1; i++) {
assertEquals("Read After Reset [" + i + "]", (position + i), input.read());
assertEquals((position + i), input.read(), "Read After Reset [" + i + "]");
}
// Reset after read limit passed, may either throw exception, or reset to last mark
try {
input.reset();
assertEquals("Re-read of reset data should be same", 1, input.read());
assertEquals(1, input.read(), "Re-read of reset data should be same");
}
catch (Exception e) {
assertTrue("Wrong read-limit IOException message", e.getMessage().contains("mark"));
assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message");
}
}
@@ -302,29 +302,29 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
}
int first = input.read();
assertTrue("Expected to read positive value", first >= 0);
assertTrue(first >= 0, "Expected to read positive value");
int readlimit = 5;
// Mark
input.mark(readlimit);
int read = input.read();
assertTrue("Expected to read positive value", read >= 0);
assertTrue(read >= 0, "Expected to read positive value");
assertTrue(input.read() >= 0);
assertTrue(input.read() >= 0);
input.reset();
assertEquals("Expected value read differs from actual", read, input.read());
assertEquals(read, input.read(), "Expected value read differs from actual");
// Reset after read limit passed, may either throw exception, or reset to last good mark
try {
input.reset();
int reRead = input.read();
assertTrue("Re-read of reset data should be same as initially marked or first", reRead == read || reRead == first);
assertTrue(reRead == read || reRead == first, "Re-read of reset data should be same as initially marked or first");
}
catch (Exception e) {
assertTrue("Wrong read-limit IOException message", e.getMessage().contains("mark"));
assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message");
}
}
@@ -332,17 +332,17 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
public void testSkip() throws Exception {
InputStream input = makeInputStream(makeOrderedArray(10));
assertEquals("Unexpected value read", 0, input.read());
assertEquals("Unexpected value read", 1, input.read());
assertEquals("Unexpected number of bytes skipped", 5, input.skip(5));
assertEquals("Unexpected value read", 7, input.read());
assertEquals(0, input.read(), "Unexpected value read");
assertEquals(1, input.read(), "Unexpected value read");
assertEquals(5, input.skip(5), "Unexpected number of bytes skipped");
assertEquals(7, input.read(), "Unexpected value read");
assertEquals("Unexpected number of bytes skipped", 2, input.skip(5)); // only 2 left to skip
assertEquals("Unexpected value read after EOF", -1, input.read());
assertEquals(2, input.skip(5), "Unexpected number of bytes skipped"); // only 2 left to skip
assertEquals(-1, input.read(), "Unexpected value read after EOF");
// Spec says skip might return 0 or negative after EOF...
assertTrue("Positive value skipped after EOF", input.skip(5) <= 0); // End of file
assertEquals("Unexpected value read after EOF", -1, input.read());
assertTrue(input.skip(5) <= 0, "Positive value skipped after EOF"); // End of file
assertEquals(-1, input.read(), "Unexpected value read after EOF");
}
@Test
@@ -30,12 +30,11 @@
package com.twelvemonkeys.io;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* LittleEndianDataInputStreamTest
@@ -31,13 +31,12 @@
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.ObjectAbstractTest;
import org.junit.Test;
import java.io.IOException;
import java.io.OutputStream;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* InputStreamAbstractTestCase
@@ -31,12 +31,12 @@
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.ObjectAbstractTest;
import org.junit.Test;
import java.io.IOException;
import java.io.Reader;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* ReaderAbstractTestCase
@@ -112,7 +112,7 @@ public abstract class ReaderAbstractTest extends ObjectAbstractTest {
int toSkip = mInput.length();
while (toSkip > 0) {
long skipped = reader.skip(toSkip);
assertFalse("Skipped < 0", skipped < 0);
assertFalse(skipped < 0, "Skipped < 0");
toSkip -= skipped;
}
@@ -30,10 +30,8 @@
package com.twelvemonkeys.io;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* SeekableAbstractTestCase
@@ -30,14 +30,13 @@
package com.twelvemonkeys.io;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* SeekableInputStreamAbstractTest
@@ -79,25 +78,25 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
return; // Not supported, skip test
}
assertTrue("Expected to read positive value", input.read() >= 0);
assertTrue(input.read() >= 0, "Expected to read positive value");
int readlimit = 5;
// Mark
input.mark(readlimit);
int read = input.read();
assertTrue("Expected to read positive value", read >= 0);
assertTrue(read >= 0, "Expected to read positive value");
input.reset();
assertEquals("Expected value read differs from actual", read, input.read());
assertEquals(read, input.read(), "Expected value read differs from actual");
// Reset after read limit passed, may either throw exception, or reset to last good mark
try {
input.reset();
assertEquals("Re-read of reset data should be first", 0, input.read());
assertEquals(0, input.read(), "Re-read of reset data should be first");
}
catch (Exception e) {
assertTrue("Wrong read-limit IOException message", e.getMessage().contains("mark"));
assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message");
}
}
@@ -127,7 +126,7 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
seekable.seek(pos);
long streamPos = seekable.getStreamPosition();
assertEquals("Stream positon should match seeked position", pos, streamPos);
assertEquals(pos, streamPos, "Stream positon should match seeked position");
}
@Test
@@ -137,7 +136,7 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
seekable.seek(pos);
seekable.flushBefore(pos);
long flushedPos = seekable.getFlushedPosition();
assertEquals("Flushed positon should match position", pos, flushedPos);
assertEquals(pos, flushedPos, "Flushed positon should match position");
try {
seekable.seek(pos - 1);
@@ -382,13 +381,13 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
int val;
val = stream.read();
assertFalse("Unexepected EOF", val == -1);
assertFalse(val == -1, "Unexepected EOF");
val = stream.read();
assertFalse("Unexepected EOF", val == -1);
assertFalse(val == -1, "Unexepected EOF");
val = stream.read();
assertFalse("Unexepected EOF", val == -1);
assertFalse(val == -1, "Unexepected EOF");
val = stream.read();
assertFalse("Unexepected EOF", val == -1);
assertFalse(val == -1, "Unexepected EOF");
stream.seek(0);
@@ -422,19 +421,19 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
stream.seek(0);
for (int i = 0; i < bytes.length; i += 2) {
assertEquals("Wrong stream position", i, stream.getStreamPosition());
assertEquals(i, stream.getStreamPosition(), "Wrong stream position");
int count = stream.read(buffer, 0, 2);
assertEquals(2, count);
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i], buffer[0]);
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i + 1], buffer[1]);
assertEquals(bytes[i], buffer[0], String.format("Wrong value read at pos %d", stream.getStreamPosition()));
assertEquals(bytes[i + 1], buffer[1], String.format("Wrong value read at pos %d", stream.getStreamPosition()));
}
stream.seek(0);
for (int i = 0; i < bytes.length; i++) {
assertEquals("Wrong stream position", i, stream.getStreamPosition());
assertEquals(i, stream.getStreamPosition(), "Wrong stream position");
int actual = stream.read();
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i] & 0xff, actual);
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i], (byte) actual);
assertEquals(bytes[i] & 0xff, actual, String.format("Wrong value read at pos %d", stream.getStreamPosition()));
assertEquals(bytes[i], (byte) actual, String.format("Wrong value read at pos %d", stream.getStreamPosition()));
}
}
@@ -456,14 +455,14 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
try {
FileUtil.read(stream); // Read until EOF
assertEquals("EOF not reached (test case broken)", -1, stream.read());
assertFalse("Underlying stream closed before close", closed[0]);
assertEquals(-1, stream.read(), "EOF not reached (test case broken)");
assertFalse(closed[0], "Underlying stream closed before close");
}
finally {
stream.close();
}
assertTrue("Underlying stream not closed", closed[0]);
assertTrue(closed[0], "Underlying stream not closed");
}
@@ -31,12 +31,12 @@
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.StringUtil;
import org.junit.Test;
import java.io.IOException;
import java.io.Reader;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* StringArrayReaderTestCase
@@ -0,0 +1,119 @@
package com.twelvemonkeys.io;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.Arrays;
import java.util.Random;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* 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
public void testCreateNullStream() {
assertThrows(IllegalArgumentException.class, () -> {
new SubStream(null, 42);
});
}
@Test
public void testCreateNegativeLength() {
assertThrows(IllegalArgumentException.class, () -> {
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
public void testCloseConsumesAllShortStream() throws IOException {
assertTimeoutPreemptively(Duration.ofMillis(500), () -> {
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[13]);
try (InputStream ignore = new SubStream(stream, 42)) {
// Nothing here...
}
assertEquals(0, stream.available());
assertEquals(-1, stream.read());
});
}
}
@@ -31,15 +31,13 @@
package com.twelvemonkeys.io.enc;
import com.twelvemonkeys.io.FileUtil;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.junit.Assert.assertEquals;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* Base64DecoderTest
* <p/>
@@ -66,7 +64,7 @@ public class Base64DecoderTest extends DecoderAbstractTest {
FileUtil.copy(in, bytes);
assertEquals("Strings does not match", "", new String(bytes.toByteArray()));
assertEquals("", new String(bytes.toByteArray()), "Strings does not match");
}
@Test
@@ -78,7 +76,7 @@ public class Base64DecoderTest extends DecoderAbstractTest {
FileUtil.copy(in, bytes);
assertEquals("Strings does not match", "test", new String(bytes.toByteArray()));
assertEquals("test", new String(bytes.toByteArray()), "Strings does not match");
}
@Test
@@ -93,11 +91,12 @@ public class Base64DecoderTest extends DecoderAbstractTest {
FileUtil.copy(in, bytes);
assertEquals("Strings does not match",
assertEquals(
"Lorem ipsum dolor sit amet, consectetuer adipiscing " +
"elit. Fusce est. Morbi luctus consectetuer justo. Vivamus " +
"dapibus laoreet purus. Nunc viverra dictum nisl. Integer " +
"ullamcorper, nisi in dictum amet.",
new String(bytes.toByteArray()));
new String(bytes.toByteArray()),
"Strings does not match");
}
}
@@ -30,13 +30,12 @@
package com.twelvemonkeys.io.enc;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import static org.junit.Assert.assertEquals;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* Base64EncoderTest
@@ -63,7 +62,7 @@ public class Base64EncoderTest extends EncoderAbstractTest {
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
out.write(data.getBytes());
assertEquals("Strings does not match", "", new String(bytes.toByteArray()));
assertEquals("", new String(bytes.toByteArray()), "Strings does not match");
}
@Test
@@ -74,7 +73,7 @@ public class Base64EncoderTest extends EncoderAbstractTest {
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
out.write(data.getBytes());
assertEquals("Strings does not match", "dGVzdA==", new String(bytes.toByteArray()));
assertEquals("dGVzdA==", new String(bytes.toByteArray()), "Strings does not match");
}
@Test
@@ -88,11 +87,12 @@ public class Base64EncoderTest extends EncoderAbstractTest {
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
out.write(data.getBytes());
assertEquals("Strings does not match",
assertEquals(
"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIEZ1" +
"c2NlIGVzdC4gTW9yYmkgbHVjdHVzIGNvbnNlY3RldHVlciBqdXN0by4gVml2YW11cyBkYXBpYnVzIGxh" +
"b3JlZXQgcHVydXMuIE51bmMgdml2ZXJyYSBkaWN0dW0gbmlzbC4gSW50ZWdlciB1bGxhbWNvcnBlciwg" +
"bmlzaSBpbiBkaWN0dW0gYW1ldC4=",
new String(bytes.toByteArray()));
new String(bytes.toByteArray()),
"Strings does not match");
}
}
@@ -32,12 +32,13 @@ package com.twelvemonkeys.io.enc;
import com.twelvemonkeys.io.FileUtil;
import com.twelvemonkeys.lang.ObjectAbstractTest;
import org.junit.Test;
import java.awt.image.ImageProducer;
import java.io.*;
import java.nio.ByteBuffer;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* AbstractDecoderTest
@@ -55,13 +56,13 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
return createDecoder();
}
@Test(expected = NullPointerException.class)
@Test
public final void testNullDecode() throws IOException {
Decoder decoder = createDecoder();
ByteArrayInputStream bytes = new ByteArrayInputStream(new byte[20]);
decoder.decode(bytes, null);
fail("null should throw NullPointerException");
assertThrows(NullPointerException.class, () -> {
decoder.decode(bytes, null);
});
}
@Test
@@ -71,7 +72,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
try {
int count = decoder.decode(bytes, ByteBuffer.allocate(128));
assertEquals("Should not be able to read any bytes", 0, count);
assertEquals( 0, count, "Should not be able to read any bytes");
}
catch (EOFException allowed) {
// Okay
@@ -94,7 +95,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
byte[] encoded = outBytes.toByteArray();
byte[] decoded = FileUtil.read(new DecoderStream(new ByteArrayInputStream(encoded), createDecoder()));
assertArrayEquals(String.format("Data %d", pLength), data, decoded);
assertArrayEquals(data, decoded, String.format("Data %d", pLength));
InputStream in = new DecoderStream(new ByteArrayInputStream(encoded), createDecoder());
outBytes = new ByteArrayOutputStream();
@@ -103,7 +104,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
in.close();
decoded = outBytes.toByteArray();
assertArrayEquals(String.format("Data %d", pLength), data, decoded);
assertArrayEquals(data, decoded, String.format("Data %d", pLength));
}
@Test
@@ -0,0 +1,130 @@
/*
* Copyright (c) 2022, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class DecoderStreamTest {
private final Random rng = new Random(5467809876546L);
private byte[] createData(final int length) {
byte[] data = new byte[length];
rng.nextBytes(data);
return data;
}
@Test
public void testDecodeSingleBytes() throws IOException {
byte[] data = createData(1327);
InputStream source = new ByteArrayInputStream(data);
try (InputStream stream = new DecoderStream(source, new NullDecoder())) {
for (byte datum : data) {
int read = stream.read();
assertNotEquals(-1, read);
assertEquals(datum, (byte) read);
}
assertEquals(-1, stream.read());
}
}
@Test
public void testDecodeArray() throws IOException {
int length = 793;
byte[] data = createData(length * 10);
InputStream source = new ByteArrayInputStream(data);
byte[] result = new byte[477];
try (InputStream stream = new DecoderStream(source, new NullDecoder())) {
int dataOffset = 0;
while (dataOffset < data.length) {
int count = stream.read(result);
assertFalse(count <= 0);
assertArrayEquals(Arrays.copyOfRange(data, dataOffset, dataOffset + count), Arrays.copyOfRange(result, 0, count));
dataOffset += count;
}
assertEquals(-1, stream.read());
}
}
@Test
public void testDecodeArrayOffset() throws IOException {
int length = 793;
byte[] data = createData(length * 10);
InputStream source = new ByteArrayInputStream(data);
byte[] result = new byte[477];
try (InputStream stream = new DecoderStream(source, new NullDecoder())) {
int dataOffset = 0;
while (dataOffset < data.length) {
int resultOffset = dataOffset % result.length;
int count = stream.read(result, resultOffset, result.length - resultOffset);
assertFalse(count <= 0);
assertArrayEquals(Arrays.copyOfRange(data, dataOffset + resultOffset, dataOffset + count), Arrays.copyOfRange(result, resultOffset, count));
dataOffset += count;
}
assertEquals(-1, stream.read());
}
}
private static final class NullDecoder implements Decoder {
@Override
public int decode(InputStream stream, ByteBuffer buffer) throws IOException {
int read = stream.read(buffer.array(), buffer.arrayOffset(), buffer.remaining());
if (read > 0) {
// Set position, should be equivalent to using buffer.put(stream.read()) until EOF or buffer full
buffer.position(read);
}
return read;
}
}
}
@@ -32,14 +32,13 @@ package com.twelvemonkeys.io.enc;
import com.twelvemonkeys.io.FileUtil;
import com.twelvemonkeys.lang.ObjectAbstractTest;
import org.junit.Test;
import java.io.*;
import java.util.Arrays;
import java.util.Random;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* AbstractEncoderTest
@@ -73,7 +72,7 @@ public abstract class EncoderAbstractTest extends ObjectAbstractTest {
}
}
private byte[] createData(final int pLength) throws Exception {
private byte[] createData(final int pLength) {
byte[] bytes = new byte[pLength];
RANDOM.nextBytes(bytes);
return bytes;
@@ -82,9 +81,8 @@ public abstract class EncoderAbstractTest extends ObjectAbstractTest {
private void runStreamTest(final int pLength) throws Exception {
byte[] data = createData(pLength);
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
OutputStream out = new EncoderStream(outBytes, createEncoder(), true);
try {
try (OutputStream out = new EncoderStream(outBytes, createEncoder(), true)) {
// Provoke failure for encoders that doesn't take array offset properly into account
int off = (data.length + 1) / 2;
out.write(data, 0, off);
@@ -92,9 +90,6 @@ public abstract class EncoderAbstractTest extends ObjectAbstractTest {
out.write(data, off, data.length - off);
}
}
finally {
out.close();
}
byte[] encoded = outBytes.toByteArray();
@@ -102,7 +97,7 @@ public abstract class EncoderAbstractTest extends ObjectAbstractTest {
// System.err.println("encoded: " + Arrays.toString(encoded));
byte[] decoded = FileUtil.read(new DecoderStream(new ByteArrayInputStream(encoded), createCompatibleDecoder()));
assertTrue(Arrays.equals(data, decoded));
assertArrayEquals(data, decoded);
InputStream in = new DecoderStream(new ByteArrayInputStream(encoded), createCompatibleDecoder());
outBytes = new ByteArrayOutputStream();
@@ -116,7 +111,7 @@ public abstract class EncoderAbstractTest extends ObjectAbstractTest {
}
decoded = outBytes.toByteArray();
assertTrue(Arrays.equals(data, decoded));
assertArrayEquals(data, decoded);
}
@Test
@@ -129,10 +124,6 @@ public abstract class EncoderAbstractTest extends ObjectAbstractTest {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
catch (Exception e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
}
for (int i = 100; i < 2000; i += 250) {
@@ -143,10 +134,6 @@ public abstract class EncoderAbstractTest extends ObjectAbstractTest {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
catch (Exception e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
}
for (int i = 2000; i < 80000; i += 1000) {
@@ -157,14 +144,8 @@ public abstract class EncoderAbstractTest extends ObjectAbstractTest {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
catch (Exception e) {
e.printStackTrace();
fail(e.getMessage() + ": " + i);
}
}
}
// TODO: Test that the transition from byte[] to ByteBuffer didn't introduce bugs when writing to a wrapped array with offset.
// TODO: Test that the transition from byte[] to ByteBuffer didn't introduce bugs when writing to a wrapped array with offset.
}
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2022, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io.enc;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Random;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class EncoderStreamTest {
private final Random rng = new Random(5467809876546L);
private byte[] createData(final int length) {
byte[] data = new byte[length];
rng.nextBytes(data);
return data;
}
@Test
public void testEncodeSingleBytes() throws IOException {
byte[] data = createData(1327);
ByteArrayOutputStream result = new ByteArrayOutputStream();
try (OutputStream stream = new EncoderStream(result, new NullEncoder())) {
for (byte datum : data) {
stream.write(datum);
}
}
assertArrayEquals(data, result.toByteArray());
}
@Test
public void testEncodeArray() throws IOException {
byte[] data = createData(1793);
ByteArrayOutputStream result = new ByteArrayOutputStream();
try (OutputStream stream = new EncoderStream(result, new NullEncoder())) {
for (int i = 0; i < 10; i++) {
stream.write(data);
}
}
byte[] encoded = result.toByteArray();
for (int i = 0; i < 10; i++) {
assertArrayEquals(data, Arrays.copyOfRange(encoded, i * data.length, (i + 1) * data.length));
}
}
@Test
public void testEncodeArrayOffset() throws IOException {
byte[] data = createData(87);
ByteArrayOutputStream result = new ByteArrayOutputStream();
try (OutputStream stream = new EncoderStream(result, new NullEncoder())) {
for (int i = 0; i < 10; i++) {
stream.write(data, 13, 59);
}
}
byte[] original = Arrays.copyOfRange(data, 13, 13 + 59);
byte[] encoded = result.toByteArray();
for (int i = 0; i < 10; i++) {
assertArrayEquals(original, Arrays.copyOfRange(encoded, i * original.length, (i + 1) * original.length));
}
}
private static final class NullEncoder implements Encoder {
@Override
public void encode(OutputStream stream, ByteBuffer buffer) throws IOException {
stream.write(buffer.array(), buffer.arrayOffset(), buffer.remaining());
}
}
}
@@ -31,9 +31,9 @@
package com.twelvemonkeys.io.ole2;
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
import org.junit.Test;
import javax.imageio.stream.MemoryCacheImageInputStream;
import java.awt.image.ImageProducer;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -43,8 +43,8 @@ import java.nio.ByteOrder;
import java.util.SortedSet;
import java.util.TreeSet;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* CompoundDocumentTestCase
*
@@ -59,8 +59,8 @@ public class CompoundDocumentTest {
protected final CompoundDocument createTestDocument() throws IOException {
URL input = getClass().getResource(SAMPLE_DATA);
assertNotNull("Missing test resource!", input);
assertEquals("Test resource not a file:// resource", "file", input.getProtocol());
assertNotNull(input, "Missing test resource!");
assertEquals( "file", input.getProtocol(), "Test resource not a file:// resource");
try {
return new CompoundDocument(new File(input.toURI()));
@@ -72,71 +72,72 @@ public class CompoundDocumentTest {
@Test
public void testRoot() throws IOException {
CompoundDocument document = createTestDocument();
try (CompoundDocument document = createTestDocument()) {
Entry root = document.getRootEntry();
Entry root = document.getRootEntry();
assertNotNull(root);
assertEquals("Root Entry", root.getName());
assertTrue(root.isRoot());
assertFalse(root.isFile());
assertFalse(root.isDirectory());
assertEquals(0, root.length());
assertNull(root.getInputStream());
assertNotNull(root);
assertEquals("Root Entry", root.getName());
assertTrue(root.isRoot());
assertFalse(root.isFile());
assertFalse(root.isDirectory());
assertEquals(0, root.length());
assertNull(root.getInputStream());
}
}
@Test
public void testContents() throws IOException {
CompoundDocument document = createTestDocument();
try (CompoundDocument document = createTestDocument()) {
Entry root = document.getRootEntry();
Entry root = document.getRootEntry();
assertNotNull(root);
assertNotNull(root);
SortedSet<Entry> children = new TreeSet<Entry>(root.getChildEntries());
assertEquals(25, children.size());
SortedSet<Entry> children = new TreeSet<Entry>(root.getChildEntries());
assertEquals(25, children.size());
// Weirdness in the file format, name is *written backwards* 1-24 + Catalog
for (String name : "1,2,3,4,5,6,7,8,9,01,02,11,12,21,22,31,32,41,42,51,61,71,81,91,Catalog".split(",")) {
assertEquals(name, children.first().getName());
children.remove(children.first());
// Weirdness in the file format, name is *written backwards* 1-24 + Catalog
for (String name : "1,2,3,4,5,6,7,8,9,01,02,11,12,21,22,31,32,41,42,51,61,71,81,91,Catalog".split(",")) {
assertEquals(name, children.first().getName());
children.remove(children.first());
}
}
}
@Test(expected = UnsupportedOperationException.class)
@Test
public void testChildEntriesUnmodifiable() throws IOException {
CompoundDocument document = createTestDocument();
try (CompoundDocument document = createTestDocument()) {
Entry root = document.getRootEntry();
Entry root = document.getRootEntry();
assertNotNull(root);
assertNotNull(root);
SortedSet<Entry> children = root.getChildEntries();
// Should not be allowed, as it modifies the internal structure
children.remove(children.first());
SortedSet<Entry> children = root.getChildEntries();
assertThrows(UnsupportedOperationException.class, () -> {
// Should not be allowed, as it modifies the internal structure
children.remove(children.first());
});
}
}
@Test
public void testReadThumbsCatalogFile() throws IOException {
CompoundDocument document = createTestDocument();
try (CompoundDocument document = createTestDocument()) {
Entry root = document.getRootEntry();
Entry root = document.getRootEntry();
assertNotNull(root);
assertEquals(25, root.getChildEntries().size());
assertNotNull(root);
assertEquals(25, root.getChildEntries().size());
Entry catalog = root.getChildEntry("Catalog");
Entry catalog = root.getChildEntry("Catalog");
assertNotNull(catalog);
assertNotNull("Input stream may not be null", catalog.getInputStream());
assertNotNull(catalog);
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
}
}
@Test
public void testReadCatalogInputStream() throws IOException {
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
assertNotNull("Missing test resource!", input);
assertNotNull(input, "Missing test resource!");
CompoundDocument document = new CompoundDocument(input);
Entry root = document.getRootEntry();
@@ -145,14 +146,14 @@ public class CompoundDocumentTest {
Entry catalog = root.getChildEntry("Catalog");
assertNotNull(catalog);
assertNotNull("Input stream may not be null", catalog.getInputStream());
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
}
@Test
public void testReadCatalogSeekableStream() throws IOException {
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
assertNotNull("Missing test resource!", input);
assertNotNull(input, "Missing test resource!");
CompoundDocument document = new CompoundDocument(new MemoryCacheSeekableStream(input));
Entry root = document.getRootEntry();
@@ -161,14 +162,14 @@ public class CompoundDocumentTest {
Entry catalog = root.getChildEntry("Catalog");
assertNotNull(catalog);
assertNotNull("Input stream may not be null", catalog.getInputStream());
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
}
@Test
public void testReadCatalogImageInputStream() throws IOException {
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
assertNotNull("Missing test resource!", input);
assertNotNull(input, "Missing test resource!");
MemoryCacheImageInputStream stream = new MemoryCacheImageInputStream(input);
stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
@@ -183,6 +184,6 @@ public class CompoundDocumentTest {
Entry catalog = root.getChildEntry("Catalog");
assertNotNull(catalog);
assertNotNull("Input stream may not be null", catalog.getInputStream());
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
}
}
@@ -31,7 +31,7 @@
package com.twelvemonkeys.io.ole2;
import com.twelvemonkeys.io.*;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
@@ -33,16 +33,16 @@ package com.twelvemonkeys.io.ole2;
import com.twelvemonkeys.io.InputStreamAbstractTest;
import com.twelvemonkeys.io.LittleEndianDataOutputStream;
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
import com.twelvemonkeys.io.SeekableInputStream;
import org.junit.Test;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Arrays;
import static org.junit.Assert.*;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* CompoundDocument_StreamTestCase
@@ -51,35 +51,7 @@ import static org.junit.Assert.*;
* @author last modified by $Author: haraldk$
* @version $Id: CompoundDocument_StreamTestCase.java,v 1.0 13.10.11 12:01 haraldk Exp$
*/
//@Ignore("Need proper in-memory creation of CompoundDocuments")
public class CompoundDocument_StreamTest extends InputStreamAbstractTest {
private static final String SAMPLE_DATA = "/Thumbs-camera.db";
protected final CompoundDocument createTestDocument() throws IOException {
URL input = getClass().getResource(SAMPLE_DATA);
assertNotNull("Missing test resource!", input);
assertEquals("Test resource not a file:// resource", "file", input.getProtocol());
try {
return new CompoundDocument(new File(input.toURI()));
}
catch (URISyntaxException e) {
throw new AssertionError(e);
}
}
private SeekableInputStream createRealInputStream() {
try {
Entry first = createTestDocument().getRootEntry().getChildEntries().first();
assertNotNull(first);
return first.getInputStream();
}
catch (IOException e) {
throw new AssertionError(e);
}
}
@Override
protected InputStream makeInputStream(byte[] data) {
try {
@@ -182,21 +154,19 @@ public class CompoundDocument_StreamTest extends InputStreamAbstractTest {
return pad;
}
// @Ignore
@Test
public void testDev() throws IOException {
public void testStreamRead() throws IOException {
InputStream stream = makeInputStream(makeOrderedArray(32));
int read;
int count = 0;
while ((read = stream.read()) >= 0) {
// System.out.printf("read %02d: 0x%02x%n", count, read & 0xFF);
assertEquals(count, read);
count++;
}
assertFalse("Short stream", count < 32);
assertFalse("Stream overrun", count > 32);
assertFalse(count < 32, "Short stream");
assertFalse(count > 32, "Stream overrun");
}
@Test
@@ -30,9 +30,8 @@
package com.twelvemonkeys.net;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* HTTPUtilTest
+14 -2
View File
@@ -4,13 +4,25 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.4</version>
<version>3.13.2-SNAPSHOT</version>
</parent>
<artifactId>common-lang</artifactId>
<packaging>jar</packaging>
<name>TwelveMonkeys :: Common :: Language support</name>
<description>
The TwelveMonkeys Common Language support
TwelveMonkeys Common language support classes.
</description>
<properties>
<project.jpms.module.name>com.twelvemonkeys.common.lang</project.jpms.module.name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

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