@@ -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