Skip to main content

[JAI] Converting to IndexColorModel but doesnt work for some images

10 replies [Last post]
bonklers
Offline
Joined: 2006-05-05
Points: 0

Hi

I have been struggling a long while now with quality problems with my gif images, I finally narrowed the problem down to that all the operations I used would drastically derange the quality of the image if the image had an indexcolormodel the solution was to convert all indexcolormodel images to directcolormodel and then convert them back when processing was done. I then searched for a method that would procude better quality than the one I had and found some code on this forum that I tried which works fine with good quality.

The problem is that if the image I try to convert was originally a jpeg image then I will get an error when I try to write it saying "bad value XXX" where XXX refers to the map size of the image which is something else than 256 for former jpeg image and 256 for former gif images (which work) so I take it I will have to force the map size to become 256 so that the gif writer will accept these images. But I am at a loss... I hope someone can enlighten me here.

details:
Im reading and writing the images using imageio, the images are loaded, processed (scaling, watermarking etcetc) and then written back again. Gif images are immediatley converted to ARGB images to prevent them from being distorted by the processing. finally I run this method if the desired output format is gif:

the problem again: at the time of writing the image with the GifWriter of imageio, it will throw an exception saying illegalargumentexception: bad value XXX, I have concluded that the bad value if the map size of the buffered image which becomes 256 for gif images but sometihng other than 256 for jpeg images.

really hope I can get some help on this, thanks!

the function that I am currently trying out, it is the code from this post:
http://www.javadesktop.org/forums/thread.jspa?forumID=54&threadID=10810&...

slightly modified to fit into my use.

public static BufferedImage toIndexColorModel(BufferedImage image, ImageConverterParams params) throws ImageConverterException{
PlanarImage surrogateImage = PlanarImage.wrapRenderedImage(image);
ParameterBlock pb = new ParameterBlock();

int w = surrogateImage.getWidth();
int h = surrogateImage.getHeight();

BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);

WritableRaster wr = bi.getWritableTile(0, 0);
WritableRaster wr3 = wr.createWritableChild(0, 0, w, h, 0, 0, new int[] { 0, 1, 2 });

wr3.setRect(surrogateImage.getData());
bi.releaseWritableTile(0, 0);
surrogateImage = PlanarImage.wrapRenderedImage(bi);

pb.removeParameters();
pb.removeSources();

pb.addSource(surrogateImage).add(ColorQuantizerDescriptor.MEDIANCUT).add(new Integer(256));
LookupTableJAI colorMap = (LookupTableJAI)JAI.create("ColorQuantizer", pb).getProperty("LUT");
KernelJAI ditherMask = KernelJAI.ERROR_FILTER_FLOYD_STEINBERG;

ColorModel cm = new IndexColorModel(8, colorMap.getByteData()[0].length, colorMap.getByteData()[0], colorMap.getByteData()[1], colorMap.getByteData()[2], Transparency.OPAQUE);

PlanarImage op = PlanarImage.wrapRenderedImage(new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED,(IndexColorModel) cm));

ImageLayout layout = new ImageLayout();
layout.setTileWidth(image.getWidth());
layout.setTileHeight(image.getHeight());
layout.setColorModel(cm);
layout.setSampleModel(op.getSampleModel());

RenderingHints rh = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);

pb.removeParameters();
pb.removeSources();
pb.addSource(surrogateImage);
pb.add(colorMap);
pb.add(ditherMask);
op= JAI.create("errordiffusion",pb,rh);

surrogateImage=(PlanarImage)op;
image = surrogateImage.getAsBufferedImage();
params.setCm(image.getColorModel());
return image;
}

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Brian Burkhalter

Using the image that you sent to me directly I am able to reproduce the
problem listed below. We will investigate it and post something as soon as
possible.

Brian

On Tue, 1 Nov 2005, jai-interest@javadesktop.org wrote:

> Hi,
>
> When I read that you were able to execute without fail I wanted to make sure I had the latest versions, I downloaded jai_imageio again, version 1.1. Playing around with the jar files I did find that it is possible to avoid the exception itself, but not the error.
>
> If I remove jai_imageio.jar from my project then the class will run without exception but the output file will be empty.
>
> If I add jai_imageio.jar again then I get the exception, here is the stacktrace:
> Exception in thread "main" java.lang.IllegalArgumentException: Bad value 245!
> at com.sun.media.imageioimpl.plugins.gif.GIFImageWriter.getNumBits(Unknown Source)
> at com.sun.media.imageioimpl.plugins.gif.GIFImageWriter.write(Unknown Source)
> at com.sun.media.imageioimpl.plugins.gif.GIFImageWriter.write(Unknown Source)
> at javax.imageio.ImageWriter.write(Unknown Source)
> at com.mobiletech.mcf.core.content.image.imageconv.TestClass.main(TestClass.java:93)
>
> As far as I see this, either a different GIFWriter which can support numBits != 256 or a way to make sure num bits will be 256 after converting to indexcolormodel using the method supplied in my test case would be the solution.
>
> I will proceed to email you one of the many images I have that will fail this test.
>
> Thanks again for your work on this
> ---
> [Message sent by forum member 'bonklers' (Andreas Gudmundsson)]
>
> http://www.javadesktop.org/forums/thread.jspa?messageID=122731&#122731
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
> For additional commands, e-mail: interest-help@jai.dev.java.net
>
>

----------------
Brian Burkhalter
Java Multimedia, Imaging, and Graphics
Sun Microsystems, Inc.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any
unauthorized review, use, disclosure or distribution is prohibited.
If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

bonklers
Offline
Joined: 2006-05-05
Points: 0

Im compiling with Java 1.5 and I have the following image related jars in the classpath:

from Imageio 1.1:
jai_imageio.jar

from Jai 1.1.3:
jai_codec.jar
jai_core.jar

Also using one class from Jimi which I havent gotten around to replace yet (ColorQuantizer)
JimiProClasses.jar

Brian Burkhalter

I was able to verify the incorrect behavior with the J2SE 1.5 core GIF writer
as well.

Assuming you are always working with 8 bits-per-sample data, inserting the
following code

// XXX BEGIN CIRCUMVENTION
int tableLength = colorMap.getNumEntries();
if(tableLength != 256) {
byte[][] newTable = new byte[3][256];
for(int i = 0; i < 3; i++) {
System.arraycopy(colorMap.getByteData()[i], 0,
newTable[i], 0, tableLength);
}
colorMap = new LookupTableJAI(newTable);
}
// XXX END CIRCUMVENTION

just after the "ColorQuantizer" operation makes the test class work with the
JAI-Image I/O GIF writer. The core J2SE GIF writer still creates an empty
file.

Would you mind filing an issue about this at? Please include the image.

https://jai-imageio-core.dev.java.net/servlets/ProjectIssues

Reason I ask is that we give higher priority to fixing issues which are filed
by users themselves as well as to issue which receive votes.

Thanks,

Brian

On Tue, 1 Nov 2005, jai-interest@javadesktop.org wrote:

> Im compiling with Java 1.5 and I have the following image related jars in the classpath:
>
> from Imageio 1.1:
> jai_imageio.jar
>
> from Jai 1.1.3:
> jai_codec.jar
> jai_core.jar
>
> Also using one class from Jimi which I havent gotten around to replace yet (ColorQuantizer)
> JimiProClasses.jar
> ---
> [Message sent by forum member 'bonklers' (Andreas Gudmundsson)]
>
> http://www.javadesktop.org/forums/thread.jspa?messageID=122758&#122758
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
> For additional commands, e-mail: interest-help@jai.dev.java.net
>
>

----------------
Brian Burkhalter
Java Multimedia, Imaging, and Graphics
Sun Microsystems, Inc.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any
unauthorized review, use, disclosure or distribution is prohibited.
If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

