Compare commits

..

17 Commits

Author SHA1 Message Date
Harald Kuhr c709fcafa9 Fixed nested tests 2026-05-04 17:20:57 +02:00
Harald Kuhr 4f6ed55218 Add @Nested to inner test-classes 2026-05-04 15:02:39 +02:00
dependabot[bot] ae7e3d8c9b Bump junit.jupiter.version from 5.14.3 to 5.14.4
Bumps `junit.jupiter.version` from 5.14.3 to 5.14.4.

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-04 14:59:29 +02:00
dependabot[bot] 43ddc84986 Bump commons-io:commons-io from 2.21.0 to 2.22.0
Bumps commons-io:commons-io from 2.21.0 to 2.22.0.

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-27 16:22:11 +02:00
dependabot[bot] e682696fac Bump github/codeql-action from 4.35.1 to 4.35.2 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.35.1 to 4.35.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/c10b8064de6f491fea524254123dbe5e09572f13...95e58e9a2cdfd71adc6e0353d5c52f41a045d225)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-22 13:18:18 +02:00
dependabot[bot] 5f190ea57d Bump actions/upload-artifact from 7.0.0 to 7.0.1 in /.github/workflows
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/bbbca2ddaa5d8feaa63e36b76fdaad77386f024f...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-17 11:00:08 +02:00
dependabot[bot] 3ca37e4b8c Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 6.3.1 to 6.4.0.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/49b2ca06f62aa7ef83ae6769a2179271e160d8e4...bccf2e31636835cf0874589931c4116687171386)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-06 14:25:27 +02:00
dependabot[bot] a30a032a9c Bump github/codeql-action from 4.32.6 to 4.35.1 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.6 to 4.35.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/0d579ffd059c29b07949a3cce3983f0780820c98...c10b8064de6f491fea524254123dbe5e09572f13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-06 12:53:18 +02:00
dependabot[bot] 77ebba4f7d Bump github/codeql-action from 4.32.4 to 4.32.6 in /.github/workflows
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.32.4 to 4.32.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/89a39a4e59826350b863aa6b6252a07ad50cf83e...0d579ffd059c29b07949a3cce3983f0780820c98)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-19 15:33:58 +01:00
Harald Kuhr 456749ded8 Using new sequence support in DDSImageWriter
+ some minor bonus clean-up
2026-03-13 14:46:19 +01:00
Harald Kuhr 47a26651b4 Using new sequence support in exising writers. 2026-03-13 14:46:19 +01:00
Harald Kuhr 10183ef830 New class for simpler sequence write support. 2026-03-13 14:46:19 +01:00
Harald Kuhr 263fb75d1d DDS cleanup (#1262)
* Refactorings and code clean-up
* 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
* Fix JavaDoc 🎉
* Sonar issues + roll back accidental check-in
* More clean-up: Removed optional flags from param, header size validation, metadata now reports compresion as lossy
* More clean-up: Now keeps stream byte order consistent (LE), support for Raster, more tests
* Mipmap support using ImageIO sequence API
* Added raster write test
+ fixed a small issue for PAM
* Sonar issues
2026-03-11 21:09:26 +01:00
dependabot[bot] e61ec45737 Bump org.apache.maven.plugins:maven-shade-plugin from 3.6.1 to 3.6.2
Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.6.1 to 3.6.2.
- [Release notes](https://github.com/apache/maven-shade-plugin/releases)
- [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.6.1...maven-shade-plugin-3.6.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-10 16:03:03 +01:00
dependabot[bot] 6e063f263c Bump actions/upload-artifact from 6.0.0 to 7.0.0 in /.github/workflows
---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-10 16:02:33 +01:00
dependabot[bot] e2cf529000 Bump org.apache.maven.plugins:maven-resources-plugin from 3.4.0 to 3.5.0
Bumps [org.apache.maven.plugins:maven-resources-plugin](https://github.com/apache/maven-resources-plugin) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/apache/maven-resources-plugin/releases)
- [Commits](https://github.com/apache/maven-resources-plugin/compare/v3.4.0...maven-resources-plugin-3.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-10 14:21:22 +01:00
dependabot[bot] 9d1c418d8d Bump mikepenz/action-junit-report in /.github/workflows
Bumps [mikepenz/action-junit-report](https://github.com/mikepenz/action-junit-report) from 6.2.0 to 6.3.1.
- [Release notes](https://github.com/mikepenz/action-junit-report/releases)
- [Commits](https://github.com/mikepenz/action-junit-report/compare/74626db7353a25a20a72816467ebf035f674c5f8...49b2ca06f62aa7ef83ae6769a2179271e160d8e4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-10 14:20:41 +01:00
27 changed files with 372 additions and 182 deletions
+3 -3
View File
@@ -35,7 +35,7 @@ jobs:
- name: Run Tests
run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5
uses: mikepenz/action-junit-report@bccf2e31636835cf0874589931c4116687171386 # v5
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
@@ -57,7 +57,7 @@ jobs:
- name: Run Tests
run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5
uses: mikepenz/action-junit-report@bccf2e31636835cf0874589931c4116687171386 # v5
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
@@ -91,7 +91,7 @@ jobs:
- name: Run Tests
run: mvn --batch-mode --no-transfer-progress test
- name: Publish Test Report
uses: mikepenz/action-junit-report@74626db7353a25a20a72816467ebf035f674c5f8 # v5
uses: mikepenz/action-junit-report@bccf2e31636835cf0874589931c4116687171386 # v5
if: ${{ !cancelled() }}
with:
report_paths: "**/target/surefire-reports/TEST*.xml"
+3 -3
View File
@@ -37,7 +37,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -51,7 +51,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
uses: github/codeql-action/autobuild@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -64,6 +64,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
with:
category: "/language:${{matrix.language}}"
+2 -2
View File
@@ -49,7 +49,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: SARIF file
path: results.sarif
@@ -57,6 +57,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
with:
sarif_file: results.sarif
@@ -284,20 +284,6 @@ abstract class AbstractDecoratedMap<K, V> extends AbstractMap<K, V> implements M
return false;
}
/*
// NOTE: Extra cautions is taken, to only remove the entry if it
// equals the entry in the map
Object key = ((Entry) o).getKey();
Entry entry = (Entry) entries.get(key);
// Same entry?
if (entry != null && entry.equals(o)) {
return AbstractWrappedMap.this.remove(key) != null;
}
return false;
*/
//noinspection unchecked
return AbstractDecoratedMap.this.removeEntry((Entry) o) != null;
}
@@ -322,7 +308,7 @@ abstract class AbstractDecoratedMap<K, V> extends AbstractMap<K, V> implements M
return containsKey(o);
}
public boolean remove(Object o) {
return AbstractDecoratedMap.this.remove(o) != null;
return AbstractDecoratedMap.this.removeEntry(getEntry((K) o)) != null;
}
public void clear() {
AbstractDecoratedMap.this.clear();
@@ -137,43 +137,43 @@ public final class BeanMap extends AbstractMap<String, Object> implements Serial
}
private class BeanIterator implements Iterator<Entry<String, Object>> {
private final Iterator<PropertyDescriptor> mIterator;
private final Iterator<PropertyDescriptor> iterator;
public BeanIterator(final Iterator<PropertyDescriptor> pIterator) {
mIterator = pIterator;
iterator = pIterator;
}
public boolean hasNext() {
return mIterator.hasNext();
return iterator.hasNext();
}
public BeanEntry next() {
return new BeanEntry(mIterator.next());
return new BeanEntry(iterator.next());
}
public void remove() {
mIterator.remove();
iterator.remove();
}
}
private class BeanEntry implements Entry<String, Object> {
private final PropertyDescriptor mDescriptor;
private final PropertyDescriptor descriptor;
public BeanEntry(final PropertyDescriptor pDescriptor) {
this.mDescriptor = pDescriptor;
this.descriptor = pDescriptor;
}
public String getKey() {
return mDescriptor.getName();
return descriptor.getName();
}
public Object getValue() {
return unwrap(new Wrapped() {
public Object run() throws IllegalAccessException, InvocationTargetException {
final Method method = mDescriptor.getReadMethod();
final Method method = descriptor.getReadMethod();
// A write-only bean.
if (method == null) {
throw new UnsupportedOperationException("No getter: " + mDescriptor.getName());
throw new UnsupportedOperationException("No getter: " + descriptor.getName());
}
return method.invoke(bean);
@@ -184,10 +184,10 @@ public final class BeanMap extends AbstractMap<String, Object> implements Serial
public Object setValue(final Object pValue) {
return unwrap(new Wrapped() {
public Object run() throws IllegalAccessException, InvocationTargetException {
final Method method = mDescriptor.getWriteMethod();
final Method method = descriptor.getWriteMethod();
// A read-only bean.
if (method == null) {
throw new UnsupportedOperationException("No write method for property: " + mDescriptor.getName());
throw new UnsupportedOperationException("No write method for property: " + descriptor.getName());
}
final Object old = getValue();
@@ -71,7 +71,6 @@ public abstract class ObjectAbstractTest {
// TODO: What more can we test?
}
// TODO: assert that either BOTH or NONE of equals/hashcode is overridden
@Test
public void testEqualsHashCode(){
Object obj = makeObject();
@@ -328,5 +327,4 @@ public abstract class ObjectAbstractTest {
return new Cloneable() {};
}
}
}
@@ -30,6 +30,8 @@
package com.twelvemonkeys.util;
import org.junit.jupiter.api.Nested;
import java.beans.IntrospectionException;
import java.io.Serializable;
import java.util.Map;
@@ -172,4 +174,16 @@ public class BeanMapTest extends MapAbstractTest {
}
static class NullBean implements Serializable { }
@Nested
public class TestBeanMapEntrySet extends TestMapEntrySet {
}
@Nested
public class TestBeanMapKeySet extends TestMapKeySet {
}
@Nested
public class TestBeanMapValues extends TestMapValues {
}
}
@@ -436,24 +436,24 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
*/
public Object[] getFullNonNullElements() {
return new Object[] {
new String(""),
new String("One"),
new Integer(2),
"Three",
new Integer(4),
"",
"One",
new Double(5),
new Float(6),
2,
"Three",
4,
"One",
5.0,
6F,
"Seven",
"Eight",
new String("Nine"),
new Integer(10),
new Short((short)11),
new Long(12),
"Nine",
10,
(short) 11,
12L,
"Thirteen",
"14",
"15",
new Byte((byte)16)
(byte) 16
};
}
@@ -1149,7 +1149,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
public void testUnsupportedRemove() {
if (isRemoveSupported()) return;
resetEmpty();
resetFull();
try {
collection.clear();
fail("clear should raise UnsupportedOperationException");
@@ -1159,7 +1159,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
verifyAll();
try {
collection.remove(null);
collection.remove(getFullElements()[0]);
fail("remove should raise UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// expected
@@ -1167,7 +1167,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
verifyAll();
try {
collection.removeAll(null);
collection.removeAll(Arrays.asList(getFullElements()));
fail("removeAll should raise UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// expected
@@ -1175,7 +1175,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
verifyAll();
try {
collection.retainAll(null);
collection.retainAll(Collections.emptySet());
fail("removeAll should raise UnsupportedOperationException");
} catch (UnsupportedOperationException e) {
// expected
@@ -1192,7 +1192,6 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
// expected
}
verifyAll();
}
@@ -212,5 +212,17 @@ public class LRUMapTest extends LinkedMapTest {
list.add(pEntry.getKey());
}
}
@Nested
public class TestLRUMapEntrySet extends TestMapEntrySet {
}
@Nested
public class TestLRUMapKeySet extends TestMapKeySet {
}
@Nested
public class TestLRUMapValues extends TestMapValues {
}
}
@@ -201,4 +201,16 @@ public class LinkedMapTest extends MapAbstractTest {
public void tearDown() throws Exception {
labRat = null;
}
@Nested
public class TestLinkedMapEntrySet extends TestMapEntrySet {
}
@Nested
public class TestLinkedMapKeySet extends TestMapKeySet {
}
@Nested
public class TestLinkedMapValues extends TestMapValues {
}
}
@@ -1255,7 +1255,7 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
}
*/
public class TestMapEntrySet extends SetAbstractTest {
protected abstract class TestMapEntrySet extends SetAbstractTest {
// Have to implement manually; entrySet doesn't support addAll
public Object[] getFullElements() {
@@ -1429,7 +1429,7 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
}
*/
public class TestMapKeySet extends SetAbstractTest {
protected abstract class TestMapKeySet extends SetAbstractTest {
public Object[] getFullElements() {
return getSampleKeys();
}
@@ -1495,7 +1495,7 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
}
*/
public class TestMapValues extends CollectionAbstractTest {
protected abstract class TestMapValues extends CollectionAbstractTest {
public Object[] getFullElements() {
return getSampleValues();
}
@@ -668,5 +668,17 @@ public class TimeoutMapTest extends MapAbstractTest {
assertFalse(timeoutMap.containsKey("xyz"));
assertNull(timeoutMap.get("xyz"));
}
@Nested
public class TestTimeoutMapEntrySet extends TestMapEntrySet {
}
@Nested
public class TestTimeoutMapKeySet extends TestMapKeySet {
}
@Nested
public class TestTimeoutMapValues extends TestMapValues {
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
</modules>
<properties>
<junit.jupiter.version>5.14.3</junit.jupiter.version>
<junit.jupiter.version>5.14.4</junit.jupiter.version>
</properties>
<dependencyManagement>
+1 -1
View File
@@ -14,7 +14,7 @@
</description>
<properties>
<junit.jupiter.version>5.14.3</junit.jupiter.version>
<junit.jupiter.version>5.14.4</junit.jupiter.version>
</properties>
+1 -1
View File
@@ -63,7 +63,7 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.21.0</version>
<version>2.22.0</version>
<scope>provided</scope>
</dependency>
@@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import com.twelvemonkeys.imageio.util.SequenceSupport;
import javax.imageio.IIOException;
import javax.imageio.IIOImage;
@@ -64,7 +65,7 @@ public final class ICOImageWriter extends DIBImageWriter {
private static final int ICO_MAX_DIMENSION = 256;
private static final int INITIAL_ENTRY_COUNT = 8;
private int sequenceIndex = -1;
private final SequenceSupport sequence = new SequenceSupport();
private ImageWriter pngDelegate;
@@ -74,7 +75,7 @@ public final class ICOImageWriter extends DIBImageWriter {
@Override
protected void resetMembers() {
sequenceIndex = -1;
sequence.reset();
if (pngDelegate != null) {
pngDelegate.dispose();
@@ -107,16 +108,12 @@ public final class ICOImageWriter extends DIBImageWriter {
@Override
public void prepareWriteSequence(final IIOMetadata streamMetadata) throws IOException {
assertOutput();
if (sequenceIndex >= 0) {
throw new IllegalStateException("writeSequence already started");
}
sequence.start();
writeICOHeader();
// Count: Needs to be updated for each new image
imageOutput.writeShort(0);
sequenceIndex = 0;
// TODO: Allow passing the initial size of the directory in the stream metadata?
// - as this is much more efficient than growing...
@@ -130,27 +127,19 @@ public final class ICOImageWriter extends DIBImageWriter {
@Override
public void endWriteSequence() {
assertOutput();
if (sequenceIndex < 0) {
throw new IllegalStateException("prepareWriteSequence not called");
}
sequenceIndex = -1;
sequence.end();
}
@Override
public void writeToSequence(final IIOImage image, final ImageWriteParam param) throws IOException {
assertOutput();
if (sequenceIndex < 0) {
throw new IllegalStateException("prepareWriteSequence not called");
}
int imageIndex = sequence.advance();
if (image.hasRaster()) {
throw new UnsupportedOperationException("Raster not supported");
}
if (sequenceIndex >= INITIAL_ENTRY_COUNT) {
if (imageIndex >= INITIAL_ENTRY_COUNT) {
growIfNecessary();
}
@@ -172,7 +161,7 @@ public final class ICOImageWriter extends DIBImageWriter {
// Uncompressed, RLE4/RLE8 or PNG compressed
boolean pngCompression = param != null && "BI_PNG".equals(param.getCompressionType());
processImageStarted(sequenceIndex);
processImageStarted(imageIndex);
if (pngCompression) {
// NOTE: Embedding a PNG in a ICO is slightly different than a BMP with BI_PNG compression,
@@ -198,17 +187,15 @@ public final class ICOImageWriter extends DIBImageWriter {
// Update count
imageOutput.seek(4);
imageOutput.writeShort(sequenceIndex + 1);
imageOutput.writeShort(imageIndex + 1);
// Write entry
int entryPosition = 6 + sequenceIndex * ENTRY_SIZE;
int entryPosition = 6 + imageIndex * ENTRY_SIZE;
imageOutput.seek(entryPosition);
long size = nextPosition - imageOffset;
writeEntry(width, height, colorModel, (int) size, (int) imageOffset);
sequenceIndex++;
imageOutput.seek(nextPosition);
}
@@ -265,7 +252,7 @@ public final class ICOImageWriter extends DIBImageWriter {
pngDelegate.addIIOWriteWarningListener(new IIOWriteWarningListener() {
@Override
public void warningOccurred(ImageWriter source, int imageIndex, String warning) {
processWarningOccurred(sequenceIndex, warning);
processWarningOccurred(sequence.current(), warning);
}
});
}
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2026, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.imageio.util;
import javax.imageio.IIOImage;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
/**
* A tiny utility class that keeps state for sequences.
* For use by {@code ImageWriter} implementations that supports sequence (multiple images in same stream).
*
* @see ImageWriter#canWriteSequence()
*/
public final class SequenceSupport {
// Initial state, no sequence running
private int index = -1;
/**
* Resets the sequence to initial state, regardless of the current sequence state.
*/
public void reset() {
index = -1;
}
/**
* Starts a new sequence.
*
* @throws IllegalStateException if a sequence is already running.
* @see ImageWriter#prepareWriteSequence(IIOMetadata)
*/
public void start() {
if (index >= 0) {
throw new IllegalStateException("prepareWriteSequence already invoked");
}
index = 0;
}
/**
* Advances the current sequence.
*
* @return the current sequence index.
* @throws IllegalStateException if a sequence is not running.
* @see ImageWriter#writeToSequence(IIOImage, ImageWriteParam)
*/
public int advance() {
if (index < 0) {
throw new IllegalStateException("prepareWriteSequence not invoked");
}
return index++;
}
/**
* Gets the current sequence index.
*
* @return the current sequence index, or {@code -1} if a sequence is not running.
*/
public int current() {
// This method does not throw IllegalStateException, to allow
// ImageWriters to use the index in cases that may or may not
// happen "inside" a sequence.
// I'm not entirely sure if this is a good idea...
return index;
}
/**
* Ends the current sequence.
* The sequence is reset to initial state, and a new sequence may be started.
*
* @return the current (last) sequence index
* @throws IllegalStateException if a sequence is not running.
* @see ImageWriter#endWriteSequence()
*/
public int end() {
if (index < 0) {
throw new IllegalStateException("prepareWriteSequence not invoked");
}
int last = index;
index = -1;
return last;
}
}
@@ -0,0 +1,89 @@
package com.twelvemonkeys.imageio.util;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class SequenceSupportTest {
@Test
void happyCase() {
SequenceSupport sequence = new SequenceSupport();
sequence.start();
assertEquals(0, sequence.current());
for (int i = 0; i < Byte.MAX_VALUE; i++) {
assertEquals(i, sequence.advance());
assertEquals(i + 1, sequence.current());
}
assertEquals(127, sequence.end());
assertEquals(-1, sequence.current());
assertThrows(IllegalStateException.class, sequence::advance);
}
@Test
void reset() {
SequenceSupport sequence = new SequenceSupport();
sequence.reset();
assertEquals(-1, sequence.current());
assertThrows(IllegalStateException.class, sequence::end);
sequence.start();
sequence.reset();
assertEquals(-1, sequence.current());
assertThrows(IllegalStateException.class, sequence::end);
sequence.start();
sequence.advance();
sequence.reset();
assertEquals(-1, sequence.current());
assertThrows(IllegalStateException.class, sequence::end);
sequence.start();
sequence.end();
sequence.reset();
assertEquals(-1, sequence.current());
assertThrows(IllegalStateException.class, sequence::end);
}
@Test
void startEnd() {
SequenceSupport sequence = new SequenceSupport();
sequence.start();
sequence.end();
assertEquals(-1, sequence.current());
assertThrows(IllegalStateException.class, sequence::end);
}
@Test
void startAlreadyStarted() {
SequenceSupport sequence = new SequenceSupport();
sequence.start();
assertThrows(IllegalStateException.class, sequence::start);
}
@Test
void advanceNotStarted() {
SequenceSupport sequence = new SequenceSupport();
assertThrows(IllegalStateException.class, sequence::advance);
}
@Test
void currentNotStarted() {
SequenceSupport sequence = new SequenceSupport();
assertEquals(-1, sequence.current());
}
@Test
void endNotStarted() {
SequenceSupport sequence = new SequenceSupport();
assertThrows(IllegalStateException.class, sequence::end);
}
}
@@ -47,9 +47,12 @@ import java.awt.Dimension;
import java.io.IOException;
import java.util.Arrays;
/**
* @see <a href="https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header">DDS_HEADER structure</a>
* @see <a href="https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide">Programming Guide for DDS</a>
*/
final class DDSHeader {
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide
private int flags;
private int mipMapCount;
@@ -69,26 +72,16 @@ final class DDSHeader {
static DDSHeader read(final ImageInputStream imageInput) throws IOException {
DDSHeader header = new DDSHeader();
// Read MAGIC bytes [0,3]
int magic = imageInput.readInt();
if (magic != DDS.MAGIC) {
throw new IIOException(String.format("Not a DDS file. Expected DDS magic 0x%8x', read 0x%8x", DDS.MAGIC, magic));
}
// DDS_HEADER structure
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header
int dwSize = imageInput.readInt(); // [4,7]
if (dwSize != DDS.HEADER_SIZE) {
throw new IIOException(String.format("Invalid DDS header size (expected %d): %d", DDS.HEADER_SIZE, dwSize));
}
// Verify setFlags
// Verify flags
header.flags = imageInput.readInt(); // [8,11]
if (!header.getFlag(DDS.FLAG_CAPS
| DDS.FLAG_HEIGHT
| DDS.FLAG_WIDTH
| DDS.FLAG_PIXELFORMAT)) {
throw new IIOException("Required DDS Flag missing in header: " + Integer.toBinaryString(header.flags));
if (!header.hasFlag(DDS.FLAG_CAPS | DDS.FLAG_HEIGHT | DDS.FLAG_WIDTH | DDS.FLAG_PIXELFORMAT)) {
// NOTE: The Microsoft DDS documentation mention that readers should not rely on these flags...
throw new IIOException("Required DDS flag missing in header: " + Integer.toBinaryString(header.flags));
}
// Read Height & Width
@@ -109,7 +102,7 @@ final class DDSHeader {
// DDS_PIXELFORMAT structure
int px_dwSize = imageInput.readInt(); // [76,79]
if (px_dwSize != DDS.PIXELFORMAT_SIZE) {
throw new IIOException(String.format("Invalid DDS PIXELFORMAT size (expected %d): %d", DDS.PIXELFORMAT_SIZE, dwSize));
throw new IIOException(String.format("Invalid DDS pixel format structure size (expected %d): %d", DDS.PIXELFORMAT_SIZE, dwSize));
}
header.pixelFormatFlags = imageInput.readInt(); // [80,83]
@@ -128,6 +121,7 @@ final class DDSHeader {
int dwReserved2 = imageInput.readInt(); // [124,127]
if (header.fourCC == DDSType.DXT10.fourCC()) {
// If DXT10, the DXT10 header will follow immediately
header.dxt10Header = DXT10Header.read(imageInput);
}
@@ -146,8 +140,8 @@ final class DDSHeader {
}
}
private boolean getFlag(int mask) {
return (flags & mask) != 0;
private boolean hasFlag(int mask) {
return (flags & mask) == mask;
}
int getWidth(int imageIndex) {
@@ -77,5 +77,4 @@ final class DDSImageMetadata extends StandardImageMetadataSupport {
return count;
}
}
@@ -33,6 +33,7 @@ package com.twelvemonkeys.imageio.plugins.dds;
import com.twelvemonkeys.imageio.ImageReaderBase;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageTypeSpecifier;
@@ -167,6 +168,12 @@ public final class DDSImageReader extends ImageReaderBase {
private void readHeader() throws IOException {
if (header == null) {
imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
int magic = imageInput.readInt();
if (magic != DDS.MAGIC) {
throw new IIOException(String.format("Not a DDS file. Expected DDS magic 0x%8x', read 0x%8x", DDS.MAGIC, magic));
}
header = DDSHeader.read(imageInput);
imageInput.flushBefore(imageInput.getStreamPosition());
}
@@ -2,6 +2,7 @@ package com.twelvemonkeys.imageio.plugins.dds;
import com.twelvemonkeys.imageio.ImageWriterBase;
import com.twelvemonkeys.imageio.util.IIOUtil;
import com.twelvemonkeys.imageio.util.SequenceSupport;
import javax.imageio.IIOException;
import javax.imageio.IIOImage;
@@ -29,9 +30,9 @@ import java.nio.file.Paths;
*/
class DDSImageWriter extends ImageWriterBase {
private long startPos;
// TODO: Create a SequenceSupport class that handles sequence prepare/write/end
private int mipmapIndex = -1;
private final SequenceSupport mipmapSequence = new SequenceSupport();
private long headerStartPos;
private DDSType mipmapType;
private Dimension mipmapDimension;
@@ -46,7 +47,8 @@ class DDSImageWriter extends ImageWriterBase {
@Override
protected void resetMembers() {
mipmapIndex = -1;
headerStartPos = 0;
mipmapSequence.reset();
mipmapType = null;
mipmapDimension = null;
}
@@ -64,30 +66,22 @@ class DDSImageWriter extends ImageWriterBase {
@Override
public void prepareWriteSequence(IIOMetadata streamMetadata) throws IOException {
assertOutput();
mipmapSequence.start();
if (mipmapIndex >= 0) {
throw new IllegalStateException("writeSequence already started");
}
mipmapIndex = 0;
startPos = imageOutput.getStreamPosition();
imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
imageOutput.writeInt(DDS.MAGIC);
imageOutput.flush();
headerStartPos = imageOutput.getStreamPosition();
}
@Override
public void endWriteSequence() throws IOException {
assertOutput();
int mipmapCount = mipmapSequence.end();
if (mipmapIndex < 0) {
throw new IllegalStateException("prepareWriteSequence not called");
}
// Go back and update header
updateHeader(mipmapCount);
// Go back and update hader
updateHeader(mipmapIndex);
mipmapIndex = -1;
mipmapType = null;
mipmapDimension = null;
@@ -103,13 +97,12 @@ class DDSImageWriter extends ImageWriterBase {
@Override
public void writeToSequence(IIOImage image, ImageWriteParam param) throws IOException {
if (mipmapIndex < 0) {
throw new IllegalStateException("prepareWriteSequence not called");
}
int mipmapIndex = mipmapSequence.advance();
Raster raster = getRaster(image);
ensureImageChannels(raster);
ensureTextureDimension(raster);
mipmapDimension = new Dimension(raster.getWidth(), raster.getHeight());
DDSImageWriteParam ddsParam = param instanceof DDSImageWriteParam
? ((DDSImageWriteParam) param)
@@ -120,7 +113,7 @@ class DDSImageWriter extends ImageWriterBase {
mipmapType = type;
}
else if (type != mipmapType) {
processWarningOccurred(mipmapIndex, "All images in DDS MipMap must use same pixel format and compression");
processWarningOccurred(mipmapIndex, "All images in DDS mipmap must use same pixel format and compression");
}
if (mipmapType == null) {
throw new IIOException("Only compressed DDS using DXT1-5 or DXT10 with block compression is currently supported");
@@ -140,9 +133,6 @@ class DDSImageWriter extends ImageWriterBase {
processImageProgress(100f);
processImageComplete();
mipmapDimension = new Dimension(raster.getWidth(), raster.getHeight());
mipmapIndex++;
}
private static Raster getRaster(IIOImage image) throws IIOException {
@@ -210,7 +200,7 @@ class DDSImageWriter extends ImageWriterBase {
//dwDepth
imageOutput.writeInt(0);
//dwMipmapCount
imageOutput.writeInt(1);
imageOutput.writeInt(1); // Should probably write 0 here for non-mipmap?
//reserved
imageOutput.write(new byte[44]);
//pixFmt
@@ -230,7 +220,7 @@ class DDSImageWriter extends ImageWriterBase {
}
long streamPosition = imageOutput.getStreamPosition();
imageOutput.seek(startPos + 8); // Seek back to start + 4 magic + 4 header size
imageOutput.seek(headerStartPos + 4); // Seek back to header start, skip 4 byte header size
int flags = imageOutput.readInt();
imageOutput.seek(imageOutput.getStreamPosition() - 4);
@@ -268,15 +258,14 @@ class DDSImageWriter extends ImageWriterBase {
//dwRGBBitCount
imageOutput.writeInt(type.blockSize() * 8); // TODO: Is bitcount always a multiple of 8?
int[] mask = type.rgbaMasks;
//dwRBitMask
imageOutput.writeInt(mask[0]);
imageOutput.writeInt(type.rgbaMasks[0]);
//dwGBitMask
imageOutput.writeInt(mask[1]);
imageOutput.writeInt(type.rgbaMasks[1]);
//dwBBitMask
imageOutput.writeInt(mask[2]);
imageOutput.writeInt(type.rgbaMasks[2]);
//dwABitMask
imageOutput.writeInt(mask[3]);
imageOutput.writeInt(type.rgbaMasks[3]);
}
else {
//write 5 zero integers as fourCC is used
@@ -302,7 +291,8 @@ class DDSImageWriter extends ImageWriterBase {
imageOutput.writeInt(DDS.PIXEL_FORMAT_FLAG_FOURCC);
}
else {
imageOutput.writeInt(DDS.PIXEL_FORMAT_FLAG_RGB | (type.rgbaMasks != null ? DDS.PIXEL_FORMAT_FLAG_ALPHAPIXELS : 0));
imageOutput.writeInt(DDS.PIXEL_FORMAT_FLAG_RGB
| (type.rgbaMasks != null && type.rgbaMasks[3] != 0 ? DDS.PIXEL_FORMAT_FLAG_ALPHAPIXELS : 0));
}
}
@@ -334,6 +324,7 @@ class DDSImageWriter extends ImageWriterBase {
if (args.length != 1) {
throw new IllegalArgumentException("Use 1 input file at a time.");
}
ImageIO.write(ImageIO.read(new File(args[0])), "dds", new MemoryCacheImageOutputStream(Files.newOutputStream(Paths.get("output.dds"))));
}
}
@@ -33,6 +33,7 @@ package com.twelvemonkeys.imageio.plugins.icns;
import com.twelvemonkeys.imageio.ImageWriterBase;
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import com.twelvemonkeys.imageio.util.SequenceSupport;
import javax.imageio.IIOException;
import javax.imageio.IIOImage;
@@ -55,7 +56,7 @@ import java.util.Iterator;
*/
public final class ICNSImageWriter extends ImageWriterBase {
private int sequenceIndex = -1;
private final SequenceSupport sequence = new SequenceSupport();
private ImageWriter pngDelegate;
ICNSImageWriter(ImageWriterSpi provider) {
@@ -64,7 +65,7 @@ public final class ICNSImageWriter extends ImageWriterBase {
@Override
protected void resetMembers() {
sequenceIndex = -1;
sequence.reset();
if (pngDelegate != null) {
pngDelegate.dispose();
@@ -97,41 +98,29 @@ public final class ICNSImageWriter extends ImageWriterBase {
@Override
public void prepareWriteSequence(final IIOMetadata streamMetadata) throws IOException {
assertOutput();
sequence.start();
// TODO: Allow TOC resource to be passed as stream metadata?
// - We only need number of icons to be written later
// - The contents of the TOC could be updated while adding to the sequence
if (sequenceIndex >= 0) {
throw new IllegalStateException("writeSequence already started");
}
writeICNSHeader();
sequenceIndex = 0;
}
@SuppressWarnings("RedundantThrows")
@Override
public void endWriteSequence() throws IOException {
assertOutput();
if (sequenceIndex < 0) {
throw new IllegalStateException("prepareWriteSequence not called");
}
sequence.end();
// TODO: Now that we know the number of icon resources, we could move all data backwards
// and write a TOC... But I don't think the benefit will outweigh the cost.
sequenceIndex = -1;
}
@Override
public void writeToSequence(final IIOImage image, final ImageWriteParam param) throws IOException {
assertOutput();
if (sequenceIndex < 0) {
throw new IllegalStateException("prepareWriteSequence not called");
}
int imageIndex = sequence.advance();
if (image.hasRaster()) {
throw new UnsupportedOperationException("image has a Raster");
@@ -148,7 +137,7 @@ public final class ICNSImageWriter extends ImageWriterBase {
imageOutput.writeInt(IconResource.typeFromImage(image.getRenderedImage(), "PNG"));
imageOutput.writeInt(0); // Size, update later
processImageStarted(sequenceIndex);
processImageStarted(imageIndex);
// Write icon in PNG format
ImageWriter writer = getPNGDelegate();
@@ -208,7 +197,7 @@ public final class ICNSImageWriter extends ImageWriterBase {
pngDelegate.addIIOWriteWarningListener(new IIOWriteWarningListener() {
@Override
public void warningOccurred(ImageWriter source, int imageIndex, String warning) {
processWarningOccurred(sequenceIndex, warning);
processWarningOccurred(sequence.current(), warning);
}
});
}
@@ -42,6 +42,7 @@ import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
import com.twelvemonkeys.imageio.util.IIOUtil;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import com.twelvemonkeys.imageio.util.SequenceSupport;
import com.twelvemonkeys.io.enc.EncoderStream;
import com.twelvemonkeys.io.enc.PackBitsEncoder;
import com.twelvemonkeys.lang.Validate;
@@ -110,12 +111,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
// Support storing multiple images in one stream (multi-page TIFF)
// Support more of the ImageIO metadata (ie. compression from metadata, etc)
/**
* Flag for active sequence writing
*/
private boolean writingSequence = false;
private int sequenceIndex = 0;
private final SequenceSupport sequence = new SequenceSupport();
/**
* Metadata writer for sequence writing
@@ -751,7 +747,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
ifd = ((TIFFImageMetadata) inData).getIFD();
}
else {
TIFFImageMetadata outData = new TIFFImageMetadata(Collections.<Entry>emptySet());
TIFFImageMetadata outData = new TIFFImageMetadata(Collections.emptySet());
try {
if (Arrays.asList(inData.getMetadataFormatNames()).contains(SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME)) {
@@ -766,7 +762,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
}
}
catch (IIOInvalidTreeException e) {
processWarningOccurred(sequenceIndex, "Could not convert image meta data: " + e.getMessage());
processWarningOccurred(sequence.current(), "Could not convert image meta data: " + e.getMessage());
}
ifd = outData.getIFD();
@@ -966,14 +962,11 @@ public final class TIFFImageWriter extends ImageWriterBase {
@Override
public void prepareWriteSequence(final IIOMetadata streamMetadata) throws IOException {
if (writingSequence) {
throw new IllegalStateException("sequence writing has already been started!");
}
sequence.start();
assertOutput();
configureStreamByteOrder(streamMetadata, imageOutput);
writingSequence = true;
sequenceTIFFWriter = new TIFFWriter(isBigTIFF() ? 8 : 4);
sequenceTIFFWriter.writeTIFFHeader(imageOutput);
sequenceLastIFDPos = imageOutput.getStreamPosition();
@@ -985,26 +978,20 @@ public final class TIFFImageWriter extends ImageWriterBase {
@Override
public void writeToSequence(final IIOImage image, final ImageWriteParam param) throws IOException {
if (!writingSequence) {
throw new IllegalStateException("prepareWriteSequence() must be called before writeToSequence()!");
}
int sequenceIndex = sequence.advance();
if (sequenceIndex > 0) {
imageOutput.flushBefore(sequenceLastIFDPos);
imageOutput.seek(imageOutput.length());
}
sequenceLastIFDPos = writePage(sequenceIndex++, image, param, sequenceTIFFWriter, sequenceLastIFDPos);
sequenceLastIFDPos = writePage(sequenceIndex, image, param, sequenceTIFFWriter, sequenceLastIFDPos);
}
@Override
public void endWriteSequence() throws IOException {
if (!writingSequence) {
throw new IllegalStateException("prepareWriteSequence() must be called before endWriteSequence()!");
}
sequence.end();
writingSequence = false;
sequenceIndex = 0;
sequenceTIFFWriter = null;
sequenceLastIFDPos = -1;
imageOutput.flush();
@@ -1014,8 +1001,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
protected void resetMembers() {
super.resetMembers();
writingSequence = false;
sequenceIndex = 0;
sequence.reset();
sequenceTIFFWriter = null;
sequenceLastIFDPos = -1;
}
+1 -1
View File
@@ -61,7 +61,7 @@
</modules>
<properties>
<junit.jupiter.version>5.14.3</junit.jupiter.version>
<junit.jupiter.version>5.14.4</junit.jupiter.version>
</properties>
<dependencies>
+1 -1
View File
@@ -191,7 +191,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.4.0</version>
<version>3.5.0</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
+2 -2
View File
@@ -15,7 +15,7 @@
</description>
<properties>
<junit.jupiter.version>5.14.3</junit.jupiter.version>
<junit.jupiter.version>5.14.4</junit.jupiter.version>
</properties>
<dependencies>
@@ -82,7 +82,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.1</version>
<version>3.6.2</version>
<executions>
<execution>
<id>jakarta</id>