mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-20 00:00:03 -04:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 75d7d5cdef | |||
| 177eec06cc | |||
| dc3d77ad95 |
+11
-24
@@ -32,6 +32,7 @@ package com.twelvemonkeys.imageio.plugins.bmp;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
|
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
|
||||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||||
|
import com.twelvemonkeys.imageio.util.SequenceSupport;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.IIOImage;
|
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 ICO_MAX_DIMENSION = 256;
|
||||||
private static final int INITIAL_ENTRY_COUNT = 8;
|
private static final int INITIAL_ENTRY_COUNT = 8;
|
||||||
|
|
||||||
private int sequenceIndex = -1;
|
private final SequenceSupport sequence = new SequenceSupport();
|
||||||
|
|
||||||
private ImageWriter pngDelegate;
|
private ImageWriter pngDelegate;
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ public final class ICOImageWriter extends DIBImageWriter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
sequenceIndex = -1;
|
sequence.reset();
|
||||||
|
|
||||||
if (pngDelegate != null) {
|
if (pngDelegate != null) {
|
||||||
pngDelegate.dispose();
|
pngDelegate.dispose();
|
||||||
@@ -107,16 +108,12 @@ public final class ICOImageWriter extends DIBImageWriter {
|
|||||||
@Override
|
@Override
|
||||||
public void prepareWriteSequence(final IIOMetadata streamMetadata) throws IOException {
|
public void prepareWriteSequence(final IIOMetadata streamMetadata) throws IOException {
|
||||||
assertOutput();
|
assertOutput();
|
||||||
|
sequence.start();
|
||||||
if (sequenceIndex >= 0) {
|
|
||||||
throw new IllegalStateException("writeSequence already started");
|
|
||||||
}
|
|
||||||
|
|
||||||
writeICOHeader();
|
writeICOHeader();
|
||||||
|
|
||||||
// Count: Needs to be updated for each new image
|
// Count: Needs to be updated for each new image
|
||||||
imageOutput.writeShort(0);
|
imageOutput.writeShort(0);
|
||||||
sequenceIndex = 0;
|
|
||||||
|
|
||||||
// TODO: Allow passing the initial size of the directory in the stream metadata?
|
// TODO: Allow passing the initial size of the directory in the stream metadata?
|
||||||
// - as this is much more efficient than growing...
|
// - as this is much more efficient than growing...
|
||||||
@@ -130,27 +127,19 @@ public final class ICOImageWriter extends DIBImageWriter {
|
|||||||
@Override
|
@Override
|
||||||
public void endWriteSequence() {
|
public void endWriteSequence() {
|
||||||
assertOutput();
|
assertOutput();
|
||||||
|
sequence.end();
|
||||||
if (sequenceIndex < 0) {
|
|
||||||
throw new IllegalStateException("prepareWriteSequence not called");
|
|
||||||
}
|
|
||||||
|
|
||||||
sequenceIndex = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToSequence(final IIOImage image, final ImageWriteParam param) throws IOException {
|
public void writeToSequence(final IIOImage image, final ImageWriteParam param) throws IOException {
|
||||||
assertOutput();
|
assertOutput();
|
||||||
|
int imageIndex = sequence.advance();
|
||||||
if (sequenceIndex < 0) {
|
|
||||||
throw new IllegalStateException("prepareWriteSequence not called");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image.hasRaster()) {
|
if (image.hasRaster()) {
|
||||||
throw new UnsupportedOperationException("Raster not supported");
|
throw new UnsupportedOperationException("Raster not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sequenceIndex >= INITIAL_ENTRY_COUNT) {
|
if (imageIndex >= INITIAL_ENTRY_COUNT) {
|
||||||
growIfNecessary();
|
growIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +161,7 @@ public final class ICOImageWriter extends DIBImageWriter {
|
|||||||
// Uncompressed, RLE4/RLE8 or PNG compressed
|
// Uncompressed, RLE4/RLE8 or PNG compressed
|
||||||
boolean pngCompression = param != null && "BI_PNG".equals(param.getCompressionType());
|
boolean pngCompression = param != null && "BI_PNG".equals(param.getCompressionType());
|
||||||
|
|
||||||
processImageStarted(sequenceIndex);
|
processImageStarted(imageIndex);
|
||||||
|
|
||||||
if (pngCompression) {
|
if (pngCompression) {
|
||||||
// NOTE: Embedding a PNG in a ICO is slightly different than a BMP with BI_PNG compression,
|
// 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
|
// Update count
|
||||||
imageOutput.seek(4);
|
imageOutput.seek(4);
|
||||||
imageOutput.writeShort(sequenceIndex + 1);
|
imageOutput.writeShort(imageIndex + 1);
|
||||||
|
|
||||||
// Write entry
|
// Write entry
|
||||||
int entryPosition = 6 + sequenceIndex * ENTRY_SIZE;
|
int entryPosition = 6 + imageIndex * ENTRY_SIZE;
|
||||||
imageOutput.seek(entryPosition);
|
imageOutput.seek(entryPosition);
|
||||||
|
|
||||||
long size = nextPosition - imageOffset;
|
long size = nextPosition - imageOffset;
|
||||||
writeEntry(width, height, colorModel, (int) size, (int) imageOffset);
|
writeEntry(width, height, colorModel, (int) size, (int) imageOffset);
|
||||||
|
|
||||||
sequenceIndex++;
|
|
||||||
|
|
||||||
imageOutput.seek(nextPosition);
|
imageOutput.seek(nextPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +252,7 @@ public final class ICOImageWriter extends DIBImageWriter {
|
|||||||
pngDelegate.addIIOWriteWarningListener(new IIOWriteWarningListener() {
|
pngDelegate.addIIOWriteWarningListener(new IIOWriteWarningListener() {
|
||||||
@Override
|
@Override
|
||||||
public void warningOccurred(ImageWriter source, int imageIndex, String warning) {
|
public void warningOccurred(ImageWriter source, int imageIndex, String warning) {
|
||||||
processWarningOccurred(sequenceIndex, warning);
|
processWarningOccurred(sequence.current(), warning);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+115
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+89
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-18
@@ -47,9 +47,12 @@ import java.awt.Dimension;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
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 {
|
final class DDSHeader {
|
||||||
|
|
||||||
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide
|
|
||||||
private int flags;
|
private int flags;
|
||||||
|
|
||||||
private int mipMapCount;
|
private int mipMapCount;
|
||||||
@@ -69,26 +72,16 @@ final class DDSHeader {
|
|||||||
static DDSHeader read(final ImageInputStream imageInput) throws IOException {
|
static DDSHeader read(final ImageInputStream imageInput) throws IOException {
|
||||||
DDSHeader header = new DDSHeader();
|
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]
|
int dwSize = imageInput.readInt(); // [4,7]
|
||||||
if (dwSize != DDS.HEADER_SIZE) {
|
if (dwSize != DDS.HEADER_SIZE) {
|
||||||
throw new IIOException(String.format("Invalid DDS header size (expected %d): %d", DDS.HEADER_SIZE, dwSize));
|
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]
|
header.flags = imageInput.readInt(); // [8,11]
|
||||||
if (!header.getFlag(DDS.FLAG_CAPS
|
if (!header.hasFlag(DDS.FLAG_CAPS | DDS.FLAG_HEIGHT | DDS.FLAG_WIDTH | DDS.FLAG_PIXELFORMAT)) {
|
||||||
| DDS.FLAG_HEIGHT
|
// NOTE: The Microsoft DDS documentation mention that readers should not rely on these flags...
|
||||||
| DDS.FLAG_WIDTH
|
throw new IIOException("Required DDS flag missing in header: " + Integer.toBinaryString(header.flags));
|
||||||
| DDS.FLAG_PIXELFORMAT)) {
|
|
||||||
throw new IIOException("Required DDS Flag missing in header: " + Integer.toBinaryString(header.flags));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read Height & Width
|
// Read Height & Width
|
||||||
@@ -109,7 +102,7 @@ final class DDSHeader {
|
|||||||
// DDS_PIXELFORMAT structure
|
// DDS_PIXELFORMAT structure
|
||||||
int px_dwSize = imageInput.readInt(); // [76,79]
|
int px_dwSize = imageInput.readInt(); // [76,79]
|
||||||
if (px_dwSize != DDS.PIXELFORMAT_SIZE) {
|
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]
|
header.pixelFormatFlags = imageInput.readInt(); // [80,83]
|
||||||
@@ -128,6 +121,7 @@ final class DDSHeader {
|
|||||||
int dwReserved2 = imageInput.readInt(); // [124,127]
|
int dwReserved2 = imageInput.readInt(); // [124,127]
|
||||||
|
|
||||||
if (header.fourCC == DDSType.DXT10.fourCC()) {
|
if (header.fourCC == DDSType.DXT10.fourCC()) {
|
||||||
|
// If DXT10, the DXT10 header will follow immediately
|
||||||
header.dxt10Header = DXT10Header.read(imageInput);
|
header.dxt10Header = DXT10Header.read(imageInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +140,8 @@ final class DDSHeader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean getFlag(int mask) {
|
private boolean hasFlag(int mask) {
|
||||||
return (flags & mask) != 0;
|
return (flags & mask) == mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getWidth(int imageIndex) {
|
int getWidth(int imageIndex) {
|
||||||
|
|||||||
-1
@@ -77,5 +77,4 @@ final class DDSImageMetadata extends StandardImageMetadataSupport {
|
|||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -33,6 +33,7 @@ package com.twelvemonkeys.imageio.plugins.dds;
|
|||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.ImageReadParam;
|
import javax.imageio.ImageReadParam;
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
@@ -167,6 +168,12 @@ public final class DDSImageReader extends ImageReaderBase {
|
|||||||
private void readHeader() throws IOException {
|
private void readHeader() throws IOException {
|
||||||
if (header == null) {
|
if (header == null) {
|
||||||
imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
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);
|
header = DDSHeader.read(imageInput);
|
||||||
imageInput.flushBefore(imageInput.getStreamPosition());
|
imageInput.flushBefore(imageInput.getStreamPosition());
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-33
@@ -2,6 +2,7 @@ package com.twelvemonkeys.imageio.plugins.dds;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.ImageWriterBase;
|
import com.twelvemonkeys.imageio.ImageWriterBase;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
|
import com.twelvemonkeys.imageio.util.SequenceSupport;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.IIOImage;
|
||||||
@@ -29,9 +30,9 @@ import java.nio.file.Paths;
|
|||||||
*/
|
*/
|
||||||
class DDSImageWriter extends ImageWriterBase {
|
class DDSImageWriter extends ImageWriterBase {
|
||||||
|
|
||||||
private long startPos;
|
private final SequenceSupport mipmapSequence = new SequenceSupport();
|
||||||
// TODO: Create a SequenceSupport class that handles sequence prepare/write/end
|
|
||||||
private int mipmapIndex = -1;
|
private long headerStartPos;
|
||||||
private DDSType mipmapType;
|
private DDSType mipmapType;
|
||||||
private Dimension mipmapDimension;
|
private Dimension mipmapDimension;
|
||||||
|
|
||||||
@@ -46,7 +47,8 @@ class DDSImageWriter extends ImageWriterBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
mipmapIndex = -1;
|
headerStartPos = 0;
|
||||||
|
mipmapSequence.reset();
|
||||||
mipmapType = null;
|
mipmapType = null;
|
||||||
mipmapDimension = null;
|
mipmapDimension = null;
|
||||||
}
|
}
|
||||||
@@ -64,30 +66,22 @@ class DDSImageWriter extends ImageWriterBase {
|
|||||||
@Override
|
@Override
|
||||||
public void prepareWriteSequence(IIOMetadata streamMetadata) throws IOException {
|
public void prepareWriteSequence(IIOMetadata streamMetadata) throws IOException {
|
||||||
assertOutput();
|
assertOutput();
|
||||||
|
mipmapSequence.start();
|
||||||
|
|
||||||
if (mipmapIndex >= 0) {
|
|
||||||
throw new IllegalStateException("writeSequence already started");
|
|
||||||
}
|
|
||||||
mipmapIndex = 0;
|
|
||||||
|
|
||||||
startPos = imageOutput.getStreamPosition();
|
|
||||||
imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||||
imageOutput.writeInt(DDS.MAGIC);
|
imageOutput.writeInt(DDS.MAGIC);
|
||||||
imageOutput.flush();
|
imageOutput.flush();
|
||||||
|
|
||||||
|
headerStartPos = imageOutput.getStreamPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endWriteSequence() throws IOException {
|
public void endWriteSequence() throws IOException {
|
||||||
assertOutput();
|
int mipmapCount = mipmapSequence.end();
|
||||||
|
|
||||||
if (mipmapIndex < 0) {
|
// Go back and update header
|
||||||
throw new IllegalStateException("prepareWriteSequence not called");
|
updateHeader(mipmapCount);
|
||||||
}
|
|
||||||
|
|
||||||
// Go back and update hader
|
|
||||||
updateHeader(mipmapIndex);
|
|
||||||
|
|
||||||
mipmapIndex = -1;
|
|
||||||
mipmapType = null;
|
mipmapType = null;
|
||||||
mipmapDimension = null;
|
mipmapDimension = null;
|
||||||
|
|
||||||
@@ -103,13 +97,12 @@ class DDSImageWriter extends ImageWriterBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToSequence(IIOImage image, ImageWriteParam param) throws IOException {
|
public void writeToSequence(IIOImage image, ImageWriteParam param) throws IOException {
|
||||||
if (mipmapIndex < 0) {
|
int mipmapIndex = mipmapSequence.advance();
|
||||||
throw new IllegalStateException("prepareWriteSequence not called");
|
|
||||||
}
|
|
||||||
|
|
||||||
Raster raster = getRaster(image);
|
Raster raster = getRaster(image);
|
||||||
ensureImageChannels(raster);
|
ensureImageChannels(raster);
|
||||||
ensureTextureDimension(raster);
|
ensureTextureDimension(raster);
|
||||||
|
mipmapDimension = new Dimension(raster.getWidth(), raster.getHeight());
|
||||||
|
|
||||||
DDSImageWriteParam ddsParam = param instanceof DDSImageWriteParam
|
DDSImageWriteParam ddsParam = param instanceof DDSImageWriteParam
|
||||||
? ((DDSImageWriteParam) param)
|
? ((DDSImageWriteParam) param)
|
||||||
@@ -120,7 +113,7 @@ class DDSImageWriter extends ImageWriterBase {
|
|||||||
mipmapType = type;
|
mipmapType = type;
|
||||||
}
|
}
|
||||||
else if (type != mipmapType) {
|
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) {
|
if (mipmapType == null) {
|
||||||
throw new IIOException("Only compressed DDS using DXT1-5 or DXT10 with block compression is currently supported");
|
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);
|
processImageProgress(100f);
|
||||||
processImageComplete();
|
processImageComplete();
|
||||||
|
|
||||||
mipmapDimension = new Dimension(raster.getWidth(), raster.getHeight());
|
|
||||||
mipmapIndex++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Raster getRaster(IIOImage image) throws IIOException {
|
private static Raster getRaster(IIOImage image) throws IIOException {
|
||||||
@@ -210,7 +200,7 @@ class DDSImageWriter extends ImageWriterBase {
|
|||||||
//dwDepth
|
//dwDepth
|
||||||
imageOutput.writeInt(0);
|
imageOutput.writeInt(0);
|
||||||
//dwMipmapCount
|
//dwMipmapCount
|
||||||
imageOutput.writeInt(1);
|
imageOutput.writeInt(1); // Should probably write 0 here for non-mipmap?
|
||||||
//reserved
|
//reserved
|
||||||
imageOutput.write(new byte[44]);
|
imageOutput.write(new byte[44]);
|
||||||
//pixFmt
|
//pixFmt
|
||||||
@@ -230,7 +220,7 @@ class DDSImageWriter extends ImageWriterBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
long streamPosition = imageOutput.getStreamPosition();
|
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();
|
int flags = imageOutput.readInt();
|
||||||
imageOutput.seek(imageOutput.getStreamPosition() - 4);
|
imageOutput.seek(imageOutput.getStreamPosition() - 4);
|
||||||
@@ -268,15 +258,14 @@ class DDSImageWriter extends ImageWriterBase {
|
|||||||
//dwRGBBitCount
|
//dwRGBBitCount
|
||||||
imageOutput.writeInt(type.blockSize() * 8); // TODO: Is bitcount always a multiple of 8?
|
imageOutput.writeInt(type.blockSize() * 8); // TODO: Is bitcount always a multiple of 8?
|
||||||
|
|
||||||
int[] mask = type.rgbaMasks;
|
|
||||||
//dwRBitMask
|
//dwRBitMask
|
||||||
imageOutput.writeInt(mask[0]);
|
imageOutput.writeInt(type.rgbaMasks[0]);
|
||||||
//dwGBitMask
|
//dwGBitMask
|
||||||
imageOutput.writeInt(mask[1]);
|
imageOutput.writeInt(type.rgbaMasks[1]);
|
||||||
//dwBBitMask
|
//dwBBitMask
|
||||||
imageOutput.writeInt(mask[2]);
|
imageOutput.writeInt(type.rgbaMasks[2]);
|
||||||
//dwABitMask
|
//dwABitMask
|
||||||
imageOutput.writeInt(mask[3]);
|
imageOutput.writeInt(type.rgbaMasks[3]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//write 5 zero integers as fourCC is used
|
//write 5 zero integers as fourCC is used
|
||||||
@@ -302,7 +291,8 @@ class DDSImageWriter extends ImageWriterBase {
|
|||||||
imageOutput.writeInt(DDS.PIXEL_FORMAT_FLAG_FOURCC);
|
imageOutput.writeInt(DDS.PIXEL_FORMAT_FLAG_FOURCC);
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
if (args.length != 1) {
|
||||||
throw new IllegalArgumentException("Use 1 input file at a time.");
|
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"))));
|
ImageIO.write(ImageIO.read(new File(args[0])), "dds", new MemoryCacheImageOutputStream(Files.newOutputStream(Paths.get("output.dds"))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-19
@@ -33,6 +33,7 @@ package com.twelvemonkeys.imageio.plugins.icns;
|
|||||||
import com.twelvemonkeys.imageio.ImageWriterBase;
|
import com.twelvemonkeys.imageio.ImageWriterBase;
|
||||||
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
|
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
|
||||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||||
|
import com.twelvemonkeys.imageio.util.SequenceSupport;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.IIOImage;
|
import javax.imageio.IIOImage;
|
||||||
@@ -55,7 +56,7 @@ import java.util.Iterator;
|
|||||||
*/
|
*/
|
||||||
public final class ICNSImageWriter extends ImageWriterBase {
|
public final class ICNSImageWriter extends ImageWriterBase {
|
||||||
|
|
||||||
private int sequenceIndex = -1;
|
private final SequenceSupport sequence = new SequenceSupport();
|
||||||
private ImageWriter pngDelegate;
|
private ImageWriter pngDelegate;
|
||||||
|
|
||||||
ICNSImageWriter(ImageWriterSpi provider) {
|
ICNSImageWriter(ImageWriterSpi provider) {
|
||||||
@@ -64,7 +65,7 @@ public final class ICNSImageWriter extends ImageWriterBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
sequenceIndex = -1;
|
sequence.reset();
|
||||||
|
|
||||||
if (pngDelegate != null) {
|
if (pngDelegate != null) {
|
||||||
pngDelegate.dispose();
|
pngDelegate.dispose();
|
||||||
@@ -97,41 +98,29 @@ public final class ICNSImageWriter extends ImageWriterBase {
|
|||||||
@Override
|
@Override
|
||||||
public void prepareWriteSequence(final IIOMetadata streamMetadata) throws IOException {
|
public void prepareWriteSequence(final IIOMetadata streamMetadata) throws IOException {
|
||||||
assertOutput();
|
assertOutput();
|
||||||
|
sequence.start();
|
||||||
|
|
||||||
// TODO: Allow TOC resource to be passed as stream metadata?
|
// TODO: Allow TOC resource to be passed as stream metadata?
|
||||||
// - We only need number of icons to be written later
|
// - We only need number of icons to be written later
|
||||||
// - The contents of the TOC could be updated while adding to the sequence
|
// - The contents of the TOC could be updated while adding to the sequence
|
||||||
|
|
||||||
if (sequenceIndex >= 0) {
|
|
||||||
throw new IllegalStateException("writeSequence already started");
|
|
||||||
}
|
|
||||||
|
|
||||||
writeICNSHeader();
|
writeICNSHeader();
|
||||||
sequenceIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("RedundantThrows")
|
@SuppressWarnings("RedundantThrows")
|
||||||
@Override
|
@Override
|
||||||
public void endWriteSequence() throws IOException {
|
public void endWriteSequence() throws IOException {
|
||||||
assertOutput();
|
assertOutput();
|
||||||
|
sequence.end();
|
||||||
if (sequenceIndex < 0) {
|
|
||||||
throw new IllegalStateException("prepareWriteSequence not called");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Now that we know the number of icon resources, we could move all data backwards
|
// 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.
|
// and write a TOC... But I don't think the benefit will outweigh the cost.
|
||||||
|
|
||||||
sequenceIndex = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToSequence(final IIOImage image, final ImageWriteParam param) throws IOException {
|
public void writeToSequence(final IIOImage image, final ImageWriteParam param) throws IOException {
|
||||||
assertOutput();
|
assertOutput();
|
||||||
|
int imageIndex = sequence.advance();
|
||||||
if (sequenceIndex < 0) {
|
|
||||||
throw new IllegalStateException("prepareWriteSequence not called");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (image.hasRaster()) {
|
if (image.hasRaster()) {
|
||||||
throw new UnsupportedOperationException("image has a Raster");
|
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(IconResource.typeFromImage(image.getRenderedImage(), "PNG"));
|
||||||
imageOutput.writeInt(0); // Size, update later
|
imageOutput.writeInt(0); // Size, update later
|
||||||
|
|
||||||
processImageStarted(sequenceIndex);
|
processImageStarted(imageIndex);
|
||||||
|
|
||||||
// Write icon in PNG format
|
// Write icon in PNG format
|
||||||
ImageWriter writer = getPNGDelegate();
|
ImageWriter writer = getPNGDelegate();
|
||||||
@@ -208,7 +197,7 @@ public final class ICNSImageWriter extends ImageWriterBase {
|
|||||||
pngDelegate.addIIOWriteWarningListener(new IIOWriteWarningListener() {
|
pngDelegate.addIIOWriteWarningListener(new IIOWriteWarningListener() {
|
||||||
@Override
|
@Override
|
||||||
public void warningOccurred(ImageWriter source, int imageIndex, String warning) {
|
public void warningOccurred(ImageWriter source, int imageIndex, String warning) {
|
||||||
processWarningOccurred(sequenceIndex, warning);
|
processWarningOccurred(sequence.current(), warning);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-23
@@ -42,6 +42,7 @@ import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
|
|||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||||
|
import com.twelvemonkeys.imageio.util.SequenceSupport;
|
||||||
import com.twelvemonkeys.io.enc.EncoderStream;
|
import com.twelvemonkeys.io.enc.EncoderStream;
|
||||||
import com.twelvemonkeys.io.enc.PackBitsEncoder;
|
import com.twelvemonkeys.io.enc.PackBitsEncoder;
|
||||||
import com.twelvemonkeys.lang.Validate;
|
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 storing multiple images in one stream (multi-page TIFF)
|
||||||
// Support more of the ImageIO metadata (ie. compression from metadata, etc)
|
// Support more of the ImageIO metadata (ie. compression from metadata, etc)
|
||||||
|
|
||||||
/**
|
private final SequenceSupport sequence = new SequenceSupport();
|
||||||
* Flag for active sequence writing
|
|
||||||
*/
|
|
||||||
private boolean writingSequence = false;
|
|
||||||
|
|
||||||
private int sequenceIndex = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata writer for sequence writing
|
* Metadata writer for sequence writing
|
||||||
@@ -751,7 +747,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
ifd = ((TIFFImageMetadata) inData).getIFD();
|
ifd = ((TIFFImageMetadata) inData).getIFD();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TIFFImageMetadata outData = new TIFFImageMetadata(Collections.<Entry>emptySet());
|
TIFFImageMetadata outData = new TIFFImageMetadata(Collections.emptySet());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (Arrays.asList(inData.getMetadataFormatNames()).contains(SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME)) {
|
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) {
|
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();
|
ifd = outData.getIFD();
|
||||||
@@ -966,14 +962,11 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareWriteSequence(final IIOMetadata streamMetadata) throws IOException {
|
public void prepareWriteSequence(final IIOMetadata streamMetadata) throws IOException {
|
||||||
if (writingSequence) {
|
sequence.start();
|
||||||
throw new IllegalStateException("sequence writing has already been started!");
|
|
||||||
}
|
|
||||||
|
|
||||||
assertOutput();
|
assertOutput();
|
||||||
configureStreamByteOrder(streamMetadata, imageOutput);
|
configureStreamByteOrder(streamMetadata, imageOutput);
|
||||||
|
|
||||||
writingSequence = true;
|
|
||||||
sequenceTIFFWriter = new TIFFWriter(isBigTIFF() ? 8 : 4);
|
sequenceTIFFWriter = new TIFFWriter(isBigTIFF() ? 8 : 4);
|
||||||
sequenceTIFFWriter.writeTIFFHeader(imageOutput);
|
sequenceTIFFWriter.writeTIFFHeader(imageOutput);
|
||||||
sequenceLastIFDPos = imageOutput.getStreamPosition();
|
sequenceLastIFDPos = imageOutput.getStreamPosition();
|
||||||
@@ -985,26 +978,20 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToSequence(final IIOImage image, final ImageWriteParam param) throws IOException {
|
public void writeToSequence(final IIOImage image, final ImageWriteParam param) throws IOException {
|
||||||
if (!writingSequence) {
|
int sequenceIndex = sequence.advance();
|
||||||
throw new IllegalStateException("prepareWriteSequence() must be called before writeToSequence()!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sequenceIndex > 0) {
|
if (sequenceIndex > 0) {
|
||||||
imageOutput.flushBefore(sequenceLastIFDPos);
|
imageOutput.flushBefore(sequenceLastIFDPos);
|
||||||
imageOutput.seek(imageOutput.length());
|
imageOutput.seek(imageOutput.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
sequenceLastIFDPos = writePage(sequenceIndex++, image, param, sequenceTIFFWriter, sequenceLastIFDPos);
|
sequenceLastIFDPos = writePage(sequenceIndex, image, param, sequenceTIFFWriter, sequenceLastIFDPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endWriteSequence() throws IOException {
|
public void endWriteSequence() throws IOException {
|
||||||
if (!writingSequence) {
|
sequence.end();
|
||||||
throw new IllegalStateException("prepareWriteSequence() must be called before endWriteSequence()!");
|
|
||||||
}
|
|
||||||
|
|
||||||
writingSequence = false;
|
|
||||||
sequenceIndex = 0;
|
|
||||||
sequenceTIFFWriter = null;
|
sequenceTIFFWriter = null;
|
||||||
sequenceLastIFDPos = -1;
|
sequenceLastIFDPos = -1;
|
||||||
imageOutput.flush();
|
imageOutput.flush();
|
||||||
@@ -1014,8 +1001,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
super.resetMembers();
|
super.resetMembers();
|
||||||
|
|
||||||
writingSequence = false;
|
sequence.reset();
|
||||||
sequenceIndex = 0;
|
|
||||||
sequenceTIFFWriter = null;
|
sequenceTIFFWriter = null;
|
||||||
sequenceLastIFDPos = -1;
|
sequenceLastIFDPos = -1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user