ipreuss
Offline
Joined: 2004-01-06
Points: 0

> System.arraycopy(colorMap.getByteData(), 0,
> newTable, 0, tableLength);

This probably should be

System.arraycopy(colorMap.getByteData()[b][ i ][/b], 0,
newTable[b][ i ][/b], 0, tableLength);

(Ah, now I understand - "[ i ]" without the spaces makes for italic font... :rolleyes: )

Brian Burkhalter

On Fri, 4 Nov 2005, jai-interest@javadesktop.org wrote:

>> System.arraycopy(colorMap.getByteData(), 0,
>> newTable, 0, tableLength);
>
> This probably should be
>
> System.arraycopy(colorMap.getByteData()[b][ i ][/b], 0,
> newTable[b][ i ][/b], 0, tableLength);

That's what I had in my mailer anyway.

Brian

> (Ah, now I understand - "[ i ]" without the spaces makes for italic font... :rolleyes: )
> ---
> [Message sent by forum member 'ipreuss' (Ilja Preuß)]
>
> http://www.javadesktop.org/forums/thread.jspa?messageID=123200&#123200
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
> For additional commands, e-mail: interest-help@jai.dev.java.net
>
>

----------------
Brian Burkhalter
Java Multimedia, Imaging, and Graphics
Sun Microsystems, Inc.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any
unauthorized review, use, disclosure or distribution is prohibited.
If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

bonklers
Offline
Joined: 2006-05-05
Points: 0

Hi,

When I read that you were able to execute without fail I wanted to make sure I had the latest versions, I downloaded jai_imageio again, version 1.1. Playing around with the jar files I did find that it is possible to avoid the exception itself, but not the error.

If I remove jai_imageio.jar from my project then the class will run without exception but the output file will be empty.

If I add jai_imageio.jar again then I get the exception, here is the stacktrace:
Exception in thread "main" java.lang.IllegalArgumentException: Bad value 245!
at com.sun.media.imageioimpl.plugins.gif.GIFImageWriter.getNumBits(Unknown Source)
at com.sun.media.imageioimpl.plugins.gif.GIFImageWriter.write(Unknown Source)
at com.sun.media.imageioimpl.plugins.gif.GIFImageWriter.write(Unknown Source)
at javax.imageio.ImageWriter.write(Unknown Source)
at com.mobiletech.mcf.core.content.image.imageconv.TestClass.main(TestClass.java:93)

As far as I see this, either a different GIFWriter which can support numBits != 256 or a way to make sure num bits will be 256 after converting to indexcolormodel using the method supplied in my test case would be the solution.

I will proceed to email you one of the many images I have that will fail this test.

Thanks again for your work on this

Brian Burkhalter

So you are using Java 5 (JDK 1.5) with JAI-Image I/O 1.1-alpha? Or are you
using the jai-imageio-core CVS tree to build you imageio stuff?

Brian

On Tue, 1 Nov 2005, jai-interest@javadesktop.org wrote:

> Hi,
>
> When I read that you were able to execute without fail I wanted to make sure I had the latest versions, I downloaded jai_imageio again, version 1.1. Playing around with the jar files I did find that it is possible to avoid the exception itself, but not the error.
>
> If I remove jai_imageio.jar from my project then the class will run without exception but the output file will be empty.
>
> If I add jai_imageio.jar again then I get the exception, here is the stacktrace:
> Exception in thread "main" java.lang.IllegalArgumentException: Bad value 245!
> at com.sun.media.imageioimpl.plugins.gif.GIFImageWriter.getNumBits(Unknown Source)
> at com.sun.media.imageioimpl.plugins.gif.GIFImageWriter.write(Unknown Source)
> at com.sun.media.imageioimpl.plugins.gif.GIFImageWriter.write(Unknown Source)
> at javax.imageio.ImageWriter.write(Unknown Source)
> at com.mobiletech.mcf.core.content.image.imageconv.TestClass.main(TestClass.java:93)
>
> As far as I see this, either a different GIFWriter which can support numBits != 256 or a way to make sure num bits will be 256 after converting to indexcolormodel using the method supplied in my test case would be the solution.
>
> I will proceed to email you one of the many images I have that will fail this test.
>
> Thanks again for your work on this
> ---
> [Message sent by forum member 'bonklers' (Andreas Gudmundsson)]
>
> http://www.javadesktop.org/forums/thread.jspa?messageID=122731&#122731
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
> For additional commands, e-mail: interest-help@jai.dev.java.net
>
>

