Skip to content

Commit e59dbd6

Browse files
Recompress unsupported data instead of throwing an exception
1 parent 54a2d32 commit e59dbd6

File tree

1 file changed

+52
-27
lines changed

1 file changed

+52
-27
lines changed

src/main/java/PrecompressedTileReaderWriter.java

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ public class PrecompressedTileReaderWriter {
6363
/** The file to be written. */
6464
private String outputFile;
6565

66+
/** Compression type. */
67+
private String compression;
68+
6669
/**
6770
* Construct a new PrecompressedTileReaderWriter to read the specified input file
6871
* and write the given output file. Tile sizes are calculated automatically.
@@ -102,15 +105,14 @@ private void initialize() throws DependencyException, FormatException, IOExcepti
102105

103106
ICompressedTileReader tileReader = (ICompressedTileReader) reader;
104107
CompressionType type = CompressionType.get(tileReader.getTileCodec(0));
105-
String compression = type.getCompression();
108+
compression = type.getCompression();
106109

107110
// set up the writer and associate it with the output file
108111
ImageWriter baseWriter = new ImageWriter();
109112
// indicating that tiles will be written in their natural order
110113
// is usually important
111114
baseWriter.setWriteSequentially(true);
112115
baseWriter.setMetadataRetrieve(omexml);
113-
baseWriter.setInterleaved(reader.isInterleaved() || compression.startsWith("JPEG"));
114116

115117
// set the tile size height and width for writing
116118
// tile size must match between reader and writer when
@@ -144,41 +146,64 @@ public void readWriteTiles() throws FormatException, IOException {
144146

145147
// tile size can vary across resolutions,
146148
// so make sure it gets updated before starting to write
149+
// for truly precompressed data, use the tile dimensions
150+
// from the reader
151+
// for data that isn't compatible with precompression,
152+
// use the (possibly adjusted) tile dimensions returned
153+
// by the writer
147154
int tileWidth = reader.getOptimalTileWidth();
148155
int tileHeight = reader.getOptimalTileHeight();
149-
writer.setTileSizeX(tileWidth);
150-
writer.setTileSizeY(tileHeight);
151-
152-
// in practice, warning and switching to a normal decompress/recompress
153-
// workflow here may be a better strategy
154-
// an exception is thrown here to make it very clear that not all
155-
// input/output combinations can be used with this feature
156+
int tw = writer.setTileSizeX(tileWidth);
157+
int th = writer.setTileSizeY(tileHeight);
158+
159+
// in practice, many input datasets will have a mix of compression
160+
// types, especially between the "real" image data and the label/macro/etc.
161+
// this level of flexibility isn't supported in the precompressed writing API
162+
// at the moment, so anything not matching the expected compression settings
163+
// will need to be recompressed
156164
if (!FormatTools.canUsePrecompressedTiles(reader, writer, series, res)) {
157-
throw new FormatException("Cannot use precompressed tiles for series " +
165+
System.out.println("Cannot use precompressed tiles for series " +
158166
series + ", resolution " + res);
167+
168+
// proceed with a standard conversion for this resolution
169+
writer.setInterleaved(reader.isInterleaved());
170+
for (int image=0; image<reader.getImageCount(); image++) {
171+
for (int y=0; y<reader.getSizeY(); y+=th) {
172+
int height = (int) Math.min(th, reader.getSizeY() - y);
173+
for (int x=0; x<reader.getSizeX(); x+=tw) {
174+
int width = (int) Math.min(tw, reader.getSizeX() - x);
175+
176+
buf = reader.openBytes(image, x, y, width, height);
177+
writer.saveBytes(image, buf, x, y, width, height);
178+
}
179+
}
180+
}
159181
}
182+
else {
183+
writer.setInterleaved(reader.isInterleaved() || compression.startsWith("JPEG"));
160184

161-
// convert each image in the current series
162-
for (int image=0; image<reader.getImageCount(); image++) {
163-
ICompressedTileReader tileReader = (ICompressedTileReader) reader;
185+
// convert each image in the current series
186+
for (int image=0; image<reader.getImageCount(); image++) {
187+
ICompressedTileReader tileReader = (ICompressedTileReader) reader;
164188

165-
// precompressed API operates on tile row/column indexes, not XY pixel coordinates
166-
// this is to prevent trying to read a tile that doesn't align with the boundaries
167-
// of the compressed tile
168-
int nXTiles = tileReader.getTileColumns(image);
169-
int nYTiles = tileReader.getTileRows(image);
189+
// precompressed API operates on tile row/column indexes, not XY pixel coordinates
190+
// this is to prevent trying to read a tile that doesn't align with the boundaries
191+
// o the compressed tile
192+
int nXTiles = tileReader.getTileColumns(image);
193+
int nYTiles = tileReader.getTileRows(image);
170194

171-
for (int y=0; y<nYTiles; y++) {
172-
for (int x=0; x<nXTiles; x++) {
173-
// the x and y coordinates for the current tile
174-
int tileX = x * tileWidth;
195+
for (int y=0; y<nYTiles; y++) {
175196
int tileY = y * tileHeight;
176-
int width = (int) Math.min(tileWidth, reader.getSizeX() - tileX);
177197
int height = (int) Math.min(tileHeight, reader.getSizeY() - tileY);
178-
179-
// read tiles from the input file and write them to the output file
180-
buf = tileReader.openCompressedBytes(image, x, y);
181-
((ICompressedTileWriter) writer).saveCompressedBytes(image, buf, tileX, tileY, width, height);
198+
for (int x=0; x<nXTiles; x++) {
199+
// the x and y coordinates for the current tile
200+
int tileX = x * tileWidth;
201+
int width = (int) Math.min(tileWidth, reader.getSizeX() - tileX);
202+
203+
// read tiles from the input file and write them to the output file
204+
buf = tileReader.openCompressedBytes(image, x, y);
205+
((ICompressedTileWriter) writer).saveCompressedBytes(image, buf, tileX, tileY, width, height);
206+
}
182207
}
183208
}
184209
}

0 commit comments

Comments
 (0)