4
votes

What I have is a a large number of frames that need to be placed together in a larger image (like a mosaic). The required positions of the images are known.

There are a very large number of images so loading them all into memory is impractical at best.

Based on some other answers here I was able to override the methods in RenderedImage (specifically getData(rect)) to load in the appropriate data and return it.

This works just fine, however the image writer is always calling getData and requesting rows of data. It seems to me I should be able to change the ImageWriterParam to call for individual tiles instead, but when I tried the write function still calls for a single line from getData.

How can I force this to use tiles and call getTile instead.

BufferedOutputStream bos=null;
try {
   bos = new BufferedOutputStream(new FileOutputStream(new File("test2.tiff")));

   ImageWriter writer =(ImageWriter) ImageIO.getImageWritersBySuffix("tif").next();

   ImageOutputStream ios=null

   ios = ImageIO.createImageOutputStream(bos); 

   writer.setOutput(ios);
   ImageWriteParam param = writer.getDefaultWriteParam();
   param.setTilingMode(ImageWriteParam.MODE_DEFAULT);

   RenderedImage mosaic = new MosaicImage(imageFiles[]);

   writer.write(null,new IIOImage(mosaic,null,null),param);

    } catch (FileNotFoundException ex) {

    }

Note I can use param.setTilingMode(ImageWriteParam.MODE_EXPLICIT); and setTiling(w,h,xoff,yoff);

However when using this, writer.write still calls getData(rect) in my image, and very annoyingly does not call for a rectangle of the size specified by w,h. It calls a rectangle of a size that is different by some random amount(probably comes from something)

For example if I use setTiling(100,100,0,0);

one would expect that even if it does not call getTile from the image, the Rectangle passed to getData should be (0,0,100,100) but instead it passes Rectangle (0,0,96,96) which is not a multiple of the image width or anything else i can think of.

Thanks for any help

1

1 Answers

4
votes

If you read up on the TIFF 6.0 spec under the TileWidth and TileLength fields, you will find the text

TileWidth must be a multiple of 16. This restriction improves performance in some graphics environments and enhances compatibility with compression schemes such as JPEG.

And similar for TileLength. 100x100 isn't divisible by 16, but 96x96 is, which I bet is the TIFF encoder trying its best to fullfill your request.