946 lines · 32.1 KB · Java
RawDownload
/* * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.awt.image; import java.awt.Color;import java.awt.Graphics;import java.awt.Transparency;import java.awt.AWTException;import java.awt.Rectangle;import java.awt.image.BufferedImage;import java.awt.image.ColorModel;import java.awt.image.DirectColorModel;import java.awt.image.IndexColorModel;import java.awt.image.ImageConsumer;import java.awt.image.ImageObserver;import sun.awt.image.ByteComponentRaster;import sun.awt.image.IntegerComponentRaster;import java.awt.image.Raster;import java.awt.image.WritableRaster;import java.awt.image.DataBuffer;import java.awt.image.DataBufferInt;import java.awt.Graphics2D;import java.awt.geom.AffineTransform;import sun.awt.image.ImageWatched;import java.util.Hashtable; public class ImageRepresentation extends ImageWatched implements ImageConsumer{    InputStreamImageSource src;    ToolkitImage image;    int tag;     long pData; // used by windows native code only -- internal state REMIND ATTN @@     int width = -1;    int height = -1;    int hints;     int availinfo;     Rectangle newbits;     BufferedImage bimage;    WritableRaster biRaster;    protected ColorModel cmodel;    ColorModel srcModel = null;    int[] srcLUT = null;    int srcLUTtransIndex = -1;    int numSrcLUT = 0;    boolean forceCMhint;    int sstride;    boolean isDefaultBI = false;    boolean isSameCM = false;     private native static void initIDs();     static {        /* ensure that the necessary native libraries are loaded */        NativeLibLoader.loadLibraries();        initIDs();    }     /**     * Create an ImageRepresentation for the given Image.  The     * width and height are unknown at this point.  The color     * model is a hint as to the color model to use when creating     * the buffered image.  If null, the src color model will     * be used.     */    public ImageRepresentation(ToolkitImage im, ColorModel cmodel, boolean                               forceCMhint) {        image = im;         if (image.getSource() instanceof InputStreamImageSource) {            src = (InputStreamImageSource) image.getSource();        }         setColorModel(cmodel);         this.forceCMhint = forceCMhint;    }     /* REMIND: Only used for Frame.setIcon - should use ImageWatcher instead */    public synchronized void reconstruct(int flags) {        if (src != null) {            src.checkSecurity(null, false);        }        int missinginfo = flags & ~availinfo;        if ((availinfo & ImageObserver.ERROR) == 0 && missinginfo != 0) {            numWaiters++;            try {                startProduction();                missinginfo = flags & ~availinfo;                while ((availinfo & ImageObserver.ERROR) == 0 &&                       missinginfo != 0)                {                    try {                        wait();                    } catch (InterruptedException e) {                        Thread.currentThread().interrupt();                        return;                    }                    missinginfo = flags & ~availinfo;                }            } finally {                decrementWaiters();            }        }    }     public void setDimensions(int w, int h) {        if (src != null) {            src.checkSecurity(null, false);        }         image.setDimensions(w, h);         newInfo(image, (ImageObserver.WIDTH | ImageObserver.HEIGHT),                0, 0, w, h);         if (w <= 0 || h <= 0) {            imageComplete(ImageConsumer.IMAGEERROR);            return;        }         if (width != w || height != h) {            // dimension mismatch => trigger recreation of the buffer            bimage = null;        }         width = w;        height = h;         availinfo |= ImageObserver.WIDTH | ImageObserver.HEIGHT;    }     public int getWidth() {        return width;    }     public int getHeight() {        return height;    }     ColorModel getColorModel() {        return cmodel;    }     BufferedImage getBufferedImage() {        return bimage;    }     /**     * Returns the BufferedImage that will be used as the representation of     * the pixel data.  Subclasses can override this method to return     * platform specific subclasses of BufferedImage that may or may not be     * accelerated.     *     * It is subclass' responsibility to propagate acceleration priority     * to the newly created image.     */    protected BufferedImage createImage(ColorModel cm,                                        WritableRaster raster,                                        boolean isRasterPremultiplied,                                        Hashtable properties)    {        BufferedImage bi =            new BufferedImage(cm, raster, isRasterPremultiplied, null);        bi.setAccelerationPriority(image.getAccelerationPriority());        return bi;    }     public void setProperties(Hashtable<?,?> props) {        if (src != null) {            src.checkSecurity(null, false);        }        image.setProperties(props);        newInfo(image, ImageObserver.PROPERTIES, 0, 0, 0, 0);    }     public void setColorModel(ColorModel model) {        if (src != null) {            src.checkSecurity(null, false);        }        srcModel = model;         // Check to see if model is INT_RGB        if (model instanceof IndexColorModel) {            if (model.getTransparency() == model.TRANSLUCENT) {                // REMIND:                // Probably need to composite anyway so force ARGB                cmodel = ColorModel.getRGBdefault();                srcLUT = null;            }            else {                IndexColorModel icm = (IndexColorModel) model;                numSrcLUT = icm.getMapSize();                srcLUT = new int[Math.max(numSrcLUT, 256)];                icm.getRGBs(srcLUT);                srcLUTtransIndex = icm.getTransparentPixel();                cmodel = model;            }        }        else {            if (cmodel == null) {                cmodel = model;                srcLUT   = null;            }            else if (model instanceof DirectColorModel) {                // If it is INT_RGB or INT_ARGB, use the model                DirectColorModel dcm = (DirectColorModel) model;                if ((dcm.getRedMask() == 0xff0000) &&                    (dcm.getGreenMask() == 0xff00) &&                    (dcm.getBlueMask()  == 0x00ff)) {                    cmodel   = model;                    srcLUT   = null;                }            }        }         isSameCM = (cmodel == model);    }     void createBufferedImage() {        // REMIND:  Be careful!  Is this called everytime there is a        // startProduction?  We only want to call it if it is new or        // there is an error        isDefaultBI = false;        try {            biRaster = cmodel.createCompatibleWritableRaster(width, height);            bimage = createImage(cmodel, biRaster,                                 cmodel.isAlphaPremultiplied(), null);        } catch (Exception e) {            // Create a default image            cmodel = ColorModel.getRGBdefault();            biRaster = cmodel.createCompatibleWritableRaster(width, height);            bimage = createImage(cmodel, biRaster, false, null);        }        int type = bimage.getType();         if ((cmodel == ColorModel.getRGBdefault()) ||               (type == BufferedImage.TYPE_INT_RGB) ||               (type == BufferedImage.TYPE_INT_ARGB_PRE)) {            isDefaultBI = true;        }        else if (cmodel instanceof DirectColorModel) {            DirectColorModel dcm = (DirectColorModel) cmodel;            if (dcm.getRedMask() == 0xff0000 &&                dcm.getGreenMask() == 0xff00 &&                dcm.getBlueMask()  == 0xff) {                isDefaultBI = true;            }        }    }     private void convertToRGB() {        int w = bimage.getWidth();        int h = bimage.getHeight();        int size = w*h;         DataBufferInt dbi = new DataBufferInt(size);        // Note that stealData() requires a markDirty() afterwards        // since we modify the data in it.        int newpixels[] = SunWritableRaster.stealData(dbi, 0);        if (cmodel instanceof IndexColorModel &&            biRaster instanceof ByteComponentRaster &&            biRaster.getNumDataElements() == 1)        {            ByteComponentRaster bct = (ByteComponentRaster) biRaster;            byte[] data = bct.getDataStorage();            int coff = bct.getDataOffset(0);            for (int i=0; i < size; i++) {                newpixels[i] = srcLUT[data[coff+i]&0xff];            }        }        else {            Object srcpixels = null;            int off=0;            for (int y=0; y < h; y++) {                for (int x=0; x < w; x++) {                    srcpixels=biRaster.getDataElements(x, y, srcpixels);                    newpixels[off++] = cmodel.getRGB(srcpixels);                }            }        }        // We modified the data array directly above so mark it as dirty now...        SunWritableRaster.markDirty(dbi);         isSameCM = false;        cmodel = ColorModel.getRGBdefault();         int bandMasks[] = {0x00ff0000,                           0x0000ff00,                           0x000000ff,                           0xff000000};         biRaster = Raster.createPackedRaster(dbi,w,h,w,                                             bandMasks,null);         bimage = createImage(cmodel, biRaster,                             cmodel.isAlphaPremultiplied(), null);        srcLUT = null;        isDefaultBI = true;    }     public void setHints(int h) {        if (src != null) {            src.checkSecurity(null, false);        }        hints = h;    }     private native void setICMpixels(int x, int y, int w, int h, int[] lut,                                    byte[] pix, int off, int scansize,                                    IntegerComponentRaster ict);    private native int setDiffICM(int x, int y, int w, int h, int[] lut,                                 int transPix, int numLut, IndexColorModel icm,                                 byte[] pix, int off, int scansize,                                 ByteComponentRaster bct, int chanOff);    static boolean s_useNative = true;     public void setPixels(int x, int y, int w, int h,                          ColorModel model,                          byte pix[], int off, int scansize) {        int lineOff=off;        int poff;        int[] newLUT=null;         if (src != null) {            src.checkSecurity(null, false);        }         // REMIND: What if the model doesn't fit in default color model?        synchronized (this) {            if (bimage == null) {                if (cmodel == null) {                    cmodel = model;                }                createBufferedImage();            }             if (w <= 0 || h <= 0) {                return;            }             int biWidth = biRaster.getWidth();            int biHeight = biRaster.getHeight();             int x1 = x+w;  // Overflow protection below            int y1 = y+h;  // Overflow protection below            if (x < 0) {                off -= x;                x = 0;            } else if (x1 < 0) {                x1 = biWidth;  // Must be overflow            }            if (y < 0) {                off -= y*scansize;                y = 0;            } else if (y1 < 0) {                y1 = biHeight;  // Must be overflow            }            if (x1 > biWidth) {                x1 = biWidth;            }            if (y1 > biHeight) {                y1 = biHeight;            }            if (x >= x1 || y >= y1) {                return;            }            // x,y,x1,y1 are all >= 0, so w,h must be >= 0            w = x1-x;            h = y1-y;            // off is first pixel read so it must be in bounds            if (off < 0 || off >= pix.length) {                // They overflowed their own array                throw new ArrayIndexOutOfBoundsException("Data offset out of bounds.");            }            // pix.length and off are >= 0 so remainder >= 0            int remainder = pix.length - off;            if (remainder < w) {                // They overflowed their own array                throw new ArrayIndexOutOfBoundsException("Data array is too short.");            }            int num;            if (scansize < 0) {                num = (off / -scansize) + 1;            } else if (scansize > 0) {                num = ((remainder-w) / scansize) + 1;            } else {                num = h;            }            if (h > num) {                // They overflowed their own array.                throw new ArrayIndexOutOfBoundsException("Data array is too short.");            }             if (isSameCM && (cmodel != model) && (srcLUT != null) &&                (model instanceof IndexColorModel) &&                (biRaster instanceof ByteComponentRaster))            {                IndexColorModel icm = (IndexColorModel) model;                ByteComponentRaster bct = (ByteComponentRaster) biRaster;                int numlut = numSrcLUT;                if (setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex,                               numSrcLUT, icm,                               pix, off, scansize, bct,                               bct.getDataOffset(0)) == 0) {                    convertToRGB();                }                else {                    // Note that setDiffICM modified the raster directly                    // so we must mark it as changed                    bct.markDirty();                    if (numlut != numSrcLUT) {                        boolean hasAlpha = icm.hasAlpha();                        if (srcLUTtransIndex != -1) {                            hasAlpha = true;                        }                        int nbits = icm.getPixelSize();                        icm = new IndexColorModel(nbits,                                                  numSrcLUT, srcLUT,                                                  0, hasAlpha,                                                  srcLUTtransIndex,                                                  (nbits > 8                                                   ? DataBuffer.TYPE_USHORT                                                   : DataBuffer.TYPE_BYTE));                        cmodel = icm;                        bimage = createImage(icm, bct, false, null);                    }                    return;                }            }             if (isDefaultBI) {                int pixel;                IntegerComponentRaster iraster =                                          (IntegerComponentRaster) biRaster;                if (srcLUT != null && model instanceof IndexColorModel) {                    if (model != srcModel) {                        // Fill in the new lut                        ((IndexColorModel)model).getRGBs(srcLUT);                        srcModel = model;                    }                     if (s_useNative) {                        // Note that setICMpixels modifies the raster directly                        // so we must mark it as changed afterwards                        setICMpixels(x, y, w, h, srcLUT, pix, off, scansize,                                     iraster);                        iraster.markDirty();                    }                    else {                        int[] storage = new int[w*h];                        int soff = 0;                        // It is an IndexColorModel                        for (int yoff=0; yoff < h; yoff++,                                 lineOff += scansize) {                            poff = lineOff;                            for (int i=0; i < w; i++) {                                storage[soff++] = srcLUT[pix[poff++]&0xff];                            }                        }                        iraster.setDataElements(x, y, w, h, storage);                    }                }                else {                    int[] storage = new int[w];                    for (int yoff=y; yoff < y+h; yoff++, lineOff += scansize) {                        poff = lineOff;                        for (int i=0; i < w; i++) {                            storage[i] = model.getRGB(pix[poff++]&0xff);                        }                        iraster.setDataElements(x, yoff, w, 1, storage);                    }                    availinfo |= ImageObserver.SOMEBITS;

Lines 1–500 of 946.