Skip to main content

Out of Memory Errors saving large Mosaic TIFF

Please note these java.net forums are being decommissioned and use the new and improved forums at https://community.oracle.com/community/java.
11 replies [Last post]
rswhite
Offline
Joined: 2011-09-07

Hello.

I'm trying to create an image to be printed 24" x 24" that needs to be printed at 2400dpi. I'm using 1024x1024 pixel tiles and trying to use the mosaic operator to create the image. The tiles are all being created properly, MOSAIC operator throws no errors and smaller images work fine. However, when I try and save the large image as a tiled TIFF it throws exceptions complaining about out of heap size error. I'm specifying 6GB to 10GB of RAM on the java command line. I can have the printer "stitch" the tiles together but I'd prefer to just be able to give them the image and have them print it.

With that being said, I've stripped down the code to a simple set that still reproduces the problem, although I doubt anyone will want to run it and wait for it to throw the error. If you don't supply a 1024x1024 input image, a blank one is created for you and should still produce the error. I've also attached this as JaiTest.java.

Can anyone give suggestions or point me in the direction of what I'm doing wrong?

import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.awt.image.renderable.ParameterBlock;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Vector;

import javax.imageio.ImageWriteParam;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.RasterFactory;
import javax.media.jai.RenderedOp;
import javax.media.jai.TiledImage;
import javax.media.jai.operator.MosaicDescriptor;

import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;
import com.sun.media.jai.codec.TIFFEncodeParam;

