Skip to main content

[JAI / ImageIO] Problem saving compressed tiffs

2 replies [Last post]
gmb2005
Offline
Joined: 2005-05-31

Out of memory - inserting images and Saving compressed tiffs

Posted: May 31, 2005 9:34 AM Reply

Hello,
I'm new to JAI / Image I/O, but I managed to write a tiny framework for some basic image operations.
Now, I'm facing the following problem:
I create a barcode (Using barrcode4j), saving it to an image, convering that image to a "Group 4 Fax Encoding" compressed tiff. That works very good. But in step 2 I open an very large bilevel "Group 4 Fax Encoding" compressed tiff an try to add the barcode at a specific position in this image. With small images that works fine, but with production images (app. 17k px x 20k px) cannot be saved. The application hangs with no exception.
And only a few bytes of the image are written to disc.
Could anybody help?
Thanks in advance

Bjoern

P.S.: Here ist the source (without creating the barcode):

/*
* Created on 20.05.2005
*
* @author björn.zapadlo
*
* TODO
*/

import java.awt.RenderingHints;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import javax.media.jai.Histogram;
import javax.media.jai.ImageLayout;
import javax.media.jai.InterpolationNearest;
import javax.media.jai.JAI;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.PlanarImage;

import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;

public class SolseitImaging {

PlanarImage inputImage;

String CMYKProfilePath;

/**
* @param filename *
* Constructor
*/
public SolseitImaging (String filename) {
this.inputImage = (PlanarImage)JAI.create("fileload", filename);
}

/**
* @param bi
* @return PlanarImage
* convert BufferedImage to PlanarImage
*/
private PlanarImage bufferedImageToPlanarImage (BufferedImage bi) {
ParameterBlock pb = new ParameterBlock();
pb.add(bi);

return (PlanarImage)JAI.create("AWTImage", pb);
}

/**
* @param profilePath
* set the path to icc profile of cmyk
*/
public void setCMYKProfilePath(String profilePath) {
this.CMYKProfilePath = profilePath;
}

/**
* @param degrees
* rotate by degrees clockwise
*/
public void rotateImage(double degrees) {
ParameterBlockJAI pb = new ParameterBlockJAI("rotate");
pb.addSource(this.inputImage);
pb.setParameter("angle", (float)Math.toRadians(degrees));
this.inputImage = JAI.create("rotate", pb);
}

/**
* convert cmyk image to rgb image
*/
public void convertCMYKToRGBImage() {
double[][] MATRIX_CMYK_TO_RGB = {
{ -0.80D, 0.00D, 0.00D, 1.0D, 0.0D }, //R
{ 0.00D, -0.80D, 0.00D, 1.0D, 0.0D }, //G
{ 0.00D, 0.00D, -0.80D, 1.0D, 0.0D } //B
};

ParameterBlock pb = new ParameterBlock();
pb.addSource(this.inputImage);
pb.add(MATRIX_CMYK_TO_RGB);

this.inputImage = (PlanarImage) JAI.create("bandcombine", pb);
}

/**
* @throws IOException
* convert rgb image to cmyk image
*/
public void convertRGBToCMYKImage() throws IOException {
// cmyk Model
int[] bitsCMYK = { 8, 8, 8, 8};
ICC_ColorSpace csCMYK = null;
csCMYK = new ICC_ColorSpace(ICC_Profile.getInstance(this.CMYKProfilePath));
ColorModel colorModelCMYK = new ComponentColorModel(csCMYK, bitsCMYK,false, false, java.awt.Transparency.OPAQUE, DataBuffer.TYPE_BYTE);

//ImageLayout to correctly load the image
ImageLayout cmykLayout = new ImageLayout();
cmykLayout.setColorModel(colorModelCMYK);
RenderingHints rh = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, cmykLayout);

cmykLayout.setSampleModel(colorModelCMYK.createCompatibleSampleModel(this.inputImage.getTileWidth(),this.inputImage.getTileHeight()));
//the colorconversion
ParameterBlock pb = new ParameterBlock();
pb.addSource(this.inputImage);
pb.add(colorModelCMYK);
this.inputImage = JAI.create("ColorConvert", pb, rh);
}

/**
* convert rgb image to grayscale
*
* typical weights for converting RGB to Grayscale
* gray = 0.3*red + 0.59*green + 0.11*blue
*/
public void convertRGBToGrayscaleImage () {
double[][] matrix = {{ 0.3D, 0.59D, 0.11D, 0D }};
ParameterBlock pb = new ParameterBlock();
pb.addSource(this.inputImage);
pb.add(matrix);
this.inputImage = JAI.create("BandCombine", pb, null);
}

/**
* convert grayscale image to bilevel image
*/
public void convertGrayscaleToBlackWhiteImage () {
// Generate a histogram.
Histogram histogram = (Histogram)JAI.create("histogram", this.inputImage).getProperty("histogram");

// Get a threshold equal to the median.
double[] threshold = histogram.getPTileThreshold(0.5);

// if background and foreground could not be separated
if (threshold[0] == 0.0 || threshold[0] == 1.0) {
threshold[0] = 127.5;
}

this.inputImage = JAI.create("binarize", this.inputImage, new Double(threshold[0]));
}

/**
* convert color indexed image to rgb image
*/
public void convertIndexedToRGBImage () {
BufferedImage src = this.inputImage.getAsBufferedImage();

BufferedImage dest = src;
src = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_RGB); //CHANGE THIS TO TYPE YOU NEED
ColorConvertOp xformOp = new ColorConvertOp(null);
xformOp.filter(dest, src);

this.inputImage = bufferedImageToPlanarImage(dest);
}

