1/*
2 * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @bug 6324581
27 * @summary Test verifies that RGB images are written to animated GIF image use
28 *          local color table if image palette is not equals to the global color
29 *          table
30 * @modules java.desktop/com.sun.imageio.plugins.gif
31 */
32
33import java.awt.Color;
34import java.awt.Graphics2D;
35import java.awt.image.BufferedImage;
36import java.io.ByteArrayInputStream;
37import java.io.ByteArrayOutputStream;
38import java.io.File;
39import java.io.FileOutputStream;
40import java.io.IOException;
41import java.util.ArrayList;
42
43import javax.imageio.IIOImage;
44import javax.imageio.ImageIO;
45import javax.imageio.ImageReader;
46import javax.imageio.ImageTypeSpecifier;
47import javax.imageio.ImageWriteParam;
48import javax.imageio.ImageWriter;
49import javax.imageio.metadata.IIOMetadata;
50import javax.imageio.stream.ImageOutputStream;
51
52import com.sun.imageio.plugins.gif.GIFImageMetadata;
53
54public class RGBAnimationTest {
55    protected static String format = "GIF";
56    protected static boolean doSave = true;
57
58    Frame[] frames;
59    ImageWriter writer;
60    ImageReader reader;
61
62    public static void main(String[] args) throws IOException  {
63        RGBAnimationTest test = new RGBAnimationTest();
64        test.doTest();
65    }
66    /** Creates a new instance of RGBAnimationTest */
67    public RGBAnimationTest() {
68        frames = new Frame[4];
69
70
71        frames[0] = new Frame(new Color[] {Color.red, Color.green});
72        frames[1] = new Frame(new Color[] {Color.green, Color.cyan});
73        frames[2] = new Frame(new Color[] {Color.cyan, Color.yellow});
74        frames[3] = new Frame(new Color[] {Color.yellow, Color.red});
75
76        writer = ImageIO.getImageWritersByFormatName(format).next();
77        reader = ImageIO.getImageReadersByFormatName(format).next();
78    }
79
80    public void doTest() throws IOException {
81        ByteArrayOutputStream baos = new ByteArrayOutputStream();
82        writer.reset();
83        ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
84        writer.setOutput(ios);
85
86        ImageWriteParam wparam = prepareWriteParam();
87
88        IIOMetadata streamMetadata = prepareStreamMetadata(wparam);
89
90        writer.prepareWriteSequence(streamMetadata);
91
92        for (int i = 0; i < frames.length; i++) {
93            BufferedImage src = frames[i].getImage();
94            IIOMetadata imageMetadata = prepareImageMetadata(i, src, wparam);
95            IIOImage img = new IIOImage(src,  null, imageMetadata);
96
97            writer.writeToSequence(img, wparam);
98        }
99        writer.endWriteSequence();
100        ios.flush();
101        ios.close();
102
103        if (doSave) {
104            File f = File.createTempFile("wr_test_", "." + format, new File("."));
105            System.out.println("Save to file: " + f.getCanonicalPath());
106            FileOutputStream fos = new FileOutputStream(f);
107            fos.write(baos.toByteArray());
108            fos.flush();
109            fos.close();
110        }
111        // read result
112        reader.reset();
113        ByteArrayInputStream bais =
114                new ByteArrayInputStream(baos.toByteArray());
115        reader.setInput(ImageIO.createImageInputStream(bais));
116
117        int minIndex = reader.getMinIndex();
118        int numImages = reader.getNumImages(true);
119
120        for (int i = 0; i < numImages; i++) {
121            BufferedImage dst = reader.read(i + minIndex);
122            frames[i].checkResult(dst);
123        }
124    }
125
126    protected IIOMetadata prepareImageMetadata(int i, BufferedImage img, ImageWriteParam wparam) {
127        GIFImageMetadata idata = (GIFImageMetadata)
128        writer.getDefaultImageMetadata(ImageTypeSpecifier.createFromRenderedImage(img), wparam);
129
130        idata.delayTime = 100;
131        idata.disposalMethod = 0;
132        idata.transparentColorFlag = false;
133
134        if (i == 0) {
135            ArrayList<byte[]> appIDs = new ArrayList<byte[]>();
136            appIDs.add(new String("NETSCAPE").getBytes());
137            ArrayList<byte[]> authCodes = new ArrayList<byte[]>();
138            authCodes.add(new String("2.0").getBytes());
139            ArrayList<byte[]> appData = new ArrayList<byte[]>();
140            byte[] authData = {1, 0, 0};
141            appData.add(authData);
142
143            idata.applicationIDs = appIDs;
144            idata.authenticationCodes = authCodes;
145            idata.applicationData = appData;
146        }
147        return idata;
148    }
149
150    protected ImageWriteParam prepareWriteParam() {
151        return writer.getDefaultWriteParam();
152    }
153
154    protected IIOMetadata prepareStreamMetadata(ImageWriteParam wparam) {
155        return writer.getDefaultStreamMetadata(wparam);
156    }
157
158}
159
160class Frame {
161    protected static int type = BufferedImage.TYPE_INT_RGB;
162    protected static int dx = 100;
163    protected static int h = 100;
164
165    protected Color[] colors;
166    protected BufferedImage img;
167
168    public Frame(Color[] colors) {
169        this.colors = colors;
170        img = null;
171    }
172
173    public BufferedImage getImage() {
174        if (img == null) {
175            img = new BufferedImage(dx * colors.length, h, type);
176            Graphics2D g = img.createGraphics();
177            for (int i = 0; i < colors.length; i++) {
178                g.setColor(colors[i]);
179                g.fillRect(dx * i, 0, dx, h);
180            }
181        }
182        return img;
183    }
184
185    public void checkResult(BufferedImage dst) {
186        int y = h / 2;
187        int x = dx / 2;
188        for (int i = 0; i < colors.length; i++) {
189
190            int srcRgb = img.getRGB(i * dx + x, y);
191            int dstRgb = dst.getRGB(i * dx + x, y);
192
193            if (srcRgb != dstRgb) {
194                throw new RuntimeException("Test failed due to color difference: " +
195                        Integer.toHexString(dstRgb) + " instead of " +
196                        Integer.toHexString(srcRgb));
197            }
198        }
199    }
200}
201