public class JaiTest
{
private static int tileWidth = 1024;
private static int tileHeight = 1024;
private static int numberOfBands = 3;
private static SampleModel sampleModel = null;
private static ColorModel colorModel = null;
private static int numberOfRows = 58;
private static int numberOfColumns = 58;

static
{
System.setProperty("com.sun.media.jai.disableMediaLib", "true");
}

public static void main( String[] args ) throws Exception
{
String templateFileName = null;
sampleModel = RasterFactory.createBandedSampleModel(DataBuffer.TYPE_BYTE, tileWidth, tileHeight, numberOfBands);
colorModel = TiledImage.createColorModel(sampleModel);

if( args.length <= 0 || args == null )
{
templateFileName = "testTemplate-1024x1024.tiff";
createTemplateTile(templateFileName);
}
else
{
templateFileName = args[0];
}

List<String> tileFileList = new ArrayList<String>();
for( int i = 0; i < numberOfRows * numberOfColumns; i++ )
{
tileFileList.add(i, templateFileName);
}

renderMosaicFromTiles(tileFileList, numberOfRows * numberOfColumns, "largeTiledTiff.tiff");
}

public static void renderMosaicFromTiles( List<String> inTileFilesList, int inImageCount, String inImageName ) throws Exception
{
int xTrans = 0;
int yTrans = 0;

ImageLayout imageLayout = new ImageLayout();
imageLayout.setTileGridXOffset(0);
imageLayout.setTileGridYOffset(0);
imageLayout.setTileWidth(tileWidth);
imageLayout.setTileHeight(tileHeight);
imageLayout.setColorModel(colorModel);
imageLayout.setSampleModel(sampleModel);

ParameterBlockJAI readParams = new ParameterBlockJAI("ImageRead", "rendered");
Vector<Object> renderedOpsVector = new Vector<Object>();

for( int i = 1; i <= inTileFilesList.size(); i++ )
{
readParams.setParameter("Input", inTileFilesList.get(i - 1));

ParameterBlockJAI transParams = new ParameterBlockJAI("Translate", "rendered");

transParams.addSource(JAI.create("ImageRead", readParams, null));

transParams.setParameter("xTrans", (float) xTrans);
transParams.setParameter("yTrans", (float) yTrans);

renderedOpsVector.addElement(JAI.create("Translate", transParams, null));

if( (i % Math.sqrt(inImageCount)) == 0 )
{
yTrans += tileHeight;
xTrans = 0;
}
else
{
xTrans += tileWidth;
}
}

ParameterBlockJAI mosaicParameterBlockJAI = new ParameterBlockJAI("Mosaic", "rendered");
mosaicParameterBlockJAI.setSources(renderedOpsVector);
mosaicParameterBlockJAI.setParameter("mosaicType", MosaicDescriptor.MOSAIC_TYPE_OVERLAY);

RenderedOp mosaicRenderedOp = JAI.create("Mosaic", mosaicParameterBlockJAI, null);
renderedOpsVector.clear();

saveRenderedOp(mosaicRenderedOp, inImageName);

ParameterBlock parameterBlock = new ParameterBlock();

double scaleX = (mosaicRenderedOp.getWidth() * .50) / mosaicRenderedOp.getWidth();
double scaleY = (mosaicRenderedOp.getHeight() * .50) / mosaicRenderedOp.getHeight();

parameterBlock.removeSources();
parameterBlock.removeParameters();
parameterBlock.addSource(mosaicRenderedOp);
parameterBlock.add(scaleX);
parameterBlock.add(scaleY);
parameterBlock.add(0.0f);
parameterBlock.add(0.0f);

String myImageName = inImageName.replaceAll("\\.tiff", "_scaleX-" + scaleX + "_scaleY-" + scaleY + ".tiff");

saveRenderedOp(JAI.create("SubsampleAverage", parameterBlock, null), myImageName);

// .25
scaleX = (mosaicRenderedOp.getWidth() * .25) / mosaicRenderedOp.getWidth();
scaleY = (mosaicRenderedOp.getHeight() * .25) / mosaicRenderedOp.getHeight();

parameterBlock.removeSources();
parameterBlock.removeParameters();
parameterBlock.addSource(mosaicRenderedOp);
parameterBlock.add(scaleX);
parameterBlock.add(scaleY);
parameterBlock.add(0.0f);
parameterBlock.add(0.0f);

myImageName = inImageName.replaceAll("\\.tiff", "_scaleX-" + scaleX + "_scaleY-" + scaleY + ".tiff");
saveRenderedOp(JAI.create("SubsampleAverage", parameterBlock, null), myImageName);
}

public static void saveRenderedOp( RenderedOp inRenderedOp, String inImageName )
{
System.out.println("DEBUG: writting image file:" + inImageName);

JAI.getDefaultInstance().getTileCache().setMemoryCapacity(1073741824L);

ParameterBlock parameterBlock = new ParameterBlock();
parameterBlock.addSource(inRenderedOp);

TIFFImageWriteParam tiffImageWriteParam = new TIFFImageWriteParam(Locale.ENGLISH);
tiffImageWriteParam.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
tiffImageWriteParam.setTiling(tileWidth, tileHeight, 0, 0);
tiffImageWriteParam.setCompressionMode(TIFFImageWriteParam.MODE_DISABLED);

ParameterBlockJAI newWriteParams = new ParameterBlockJAI("ImageWrite", "rendered");
newWriteParams.addSource(inRenderedOp);
newWriteParams.setParameter("Output", inImageName);
newWriteParams.setParameter("Format", "TIFF");
newWriteParams.setParameter("WriteParam", tiffImageWriteParam);
JAI.create("ImageWrite", newWriteParams);
}

public static void createTemplateTile( String inImageName ) throws Exception
{
TiledImage tiledImage = new TiledImage(0, 0, tileWidth, tileHeight, 0, 0, sampleModel, colorModel);

TIFFEncodeParam tiffEncodeParam = new TIFFEncodeParam();
tiffEncodeParam.setWriteTiled(true);
tiffEncodeParam.setCompression(TIFFEncodeParam.COMPRESSION_NONE);

int xIndex = 0;
int yIndex = 0;
WritableRaster writableRaster = null;
for( int x = 0; x < tileWidth; x++ )
{
for( int y = 0; y < tileHeight; y++ )
{
xIndex = tiledImage.XToTileX(x);
yIndex = tiledImage.YToTileY(y);
writableRaster = tiledImage.getWritableTile(xIndex, yIndex);

// grey
writableRaster.setPixel(x, y, new int[] { 128, 128, 128 });
tiledImage.releaseWritableTile(xIndex, yIndex);
}
}

System.out.println("writting: " + inImageName);
JAI.create("filestore", tiledImage, inImageName, "TIFF", tiffEncodeParam);
}

}

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
rswhite
Offline
Joined: 2011-09-07

I forgot to rename the file from .java to something else. I changed it to .txt extension.

rswhite wrote:

Hello.

I'm trying to create an image to be printed 24" x 24" that needs to be printed at 2400dpi. I'm using 1024x1024 pixel tiles and trying to use the mosaic operator to create the image. The tiles are all being created properly, MOSAIC operator throws no errors and smaller images work fine. However, when I try and save the large image as a tiled TIFF it throws exceptions complaining about out of heap size error. I'm specifying 6GB to 10GB of RAM on the java command line. I can have the printer "stitch" the tiles together but I'd prefer to just be able to give them the image and have them print it.

With that being said, I've stripped down the code to a simple set that still reproduces the problem, although I doubt anyone will want to run it and wait for it to throw the error. If you don't supply a 1024x1024 input image, a blank one is created for you and should still produce the error. I've also attached this as JaiTest.java.

Can anyone give suggestions or point me in the direction of what I'm doing wrong?

import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.awt.image.renderable.ParameterBlock;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Vector;

import javax.imageio.ImageWriteParam;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.RasterFactory;
import javax.media.jai.RenderedOp;
import javax.media.jai.TiledImage;
import javax.media.jai.operator.MosaicDescriptor;

import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;
import com.sun.media.jai.codec.TIFFEncodeParam;

