⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 indexedimage.java.svn-base

📁 j2me设计的界面包
💻 SVN-BASE
字号:
/* * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.lwuit;import com.sun.lwuit.geom.Dimension;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;/** * An indexed image is an image "compressed" in memory to occupy as little memory  * as possible in this sense it is slower to draw and only a single indexed image * can be drawn at any given time. However, this allows images with low color counts * to use as little as one byte per pixel which can save up to 4 times of the memory * overhead.  *  * @author Shai Almog */public class IndexedImage extends Image {    private int width;    private int height;        // package protected for access by the resource editor    byte[] imageDataByte;    int[] palette;         /**     * Creates an indexed image with byte data     */    public IndexedImage(int width, int height, int[] palette, byte[] data) {        super(null);        this.width = width;        this.height = height;        this.palette = palette;        this.imageDataByte = data;    }    /**     * Converts an image to a package image after which the original image can be GC'd     */    private IndexedImage(int width, int height, int[] palette, int[] rgb) {        super(null);                this.width = width;        this.height = height;        this.palette = palette;                // byte based package image        imageDataByte = new byte[width * height];        for(int iter = 0 ; iter < imageDataByte.length ; iter++) {            imageDataByte[iter] = (byte)paletteOffset(rgb[iter]);        }    }    /**     * Finds the offset within the palette of the given rgb value     *      * @param value ARGB value from the image     * @return offset within the palette array     */    private int paletteOffset(int rgb) {        for(int iter = 0 ; iter < palette.length ; iter++) {            if(rgb == palette[iter]) {                return iter;            }        }        throw new IllegalStateException("Invalid palette request in paletteOffset");    }    /**     * Packs the image loaded by MIDP     *      * @param imageName a name to load using Image.createImage()     * @return a packed image     */    public static Image pack(String imageName) throws IOException {        return pack(Image.createImage(imageName));    }    /**     * @inheritDoc     */    public Image subImage(int x, int y, int width, int height, boolean processAlpha)  {        byte[] arr = new byte[width * height];        for(int iter = 0 ; iter < arr.length ; iter++) {            int destY = iter / width;            int destX = iter % width;            int offset = x + destX + ((y + destY) * this.width);            arr[iter] = imageDataByte[offset];        }                return new IndexedImage(width, height, palette, arr);    }    /**     * Unsupported in the current version, this method will be implemented in a future release     */    public Image rotate(int degrees) {        throw new RuntimeException("The rotate method is not supported by Packed images at the moment");    }    /**     * @inheritDoc     */    public Image modifyAlpha(byte alpha) {        int[] newPalette = new int[palette.length];        System.arraycopy(palette, 0, newPalette, 0, palette.length);        int alphaInt = (((int)alpha) << 24) & 0xff000000;        for(int iter = 0 ; iter < palette.length ; iter++) {            if((palette[iter] & 0xff000000) != 0) {                newPalette[iter] = (palette[iter] & 0xffffff) | alphaInt;            }        }        return new IndexedImage(width, height, newPalette, imageDataByte);    }        /**     * This method is unsupported in this image type     */    public Graphics getGraphics() {        throw new RuntimeException("Packed image objects are immutable");    }    /**     * @inheritDoc     */    void getRGB(int[] rgbData,            int offset,            int scanlength,            int x,            int y,            int width,            int height){        // need to support scanlength???        int startPoint = y * this.width + x;        for(int rows = 0 ; rows < height ; rows++) {            int currentRow = rows * width;            for(int columns = 0 ; columns < width ; columns++) {                int i = imageDataByte[startPoint + columns] & 0xff;                rgbData[offset + currentRow + columns] = palette[i];            }            startPoint += this.width;        }    }            /**     * Packs the source rgba image and returns null if it fails     *      * @param rgb array containing ARGB data     * @param width width of the image in the rgb array     * @param height height of the image     * @return a packed image or null     */    public static IndexedImage pack(int[] rgb, int width, int height) {        int arrayLength = width * height;                // using a Vector is slower for a small scale device and this is mission critical code        int[] tempPalette = new int[256];        int paletteLocation = 0;        for(int iter = 0 ; iter < arrayLength ; iter++) {            int current = rgb[iter];            if(!contains(tempPalette, paletteLocation, current)) {                if(paletteLocation > 255) {                    return null;                }                tempPalette[paletteLocation] = current;                paletteLocation++;            }        }        // we need to "shrink" the palette array        if(paletteLocation != tempPalette.length) {            int[] newArray = new int[paletteLocation];            System.arraycopy(tempPalette, 0, newArray, 0, paletteLocation);            tempPalette = newArray;        }                        IndexedImage i = new IndexedImage(width, height, tempPalette, rgb);        return i;    }        /**     * Tries to pack the given image and would return the packed image or source     * image if packing failed     *      * @param sourceImage the image which would be converted to a packed image if possible     * @return the source image if packing failed or a newly packed image if it succeeded     */    public static Image pack(final Image sourceImage) {        int width = sourceImage.getWidth();        int height = sourceImage.getHeight();        int[] rgb = sourceImage.getRGB();                Image i = pack(rgb, width, height);        if(i == null) {            return sourceImage;        }        return i;    }            /**     * Searches the array up to "length" and returns true if value is within the     * array up to that point.     */    private static boolean contains(int[] array, int length, int value) {        for(int iter = 0 ; iter < length ; iter++) {            if(array[iter] == value) {                return true;            }        }        return false;    }        static int[] lineCache;    void drawImage(Graphics g, int x, int y) {         if(lineCache == null || lineCache.length < width * 3) {             lineCache = new int[width * 3];         }                // for performance we can calculate the visible drawing area so we don't have to        // calculate the whole array        int clipY = g.getClipY();        int clipBottomY = g.getClipHeight() + clipY;        int firstLine = 0;        int lastLine = height;        if(clipY > y) {            firstLine = clipY - y;        }         if(clipBottomY < y + height) {            lastLine = clipBottomY - y;        }                        for(int line = firstLine ; line < lastLine ; line += 3) {            int currentPos = line * width;            int rowsToDraw = Math.min(3, height - line);            int amount = width * rowsToDraw;            for(int position = 0 ; position < amount ; position++) {                int i = imageDataByte[position + currentPos] & 0xff;                                lineCache[position] = palette[i];            }            g.drawRGB(lineCache, 0, width, x, y + line, width, rowsToDraw, true);        }    }        /**     * @inheritDoc     */    public int getWidth() {        return width;    }        /**     * @inheritDoc     */    public int getHeight() {        return height;    }        /**     * @inheritDoc     */    public void scale(int width, int height) {        IndexedImage p = (IndexedImage)scaled(width, height);        this.imageDataByte = p.imageDataByte;        this.width = width;        this.height = height;    }        /**     * @inheritDoc     */    public Image scaled(int width, int height) {        int srcWidth = getWidth();        int srcHeight = getHeight();        // no need to scale        if(srcWidth == width && srcHeight == height){            return this;        }        Dimension d = new Dimension(width, height);        Image i = getCachedImage(d);        // currently we only support byte data...        i = new IndexedImage(width, height, palette, scaleArray(imageDataByte, width, height));        cacheImage(d, i);        return i;    }        byte[] scaleArray(byte[] sourceArray, int width, int height) {        int srcWidth = getWidth();        int srcHeight = getHeight();        // no need to scale        if(srcWidth == width && srcHeight == height){            return sourceArray;        }        byte[] destinationArray = new byte[width * height];                //Horizontal Resize        int yRatio = (srcHeight << 16) / height;        int xRatio = (srcWidth << 16) / width;        int xPos = xRatio / 2;        int yPos = yRatio / 2;        for (int x = 0; x < width; x++) {            int srcX = xPos >> 16;            for(int y = 0 ; y < height ; y++) {                int srcY = yPos >> 16;                int destPixel = x + y * width;                int srcPixel = srcX + srcY * srcWidth;                if((destPixel >= 0 && destPixel < destinationArray.length) &&                     (srcPixel >= 0 && srcPixel < sourceArray.length)) {                    destinationArray[destPixel] = sourceArray[srcPixel];                }                yPos += yRatio;            }            yPos = yRatio / 2;            xPos += xRatio;        }        return destinationArray;    }        /**     * @inheritDoc     */    public int[] getRGB() {        int[] rgb = new int[width * height];        for(int iter = 0 ; iter < rgb.length ; iter++) {            int i = imageDataByte[iter] & 0xff;            rgb[iter] = palette[i];        }        return rgb;    }    int[] getPalette() {        return palette;    }    byte[] getImageDataByte() {        return imageDataByte;    }        /**     * This method allows us to store a package image into a persistant stream easily     * thus allowing us to store the image in RMS.     *      * @return a byte array that can be loaded using the load method     */    public byte[] toByteArray() {        try {            ByteArrayOutputStream array = new ByteArrayOutputStream();            DataOutputStream out = new DataOutputStream(array);            out.writeShort(width);            out.writeShort(height);            out.writeByte(palette.length);            for (int iter = 0; iter < palette.length; iter++) {                out.writeInt(palette[iter]);            }            out.write(imageDataByte);            out.close();            return array.toByteArray();        } catch (IOException ex) {            // will never happen since IO is purely in memory            ex.printStackTrace();            return null;        }    }        /**     * Loads a packaged image that was stored in a stream using the toByteArray method     *      * @param data previously stored image data     * @return newly created packed image     */    public static IndexedImage load(byte[] data) {        try {            DataInputStream input = new DataInputStream(new ByteArrayInputStream(data));            int width = input.readShort();            int height = input.readShort();            int[] palette = new int[input.readByte() & 0xff];            for (int iter = 0; iter < palette.length; iter++) {                palette[iter] = input.readInt();            }            byte[] arr = new byte[width * height];            input.readFully(arr);            return new IndexedImage(width, height, palette, arr);        } catch (IOException ex) {            ex.printStackTrace();            return null;        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -