J2ME中GIF动画处理类文件

本文介绍了一个用于解析和绘制GIF图像的Java类库,包括读取GIF文件、解码帧数据、处理透明度及动画循环播放等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

private GIFDecode gifd;  private int ind;  private int gifCount;  private Image frame;

 void initGIF() {   gifd = new GIFDecode();   gifd.read(this.getClass().getResourceAsStream("/ar.gif"));//载入gif图片   ind = 0;   gifCount = gifd.getFrameCount();//获得帧数   System.out.println("gifCount="+gifCount);  }

 void drawProgressBar(Graphics g, int xpos, int ypos, int anchor) {   frame = gifd.getFrame(ind);   ind++;   if (ind >= gifCount) {    ind = 0;   }   g.drawImage(frame, xpos, ypos, anchor);//循环绘图  }

//////////////////////////////////////////////////////////////////////////////////

import java.util.Vector; import java.io.InputStream; import javax.microedition.lcdui.Image;

public class GIFDecode {     /**      * File read status: No errors.      */     public static final int STATUS_OK = 0;

    /**      * File read status: Error decoding file (may be partially decoded)      */     public static final int STATUS_FORMAT_ERROR = 1;

    /**      * File read status: Unable to open source.      */     public static final int STATUS_OPEN_ERROR = 2;

    protected InputStream in;     protected int status;

    protected int width; // full image width     protected int height; // full image height     protected boolean gctFlag; // global color table used     protected int gctSize; // size of global color table     protected int loopCount = 1; // iterations; 0 = repeat forever

    protected int[] gct; // global color table     protected int[] lct; // local color table     protected int[] act; // active color table

    protected int bgIndex; // background color index     protected int bgColor; // background color     protected int lastBgColor; // previous bg color     protected int pixelAspect; // pixel aspect ratio

    protected boolean lctFlag; // local color table flag     protected boolean interlace; // interlace flag     protected int lctSize; // local color table size

    protected int ix, iy, iw, ih; // current image rectangle     protected int lrx, lry, lrw, lrh;     protected Image image; // current frame     protected Image lastImage; // previous frame

    protected byte[] block = new byte[256]; // current data block     protected int blockSize = 0; // block size

    // last graphic control extension info     protected int dispose = 0;     // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev     protected int lastDispose = 0;     protected boolean transparency = false; // use transparent color     protected int delay = 0; // delay in milliseconds     protected int transIndex; // transparent color index

    protected static final int MaxStackSize = 4096;     // max decoder pixel stack size

    // LZW decoder working arrays     protected short[] prefix;     protected byte[] suffix;     protected byte[] pixelStack;     protected byte[] pixels;

    protected Vector frames; // frames read from current file     protected int frameCount;

    static class GifFrame {         public GifFrame(Image im, int del) {             image = im;             delay = del;         }

        public Image image;         public int delay;     }

    /**      * Gets display duration for specified frame.      *      * @param n      *            int index of frame      * @return delay in milliseconds      */     public int getDelay(int n) {         delay = -1;         if ((n >= 0) && (n < frameCount)) {             delay = ((GifFrame) frames.elementAt(n)).delay;         }         return delay;     }

    /**      * Gets the number of frames read from file.      *      * @return frame count      */     public int getFrameCount() {         return frameCount;     }

    /**      * Gets the first (or only) image read.      *      * @return BufferedImage containing first frame, or null if none.      */     public Image getImage() {         return getFrame(0);     }

    /**      * Gets the "Netscape" iteration count, if any. A count of 0 means repeat      * indefinitiely.      *      * @return iteration count if one was specified, else 1.      */     public int getLoopCount() {         return loopCount;     }

    /**      * Creates new frame image from current data (and previous frames as      * specified by their disposition codes).      */     protected void setPixels() {         // expose destination image's pixels as int array         int[] dest = new int[width * height];

        // fill in starting image contents based on last image's dispose code         if (lastDispose > 0) {             if (lastDispose == 3) {                 // use image before last                 int n = frameCount - 2;                 if (n > 0) {                     lastImage = getFrame(n - 1);                 } else {                     lastImage = null;                 }             }

            if (lastImage != null) {                 lastImage.getRGB(dest, 0, width, 0, 0, width, height);                 // copy pixels

                if (lastDispose == 2) {                     // fill last image rect area with background color                     int c = 0;                     if (!transparency) {                         c = lastBgColor;                     }                     for (int i = 0; i < lrh; i++) {                         int n1 = (lry + i) * width + lrx;                         int n2 = n1 + lrw;                         for (int k = n1; k < n2; k++) {                             dest[k] = c;                         }                     }                 }             }         }

        // copy each source line to the appropriate place in the destination         int pass = 1;         int inc = 8;         int iline = 0;         for (int i = 0; i < ih; i++) {             int line = i;             if (interlace) {                 if (iline >= ih) {                     pass++;                     switch (pass) {                         case 2:                             iline = 4;                             break;                         case 3:                             iline = 2;                             inc = 4;                             break;                         case 4:                             iline = 1;                             inc = 2;                     }                 }                 line = iline;                 iline += inc;             }             line += iy;             if (line < height) {                 int k = line * width;                 int dx = k + ix; // start of line in dest                 int dlim = dx + iw; // end of dest line                 if ((k + width) < dlim) {                     dlim = k + width; // past dest edge                 }                 int sx = i * iw; // start of line in source                 while (dx < dlim) {                     // map color and insert in destination                     int index = ((int) pixels[sx++]) & 0xff;                     int c = act[index];                     if (c != 0) {                         dest[dx] = c;                     }                     dx++;                 }             }         }         image = Image.createRGBImage(dest, width, height, false);     }

    /**      * Gets the image contents of frame n.      *      * @return BufferedImage representation of frame, or null if n is invalid.      */     public Image getFrame(int n) {         Image im = null;         if ((n >= 0) && (n < frameCount)) {             im = ((GifFrame) frames.elementAt(n)).image;         }         return im;     }

    /**      * Reads GIF image from stream      *      * @param BufferedInputStream      *            containing GIF file.      * @return read status code (0 = no errors)      */     public int read(InputStream is) {         init();         if (is != null) {             in = is;             readHeader();             if (!err()) {                 readContents();                 if (frameCount < 0) {                     status = STATUS_FORMAT_ERROR;                 }             }         } else {             status = STATUS_OPEN_ERROR;         }         try {             is.close();         } catch (Exception e) {             e.printStackTrace();         }         return status;     }

    /**      * Decodes LZW image data into pixel array. Adapted from John Cristy's      * ImageMagick.      */     protected void decodeImageData() {         int NullCode = -1;         int npix = iw * ih;         int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi;

        if ((pixels == null) || (pixels.length < npix)) {             pixels = new byte[npix]; // allocate new pixel array         }         if (prefix == null) {             prefix = new short[MaxStackSize];         }         if (suffix == null) {             suffix = new byte[MaxStackSize];         }         if (pixelStack == null) {             pixelStack = new byte[MaxStackSize + 1];         }

        // Initialize GIF data stream decoder.

        data_size = read();         clear = 1 << data_size;         end_of_information = clear + 1;         available = clear + 2;         old_code = NullCode;         code_size = data_size + 1;         code_mask = (1 << code_size) - 1;         for (code = 0; code < clear; code++) {             prefix[code] = 0;             suffix[code] = (byte) code;         }

        // Decode GIF pixel stream.

        datum = bits = count = first = top = pi = bi = 0;

        for (i = 0; i < npix; ) {             if (top == 0) {                 if (bits < code_size) {                     // Load bytes until there are enough bits for a code.                     if (count == 0) {                         // Read a new data block.                         count = readBlock();                         if (count <= 0) {                             break;                         }                         bi = 0;                     }                     datum += (((int) block[bi]) & 0xff) << bits;                     bits += 8;                     bi++;                     count--;                     continue;                 }

                // Get the next code.

                code = datum & code_mask;                 datum >>= code_size;                 bits -= code_size;

                // Interpret the code

                if ((code > available) || (code == end_of_information)) {                     break;                 }                 if (code == clear) {                     // Reset decoder.                     code_size = data_size + 1;                     code_mask = (1 << code_size) - 1;                     available = clear + 2;                     old_code = NullCode;                     continue;                 }                 if (old_code == NullCode) {                     pixelStack[top++] = suffix[code];                     old_code = code;                     first = code;                     continue;                 }                 in_code = code;                 if (code == available) {                     pixelStack[top++] = (byte) first;                     code = old_code;                 } while (code > clear) {                     pixelStack[top++] = suffix[code];                     code = prefix[code];                 }                 first = ((int) suffix[code]) & 0xff;

                // Add a new string to the string table,

                if (available >= MaxStackSize) {                     break;                 }                 pixelStack[top++] = (byte) first;                 prefix[available] = (short) old_code;                 suffix[available] = (byte) first;                 available++;                 if (((available & code_mask) == 0)                     && (available < MaxStackSize)) {                     code_size++;                     code_mask += available;                 }                 old_code = in_code;             }

            // Pop a pixel off the pixel stack.

            top--;             pixels[pi++] = pixelStack[top];             i++;         }

        for (i = pi; i < npix; i++) {             pixels[i] = 0; // clear missing pixels         }

    }

    /**      * Returns true if an error was encountered during reading/decoding      */     protected boolean err() {         return status != STATUS_OK;     }

    /**      * Initializes or re-initializes reader      */     protected void init() {         status = STATUS_OK;         frameCount = 0;         frames = new Vector();         gct = null;         lct = null;     }

    /**      * Reads a single byte from the input stream.      */     protected int read() {         int curByte = 0;         try {             curByte = in.read();         } catch (Exception e) {             status = STATUS_FORMAT_ERROR;         }         return curByte;     }

    /**      * Reads next variable length block from input.      *      * @return number of bytes stored in "buffer"      */     protected int readBlock() {         blockSize = read();         int n = 0;         if (blockSize > 0) {             try {                 int count = 0;                 while (n < blockSize) {                     count = in.read(block, n, blockSize - n);                     if (count == -1) {                         break;                     }                     n += count;                 }             } catch (Exception e) {                 e.printStackTrace();             }

            if (n < blockSize) {                 status = STATUS_FORMAT_ERROR;             }         }         return n;     }

    /**      * Reads color table as 256 RGB integer values      *      * @param ncolors      *            int number of colors to read      * @return int array containing 256 colors (packed ARGB with full alpha)      */     protected int[] readColorTable(int ncolors) {         int nbytes = 3 * ncolors;         int[] tab = null;         byte[] c = new byte[nbytes];         int n = 0;         try {             n = in.read(c);         } catch (Exception e) {             e.printStackTrace();         }         if (n < nbytes) {             status = STATUS_FORMAT_ERROR;         } else {             tab = new int[256]; // max size to avoid bounds checks             int i = 0;             int j = 0;             while (i < ncolors) {                 int r = ((int) c[j++]) & 0xff;                 int g = ((int) c[j++]) & 0xff;                 int b = ((int) c[j++]) & 0xff;                 tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;             }         }         return tab;     }

    /**      * Main file parser. Reads GIF content blocks.      */     protected void readContents() {         // read GIF file content blocks         boolean done = false;         while (!(done || err())) {             int code = read();             switch (code) {

                case 0x2C: // image separator                     readImage();                     break;

                case 0x21: // extension                     code = read();                     switch (code) {                         case 0xf9: // graphics control extension                             readGraphicControlExt();                             break;

                        case 0xff: // application extension                             readBlock();                             String app = "";                             for (int i = 0; i < 11; i++) {                                 app += (char) block[i];                             }                             if (app.equals("NETSCAPE2.0")) {                                 readNetscapeExt();                             } else {                                 skip(); // don't care                             }                             break;

                        default: // uninteresting extension                             skip();                     }                     break;

                case 0x3b: // terminator                     done = true;                     break;

                case 0x00: // bad byte, but keep going and see what happens                     break;

                default:                     status = STATUS_FORMAT_ERROR;             }         }     }

    /**      * Reads Graphics Control Extension values      */     protected void readGraphicControlExt() {         read(); // block size         int packed = read(); // packed fields         dispose = (packed & 0x1c) >> 2; // disposal method         if (dispose == 0) {             dispose = 1; // elect to keep old image if discretionary         }         transparency = (packed & 1) != 0;         delay = readShort() * 10; // delay in milliseconds         transIndex = read(); // transparent color index         read(); // block terminator     }

    /**      * Reads GIF file header information.      */     protected void readHeader() {         String id = "";         for (int i = 0; i < 6; i++) {             id += (char) read();         }         if (!id.startsWith("GIF")) {             status = STATUS_FORMAT_ERROR;             return;         }

        readLSD();         if (gctFlag && !err()) {             gct = readColorTable(gctSize);             bgColor = gct[bgIndex];         }     }

    /**      * Reads next frame image      */     protected void readImage() {         ix = readShort(); // (sub)image position & size         iy = readShort();         iw = readShort();         ih = readShort();

        int packed = read();         lctFlag = (packed & 0x80) != 0; // 1 - local color table flag         interlace = (packed & 0x40) != 0; // 2 - interlace flag         // 3 - sort flag         // 4-5 - reserved         lctSize = 2 << (packed & 7); // 6-8 - local color table size

        if (lctFlag) {             lct = readColorTable(lctSize); // read table             act = lct; // make local table active         } else {             act = gct; // make global table active             if (bgIndex == transIndex) {                 bgColor = 0;             }         }         int save = 0;         if (transparency) {             save = act[transIndex];             act[transIndex] = 0; // set transparent color if specified         }

        if (act == null) {             status = STATUS_FORMAT_ERROR; // no color table defined         }

        if (err()) {             return;         }

        decodeImageData(); // decode pixel data         skip();

        if (err()) {             return;         }

        frameCount++;

        // create new image to receive frame data         image = Image.createImage(width, height);

        setPixels(); // transfer pixel data to image

        frames.addElement(new GifFrame(image, delay)); // add image to frame         // list

        if (transparency) {             act[transIndex] = save;         }         resetFrame();

    }

    /**      * Reads Logical Screen Descriptor      */     protected void readLSD() {

        // logical screen size         width = readShort();         height = readShort();

        // packed fields         int packed = read();         gctFlag = (packed & 0x80) != 0; // 1 : global color table flag         // 2-4 : color resolution         // 5 : gct sort flag         gctSize = 2 << (packed & 7); // 6-8 : gct size

        bgIndex = read(); // background color index         pixelAspect = read(); // pixel aspect ratio     }

    /**      * Reads Netscape extenstion to obtain iteration count      */     protected void readNetscapeExt() {         do {             readBlock();             if (block[0] == 1) {                 // loop count sub-block                 int b1 = ((int) block[1]) & 0xff;                 int b2 = ((int) block[2]) & 0xff;                 loopCount = (b2 << 8) | b1;             }         } while ((blockSize > 0) && !err());     }

    /**      * Reads next 16-bit value, LSB first      */     protected int readShort() {         // read 16-bit value, LSB first         return read() | (read() << 8);     }

    /**      * Resets frame state for reading next image.      */     protected void resetFrame() {         lastDispose = dispose;         lrx = ix;         lry = iy;         lrw = iw;         lrh = ih;         lastImage = image;         lastBgColor = bgColor;         dispose = 0;         transparency = false;         delay = 0;         lct = null;     }

    /**      * Skips variable length blocks up to and including next zero length block.      */     protected void skip() {         do {             readBlock();         } while ((blockSize > 0) && !err());     }

}

资源下载链接为: https://pan.quark.cn/s/1bfadf00ae14 华为移动服务(Huawei Mobile Services,简称 HMS)是一个全面开放的移动服务生态系统,为企业和开发者提供了丰富的工具和 API,助力他们构建、运营和推广应用。其中,HMS Scankit 是华为推出的一款扫描服务 SDK,支持快速集成到安卓应用中,能够提供高效且稳定的二维码和条形码扫描功能,适用于商品扫码、支付验证、信息获取等多种场景。 集成 HMS Scankit SDK 主要包括以下步骤:首先,在项目的 build.gradle 文件中添加 HMS Core 库和 Scankit 依赖;其次,在 AndroidManifest.xml 文件中添加相机访问和互联网访问权限;然后,在应用程序的 onCreate 方法中调用 HmsClient 进行初始化;接着,可以选择自定义扫描界面或使用 Scankit 提供的默认扫描界面;最后,实现 ScanCallback 接口以处理扫描成功和失败的回调。 HMS Scankit 内部集成了开源的 Zxing(Zebra Crossing)库,这是一个功能强大的条码和二维码处理库,提供了解码、生成、解析等多种功能,既可以单独使用,也可以与其他扫描框架结合使用。在 HMS Scankit 中,Zxing 经过优化,以更好地适应华为设备,从而提升扫描性能。 通常,ScanKitDemoGuide 包含了集成 HMS Scankit 的示例代码,涵盖扫描界面的布局、扫描操作的启动和停止以及扫描结果的处理等内容。开发者可以参考这些代码,快速掌握在自己的应用中实现扫码功能的方法。例如,启动扫描的方法如下: 处理扫描结果的回调如下: HMS Scankit 支持所有安卓手机,但在华为设备上能够提供最佳性能和体验,因为它针对华为硬件进行了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值