public class JaiTest
{
private static int tileWidth = 1024;
private static int tileHeight = 1024;
private static int numberOfBands = 3;
private static SampleModel sampleModel = null;
private static ColorModel colorModel = null;
private static int numberOfRows = 58;
private static int numberOfColumns = 58;

static
{
System.setProperty("com.sun.media.jai.disableMediaLib", "true");
}

public static void main( String[] args ) throws Exception
{
String templateFileName = null;
sampleModel = RasterFactory.createBandedSampleModel(DataBuffer.TYPE_BYTE, tileWidth, tileHeight, numberOfBands);
colorModel = TiledImage.createColorModel(sampleModel);

if( args.length <= 0 || args == null )
{
templateFileName = "testTemplate-1024x1024.tiff";
createTemplateTile(templateFileName);
}
else
{
templateFileName = args[0];
}

List<String> tileFileList = new ArrayList<String>();
for( int i = 0; i < numberOfRows * numberOfColumns; i++ )
{
tileFileList.add(i, templateFileName);
}

renderMosaicFromTiles(tileFileList, numberOfRows * numberOfColumns, "largeTiledTiff.tiff");
}

public static void renderMosaicFromTiles( List<String> inTileFilesList, int inImageCount, String inImageName ) throws Exception
{
int xTrans = 0;
int yTrans = 0;

ImageLayout imageLayout = new ImageLayout();
imageLayout.setTileGridXOffset(0);
imageLayout.setTileGridYOffset(0);
imageLayout.setTileWidth(tileWidth);
imageLayout.setTileHeight(tileHeight);
imageLayout.setColorModel(colorModel);
imageLayout.setSampleModel(sampleModel);

ParameterBlockJAI readParams = new ParameterBlockJAI("ImageRead", "rendered");
Vector<Object> renderedOpsVector = new Vector<Object>();

for( int i = 1; i <= inTileFilesList.size(); i++ )
{
readParams.setParameter("Input", inTileFilesList.get(i - 1));

ParameterBlockJAI transParams = new ParameterBlockJAI("Translate", "rendered");

transParams.addSource(JAI.create("ImageRead", readParams, null));

transParams.setParameter("xTrans", (float) xTrans);
transParams.setParameter("yTrans", (float) yTrans);

renderedOpsVector.addElement(JAI.create("Translate", transParams, null));

if( (i % Math.sqrt(inImageCount)) == 0 )
{
yTrans += tileHeight;
xTrans = 0;
}
else
{
xTrans += tileWidth;
}
}

ParameterBlockJAI mosaicParameterBlockJAI = new ParameterBlockJAI("Mosaic", "rendered");
mosaicParameterBlockJAI.setSources(renderedOpsVector);
mosaicParameterBlockJAI.setParameter("mosaicType", MosaicDescriptor.MOSAIC_TYPE_OVERLAY);

RenderedOp mosaicRenderedOp = JAI.create("Mosaic", mosaicParameterBlockJAI, null);
renderedOpsVector.clear();

saveRenderedOp(mosaicRenderedOp, inImageName);

ParameterBlock parameterBlock = new ParameterBlock();

double scaleX = (mosaicRenderedOp.getWidth() * .50) / mosaicRenderedOp.getWidth();
double scaleY = (mosaicRenderedOp.getHeight() * .50) / mosaicRenderedOp.getHeight();

parameterBlock.removeSources();
parameterBlock.removeParameters();
parameterBlock.addSource(mosaicRenderedOp);
parameterBlock.add(scaleX);
parameterBlock.add(scaleY);
parameterBlock.add(0.0f);
parameterBlock.add(0.0f);

String myImageName = inImageName.replaceAll("\\.tiff", "_scaleX-" + scaleX + "_scaleY-" + scaleY + ".tiff");

saveRenderedOp(JAI.create("SubsampleAverage", parameterBlock, null), myImageName);

// .25
scaleX = (mosaicRenderedOp.getWidth() * .25) / mosaicRenderedOp.getWidth();
scaleY = (mosaicRenderedOp.getHeight() * .25) / mosaicRenderedOp.getHeight();

parameterBlock.removeSources();
parameterBlock.removeParameters();
parameterBlock.addSource(mosaicRenderedOp);
parameterBlock.add(scaleX);
parameterBlock.add(scaleY);
parameterBlock.add(0.0f);
parameterBlock.add(0.0f);

myImageName = inImageName.replaceAll("\\.tiff", "_scaleX-" + scaleX + "_scaleY-" + scaleY + ".tiff");
saveRenderedOp(JAI.create("SubsampleAverage", parameterBlock, null), myImageName);
}

public static void saveRenderedOp( RenderedOp inRenderedOp, String inImageName )
{
System.out.println("DEBUG: writting image file:" + inImageName);

JAI.getDefaultInstance().getTileCache().setMemoryCapacity(1073741824L);

ParameterBlock parameterBlock = new ParameterBlock();
parameterBlock.addSource(inRenderedOp);

TIFFImageWriteParam tiffImageWriteParam = new TIFFImageWriteParam(Locale.ENGLISH);
tiffImageWriteParam.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
tiffImageWriteParam.setTiling(tileWidth, tileHeight, 0, 0);
tiffImageWriteParam.setCompressionMode(TIFFImageWriteParam.MODE_DISABLED);

ParameterBlockJAI newWriteParams = new ParameterBlockJAI("ImageWrite", "rendered");
newWriteParams.addSource(inRenderedOp);
newWriteParams.setParameter("Output", inImageName);
newWriteParams.setParameter("Format", "TIFF");
newWriteParams.setParameter("WriteParam", tiffImageWriteParam);
JAI.create("ImageWrite", newWriteParams);
}

public static void createTemplateTile( String inImageName ) throws Exception
{
TiledImage tiledImage = new TiledImage(0, 0, tileWidth, tileHeight, 0, 0, sampleModel, colorModel);

TIFFEncodeParam tiffEncodeParam = new TIFFEncodeParam();
tiffEncodeParam.setWriteTiled(true);
tiffEncodeParam.setCompression(TIFFEncodeParam.COMPRESSION_NONE);

int xIndex = 0;
int yIndex = 0;
WritableRaster writableRaster = null;
for( int x = 0; x < tileWidth; x++ )
{
for( int y = 0; y < tileHeight; y++ )
{
xIndex = tiledImage.XToTileX(x);
yIndex = tiledImage.YToTileY(y);
writableRaster = tiledImage.getWritableTile(xIndex, yIndex);

// grey
writableRaster.setPixel(x, y, new int[] { 128, 128, 128 });
tiledImage.releaseWritableTile(xIndex, yIndex);
}
}

System.out.println("writting: " + inImageName);
JAI.create("filestore", tiledImage, inImageName, "TIFF", tiffEncodeParam);
}

}

rgd
Offline
Joined: 2005-08-23

Hey...

I don't see anything obviously wrong at a quick glance. In order to
distinguish between a problem making the image and a problem writing it,
try this... instead of writing out the image, loop over each tile and
get the tile explicitly (then do nothing with it). If that works, you
know the image generation works and it's a problem with the tiff writer.
If not, you know to look upstream.

It's quite possible the tiff writer is trying to get the entire image
into memory, which won't work. The image size you list is 3.3GB per
band.. then times 3 if it's color. Even 6-10 GB of RAM is not enough.
It *shouldn't* need to do this, but it's a possibility.

You might also try writing the image as a striped file rather than tiles
(basically the tiles are full-width).

Good luck...

-Bob

On 10/31/11 12:12 PM, forums@java.net wrote:
> I forgot to rename the file from .java to something else. I changed it to
> .txt extension.
>
>
>
>

rswhite wrote:

>
> Hello.
>
> I'm trying to create an image to be printed 24" x 24" that needs to be
> printed at 2400dpi. I'm using 1024x1024 pixel tiles and trying to use the
> mosaic operator to create the image. The tiles are all being created
> properly, MOSAIC operator throws no errors and smaller images work fine.
> However, when I try and save the large image as a tiled TIFF it throws
> exceptions complaining about out of heap size error. I'm specifying 6GB to
> 10GB of RAM on the java command line. I can have the printer "stitch" the
> tiles together but I'd prefer to just be able to give them the image and
> have
> them print it.
>
> With that being said, I've stripped down the code to a simple set that
> still
> reproduces the problem, although I doubt anyone will want to run it and
> wait
> for it to throw the error. If you don't supply a 1024x1024 input image, a
> blank one is created for you and should still produce the error. I've also
> attached this as JaiTest.java.
>
>
>
> Can anyone give suggestions or point me in the direction of what I'm doing
> wrong?
>
>
>
> import java.awt.image.ColorModel;
> import java.awt.image.DataBuffer;
> import java.awt.image.SampleModel;
> import java.awt.image.WritableRaster;
> import java.awt.image.renderable.ParameterBlock;
> import java.util.ArrayList;
> import java.util.List;
> import java.util.Locale;
> import java.util.Vector;
> import javax.imageio.ImageWriteParam;
> import javax.media.jai.ImageLayout;
> import javax.media.jai.JAI;
> import javax.media.jai.ParameterBlockJAI;
> import javax.media.jai.RasterFactory;
> import javax.media.jai.RenderedOp;
> import javax.media.jai.TiledImage;
> import javax.media.jai.operator.MosaicDescriptor;
> import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;
> import com.sun.media.jai.codec.TIFFEncodeParam;
> public class JaiTest
> {
> private static int tileWidth = 1024;
> private static int tileHeight = 1024;
> private static int numberOfBands = 3;
> private static SampleModel sampleModel = null;
> private static ColorModel colorModel = null;
> private static int numberOfRows = 58;
> private static int numberOfColumns = 58;
> static
> {
> System.setProperty("com.sun.media.jai.disableMediaLib",
> "true");
> }
> public static void main( String[] args ) throws Exception
> {
> String templateFileName = null;
> sampleModel =
> RasterFactory.createBandedSampleModel(DataBuffer.TYPE_BYTE, tileWidth,
> tileHeight, numberOfBands);
> colorModel = TiledImage.createColorModel(sampleModel);
> if( args.length <= 0 || args == null )
> {
> templateFileName = "testTemplate-1024x1024.tiff";
> createTemplateTile(templateFileName);
> }
> else
> {
> templateFileName = args[0];
> }
> List tileFileList = new ArrayList();
> for( int i = 0; i < numberOfRows * numberOfColumns; i++ )
> {
> tileFileList.add(i, templateFileName);
> }
> renderMosaicFromTiles(tileFileList, numberOfRows *
> numberOfColumns, "largeTiledTiff.tiff");
> }
> public static void renderMosaicFromTiles( List
> inTileFilesList, int inImageCount, String inImageName ) throws Exception
> {
> int xTrans = 0;
> int yTrans = 0;
> ImageLayout imageLayout = new ImageLayout();
> imageLayout.setTileGridXOffset(0);
> imageLayout.setTileGridYOffset(0);
> imageLayout.setTileWidth(tileWidth);
> imageLayout.setTileHeight(tileHeight);
> imageLayout.setColorModel(colorModel);
> imageLayout.setSampleModel(sampleModel);
> ParameterBlockJAI readParams = new
> ParameterBlockJAI("ImageRead", "rendered");
> Vector renderedOpsVector = new Vector();
> for( int i = 1; i <= inTileFilesList.size(); i++ )
> {
> readParams.setParameter("Input", inTileFilesList.get(i -
> 1));
> ParameterBlockJAI transParams = new
> ParameterBlockJAI("Translate", "rendered");
> transParams.addSource(JAI.create("ImageRead",
> readParams, null));
> transParams.setParameter("xTrans", (float) xTrans);
> transParams.setParameter("yTrans", (float) yTrans);
> renderedOpsVector.addElement(JAI.create("Translate",
> transParams, null));
> if( (i % Math.sqrt(inImageCount)) == 0 )
> {
> yTrans += tileHeight;
> xTrans = 0;
> }
> else
> {
> xTrans += tileWidth;
> }
> }
> ParameterBlockJAI mosaicParameterBlockJAI = new
> ParameterBlockJAI("Mosaic", "rendered");
> mosaicParameterBlockJAI.setSources(renderedOpsVector);
> mosaicParameterBlockJAI.setParameter("mosaicType",
> MosaicDescriptor.MOSAIC_TYPE_OVERLAY);
> RenderedOp mosaicRenderedOp = JAI.create("Mosaic",
> mosaicParameterBlockJAI, null);
> renderedOpsVector.clear();
> saveRenderedOp(mosaicRenderedOp, inImageName);
> ParameterBlock parameterBlock = new ParameterBlock();
> double scaleX = (mosaicRenderedOp.getWidth() * .50) /
> mosaicRenderedOp.getWidth();
> double scaleY = (mosaicRenderedOp.getHeight() * .50) /
> mosaicRenderedOp.getHeight();
> parameterBlock.removeSources();
> parameterBlock.removeParameters();
> parameterBlock.addSource(mosaicRenderedOp);
> parameterBlock.add(scaleX);
> parameterBlock.add(scaleY);
> parameterBlock.add(0.0f);
> parameterBlock.add(0.0f);
> String myImageName = inImageName.replaceAll("\\.tiff",
> "_scaleX-" + scaleX + "_scaleY-" + scaleY + ".tiff");
> saveRenderedOp(JAI.create("SubsampleAverage", parameterBlock,
> null), myImageName);
> // .25
> scaleX = (mosaicRenderedOp.getWidth() * .25) /
> mosaicRenderedOp.getWidth();
> scaleY = (mosaicRenderedOp.getHeight() * .25) /
> mosaicRenderedOp.getHeight();
> parameterBlock.removeSources();
> parameterBlock.removeParameters();
> parameterBlock.addSource(mosaicRenderedOp);
> parameterBlock.add(scaleX);
> parameterBlock.add(scaleY);
> parameterBlock.add(0.0f);
> parameterBlock.add(0.0f);
> myImageName = inImageName.replaceAll("\\.tiff", "_scaleX-" +
> scaleX + "_scaleY-" + scaleY + ".tiff");
> saveRenderedOp(JAI.create("SubsampleAverage", parameterBlock,
> null), myImageName);
> }
> public static void saveRenderedOp( RenderedOp inRenderedOp, String
> inImageName )
> {
> System.out.println("DEBUG: writting image file:" +
> inImageName);
>
> JAI.getDefaultInstance().getTileCache().setMemoryCapacity(1073741824L);
> ParameterBlock parameterBlock = new ParameterBlock();
> parameterBlock.addSource(inRenderedOp);
> TIFFImageWriteParam tiffImageWriteParam = new
> TIFFImageWriteParam(Locale.ENGLISH);
>
> tiffImageWriteParam.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
> tiffImageWriteParam.setTiling(tileWidth, tileHeight, 0, 0);
>
> tiffImageWriteParam.setCompressionMode(TIFFImageWriteParam.MODE_DISABLED);
> ParameterBlockJAI newWriteParams = new
> ParameterBlockJAI("ImageWrite", "rendered");
> newWriteParams.addSource(inRenderedOp);
> newWriteParams.setParameter("Output", inImageName);
> newWriteParams.setParameter("Format", "TIFF");
> newWriteParams.setParameter("WriteParam", tiffImageWriteParam);
> JAI.create("ImageWrite", newWriteParams);
> }
> public static void createTemplateTile( String inImageName ) throws
> Exception
> {
> TiledImage tiledImage = new TiledImage(0, 0, tileWidth,
> tileHeight, 0, 0, sampleModel, colorModel);
> TIFFEncodeParam tiffEncodeParam = new TIFFEncodeParam();
> tiffEncodeParam.setWriteTiled(true);
>
> tiffEncodeParam.setCompression(TIFFEncodeParam.COMPRESSION_NONE);
> int xIndex = 0;
> int yIndex = 0;
> WritableRaster writableRaster = null;
> for( int x = 0; x < tileWidth; x++ )
> {
> for( int y = 0; y < tileHeight; y++ )
> {
> xIndex = tiledImage.XToTileX(x);
> yIndex = tiledImage.YToTileY(y);
> writableRaster =
> tiledImage.getWritableTile(xIndex, yIndex);
> // grey
> writableRaster.setPixel(x, y, new int[] { 128,
> 128, 128 });
> tiledImage.releaseWritableTile(xIndex, yIndex);
> }
> }
> System.out.println("writting: " + inImageName);
> JAI.create("filestore", tiledImage, inImageName, "TIFF",
> tiffEncodeParam);
> }
> }
>
>
>

>
>

rswhite
Offline
Joined: 2011-09-07

First off, thanks for the reply and the suggestions.

I loop through the tiles in the mosaic RenderedOp and that is when it throws the OoM exception. Writing it as a striped image results in the same behavior. Any other suggestion? At this point I think I may just have to dig through the JAI source code to see what's going on.

Thanks.

rgd
Offline
Joined: 2005-08-23

The only other thing I can think of offhand is to compare the size of
the tile cache to the size of available memory. If the size of the
cache exceeds the size of memory, you can get OOM from the cache even
though that memory really isn't needed. Of course you need a healthy
margin there to account for VM and non-cache memory use.

Something radical to try would be to disable the tile cache entirely.
It'll slow the heck out of the program, but you can see if it actually
works then. Tuning the tile cache size is often the key to performance.

-Bob

On 11/1/11 10:21 PM, forums@java.net wrote:
> First off, thanks for the reply and the suggestions.
>
> I loop through the tiles in the mosaic RenderedOp and that is when it
> throws
> the OoM exception. Writing it as a striped image results in the same
> behavior. Any other suggestion? At this point I think I may just have to
> dig
> through the JAI source code to see what's going on.
>
>
>
> Thanks.
>
>
>
>

rswhite
Offline
Joined: 2011-09-07

I finally found the issue. I had typed up a nice long response hit reply and it didn't post. So here is the condensed version:

1. Thank you for your suggestions and advice. They were very helpful and made me see things from a different perspective which ultimately lead to a solution. I really appreciate it.

2. I wasn't specifying ImageLayout in two places in this code but I was in my program. I don't think this was an issue yet but would have been after I fixed problem #3.

3. I needed to call the memoryControl() method in the TileCache class. By default it keeps all the tiles in memory.

Thanks again.

rgd
Offline
Joined: 2005-08-23

Glad it worked out.

-Bob

Sent from my iPhone

On Nov 5, 2011, at 3:04 PM, forums@java.net wrote:

> I finally found the issue. I had typed up a nice long response hit reply and
> it didn't post. So here is the condensed version:
>
>
>
> 1. Thank you for your suggestions and advice. They were very helpful and made
> me see things from a different perspective which ultimately lead to a
> solution. I really appreciate it.
>
> 2. I wasn't specifying ImageLayout in two places in this code but I was in
> my program. I don't think this was an issue yet but would have been after I
> fixed problem #3.
>
> 3. I needed to call the memoryControl() method in the TileCache class. By
> default it keeps all the tiles in memory.
>
>
>
> Thanks again.
>
>
>
>
>
>

rswhite
Offline
Joined: 2011-09-07

