jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java
author jdv
Thu, 29 Sep 2016 10:57:34 +0530
changeset 41403 be56daafbeaa
parent 35667 ed476aba94de
child 41784 c1e614077765
permissions -rw-r--r--
8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener. Reviewed-by: prr, bpb, serb, psadhukhan
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
41403
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
     2
 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2378
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2378
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2378
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2378
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2378
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package com.sun.imageio.plugins.gif;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.awt.Dimension;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.awt.Rectangle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.awt.image.ColorModel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.awt.image.ComponentSampleModel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.awt.image.DataBufferByte;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.awt.image.IndexColorModel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.awt.image.Raster;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
import java.awt.image.RenderedImage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
import java.awt.image.SampleModel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.awt.image.WritableRaster;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
import java.nio.ByteOrder;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.util.Arrays;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.util.Iterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
import java.util.Locale;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
import javax.imageio.IIOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
import javax.imageio.IIOImage;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
import javax.imageio.ImageTypeSpecifier;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
import javax.imageio.ImageWriteParam;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
import javax.imageio.ImageWriter;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
import javax.imageio.spi.ImageWriterSpi;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
import javax.imageio.metadata.IIOInvalidTreeException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
import javax.imageio.metadata.IIOMetadata;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
import javax.imageio.metadata.IIOMetadataFormatImpl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
import javax.imageio.metadata.IIOMetadataNode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
import javax.imageio.stream.ImageOutputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
import org.w3c.dom.Node;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
import org.w3c.dom.NodeList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
import com.sun.imageio.plugins.common.LZWCompressor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
import com.sun.imageio.plugins.common.PaletteBuilder;
2378
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
    58
import sun.awt.image.ByteComponentRaster;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
public class GIFImageWriter extends ImageWriter {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    private static final boolean DEBUG = false; // XXX false for release!
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
    static final String STANDARD_METADATA_NAME =
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    IIOMetadataFormatImpl.standardMetadataFormatName;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    static final String STREAM_METADATA_NAME =
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    GIFWritableStreamMetadata.NATIVE_FORMAT_NAME;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    static final String IMAGE_METADATA_NAME =
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    GIFWritableImageMetadata.NATIVE_FORMAT_NAME;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    /**
35667
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
    73
     * The {@code output} case to an {@code ImageOutputStream}.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    private ImageOutputStream stream = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
     * Whether a sequence is being written.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    private boolean isWritingSequence = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
     * Whether the header has been written.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    private boolean wroteSequenceHeader = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
     * The stream metadata of a sequence.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    private GIFWritableStreamMetadata theStreamMetadata = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
     * The index of the image being written.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    private int imageIndex = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     * The number of bits represented by the value which should be a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     * legal length for a color table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    private static int getNumBits(int value) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
        int numBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        switch(value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        case 2:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
            numBits = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        case 4:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
            numBits = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        case 8:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
            numBits = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
        case 16:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            numBits = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
        case 32:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
            numBits = 5;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        case 64:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
            numBits = 6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
        case 128:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
            numBits = 7;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        case 256:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
            numBits = 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
            throw new IOException("Bad palette length: "+value+"!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
        return numBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
     * Compute the source region and destination dimensions taking any
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
     * parameter settings into account.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    private static void computeRegions(Rectangle sourceBounds,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                                       Dimension destSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
                                       ImageWriteParam p) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
        ImageWriteParam param;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        int periodX = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
        int periodY = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
        if (p != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
            int[] sourceBands = p.getSourceBands();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
            if (sourceBands != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
                (sourceBands.length != 1 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
                 sourceBands[0] != 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
                throw new IllegalArgumentException("Cannot sub-band image!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            // Get source region and subsampling factors
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            Rectangle sourceRegion = p.getSourceRegion();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            if (sourceRegion != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
                // Clip to actual image bounds
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                sourceRegion = sourceRegion.intersection(sourceBounds);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                sourceBounds.setBounds(sourceRegion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            // Adjust for subsampling offsets
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
            int gridX = p.getSubsamplingXOffset();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            int gridY = p.getSubsamplingYOffset();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            sourceBounds.x += gridX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
            sourceBounds.y += gridY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
            sourceBounds.width -= gridX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
            sourceBounds.height -= gridY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
            // Get subsampling factors
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
            periodX = p.getSourceXSubsampling();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
            periodY = p.getSourceYSubsampling();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        // Compute output dimensions
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        destSize.setSize((sourceBounds.width + periodX - 1)/periodX,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
                         (sourceBounds.height + periodY - 1)/periodY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        if (destSize.width <= 0 || destSize.height <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
            throw new IllegalArgumentException("Empty source region!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
     * Create a color table from the image ColorModel and SampleModel.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    private static byte[] createColorTable(ColorModel colorModel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                                           SampleModel sampleModel)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        byte[] colorTable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        if (colorModel instanceof IndexColorModel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
            IndexColorModel icm = (IndexColorModel)colorModel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
            int mapSize = icm.getMapSize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
             * The GIF image format assumes that size of image palette
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
             * is power of two. We will use closest larger power of two
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
             * as size of color table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
            int ctSize = getGifPaletteSize(mapSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
            byte[] reds = new byte[ctSize];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            byte[] greens = new byte[ctSize];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
            byte[] blues = new byte[ctSize];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
            icm.getReds(reds);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
            icm.getGreens(greens);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
            icm.getBlues(blues);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
            /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
             * fill tail of color component arrays by replica of first color
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
             * in order to avoid appearance of extra colors in the color table
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
            for (int i = mapSize; i < ctSize; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                reds[i] = reds[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                greens[i] = greens[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                blues[i] = blues[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
            colorTable = new byte[3*ctSize];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            int idx = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
            for (int i = 0; i < ctSize; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                colorTable[idx++] = reds[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
                colorTable[idx++] = greens[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                colorTable[idx++] = blues[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
        } else if (sampleModel.getNumBands() == 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
            // create gray-scaled color table for single-banded images
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
            int numBits = sampleModel.getSampleSize()[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            if (numBits > 8) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                numBits = 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
            int colorTableLength = 3*(1 << numBits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
            colorTable = new byte[colorTableLength];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
            for (int i = 0; i < colorTableLength; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                colorTable[i] = (byte)(i/3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
            // We do not have enough information here
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
            // to create well-fit color table for RGB image.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            colorTable = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        return colorTable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
     * According do GIF specification size of clor table (palette here)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
     * must be in range from 2 to 256 and must be power of 2.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    private static int getGifPaletteSize(int x) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
        if (x <= 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            return 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        x = x - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        x = x | (x >> 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        x = x | (x >> 2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
        x = x | (x >> 4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        x = x | (x >> 8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        x = x | (x >> 16);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        return x + 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
    public GIFImageWriter(GIFImageWriterSpi originatingProvider) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        super(originatingProvider);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        if (DEBUG) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
            System.err.println("GIF Writer is created");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
    public boolean canWriteSequence() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
    /**
35667
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   275
     * Merges {@code inData} into {@code outData}. The supplied
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
     * metadata format name is attempted first and failing that the standard
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
     * metadata format name is attempted.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    private void convertMetadata(String metadataFormatName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
                                 IIOMetadata inData,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
                                 IIOMetadata outData) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        String formatName = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        String nativeFormatName = inData.getNativeMetadataFormatName();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        if (nativeFormatName != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
            nativeFormatName.equals(metadataFormatName)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
            formatName = metadataFormatName;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            String[] extraFormatNames = inData.getExtraMetadataFormatNames();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
            if (extraFormatNames != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
                for (int i = 0; i < extraFormatNames.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
                    if (extraFormatNames[i].equals(metadataFormatName)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                        formatName = metadataFormatName;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
                        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        if (formatName == null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            inData.isStandardMetadataFormatSupported()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            formatName = STANDARD_METADATA_NAME;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
        if (formatName != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                Node root = inData.getAsTree(formatName);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                outData.mergeTree(formatName, root);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
            } catch(IIOInvalidTreeException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
                // ignore
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
     * Creates a default stream metadata object and merges in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
     * supplied metadata.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
    public IIOMetadata convertStreamMetadata(IIOMetadata inData,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
                                             ImageWriteParam param) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        if (inData == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
            throw new IllegalArgumentException("inData == null!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
        IIOMetadata sm = getDefaultStreamMetadata(param);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
        convertMetadata(STREAM_METADATA_NAME, inData, sm);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        return sm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
     * Creates a default image metadata object and merges in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
     * supplied metadata.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
    public IIOMetadata convertImageMetadata(IIOMetadata inData,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
                                            ImageTypeSpecifier imageType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
                                            ImageWriteParam param) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
        if (inData == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
            throw new IllegalArgumentException("inData == null!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        if (imageType == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
            throw new IllegalArgumentException("imageType == null!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
        GIFWritableImageMetadata im =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
            (GIFWritableImageMetadata)getDefaultImageMetadata(imageType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                                                              param);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        // Save interlace flag state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
        boolean isProgressive = im.interlaceFlag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
        convertMetadata(IMAGE_METADATA_NAME, inData, im);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
        // Undo change to interlace flag if not MODE_COPY_FROM_METADATA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        if (param != null && param.canWriteProgressive() &&
22567
5816a47fa4dd 8032047: Fix static lint warnings in client libraries
darcy
parents: 5506
diff changeset
   360
            param.getProgressiveMode() != ImageWriteParam.MODE_COPY_FROM_METADATA) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
            im.interlaceFlag = isProgressive;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
        return im;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
    public void endWriteSequence() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
        if (stream == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
            throw new IllegalStateException("output == null!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        if (!isWritingSequence) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            throw new IllegalStateException("prepareWriteSequence() was not invoked!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        writeTrailer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
        resetLocal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
    public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                                               ImageWriteParam param) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        GIFWritableImageMetadata imageMetadata =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            new GIFWritableImageMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        // Image dimensions
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
        SampleModel sampleModel = imageType.getSampleModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        Rectangle sourceBounds = new Rectangle(sampleModel.getWidth(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
                                               sampleModel.getHeight());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        Dimension destSize = new Dimension();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
        computeRegions(sourceBounds, destSize, param);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        imageMetadata.imageWidth = destSize.width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        imageMetadata.imageHeight = destSize.height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        // Interlacing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        if (param != null && param.canWriteProgressive() &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
            param.getProgressiveMode() == ImageWriteParam.MODE_DISABLED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
            imageMetadata.interlaceFlag = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
            imageMetadata.interlaceFlag = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        // Local color table
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        ColorModel colorModel = imageType.getColorModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
        imageMetadata.localColorTable =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
            createColorTable(colorModel, sampleModel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        // Transparency
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
        if (colorModel instanceof IndexColorModel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
            int transparentIndex =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
                ((IndexColorModel)colorModel).getTransparentPixel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
            if (transparentIndex != -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
                imageMetadata.transparentColorFlag = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                imageMetadata.transparentColorIndex = transparentIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
        return imageMetadata;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
    public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
        GIFWritableStreamMetadata streamMetadata =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
            new GIFWritableStreamMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
        streamMetadata.version = "89a";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
        return streamMetadata;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
    public ImageWriteParam getDefaultWriteParam() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        return new GIFImageWriteParam(getLocale());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
    public void prepareWriteSequence(IIOMetadata streamMetadata)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        if (stream == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
            throw new IllegalStateException("Output is not set.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
        resetLocal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        // Save the possibly converted stream metadata as an instance variable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
        if (streamMetadata == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
            this.theStreamMetadata =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                (GIFWritableStreamMetadata)getDefaultStreamMetadata(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
            this.theStreamMetadata = new GIFWritableStreamMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
            convertMetadata(STREAM_METADATA_NAME, streamMetadata,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
                            theStreamMetadata);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
        this.isWritingSequence = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
    public void reset() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
        super.reset();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
        resetLocal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
     * Resets locally defined instance variables.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
    private void resetLocal() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
        this.isWritingSequence = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
        this.wroteSequenceHeader = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
        this.theStreamMetadata = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
        this.imageIndex = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
    public void setOutput(Object output) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
        super.setOutput(output);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
        if (output != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
            if (!(output instanceof ImageOutputStream)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                throw new
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
                    IllegalArgumentException("output is not an ImageOutputStream");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
            this.stream = (ImageOutputStream)output;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
            this.stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
            this.stream = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
    public void write(IIOMetadata sm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
                      IIOImage iioimage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
                      ImageWriteParam p) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        if (stream == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
            throw new IllegalStateException("output == null!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
        if (iioimage == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            throw new IllegalArgumentException("iioimage == null!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        if (iioimage.hasRaster()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
            throw new UnsupportedOperationException("canWriteRasters() == false!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
        resetLocal();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        GIFWritableStreamMetadata streamMetadata;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
        if (sm == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
            streamMetadata =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
                (GIFWritableStreamMetadata)getDefaultStreamMetadata(p);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
            streamMetadata =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
                (GIFWritableStreamMetadata)convertStreamMetadata(sm, p);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        write(true, true, streamMetadata, iioimage, p);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
    public void writeToSequence(IIOImage image, ImageWriteParam param)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
        if (stream == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
            throw new IllegalStateException("output == null!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
        if (image == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
            throw new IllegalArgumentException("image == null!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
        if (image.hasRaster()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
            throw new UnsupportedOperationException("canWriteRasters() == false!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        if (!isWritingSequence) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
            throw new IllegalStateException("prepareWriteSequence() was not invoked!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
        write(!wroteSequenceHeader, false, theStreamMetadata,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
              image, param);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
        if (!wroteSequenceHeader) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
            wroteSequenceHeader = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
        this.imageIndex++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
    private boolean needToCreateIndex(RenderedImage image) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
        SampleModel sampleModel = image.getSampleModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
        ColorModel colorModel = image.getColorModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
        return sampleModel.getNumBands() != 1 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
            sampleModel.getSampleSize()[0] > 8 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            colorModel.getComponentSize()[0] > 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
     * Writes any extension blocks, the Image Descriptor, the image data,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
     * and optionally the header (Signature and Logical Screen Descriptor)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
     * and trailer (Block Terminator).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
     * @param writeHeader Whether to write the header.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
     * @param writeTrailer Whether to write the trailer.
35667
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   557
     * @param sm The stream metadata or {@code null} if
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   558
     * {@code writeHeader} is {@code false}.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
     * @param iioimage The image and image metadata.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
     * @param p The write parameters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
     * @throws IllegalArgumentException if the number of bands is not 1.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
     * @throws IllegalArgumentException if the number of bits per sample is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
     * greater than 8.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
     * @throws IllegalArgumentException if the color component size is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
     * greater than 8.
35667
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   567
     * @throws IllegalArgumentException if {@code writeHeader} is
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   568
     * {@code true} and {@code sm} is {@code null}.
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   569
     * @throws IllegalArgumentException if {@code writeHeader} is
ed476aba94de 8138838: docs cleanup for java.desktop
avstepan
parents: 25859
diff changeset
   570
     * {@code false} and a sequence is not being written.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
    private void write(boolean writeHeader,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
                       boolean writeTrailer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
                       IIOMetadata sm,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                       IIOImage iioimage,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
                       ImageWriteParam p) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        RenderedImage image = iioimage.getRenderedImage();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        // Check for ability to encode image.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
        if (needToCreateIndex(image)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
            image = PaletteBuilder.createIndexedImage(image);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            iioimage.setRenderedImage(image);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
        ColorModel colorModel = image.getColorModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
        SampleModel sampleModel = image.getSampleModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
        // Determine source region and destination dimensions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
        Rectangle sourceBounds = new Rectangle(image.getMinX(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
                                               image.getMinY(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
                                               image.getWidth(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
                                               image.getHeight());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
        Dimension destSize = new Dimension();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
        computeRegions(sourceBounds, destSize, p);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
        // Convert any provided image metadata.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
        GIFWritableImageMetadata imageMetadata = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
        if (iioimage.getMetadata() != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
            imageMetadata = new GIFWritableImageMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
            convertMetadata(IMAGE_METADATA_NAME, iioimage.getMetadata(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
                            imageMetadata);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
            // Converted rgb image can use palette different from global.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
            // In order to avoid color artefacts we want to be sure we use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
            // appropriate palette. For this we initialize local color table
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
            // from current color and sample models.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
            // At this point we can guarantee that local color table can be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
            // build because image was already converted to indexed or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
            // gray-scale representations
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            if (imageMetadata.localColorTable == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
                imageMetadata.localColorTable =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
                    createColorTable(colorModel, sampleModel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                // in case of indexed image we should take care of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                // transparent pixels
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
                if (colorModel instanceof IndexColorModel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
                    IndexColorModel icm =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
                        (IndexColorModel)colorModel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                    int index = icm.getTransparentPixel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
                    imageMetadata.transparentColorFlag = (index != -1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
                    if (imageMetadata.transparentColorFlag) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                        imageMetadata.transparentColorIndex = index;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
                    /* NB: transparentColorFlag might have not beed reset for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                       greyscale images but explicitly reseting it here
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                       is potentially not right thing to do until we have way
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                       to find whether current value was explicitly set by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                       the user.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
                    */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
        // Global color table values.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
        byte[] globalColorTable = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
        // Write the header (Signature+Logical Screen Descriptor+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
        // Global Color Table).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        if (writeHeader) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
            if (sm == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
                throw new IllegalArgumentException("Cannot write null header!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
            GIFWritableStreamMetadata streamMetadata =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
                (GIFWritableStreamMetadata)sm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
            // Set the version if not set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
            if (streamMetadata.version == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
                streamMetadata.version = "89a";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
            // Set the Logical Screen Desriptor if not set.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
            if (streamMetadata.logicalScreenWidth ==
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
                GIFMetadata.UNDEFINED_INTEGER_VALUE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
            {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
                streamMetadata.logicalScreenWidth = destSize.width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
            if (streamMetadata.logicalScreenHeight ==
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
                GIFMetadata.UNDEFINED_INTEGER_VALUE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
            {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
                streamMetadata.logicalScreenHeight = destSize.height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
            if (streamMetadata.colorResolution ==
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
                GIFMetadata.UNDEFINED_INTEGER_VALUE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
                streamMetadata.colorResolution = colorModel != null ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
                    colorModel.getComponentSize()[0] :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
                    sampleModel.getSampleSize()[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
            // Set the Global Color Table if not set, i.e., if not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
            // provided in the stream metadata.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
            if (streamMetadata.globalColorTable == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
                if (isWritingSequence && imageMetadata != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                    imageMetadata.localColorTable != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                    // Writing a sequence and a local color table was
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                    // provided in the metadata of the first image: use it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                    streamMetadata.globalColorTable =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
                        imageMetadata.localColorTable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
                } else if (imageMetadata == null ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
                           imageMetadata.localColorTable == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
                    // Create a color table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
                    streamMetadata.globalColorTable =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
                        createColorTable(colorModel, sampleModel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
            // Set the Global Color Table. At this point it should be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
            // A) the global color table provided in stream metadata, if any;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
            // B) the local color table of the image metadata, if any, if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
            //    writing a sequence;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
            // C) a table created on the basis of the first image ColorModel
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
            //    and SampleModel if no local color table is available; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
            // D) null if none of the foregoing conditions obtain (which
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
            //    should only be if a sequence is not being written and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
            //    a local color table is provided in image metadata).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
            globalColorTable = streamMetadata.globalColorTable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
            // Write the header.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
            int bitsPerPixel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
            if (globalColorTable != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                bitsPerPixel = getNumBits(globalColorTable.length/3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
            } else if (imageMetadata != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                       imageMetadata.localColorTable != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
                bitsPerPixel =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                    getNumBits(imageMetadata.localColorTable.length/3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                bitsPerPixel = sampleModel.getSampleSize(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
            writeHeader(streamMetadata, bitsPerPixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
        } else if (isWritingSequence) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
            globalColorTable = theStreamMetadata.globalColorTable;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
            throw new IllegalArgumentException("Must write header for single image!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
        // Write extension blocks, Image Descriptor, and image data.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
        writeImage(iioimage.getRenderedImage(), imageMetadata, p,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                   globalColorTable, sourceBounds, destSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
        // Write the trailer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
        if (writeTrailer) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
            writeTrailer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
     * Writes any extension blocks, the Image Descriptor, and the image data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
     * @param iioimage The image and image metadata.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
     * @param param The write parameters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
     * @param globalColorTable The Global Color Table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
     * @param sourceBounds The source region.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
     * @param destSize The destination dimensions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
    private void writeImage(RenderedImage image,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
                            GIFWritableImageMetadata imageMetadata,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
                            ImageWriteParam param, byte[] globalColorTable,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
                            Rectangle sourceBounds, Dimension destSize)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
        ColorModel colorModel = image.getColorModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
        SampleModel sampleModel = image.getSampleModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
        boolean writeGraphicsControlExtension;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
        if (imageMetadata == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
            // Create default metadata.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
            imageMetadata = (GIFWritableImageMetadata)getDefaultImageMetadata(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
                new ImageTypeSpecifier(image), param);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
            // Set GraphicControlExtension flag only if there is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
            // transparency.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
            writeGraphicsControlExtension = imageMetadata.transparentColorFlag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
            // Check for GraphicControlExtension element.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
            NodeList list = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
                IIOMetadataNode root = (IIOMetadataNode)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
                    imageMetadata.getAsTree(IMAGE_METADATA_NAME);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
                list = root.getElementsByTagName("GraphicControlExtension");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
            } catch(IllegalArgumentException iae) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
                // Should never happen.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
            // Set GraphicControlExtension flag if element present.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
            writeGraphicsControlExtension =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
                list != null && list.getLength() > 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
            // If progressive mode is not MODE_COPY_FROM_METADATA, ensure
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
            // the interlacing is set per the ImageWriteParam mode setting.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
            if (param != null && param.canWriteProgressive()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
                if (param.getProgressiveMode() ==
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
                    ImageWriteParam.MODE_DISABLED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
                    imageMetadata.interlaceFlag = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
                } else if (param.getProgressiveMode() ==
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
                           ImageWriteParam.MODE_DEFAULT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
                    imageMetadata.interlaceFlag = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
        // Unset local color table if equal to global color table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
        if (Arrays.equals(globalColorTable, imageMetadata.localColorTable)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
            imageMetadata.localColorTable = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
        // Override dimensions
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
        imageMetadata.imageWidth = destSize.width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
        imageMetadata.imageHeight = destSize.height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
        // Write Graphics Control Extension.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
        if (writeGraphicsControlExtension) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
            writeGraphicControlExtension(imageMetadata);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
        // Write extension blocks.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
        writePlainTextExtension(imageMetadata);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
        writeApplicationExtension(imageMetadata);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
        writeCommentExtension(imageMetadata);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
        // Write Image Descriptor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
        int bitsPerPixel =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
            getNumBits(imageMetadata.localColorTable == null ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
                       (globalColorTable == null ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
                        sampleModel.getSampleSize(0) :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
                        globalColorTable.length/3) :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
                       imageMetadata.localColorTable.length/3);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
        writeImageDescriptor(imageMetadata, bitsPerPixel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
        // Write image data
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
        writeRasterData(image, sourceBounds, destSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
                        param, imageMetadata.interlaceFlag);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
    private void writeRows(RenderedImage image, LZWCompressor compressor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
                           int sx, int sdx, int sy, int sdy, int sw,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
                           int dy, int ddy, int dw, int dh,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
                           int numRowsWritten, int progressReportRowPeriod)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
        if (DEBUG) System.out.println("Writing unoptimized");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
        int[] sbuf = new int[sw];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
        byte[] dbuf = new byte[dw];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
        Raster raster =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
            image.getNumXTiles() == 1 && image.getNumYTiles() == 1 ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
            image.getTile(0, 0) : image.getData();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
        for (int y = dy; y < dh; y += ddy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
            if (numRowsWritten % progressReportRowPeriod == 0) {
41403
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   831
                processImageProgress((numRowsWritten*100.0F)/dh);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
                    processWriteAborted();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
            raster.getSamples(sx, sy, sw, 1, 0, sbuf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
            for (int i = 0, j = 0; i < dw; i++, j += sdx) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
                dbuf[i] = (byte)sbuf[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
            compressor.compress(dbuf, 0, dw);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
            numRowsWritten++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
            sy += sdy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
    private void writeRowsOpt(byte[] data, int offset, int lineStride,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
                              LZWCompressor compressor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
                              int dy, int ddy, int dw, int dh,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
                              int numRowsWritten, int progressReportRowPeriod)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
        if (DEBUG) System.out.println("Writing optimized");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
        offset += dy*lineStride;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
        lineStride *= ddy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
        for (int y = dy; y < dh; y += ddy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
            if (numRowsWritten % progressReportRowPeriod == 0) {
41403
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   859
                processImageProgress((numRowsWritten*100.0F)/dh);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
                    processWriteAborted();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
            compressor.compress(data, offset, dw);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
            numRowsWritten++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
            offset += lineStride;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
    private void writeRasterData(RenderedImage image,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
                                 Rectangle sourceBounds,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
                                 Dimension destSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
                                 ImageWriteParam param,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
                                 boolean interlaceFlag) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
        int sourceXOffset = sourceBounds.x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
        int sourceYOffset = sourceBounds.y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
        int sourceWidth = sourceBounds.width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
        int sourceHeight = sourceBounds.height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
        int destWidth = destSize.width;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
        int destHeight = destSize.height;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
        int periodX;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
        int periodY;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
        if (param == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
            periodX = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
            periodY = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
            periodX = param.getSourceXSubsampling();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
            periodY = param.getSourceYSubsampling();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
        SampleModel sampleModel = image.getSampleModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
        int bitsPerPixel = sampleModel.getSampleSize()[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        int initCodeSize = bitsPerPixel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
        if (initCodeSize == 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
            initCodeSize++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
        stream.write(initCodeSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
        LZWCompressor compressor =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
            new LZWCompressor(stream, initCodeSize, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
2378
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   908
        /* At this moment we know that input image is indexed image.
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   909
         * We can directly copy data iff:
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   910
         *   - no subsampling required (periodX = 1, periodY = 0)
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   911
         *   - we can access data directly (image is non-tiled,
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   912
         *     i.e. image data are in single block)
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   913
         *   - we can calculate offset in data buffer (next 3 lines)
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   914
         */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        boolean isOptimizedCase =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
            periodX == 1 && periodY == 1 &&
2378
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   917
            image.getNumXTiles() == 1 && image.getNumYTiles() == 1 &&
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
            sampleModel instanceof ComponentSampleModel &&
2378
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   919
            image.getTile(0, 0) instanceof ByteComponentRaster &&
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
            image.getTile(0, 0).getDataBuffer() instanceof DataBufferByte;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
        int numRowsWritten = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
        int progressReportRowPeriod = Math.max(destHeight/20, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
41403
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   926
        clearAbortRequest();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
        processImageStarted(imageIndex);
41403
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   928
        if (abortRequested()) {
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   929
            processWriteAborted();
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   930
            return;
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   931
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
        if (interlaceFlag) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
            if (DEBUG) System.out.println("Writing interlaced");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
            if (isOptimizedCase) {
2378
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   937
                ByteComponentRaster tile =
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   938
                    (ByteComponentRaster)image.getTile(0, 0);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
                byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
                ComponentSampleModel csm =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
                    (ComponentSampleModel)tile.getSampleModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
                int offset = csm.getOffset(sourceXOffset, sourceYOffset, 0);
2378
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   943
                // take into account the raster data offset
256dd41b49ab 6795544: GIFImageWriter does not write the subImage of BufferedImage to a file correctly.
bae
parents: 2
diff changeset
   944
                offset += tile.getDataOffset(0);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
                int lineStride = csm.getScanlineStride();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
                writeRowsOpt(data, offset, lineStride, compressor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
                             0, 8, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
                             numRowsWritten, progressReportRowPeriod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
                numRowsWritten += destHeight/8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
                writeRowsOpt(data, offset, lineStride, compressor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
                             4, 8, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
                             numRowsWritten, progressReportRowPeriod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
                numRowsWritten += (destHeight - 4)/8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
                writeRowsOpt(data, offset, lineStride, compressor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
                             2, 4, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
                             numRowsWritten, progressReportRowPeriod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
                numRowsWritten += (destHeight - 2)/4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
                writeRowsOpt(data, offset, lineStride, compressor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
                             1, 2, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
                             numRowsWritten, progressReportRowPeriod);
41403
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   980
                if (abortRequested()) {
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   981
                    return;
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
   982
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
                writeRows(image, compressor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
                          sourceXOffset, periodX,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
                          sourceYOffset, 8*periodY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
                          sourceWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
                          0, 8, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
                          numRowsWritten, progressReportRowPeriod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
                numRowsWritten += destHeight/8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
                writeRows(image, compressor, sourceXOffset, periodX,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
                          sourceYOffset + 4*periodY, 8*periodY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
                          sourceWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
                          4, 8, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
                          numRowsWritten, progressReportRowPeriod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
                numRowsWritten += (destHeight - 4)/8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
                writeRows(image, compressor, sourceXOffset, periodX,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
                          sourceYOffset + 2*periodY, 4*periodY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
                          sourceWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
                          2, 4, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
                          numRowsWritten, progressReportRowPeriod);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
                if (abortRequested()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
                numRowsWritten += (destHeight - 2)/4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
                writeRows(image, compressor, sourceXOffset, periodX,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
                          sourceYOffset + periodY, 2*periodY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
                          sourceWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
                          1, 2, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
                          numRowsWritten, progressReportRowPeriod);
41403
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
  1026
                if (abortRequested()) {
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
  1027
                    return;
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
  1028
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
            if (DEBUG) System.out.println("Writing non-interlaced");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
            if (isOptimizedCase) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
                Raster tile = image.getTile(0, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
                byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
                ComponentSampleModel csm =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
                    (ComponentSampleModel)tile.getSampleModel();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
                int offset = csm.getOffset(sourceXOffset, sourceYOffset, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
                int lineStride = csm.getScanlineStride();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
                writeRowsOpt(data, offset, lineStride, compressor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
                             0, 1, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
                             numRowsWritten, progressReportRowPeriod);
41403
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
  1044
                if (abortRequested()) {
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
  1045
                    return;
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
  1046
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
                writeRows(image, compressor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
                          sourceXOffset, periodX,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
                          sourceYOffset, periodY,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
                          sourceWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
                          0, 1, destWidth, destHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
                          numRowsWritten, progressReportRowPeriod);
41403
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
  1054
                if (abortRequested()) {
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
  1055
                    return;
be56daafbeaa 8164931: Verify if writer.abort() works properly for all writers in IIOWriteProgressListener.
jdv
parents: 35667
diff changeset
  1056
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
        compressor.flush();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
        stream.write(0x00);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
        processImageComplete();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
    private void writeHeader(String version,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
                             int logicalScreenWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
                             int logicalScreenHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
                             int colorResolution,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
                             int pixelAspectRatio,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
                             int backgroundColorIndex,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
                             boolean sortFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
                             int bitsPerPixel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
                             byte[] globalColorTable) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
            // Signature
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
            stream.writeBytes("GIF"+version);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
            // Screen Descriptor
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
            // Width
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
            stream.writeShort((short)logicalScreenWidth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
            // Height
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
            stream.writeShort((short)logicalScreenHeight);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
            // Global Color Table
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
            // Packed fields
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
            int packedFields = globalColorTable != null ? 0x80 : 0x00;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
            packedFields |= ((colorResolution - 1) & 0x7) << 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
            if (sortFlag) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
                packedFields |= 0x8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
            packedFields |= (bitsPerPixel - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
            stream.write(packedFields);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
            // Background color index
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
            stream.write(backgroundColorIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
            // Pixel aspect ratio
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
            stream.write(pixelAspectRatio);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
            // Global Color Table
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
            if (globalColorTable != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
                stream.write(globalColorTable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
            throw new IIOException("I/O error writing header!", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
    private void writeHeader(IIOMetadata streamMetadata, int bitsPerPixel)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
        GIFWritableStreamMetadata sm;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
        if (streamMetadata instanceof GIFWritableStreamMetadata) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
            sm = (GIFWritableStreamMetadata)streamMetadata;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
            sm = new GIFWritableStreamMetadata();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
            Node root =
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
                streamMetadata.getAsTree(STREAM_METADATA_NAME);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
            sm.setFromTree(STREAM_METADATA_NAME, root);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
        writeHeader(sm.version,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
                    sm.logicalScreenWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
                    sm.logicalScreenHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
                    sm.colorResolution,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
                    sm.pixelAspectRatio,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
                    sm.backgroundColorIndex,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
                    sm.sortFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
                    bitsPerPixel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
                    sm.globalColorTable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
    private void writeGraphicControlExtension(int disposalMethod,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
                                              boolean userInputFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
                                              boolean transparentColorFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
                                              int delayTime,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
                                              int transparentColorIndex)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
            stream.write(0x21);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
            stream.write(0xf9);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
            stream.write(4);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
            int packedFields = (disposalMethod & 0x3) << 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
            if (userInputFlag) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
                packedFields |= 0x2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
            if (transparentColorFlag) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
                packedFields |= 0x1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
            stream.write(packedFields);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
            stream.writeShort((short)delayTime);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
            stream.write(transparentColorIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
            stream.write(0x00);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
            throw new IIOException("I/O error writing Graphic Control Extension!", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
    private void writeGraphicControlExtension(GIFWritableImageMetadata im)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
        writeGraphicControlExtension(im.disposalMethod,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
                                     im.userInputFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
                                     im.transparentColorFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
                                     im.delayTime,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
                                     im.transparentColorIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
    private void writeBlocks(byte[] data) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
        if (data != null && data.length > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
            int offset = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
            while (offset < data.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
                int len = Math.min(data.length - offset, 255);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
                stream.write(len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1181
                stream.write(data, offset, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
                offset += len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
    private void writePlainTextExtension(GIFWritableImageMetadata im)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
        if (im.hasPlainTextExtension) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
                stream.write(0x21);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
                stream.write(0x1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
                stream.write(12);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
                stream.writeShort(im.textGridLeft);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
                stream.writeShort(im.textGridTop);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
                stream.writeShort(im.textGridWidth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
                stream.writeShort(im.textGridHeight);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
                stream.write(im.characterCellWidth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
                stream.write(im.characterCellHeight);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
                stream.write(im.textForegroundColor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
                stream.write(im.textBackgroundColor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
                writeBlocks(im.text);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
                stream.write(0x00);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
                throw new IIOException("I/O error writing Plain Text Extension!", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
    private void writeApplicationExtension(GIFWritableImageMetadata im)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
        if (im.applicationIDs != null) {
23312
4711f66e7d5c 8033716: Fix raw and unchecked lint warnings in com.sun.imageio
henryjen
parents: 22567
diff changeset
  1217
            Iterator<byte[]> iterIDs = im.applicationIDs.iterator();
4711f66e7d5c 8033716: Fix raw and unchecked lint warnings in com.sun.imageio
henryjen
parents: 22567
diff changeset
  1218
            Iterator<byte[]> iterCodes = im.authenticationCodes.iterator();
4711f66e7d5c 8033716: Fix raw and unchecked lint warnings in com.sun.imageio
henryjen
parents: 22567
diff changeset
  1219
            Iterator<byte[]> iterData = im.applicationData.iterator();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
            while (iterIDs.hasNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
                    stream.write(0x21);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
                    stream.write(0xff);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
                    stream.write(11);
23312
4711f66e7d5c 8033716: Fix raw and unchecked lint warnings in com.sun.imageio
henryjen
parents: 22567
diff changeset
  1227
                    stream.write(iterIDs.next(), 0, 8);
4711f66e7d5c 8033716: Fix raw and unchecked lint warnings in com.sun.imageio
henryjen
parents: 22567
diff changeset
  1228
                    stream.write(iterCodes.next(), 0, 3);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
23312
4711f66e7d5c 8033716: Fix raw and unchecked lint warnings in com.sun.imageio
henryjen
parents: 22567
diff changeset
  1230
                    writeBlocks(iterData.next());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
                    stream.write(0x00);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
                } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
                    throw new IIOException("I/O error writing Application Extension!", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
    private void writeCommentExtension(GIFWritableImageMetadata im)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
        if (im.comments != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
            try {
23312
4711f66e7d5c 8033716: Fix raw and unchecked lint warnings in com.sun.imageio
henryjen
parents: 22567
diff changeset
  1244
                Iterator<byte[]> iter = im.comments.iterator();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
                while (iter.hasNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
                    stream.write(0x21);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
                    stream.write(0xfe);
23312
4711f66e7d5c 8033716: Fix raw and unchecked lint warnings in com.sun.imageio
henryjen
parents: 22567
diff changeset
  1248
                    writeBlocks(iter.next());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
                    stream.write(0x00);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
                throw new IIOException("I/O error writing Comment Extension!", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1257
    private void writeImageDescriptor(int imageLeftPosition,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
                                      int imageTopPosition,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
                                      int imageWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
                                      int imageHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1261
                                      boolean interlaceFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
                                      boolean sortFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1263
                                      int bitsPerPixel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1264
                                      byte[] localColorTable)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1265
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1266
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1267
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1268
            stream.write(0x2c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1269
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1270
            stream.writeShort((short)imageLeftPosition);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1271
            stream.writeShort((short)imageTopPosition);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1272
            stream.writeShort((short)imageWidth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1273
            stream.writeShort((short)imageHeight);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1274
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1275
            int packedFields = localColorTable != null ? 0x80 : 0x00;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1276
            if (interlaceFlag) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
                packedFields |= 0x40;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
            if (sortFlag) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1280
                packedFields |= 0x8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1281
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1282
            packedFields |= (bitsPerPixel - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1283
            stream.write(packedFields);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1284
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1285
            if (localColorTable != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1286
                stream.write(localColorTable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1287
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1288
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1289
            throw new IIOException("I/O error writing Image Descriptor!", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1290
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1291
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1292
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1293
    private void writeImageDescriptor(GIFWritableImageMetadata imageMetadata,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1294
                                      int bitsPerPixel)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1295
      throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1296
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1297
        writeImageDescriptor(imageMetadata.imageLeftPosition,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1298
                             imageMetadata.imageTopPosition,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1299
                             imageMetadata.imageWidth,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1300
                             imageMetadata.imageHeight,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1301
                             imageMetadata.interlaceFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1302
                             imageMetadata.sortFlag,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1303
                             bitsPerPixel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1304
                             imageMetadata.localColorTable);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1305
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1306
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1307
    private void writeTrailer() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1308
        stream.write(0x3b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1309
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1310
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1311
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1312
class GIFImageWriteParam extends ImageWriteParam {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1313
    GIFImageWriteParam(Locale locale) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1314
        super(locale);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1315
        this.canWriteCompressed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1316
        this.canWriteProgressive = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1317
        this.compressionTypes = new String[] {"LZW", "lzw"};
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1318
        this.compressionType = compressionTypes[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1319
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1320
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1321
    public void setCompressionMode(int mode) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1322
        if (mode == MODE_DISABLED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1323
            throw new UnsupportedOperationException("MODE_DISABLED is not supported.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1324
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1325
        super.setCompressionMode(mode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1326
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1327
}