mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-16 13:25:34 +00:00
6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly
Reviewed-by: igor, prr
This commit is contained in:
parent
47a5b98c7f
commit
8c2a336349
@ -55,6 +55,7 @@ import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import com.sun.imageio.plugins.common.LZWCompressor;
|
||||
import com.sun.imageio.plugins.common.PaletteBuilder;
|
||||
import sun.awt.image.ByteComponentRaster;
|
||||
|
||||
public class GIFImageWriter extends ImageWriter {
|
||||
private static final boolean DEBUG = false; // XXX false for release!
|
||||
@ -905,10 +906,18 @@ public class GIFImageWriter extends ImageWriter {
|
||||
LZWCompressor compressor =
|
||||
new LZWCompressor(stream, initCodeSize, false);
|
||||
|
||||
/* At this moment we know that input image is indexed image.
|
||||
* We can directly copy data iff:
|
||||
* - no subsampling required (periodX = 1, periodY = 0)
|
||||
* - we can access data directly (image is non-tiled,
|
||||
* i.e. image data are in single block)
|
||||
* - we can calculate offset in data buffer (next 3 lines)
|
||||
*/
|
||||
boolean isOptimizedCase =
|
||||
periodX == 1 && periodY == 1 &&
|
||||
sampleModel instanceof ComponentSampleModel &&
|
||||
image.getNumXTiles() == 1 && image.getNumYTiles() == 1 &&
|
||||
sampleModel instanceof ComponentSampleModel &&
|
||||
image.getTile(0, 0) instanceof ByteComponentRaster &&
|
||||
image.getTile(0, 0).getDataBuffer() instanceof DataBufferByte;
|
||||
|
||||
int numRowsWritten = 0;
|
||||
@ -921,11 +930,14 @@ public class GIFImageWriter extends ImageWriter {
|
||||
if (DEBUG) System.out.println("Writing interlaced");
|
||||
|
||||
if (isOptimizedCase) {
|
||||
Raster tile = image.getTile(0, 0);
|
||||
ByteComponentRaster tile =
|
||||
(ByteComponentRaster)image.getTile(0, 0);
|
||||
byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData();
|
||||
ComponentSampleModel csm =
|
||||
(ComponentSampleModel)tile.getSampleModel();
|
||||
int offset = csm.getOffset(sourceXOffset, sourceYOffset, 0);
|
||||
// take into account the raster data offset
|
||||
offset += tile.getDataOffset(0);
|
||||
int lineStride = csm.getScanlineStride();
|
||||
|
||||
writeRowsOpt(data, offset, lineStride, compressor,
|
||||
|
||||
161
jdk/test/javax/imageio/plugins/gif/EncodeSubImageTest.java
Normal file
161
jdk/test/javax/imageio/plugins/gif/EncodeSubImageTest.java
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6795544
|
||||
*
|
||||
* @summary Test verifes that Image I/O gif writer correctly handles
|
||||
* buffered images based on translated reasters (typically
|
||||
* produced by getSubImage() method).
|
||||
*
|
||||
* @run main EncodeSubImageTest gif
|
||||
*/
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
|
||||
public class EncodeSubImageTest {
|
||||
private static String format = "gif";
|
||||
private static ImageWriter writer;
|
||||
private static String file_suffix;
|
||||
private static final int subSampleX = 2;
|
||||
private static final int subSampleY = 2;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
if (args.length > 0) {
|
||||
format = args[0];
|
||||
}
|
||||
|
||||
writer = ImageIO.getImageWritersByFormatName(format).next();
|
||||
|
||||
file_suffix =writer.getOriginatingProvider().getFileSuffixes()[0];
|
||||
|
||||
BufferedImage src = createTestImage();
|
||||
EncodeSubImageTest m1 = new EncodeSubImageTest(src);
|
||||
m1.doTest("test_src");
|
||||
|
||||
BufferedImage sub = src.getSubimage(subImageOffset, subImageOffset,
|
||||
src.getWidth() - 2 * subImageOffset,
|
||||
src.getHeight() - 2 * subImageOffset);
|
||||
EncodeSubImageTest m2 = new EncodeSubImageTest(sub);
|
||||
m2.doTest("test_sub");
|
||||
}
|
||||
|
||||
BufferedImage img;
|
||||
|
||||
public EncodeSubImageTest(BufferedImage img) {
|
||||
this.img = img;
|
||||
}
|
||||
|
||||
public void doTest(String prefix) throws IOException {
|
||||
System.out.println(prefix);
|
||||
File f = new File(prefix + file_suffix);
|
||||
write(f, false);
|
||||
verify(f, false);
|
||||
|
||||
System.out.println(prefix + "_subsampled");
|
||||
f = new File(prefix + "_subsampled");
|
||||
write(f, true);
|
||||
verify(f, true);
|
||||
|
||||
System.out.println(prefix + ": Test PASSED.");
|
||||
}
|
||||
|
||||
private static final int subImageOffset = 10;
|
||||
|
||||
private void verify(File f, boolean isSubsampled) {
|
||||
BufferedImage dst = null;
|
||||
try {
|
||||
dst = ImageIO.read(f);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Test FAILED: can't readin test image " +
|
||||
f.getAbsolutePath(), e);
|
||||
}
|
||||
if (dst == null) {
|
||||
throw new RuntimeException("Test FAILED: no dst image available.");
|
||||
}
|
||||
|
||||
checkPixel(dst, 0, 0, isSubsampled);
|
||||
|
||||
checkPixel(dst, img.getWidth() / 2, img.getHeight() / 2, isSubsampled);
|
||||
}
|
||||
|
||||
private void checkPixel(BufferedImage dst, int x, int y,
|
||||
boolean isSubsampled)
|
||||
{
|
||||
int dx = isSubsampled ? x / subSampleX : x;
|
||||
int dy = isSubsampled ? y / subSampleY : y;
|
||||
int src_rgb = img.getRGB(x, y);
|
||||
System.out.printf("src_rgb: %x\n", src_rgb);
|
||||
|
||||
int dst_rgb = dst.getRGB(dx, dy);
|
||||
System.out.printf("dst_rgb: %x\n", dst_rgb);
|
||||
|
||||
if (src_rgb != dst_rgb) {
|
||||
throw new RuntimeException("Test FAILED: invalid color in dst");
|
||||
}
|
||||
}
|
||||
|
||||
private static BufferedImage createTestImage() {
|
||||
int w = 100;
|
||||
int h = 100;
|
||||
|
||||
BufferedImage src = new BufferedImage(w, h,
|
||||
BufferedImage.TYPE_BYTE_INDEXED);
|
||||
Graphics g = src.createGraphics();
|
||||
g.setColor(Color.red);
|
||||
g.fillRect(0, 0, w, h);
|
||||
g.setColor(Color.green);
|
||||
g.fillRect(subImageOffset, subImageOffset,
|
||||
w - 2 * subImageOffset, h - 2* subImageOffset);
|
||||
g.setColor(Color.blue);
|
||||
g.fillRect(2 * subImageOffset, 2 * subImageOffset,
|
||||
w - 4 * subImageOffset, h - 4 * subImageOffset);
|
||||
g.dispose();
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
private void write(File f, boolean subsample) throws IOException {
|
||||
ImageOutputStream ios = ImageIO.createImageOutputStream(f);
|
||||
|
||||
writer.setOutput(ios);
|
||||
ImageWriteParam p = writer.getDefaultWriteParam();
|
||||
if (subsample) {
|
||||
p.setSourceSubsampling(subSampleX, subSampleY, 0, 0);
|
||||
}
|
||||
writer.write(null, new IIOImage(img, null, null), p);
|
||||
ios.close();
|
||||
writer.reset();
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user