JDK-6795544 : GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.imageio
  • Affected Version: 6u10,6u11
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_2.5.1,windows_xp
  • CPU: x86,sparc
  • Submitted: 2009-01-20
  • Updated: 2011-03-07
  • Resolved: 2011-03-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b54Fixed
Description
When I save the subImage of BufferedImage with GIFImageWriter, the ImageWriter
write an incorrect region of the original image to a file.

I try to show the subImage on JFrame, the subImage seems like expected.
So I guess that GIFImageWriter does not work correctly.

If I use jpg/png ImageWrite, the ImageWriter will write a correct region
to a file.

- STEPS TO FOLLOW TO REPRODUCE THE PROBLEM:

OS: Windows XP SP2
JRE: 6u10, 6u11

1. Compile the following java code.
2. Run the program with a image (larger than 60x60).


- EXPECTED VERSUS ACTUAL BEHAVIOR:

EXPECTED:

Save a correct middle region (rectangular (30,30)-(60,60)) of the original file.

ACTUAL:

Save an incorrect middle region (rectangular (0,0)-(30,30)) of the original file.


For the following source code, this bug can be reproduced always.

---------- BEGIN SOURCE ----------

package test;

import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;

public class SaveSubImage extends JFrame {

	/**
	 * inFile (GIF)
	 */
	private static final String IN_GIF = "./resource/image.gif";

	/**
	 * outFile1
	 */
	private static final String OUT_GIF_1 = "./resource/image_sub_1.gif";

	/**
	 * outFile2
	 */
	private static final String OUT_GIF_2 = "./resource/image_sub_2.gif";

	/**
	 * imageFormat (jpg/png/gif)
	 */
	private static final String IMAGE_FORMAT = "gif";

	/**
	 * main.
	 * 
	 * @param args
	 *            args
	 */
	public static void main(String[] args) {

		try {
			BufferedImage originalImage = ImageIO.read(new File(IN_GIF));

			ImageWriter writer = ImageIO.getImageWritersByFormatName(
					IMAGE_FORMAT).next();

			// not correctly
			BufferedImage subImage1 = originalImage.getSubimage(30, 30, 30, 30);
			writer.setOutput(new FileImageOutputStream(new File(OUT_GIF_1)));
			writer.write(subImage1);

		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

---------- END SOURCE ------------
Bug WorkaroundIf reconstructing a subImage of BufferedImage, the program will work correctly.

---------- BEGIN SOURCE ----------

			// correctly
			BufferedImage subImage2 = originalImage.getSubimage(30, 30, 30, 30);
			BufferedImage subImage3 = new BufferedImage(subImage2.getHeight(),
					subImage2.getWidth(), subImage2.getType(),
					(IndexColorModel) subImage2.getColorModel());
			subImage3.setData(subImage2.getData());
			writer.setOutput(new FileImageOutputStream(new File(OUT_GIF_2)));
			writer.write(subImage3);

---------- END SOURCE ------------

Comments
SUGGESTED FIX http://sa.sfbay.sun.com/projects/java2d_data/7/6795544.0
2009-01-23

EVALUATION The reason of problem here is that the optimized writing loop (utilized direct access to image data buffer) does not take into account a data band offset (which is non-trivial for sub-images, for example). It results in writing image data starting from top left corner of the parent image instead of expected top left corner of the sub-image. We should take into account data bands offset, calculated by translated raster instance.
2009-01-21