/**
* @param width
* @param height
* scale by a factor
*/
public void scaleImage(float width, float height) {
ParameterBlockJAI pb = new ParameterBlockJAI("scale");
pb.addSource(this.inputImage);
pb.setParameter("xScale", width); //x Scale Factor
pb.setParameter("yScale", height); //y Scale Factor
pb.setParameter("xTrans", 0.0F); //x Translate amount
pb.setParameter("yTrans", 0.0F); //y Translate amount
pb.setParameter("interpolation", new InterpolationNearest());
this.inputImage = JAI.create("scale", pb, null);
}

/**
* @param width
* @param height
* scale by pixels / points
*/
public void scaleImage(int width, int height) {
float widthFactor, heightFactor;

widthFactor = (float)(this.inputImage.getWidth() / width);
heightFactor = (float)(this.inputImage.getHeight() / height);

scaleImage (widthFactor,heightFactor);
}

/**
* invert the image
*/
public void invertImage () {
ParameterBlockJAI pb = new ParameterBlockJAI("invert");
pb.addSource(this.inputImage);

this.inputImage = JAI.create("invert", pb);
}

/**
* changes black and white pixels in bilevel images
*/
public void virtualInvertBlackWhiteImage()
{
// Invert the colormodel
byte[] map = new byte[] {(byte)( 255),(byte)(0)};
IndexColorModel colorModel = new IndexColorModel(1, 2, map, map, map);

// Create a bufferedimage with the good colormodel
// and the same data and dimensions as the original image
BufferedImage bi = new BufferedImage(this.inputImage.getWidth(), this.inputImage.getHeight(), BufferedImage.TYPE_BYTE_BINARY, colorModel);
bi.setData(this.inputImage.getAsBufferedImage().getData());

// Invert the image
DataBufferByte dataBufferByte = (DataBufferByte)bi.getRaster().getDataBuffer();
byte[] buffer = dataBufferByte.getData();
for (int dat = 0; dat < buffer.length; dat++) {
buffer[dat] = (byte)(~buffer[dat]);
}

this.inputImage = bufferedImageToPlanarImage(bi);
}

/**
* @param filename
* @param compressionType
* @param xRes
* @param yRes
* @throws FileNotFoundException
* @throws IOException
* save compressed image to file
*/
public void saveCompressedTiffImage (String filename, String compressionType) throws FileNotFoundException, IOException {
// Create IIOImage
IIOImage iioImage = new IIOImage(this.inputImage, null, null);

// Get Writer for TIFF
Iterator writers = ImageIO.getImageWritersByFormatName("tiff");
ImageWriter writer = (ImageWriter)writers.next();

// Set WriteParam's
TIFFImageWriteParam writeParam = (TIFFImageWriteParam)writer.getDefaultWriteParam();
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
writeParam.setCompressionType(compressionType);

/*TIFFField[] extras = new TIFFField[4];
extras[0] = new TIFFField(282,TIFFField.TIFF_RATIONAL, 1, (Object)new long[][] {{xRes,(long)1},{(long)0 ,(long)0}});
extras[1] = new TIFFField(283,TIFFField.TIFF_RATIONAL, 1, (Object)new long[][] {{yRes,(long)1},{(long)0 ,(long)0}});
extras[2] = new TIFFField(262, TIFFField.TIFF_SHORT, 1, (Object) new char[] {0});
extras[3] = new TIFFField(296, TIFFField.TIFF_SHORT, 1, (Object) new char[] {2});*/

// Create File to save the image
File f = new File(filename);
ImageOutputStream ios = ImageIO.createImageOutputStream(f);
writer.setOutput(ios);

// Save the image
writer.write(null, iioImage, writeParam);
ios.close();
}

/**
* @param filenameTop
* @param posX
* @param posY
* inserts one image in another
*/
public void insertImage (String filenameTop, int posX, int posY) {
PlanarImage topImage = (PlanarImage)JAI.create("fileload", filenameTop);

// move coordinate system
ParameterBlock pbTranslate = new ParameterBlock();
pbTranslate.addSource(topImage);
pbTranslate.add((float)posX);
pbTranslate.add((float)posX);
topImage = JAI.create("translate",pbTranslate,null);

ParameterBlock pbOverlay = new ParameterBlock();
pbOverlay.addSource(this.inputImage);
pbOverlay.addSource(topImage);

// Inserting Barcode
this.inputImage = JAI.create("overlay", pbOverlay);
}

/**
* @param filename
* @param imageType
* save image to file
*/
public void saveImage(String filename, String imageType) {
try {
File f = new File(filename);
ImageIO.write(this.inputImage, imageType, f);

} catch (Exception e) { }
}

public static void main (String args[]) {
/*SolseitImaging myBC = new SolseitImaging("d:\\bctest.tif");

myBC.rotateImage (270);
myBC.convertGrayscaleToBlackWhiteImage ();
myBC.virtualInvertBlackWhiteImage();
try {
myBC.saveCompressedTiffImage("D:\\bctest1.tif", "CCITT T.6");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/

SolseitImaging mySI = new SolseitImaging("d:\\TIFF_Test.tif");

mySI.insertImage("D:\\bctest1.tif", 400, 400);

try {
mySI.saveCompressedTiffImage("d:\\TIFF_Test1_mit_barcode.tif", "CCITT T.6");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}

Message was edited by: gmb2005

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
bpb
Offline
Joined: 2004-06-23

This looks like the same issue previously posted to interest@jai-imageio.dev.java.net.

It sounds like the problem is in the image saving portion.

What is the exact nature of your "production" images?

Brian

gmb2005
Offline
Joined: 2005-05-31

Yes, It's the same, but in my eyes, it is an image IO problem.
The source above is the new source, include image io tools code in the both saving methods.