----------------
Brian Burkhalter
Java Multimedia, Imaging, and Graphics
Sun Microsystems, Inc.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any
unauthorized review, use, disclosure or distribution is prohibited.
If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

bonklers
Offline
Joined: 2006-05-05
Points: 0

Thanks for responding!

I am honestly threading on thin ground here since my knowledge of image processing is minimal.

I should be using JAI v1.1.3alpha which was the latest I could find

I have created a class that will run and encounter this error, it is a bit awkwardly done because I quickly cut bits out from various places and then filled in the blanks. This code will get the bad value illegalargumentexception on most images except for some gif's which work fine, I believe the error to be in the toIndexColorModel function.

change the two file location strings to point to the test files.

code:

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.awt.image.renderable.ParameterBlock;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.KernelJAI;
import javax.media.jai.LookupTableJAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.operator.ColorQuantizerDescriptor;

public class TestClass {
private static String sourceTestFileLocation = "your test image";
private static String destinationTestFileLocation = "c:/temp/testResult.gif";

public static void main(String [] args){
// Load the image
ByteArrayInputStream imageStream = null;
try {
imageStream = new ByteArrayInputStream(TestClass.fileToByte(new File(sourceTestFileLocation)));
} catch (IOException e) {
e.printStackTrace();
}

BufferedImage image = null;
ImageInputStream iis = null;
ImageReader reader = null;

try {
iis = ImageIO.createImageInputStream(imageStream);

Iterator readers = ImageIO.getImageReaders(iis);

if(!readers.hasNext()){
return;
}
reader = (ImageReader)readers.next();
reader.setInput(iis,false);
image = reader.read(0);
}catch(IOException ioe){
ioe.printStackTrace();
}

// convert all images to directcolormodel
image = TestClass.toBuffImageRGBorARGB(image);

// here there could have been lots of processing

// preparing to write the image back to disk, always writing gif since that is the problem so convert the colormodel to indexcolormodel

image = TestClass.toIndexColorModel(image);

// Write the image back to disk
FileOutputStream output = null;
try {
output = new FileOutputStream(destinationTestFileLocation);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Iterator writers = ImageIO.getImageWriters(new ImageTypeSpecifier(image),"gif");

if(!writers.hasNext()){
return;
}
ImageWriter writer = (ImageWriter)writers.next();
ImageOutputStream ios = null;

try{
ios = ImageIO.createImageOutputStream(output);

writer.setOutput(ios);
writer.write(image);
ios.flush();
output.flush();

} catch(IOException ioe){
ioe.printStackTrace();
} finally {
writer.dispose();
try{
ios.close();
output.close();
} catch(IOException ignored){}
writer = null;
ios = null;
output = null;
}

}

public static byte[] fileToByte(File inputFile) throws IOException{
InputStream innfil = null;
innfil = new FileInputStream(inputFile);

if (inputFile.length() > Integer.MAX_VALUE) {
//throw new ImageDAOException("Test file is too large: "+inputFile.getName());
}

byte[] byteArray = new byte[(int)inputFile.length()];

int offset = 0;
int numRead = 0;

while (offset < byteArray.length && (numRead=innfil.read(byteArray, offset, byteArray.length-offset)) >= 0) {
offset += numRead;
}

// Ensure all the bytes have been read in
if (offset < byteArray.length) {
//throw new ImageDAOException("Could not completely read file "+inputFile.getName());
}

innfil.close();
return byteArray;
}

public static BufferedImage toIndexColorModel(BufferedImage image) {
PlanarImage surrogateImage = PlanarImage.wrapRenderedImage(image);
ParameterBlock pb = new ParameterBlock();

int w = surrogateImage.getWidth();
int h = surrogateImage.getHeight();

BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);

WritableRaster wr = bi.getWritableTile(0, 0);
WritableRaster wr3 = wr.createWritableChild(0, 0, w, h, 0, 0, new int[] { 0, 1, 2 });

wr3.setRect(surrogateImage.getData());
bi.releaseWritableTile(0, 0);
surrogateImage = PlanarImage.wrapRenderedImage(bi);

pb.removeParameters();
pb.removeSources();

pb.addSource(surrogateImage).add(ColorQuantizerDescriptor.MEDIANCUT).add(new Integer(256));
LookupTableJAI colorMap = (LookupTableJAI)JAI.create("ColorQuantizer", pb).getProperty("LUT");
KernelJAI ditherMask = KernelJAI.ERROR_FILTER_FLOYD_STEINBERG;

ColorModel cm = new IndexColorModel(8, colorMap.getByteData()[0].length, colorMap.getByteData()[0], colorMap.getByteData()[1], colorMap.getByteData()[2], Transparency.OPAQUE);

PlanarImage op = PlanarImage.wrapRenderedImage(new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED,(IndexColorModel) cm));

ImageLayout layout = new ImageLayout();
layout.setTileWidth(image.getWidth());
layout.setTileHeight(image.getHeight());
layout.setColorModel(cm);
layout.setSampleModel(op.getSampleModel());

RenderingHints rh = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);

pb.removeParameters();
pb.removeSources();
pb.addSource(surrogateImage);
pb.add(colorMap);
pb.add(ditherMask);
op= JAI.create("errordiffusion",pb,rh);

surrogateImage=(PlanarImage)op;
image = surrogateImage.getAsBufferedImage();
return image;
}

public static final BufferedImage toBuffImageRGBorARGB(BufferedImage source) {
if (source.getType() != BufferedImage.TYPE_INT_RGB ||
source.getType() != BufferedImage.TYPE_INT_ARGB) {
int type = BufferedImage.TYPE_INT_RGB;
if (source.getColorModel().hasAlpha())
type = BufferedImage.TYPE_INT_ARGB;
BufferedImage bi = new BufferedImage(source.getWidth(), source.getHeight(), type);
Graphics2D graphics2D = null;
try {
graphics2D = bi.createGraphics();
graphics2D.drawImage(source, null, 0, 0);
} finally {
if (graphics2D != null)
graphics2D.dispose();
}
return bi;
}
return source;
}
}

Brian Burkhalter

Thanks for posting this test case. When we don't have to write a test case
ourselves then we can devote the time we would have spent writing the test to
actually fixing problems.

Unfortunately I have not been able to reproduce the problem with any of the
images I have tried thus far. Do you suppose it would be possible for you to
supply a test image for which this code fails in the way you described? If so
you may post the image directly to my e-mail account rather than to the entire
list so as not inconvenience others. If there is an issue of confidentiality
about the data please let me know.

Thanks,

Brian

On Mon, 31 Oct 2005, jai-interest@javadesktop.org wrote:

> Thanks for responding!
>
> I am honestly threading on thin ground here since my knowledge of image processing is minimal.
>
> I should be using JAI v1.1.3alpha which was the latest I could find
>
> I have created a class that will run and encounter this error, it is a bit awkwardly done because I quickly cut bits out from various places and then filled in the blanks. This code will get the bad value illegalargumentexception on most images except for some gif's which work fine, I believe the error to be in the toIndexColorModel function.
>
> change the two file location strings to point to the test files.
>
> code:
>
>
> import java.awt.Graphics2D;
> import java.awt.RenderingHints;
> import java.awt.Transparency;
> import java.awt.image.BufferedImage;
> import java.awt.image.ColorModel;
> import java.awt.image.IndexColorModel;
> import java.awt.image.WritableRaster;
> import java.awt.image.renderable.ParameterBlock;
> import java.io.ByteArrayInputStream;
> import java.io.File;
> import java.io.FileInputStream;
> import java.io.FileNotFoundException;
> import java.io.FileOutputStream;
> import java.io.IOException;
> import java.io.InputStream;
> import java.util.Iterator;
>
> import javax.imageio.ImageIO;
> import javax.imageio.ImageReader;
> import javax.imageio.ImageTypeSpecifier;
> import javax.imageio.ImageWriter;
> import javax.imageio.stream.ImageInputStream;
> import javax.imageio.stream.ImageOutputStream;
> import javax.media.jai.ImageLayout;
> import javax.media.jai.JAI;
> import javax.media.jai.KernelJAI;
> import javax.media.jai.LookupTableJAI;
> import javax.media.jai.PlanarImage;
> import javax.media.jai.operator.ColorQuantizerDescriptor;
>
> public class TestClass {
> private static String sourceTestFileLocation = "your test image";
> private static String destinationTestFileLocation = "c:/temp/testResult.gif";
>
> public static void main(String [] args){
> // Load the image
> ByteArrayInputStream imageStream = null;
> try {
> imageStream = new ByteArrayInputStream(TestClass.fileToByte(new File(sourceTestFileLocation)));
> } catch (IOException e) {
> e.printStackTrace();
> }
>
> BufferedImage image = null;
> ImageInputStream iis = null;
> ImageReader reader = null;
>
> try {
> iis = ImageIO.createImageInputStream(imageStream);
>
> Iterator readers = ImageIO.getImageReaders(iis);
>
> if(!readers.hasNext()){
> return;
> }
> reader = (ImageReader)readers.next();
> reader.setInput(iis,false);
> image = reader.read(0);
> }catch(IOException ioe){
> ioe.printStackTrace();
> }
>
> // convert all images to directcolormodel
> image = TestClass.toBuffImageRGBorARGB(image);
>
> // here there could have been lots of processing
>
> // preparing to write the image back to disk, always writing gif since that is the problem so convert the colormodel to indexcolormodel
>
> image = TestClass.toIndexColorModel(image);
>
> // Write the image back to disk
> FileOutputStream output = null;
> try {
> output = new FileOutputStream(destinationTestFileLocation);
> } catch (FileNotFoundException e) {
> e.printStackTrace();
> }
> Iterator writers = ImageIO.getImageWriters(new ImageTypeSpecifier(image),"gif");
>
> if(!writers.hasNext()){
> return;
> }
> ImageWriter writer = (ImageWriter)writers.next();
> ImageOutputStream ios = null;
>
> try{
> ios = ImageIO.createImageOutputStream(output);
>
> writer.setOutput(ios);
> writer.write(image);
> ios.flush();
> output.flush();
>
> } catch(IOException ioe){
> ioe.printStackTrace();
> } finally {
> writer.dispose();
> try{
> ios.close();
> output.close();
> } catch(IOException ignored){}
> writer = null;
> ios = null;
> output = null;
> }
>
> }
>
> public static byte[] fileToByte(File inputFile) throws IOException{
> InputStream innfil = null;
> innfil = new FileInputStream(inputFile);
>
> if (inputFile.length() > Integer.MAX_VALUE) {
> //throw new ImageDAOException("Test file is too large: "+inputFile.getName());
> }
>
> byte[] byteArray = new byte[(int)inputFile.length()];
>
> int offset = 0;
> int numRead = 0;
>
> while (offset < byteArray.length && (numRead=innfil.read(byteArray, offset, byteArray.length-offset)) >= 0) {
> offset += numRead;
> }
>
> // Ensure all the bytes have been read in
> if (offset < byteArray.length) {
> //throw new ImageDAOException("Could not completely read file "+inputFile.getName());
> }
>
> innfil.close();
> return byteArray;
> }
>
> public static BufferedImage toIndexColorModel(BufferedImage image) {
> PlanarImage surrogateImage = PlanarImage.wrapRenderedImage(image);
> ParameterBlock pb = new ParameterBlock();
>
> int w = surrogateImage.getWidth();
> int h = surrogateImage.getHeight();
>
> BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
>
> WritableRaster wr = bi.getWritableTile(0, 0);
> WritableRaster wr3 = wr.createWritableChild(0, 0, w, h, 0, 0, new int[] { 0, 1, 2 });
>
> wr3.setRect(surrogateImage.getData());
> bi.releaseWritableTile(0, 0);
> surrogateImage = PlanarImage.wrapRenderedImage(bi);
>
> pb.removeParameters();
> pb.removeSources();
>
> pb.addSource(surrogateImage).add(ColorQuantizerDescriptor.MEDIANCUT).add(new Integer(256));
> LookupTableJAI colorMap = (LookupTableJAI)JAI.create("ColorQuantizer", pb).getProperty("LUT");
> KernelJAI ditherMask = KernelJAI.ERROR_FILTER_FLOYD_STEINBERG;
>
> ColorModel cm = new IndexColorModel(8, colorMap.getByteData()[0].length, colorMap.getByteData()[0], colorMap.getByteData()[1], colorMap.getByteData()[2], Transparency.OPAQUE);
>
> PlanarImage op = PlanarImage.wrapRenderedImage(new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED,(IndexColorModel) cm));
>
> ImageLayout layout = new ImageLayout();
> layout.setTileWidth(image.getWidth());
> layout.setTileHeight(image.getHeight());
> layout.setColorModel(cm);
> layout.setSampleModel(op.getSampleModel());
>
> RenderingHints rh = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
>
> pb.removeParameters();
> pb.removeSources();
> pb.addSource(surrogateImage);
> pb.add(colorMap);
> pb.add(ditherMask);
> op= JAI.create("errordiffusion",pb,rh);
>
> surrogateImage=(PlanarImage)op;
> image = surrogateImage.getAsBufferedImage();
> return image;
> }
>
> public static final BufferedImage toBuffImageRGBorARGB(BufferedImage source) {
> if (source.getType() != BufferedImage.TYPE_INT_RGB ||
> source.getType() != BufferedImage.TYPE_INT_ARGB) {
> int type = BufferedImage.TYPE_INT_RGB;
> if (source.getColorModel().hasAlpha())
> type = BufferedImage.TYPE_INT_ARGB;
> BufferedImage bi = new BufferedImage(source.getWidth(), source.getHeight(), type);
> Graphics2D graphics2D = null;
> try {
> graphics2D = bi.createGraphics();
> graphics2D.drawImage(source, null, 0, 0);
> } finally {
> if (graphics2D != null)
> graphics2D.dispose();
> }
> return bi;
> }
> return source;
> }
> }
> ---
> [Message sent by forum member 'bonklers' (Andreas Gudmundsson)]
>
> http://www.javadesktop.org/forums/thread.jspa?messageID=122669&#122669
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
> For additional commands, e-mail: interest-help@jai.dev.java.net
>
>

----------------
Brian Burkhalter
Java Multimedia, Imaging, and Graphics
Sun Microsystems, Inc.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any
unauthorized review, use, disclosure or distribution is prohibited.
If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

Brian Burkhalter

Hello. I don't think this has anything to do with the image being a JPEG.

Which version of JAI are you using? Would you be able to supply a complete,
self-contained test case?

Brian

On Sun, 30 Oct 2005, jai-interest@javadesktop.org wrote:

> Hi
>
> I have been struggling a long while now with quality problems with my gif images, I finally narrowed the problem down to that all the operations I used would drastically derange the quality of the image if the image had an indexcolormodel the solution was to convert all indexcolormodel images to directcolormodel and then convert them back when processing was done. I then searched for a method that would procude better quality than the one I had and found some code on this forum that I tried which works fine with good quality.
>
> The problem is that if the image I try to convert was originally a jpeg image then I will get an error when I try to write it saying "bad value XXX" where XXX refers to the map size of the image which is something else than 256 for former jpeg image and 256 for former gif images (which work) so I take it I will have to force the map size to become 256 so that the gif writer will accept these images. But I am at a loss... I hope someone can enlighten me here.
>
> details:
> Im reading and writing the images using imageio, the images are loaded, processed (scaling, watermarking etcetc) and then written back again. Gif images are immediatley converted to ARGB images to prevent them from being distorted by the processing. finally I run this method if the desired output format is gif:
>
> the problem again: at the time of writing the image with the GifWriter of imageio, it will throw an exception saying illegalargumentexception: bad value XXX, I have concluded that the bad value if the map size of the buffered image which becomes 256 for gif images but sometihng other than 256 for jpeg images.
>
> really hope I can get some help on this, thanks!
>
> the function that I am currently trying out, it is the code from this post:
> http://www.javadesktop.org/forums/thread.jspa?forumID=54&threadID=10810&...
>
> slightly modified to fit into my use.
>
> public static BufferedImage toIndexColorModel(BufferedImage image, ImageConverterParams params) throws ImageConverterException{
> PlanarImage surrogateImage = PlanarImage.wrapRenderedImage(image);
> ParameterBlock pb = new ParameterBlock();
>
> int w = surrogateImage.getWidth();
> int h = surrogateImage.getHeight();
>
> BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
>
> WritableRaster wr = bi.getWritableTile(0, 0);
> WritableRaster wr3 = wr.createWritableChild(0, 0, w, h, 0, 0, new int[] { 0, 1, 2 });
>
> wr3.setRect(surrogateImage.getData());
> bi.releaseWritableTile(0, 0);
> surrogateImage = PlanarImage.wrapRenderedImage(bi);
>
> pb.removeParameters();
> pb.removeSources();
>
> pb.addSource(surrogateImage).add(ColorQuantizerDescriptor.MEDIANCUT).add(new Integer(256));
> LookupTableJAI colorMap = (LookupTableJAI)JAI.create("ColorQuantizer", pb).getProperty("LUT");
> KernelJAI ditherMask = KernelJAI.ERROR_FILTER_FLOYD_STEINBERG;
>
> ColorModel cm = new IndexColorModel(8, colorMap.getByteData()[0].length, colorMap.getByteData()[0], colorMap.getByteData()[1], colorMap.getByteData()[2], Transparency.OPAQUE);
>
> PlanarImage op = PlanarImage.wrapRenderedImage(new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED,(IndexColorModel) cm));
>
> ImageLayout layout = new ImageLayout();
> layout.setTileWidth(image.getWidth());
> layout.setTileHeight(image.getHeight());
> layout.setColorModel(cm);
> layout.setSampleModel(op.getSampleModel());
>
> RenderingHints rh = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
>
> pb.removeParameters();
> pb.removeSources();
> pb.addSource(surrogateImage);
> pb.add(colorMap);
> pb.add(ditherMask);
> op= JAI.create("errordiffusion",pb,rh);
>
> surrogateImage=(PlanarImage)op;
> image = surrogateImage.getAsBufferedImage();
> params.setCm(image.getColorModel());
> return image;
> }
> ---
> [Message sent by forum member 'bonklers' (Andreas Gudmundsson)]
>
> http://www.javadesktop.org/forums/thread.jspa?messageID=122440&#122440
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
> For additional commands, e-mail: interest-help@jai.dev.java.net
>
>

----------------
Brian Burkhalter
Java Multimedia, Imaging, and Graphics
Sun Microsystems, Inc.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any
unauthorized review, use, disclosure or distribution is prohibited.
If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net