gifimagedecoder.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 970 行 · 第 1/2 页

JAVA
970
字号
                }                return true;            }            /* It must be data: save code in CurCode */            curCode = code;            /* Whenever it gets here outCount is always equal to                OUTCODELENGTH, so no need to reset outCount. */            //outCount = OUTCODELENGTH;            /* If greater or equal to freeCode, not in the hash table             * yet; repeat the last character decoded             */            if (curCode >= freeCode) {                if (curCode > freeCode) {                    /*                     * if we get a code too far outside our range, it                     * could case the parser to start traversing parts                     * of our data structure that are out of range...                     */                    /*In native version: goto flushit;*/                    while (!blockEnd) {                        if (readBytes(block, 0, blockLength + 1) != 0) {                            /* quietly accept truncated GIF images */                            return false;                        }                        blockLength = block[blockLength];                        blockEnd = (blockLength == 0);                    }                    return true;                }                curCode = oldCode;                outCode[--outCount] = (byte)prevChar;            }            /* Unless this code is raw data, pursue the chain pointed             * to by curCode through the hash table to its end; each             * code in the chain puts its associated output code on             * the output queue.             */             while (curCode > bitMask) {                 outCode[--outCount] = suffix[curCode];                 if (outCount == 0) {                     /*                      * In theory this should never happen since our                      * prefix and suffix arrays are monotonically                      * decreasing and so outCode will only be filled                      * as much as those arrays, but I don't want to                      * take that chance and the test is probably                      * cheap compared to the read and write operations.                      * If we ever do overflow the array, we will just                      * flush the rest of the data and quietly accept                      * the GIF as truncated here.                      */                     //In native version: goto flushit;                     while (!blockEnd) {                        if (readBytes(block, 0, blockLength + 1) != 0) {                            /* quietly accept truncated GIF images */                            return false;                        }                        blockLength = block[blockLength];                        blockEnd = (blockLength == 0);                    }                    return true;                 }                 curCode = prefix[curCode];             }            /* The last code in the chain is treated as raw data. */            prevChar = (char)curCode;            outCode[--outCount] = (byte)prevChar;            /* Now we put the data out to the Output routine. It's             * been stacked LIFO, so deal with it that way...             */            len = OUTCODELENGTH - outCount; /* This is why I commented out                                               the code that resets outCount. */            while (--len >= 0) {                rasline[off++] = outCode[outCount++];                /* Update the X-coordinate, and if it overflows, update the                 * Y-coordinate                 */                if (--x == 0) {                    int count;                    /* If a non-interlaced picture, just increment y to the next                     * scan line.  If it's interlaced, deal with the interlace as                     * described in the GIF spec.  Put the decoded scan line out                     * to the screen if we haven't gone past the bottom of it                     *///                    count = sendPixels(relx, rely+y, width, passht, rasline, model);                    count = sendPixels(relx, rely+y, width, 1, rasline, model);                    if (count <= 0) {                        /* Nobody is listening any more. */                        return false;                    }                    x = width;                    off = 0;                    /*  pass        inc     ht      ystart */                    /*   0           8      8          0   */                    /*   1           8      4          4   */                    /*   2           4      2          2   */                    /*   3           2      1          1   */                    y += passinc;                    while (y >= height) {                        passinc = passht;                        passht >>= 1;                        y = passht;                        if (passht == 0) {                            //In native version: goto flushit;                            while (!blockEnd) {                                if (readBytes(block, 0, blockLength + 1) != 0) {                                    /* quietly accept truncated GIF images */                                    return false;                                }                                blockLength = block[blockLength] & 0xff;                                blockEnd = (blockLength == 0);                            }                            return true;                        }                    }                }            }            /* Build the hash table on-the-fly. No table is stored in the file. */            prefix[freeCode] = (short)oldCode;            suffix[freeCode] = (byte)prevChar;            oldCode = code;            /* Point to the next slot in the table.  If we exceed the             * maxCode, increment the code size unless             * it's already 12.  If it is, do nothing: the next code             * decompressed better be CLEAR             */            if (++freeCode >= maxCode) {                if (codeSize < 12) {                    codeSize++;                    maxCode <<= 1;                    codeMask = maxCode - 1;                } else {                    /* Just in case */                    freeCode = maxCode - 1;                }            }        }    }    private int sendPixels(int x, int y, int width, int height, byte rasline[], ColorModel model) {	int rasbeg, rasend, x2;	if (y < 0) {	    height += y;	    y = 0;	}	if (y + height > global_height) {	    height = global_height - y;	}	if (height <= 0) {	    return 1;	}	// rasline[0]     == pixel at coordinate (x,y)	// rasline[width] == pixel at coordinate (x+width, y)	if (x < 0) {	    rasbeg = -x;	    width += x;		// same as (width -= rasbeg)	    x2 = 0;		// same as (x2     = x + rasbeg)	} else {	    rasbeg = 0;	    // width -= 0;	// same as (width -= rasbeg)	    x2 = x;		// same as (x2     = x + rasbeg)	}	// rasline[rasbeg]          == pixel at coordinate (x2,y)	// rasline[width]           == pixel at coordinate (x+width, y)	// rasline[rasbeg + width]  == pixel at coordinate (x2+width, y)	if (x2 + width > global_width) {	    width = global_width - x2;	}	if (width <= 0) {	    return 1;	}	rasend = rasbeg + width;	// rasline[rasbeg] == pixel at coordinate (x2,y)	// rasline[rasend] == pixel at coordinate (x2+width, y)	int off = y * global_width + x2;	boolean save = (curframe.disposal_method == GifFrame.DISPOSAL_SAVE);	if (trans_pixel >= 0 && !curframe.initialframe) {	    if (saved_image != null && saved_model == model) {		for (int i = rasbeg; i < rasend; i++, off++) {		    byte pixel = rasline[i];		    if ((pixel & 0xff) == trans_pixel) {			rasline[i] = saved_image[off];		    } else if (save) {			saved_image[off] = pixel;		    }		}	    } else {		// We have to do this the hard way - only transmit		// the non-transparent sections of the line...		int runstart = -1;		int count = 1;		for (int i = rasbeg; i < rasend; i++, off++) {		    byte pixel = rasline[i];		    if ((pixel & 0xff) == trans_pixel) {			if (runstart >= 0) {//			    count = setPixels(x + runstart, y, i - runstart, height, model, rasline, runstart, 0);			    count = setPixels(x + runstart, y, i - runstart, height, model, rasline, runstart, i - runstart);			    if (count == 0) {				break;			    }			}			runstart = -1;		    } else {			if (runstart < 0) {			    runstart = i;			}			if (save) {			    saved_image[off] = pixel;			}		    }		}		if (runstart >= 0) {//		    count = setPixels(x + runstart, y, rasend - runstart, height, model, rasline, runstart, 0);		    count = setPixels(x + runstart, y, rasend - runstart, height, model, rasline, runstart, rasend - runstart);		}		// Since (saved_model != model), store must be null...		return count;	    }	} else if (save) {	    System.arraycopy(rasline, rasbeg, saved_image, off, width);	}//	int count = setPixels(x2, y, width, height, model, rasline, rasbeg, 0);	int count = setPixels(x2, y, width, height, model, rasline, rasbeg, width);	return count;    }    /**     * Read Image data     */    private boolean readImage(boolean first, int disposal_method, int delay)	throws IOException    {	if (curframe != null && !curframe.dispose()) {	    abort();	    return false;	}	long tm = 0;	if (verbose) {	    tm = System.currentTimeMillis();	}	// Allocate the buffer	byte block[] = new byte[256 + 3];	// Read the image descriptor	if (readBytes(block, 0, 10) != 0) {	    throw new IOException();	}	int x = ExtractWord(block, 0);	int y = ExtractWord(block, 2);	int width = ExtractWord(block, 4);	int height = ExtractWord(block, 6);	boolean interlace = (block[8] & INTERLACEMASK) != 0;	IndexColorModel model = global_model;	if ((block[8] & COLORMAPMASK) != 0) {	    // We read one extra byte above so now when we must	    // transfer that byte as the first colormap byte	    // and manually read the code size when we are done	    int num_local_colors = 1 << ((block[8] & 0x7) + 1);	    // Read local colors	    byte[] local_colormap = new byte[num_local_colors * 3];	    local_colormap[0] = block[9];	    if (readBytes(local_colormap, 1, num_local_colors * 3 - 1) != 0) {		throw new IOException();	    }	    // Now read the "real" code size byte which follows	    // the local color table	    if (readBytes(block, 9, 1) != 0) {		throw new IOException();	    }	    model = new IndexColorModel(8, num_local_colors, local_colormap,					0, false, trans_pixel);	} else if (model == null		   || trans_pixel != model.getTransparentPixel()) {	    model = new IndexColorModel(8, num_global_colors, global_colormap,					0, false, trans_pixel);	    global_model = model;	}	// Notify the consumers	if (first) {            if (global_width == 0) global_width = width;            if (global_height == 0) global_height = height;	    setDimensions(global_width, global_height);	    setProperties(props);	    setColorModel(model);	    headerComplete();	}	if (disposal_method == GifFrame.DISPOSAL_SAVE && saved_image == null) {	    saved_image = new byte[global_width * global_height];	}	int hints = (interlace ? interlaceflags : normalflags);	setHints(hints);	curframe = new GifFrame(this, disposal_method, delay,				(curframe == null), model,				x, y, width, height);	// allocate the raster data	byte rasline[] = new byte[width];	if (verbose) {	    System.out.print("Reading a " + width + " by " + height + " " +		      (interlace ? "" : "non-") + "interlaced image...");	}	boolean ret = parseImage(x, y, width, height,				 interlace, ExtractByte(block, 9),				 block, rasline, model);	if (!ret) {	    abort();	}	if (verbose) {	    System.out.println("done in "			       + (System.currentTimeMillis() - tm)			       + "ms");	}	return ret;    }    /*      * Since I translated the JNI version of parseImage() into Java,     * we no longer need initIDs().     */    /* // if we're using JNI, we need to find the method and field IDs.     * private static native void initIDs();     * static {     * 	 initIDs();     * }     */}class GifFrame {    private static final boolean verbose = false;    private static IndexColorModel trans_model;    static final int DISPOSAL_NONE      = 0x00;    static final int DISPOSAL_SAVE      = 0x01;    static final int DISPOSAL_BGCOLOR   = 0x02;    static final int DISPOSAL_PREVIOUS  = 0x03;    GifImageDecoder decoder;    int disposal_method;    int delay;    IndexColorModel model;    int x;    int y;    int width;    int height;    boolean initialframe;    public GifFrame(GifImageDecoder id, int dm, int dl, boolean init,		    IndexColorModel cm, int x, int y, int w, int h) {	this.decoder = id;	this.disposal_method = dm;	this.delay = dl;	this.model = cm;	this.initialframe = init;	this.x = x;	this.y = y;	this.width = w;	this.height = h;    }    private void setPixels(int x, int y, int w, int h,			   ColorModel cm, byte[] pix, int off, int scan) {	decoder.setPixels(x, y, w, h, cm, pix, off, scan);    }    public boolean dispose() {	if (decoder.imageComplete(ImageConsumer.SINGLEFRAMEDONE, false) == 0) {	    return false;	} else {	    if (delay > 0) {		try {		    if (verbose) {			System.out.println("sleeping: "+delay);		    }		    Thread.sleep(delay);		} catch (InterruptedException e) {		    return false;		}	    } else {		Thread.yield();	    }	    	    if (verbose && disposal_method != 0) {		System.out.println("disposal method: "+disposal_method);	    }	    int global_width = decoder.global_width;	    int global_height = decoder.global_height;	    if (x < 0) {		width += x;		x = 0;	    }	    if (x + width > global_width) {		width = global_width - x;	    }	    if (width <= 0) {		disposal_method = DISPOSAL_NONE;	    } else {		if (y < 0) {		    height += y;		    y = 0;		}		if (y + height > global_height) {		    height = global_height - y;		}		if (height <= 0) {		    disposal_method = DISPOSAL_NONE;		}	    }	    switch (disposal_method) {	    case DISPOSAL_PREVIOUS:		byte[] saved_image = decoder.saved_image;		IndexColorModel saved_model = decoder.saved_model;		if (saved_image != null) {		    setPixels(x, y, width, height,			      saved_model, saved_image,			      y * global_width + x, global_width);		}		break;	    case DISPOSAL_BGCOLOR:		byte tpix;		if (model.getTransparentPixel() < 0) {		    model = trans_model;		    if (model == null) {			model = new IndexColorModel(8, 1,						    new byte[4], 0, true);			trans_model = model;		    }		    tpix = 0;		} else {		    tpix = (byte) model.getTransparentPixel();		}		int rassize = width * height; 		byte[] rasfill = new byte[rassize];		if (tpix != 0) {		    for (int i = 0; i < rassize; i++) {			rasfill[i] = tpix;		    }		}//		setPixels(x, y, width, height, model, rasfill, 0, 0);		setPixels(x, y, width, height, model, rasfill, 0, width);		break;	    case DISPOSAL_SAVE:		decoder.saved_model = model;		break;	    }	}	return true;    }}

⌨️ 快捷键说明

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