Unfortunately it didn't work out. It just made it a lot better now it fails when it's about 75% in. I've tried setting disableDefaultTileCache() and it still runs out of memory. However, now it's just from the main thread no stack trace:

"Exception in thread "main" java.lang.OutOfMemoryError: Java heap space".

That's it, no stack info.

I'll try and grab a version of JProfiler and maybe try to see what's going on. Is there a better way I can be doing this? I tried with a TiledImage and it runs out of head space too.

imagero
Offline
Joined: 2003-11-18

Well, TiledImage can't help you because it helds all tiles in memory.

I would try to show your resulting PlanarImage with JadeDisplay.

If it works with JadeDisplay, then it is definitely TiffWriter problem.

imagero
Offline
Joined: 2003-11-18

BTW If this is TiffWriter problem, you may try Imagero's TiffWriter which will NOT pull complete image in memory, it will write it tile by tile - and free resources after each tile.

I don't have implementation which takes PlanarImage.

You may use Imagero's TiledImage (differs from JAI's TiledImage) or you may provide Blob implementation for each mosaic image (which would just load it on request) and pass it direct to Imagero's TiffWriter.

If you have interest, I may post working example (with Imagero's TiledImage).

Currently Imagero is free for non commercial use and it is possible that I'll make it free in near future.

rgd
Offline
Joined: 2005-08-23

If you've disabled the tile cache then it's real memory you're running
out of. Have you tried increasing what's available to the VM (-Xmx
option to java). Otherwise, a profiler is probably going to be your
best bet. There are probably some dead pointers to images or tiles
lying around in the code somewhere that are forcing them to stay around.
Either that, or what you're trying to do simply won't fit in available
memory!

-Bob

On 11/11/11 8:23 PM, forums@java.net wrote:
> Unfortunately it didn't work out. It just made it a lot better now it fails
> when it's about 75% in. I've tried setting disableDefaultTileCache() and it
> still runs out of memory. However, now it's just from the main thread no
> stack trace:
>
> "Exception in thread "main" java.lang.OutOfMemoryError: Java heap space".
>
> That's it, no stack info.
>
>
> I'll try and grab a version of JProfiler and maybe try to see what's going
> on. Is there a better way I can be doing this? I tried with a TiledImage
> and
> it runs out of head space too.
>
>
>
>

rswhite
Offline
Joined: 2011-09-07

It appears I found the issue. I had to stop specifying the X and Y grid offsets for the tiles. Since the translate operator overrides them, I thought it would be ok but it really screwed up the tile sizes, which has a casacade like effect on my memory usage. I am now using the following for the tiles:

imageLayout.setTileWidth(tileWidth);
imageLayout.setTileHeight(tileHeight);
imageLayout.setColorModel(colorModel);
imageLayout.setSampleModel(sampleModel);

and am using this for the mosaic layout:

mosaicImageLayout.setWidth( tileWidth * numberOfColumns );
mosaicImageLayout.setHeight( tileHeight * numberOfRows );
mosaicImageLayout.setTileGridXOffset(0);
mosaicImageLayout.setTileGridYOffset(0);
mosaicImageLayout.setTileWidth(tileWidth);
mosaicImageLayout.setTileHeight(tileHeight);
mosaicImageLayout.setColorModel(colorModel);
mosaicImageLayout.setSampleModel(sampleModel);

I also turned off interpolation for the translate operation:

transParams.setParameter("interpolation", null);

Thanks for all of the help. Time to buy some solid state drives and more RAM :)