终于搞定多张JPG图片转成GIF动画这个难题,解决方法如下。 您所在的位置:网站首页 newimage/wcorner23.gif 终于搞定多张JPG图片转成GIF动画这个难题,解决方法如下。

终于搞定多张JPG图片转成GIF动画这个难题,解决方法如下。

2022-03-26 12:05| 来源: 网络整理| 查看: 265

   这几天,一直在搞这个问题,就是想把自己所得到的多张的JPG图片文件,转成一张GIF的动画,然后让它来执行。

     刚开始的时候,也摸索了很久,这个问题,看到网上面的也有很多的方法,但是都是不能够使用,很是郁闷。其实网上的方法,也是能够用的,但是有它的局限性,一般来说,都是用的是LZW的一种GIF算法来实现这个过程,作为一名软件人员,所要做的事是使用轮子,所以,可以直接使用别人写好的算法,然后根据自己的需求来实现一些相应的功能,GIF也是如此。

   刚才提到了网上的一些方法,它的局限性在于,只是适用于JAVA,而不是android上,而我们的目标正是实现在andorid上,到底有什么不一样的地方呢,下面我详细说一下。

  根据我几天以来的发现,第一种方案, android里面,也可以实现一些纯java 的程度,只是会有一些限制,例如有很多纯java 的库包在android中,并不存在,所以这个方法实现起来并不容易,故弃之。

    说到这里,还是要提到网上一些适用于JAVA的方法,为什么在android里面,就不能用了呢,这是因为,在这些代码里面,使用了一些java.awt.*里面的库,以及一个ImageIO的库包,所以不能在android里面实现,我也想过,把这些库包提出来放到android工程下面去使用,结果失败,老是报 Conversion to Dalvik format failed with error 1错误,查了网上各种各样的方法,都没有生效,郁闷之。如果各网友想要查,可以在jdk的lib下面找到一个rt.jar的库包,里面就有这些所需要调用到的库文件。所以这种方法,也被我放弃。

  最后,我还是想,到底怎么才可以实现这个功能,我后来想到对这些java文件,进行一些改造,用一些android里面的类来替代awt和ImageIO库,这样应该可以吧,

在自己的不断努力之下,终于实现了这一功能,说起来实现的非常巧,并不是说我功力有多深,只是随例试了一下,给我试出来了,个人也是感觉自己运气比较好,呵呵。

  下面就不说废话了,直接帖代码:

     

public class jpgToGif {

   //synchronized    public  static void jpgToGif(String pic[],                String newPic) {            try {              Log.i("jpgToGif","is connection ="+newPic);              AnimatedGifEncoder1 e = new AnimatedGifEncoder1();                 e.setRepeat(1);                e.start(newPic);                             for (int i = 0; i < pic.length; i++) {                    e.setDelay(200); // 设置播放的延迟时间                   Bitmap src=BitmapFactory.decodeFile(pic[i]);                  e.addFrame(src); // 添加到帧中                }                e.finish();//刷新任何未决的数据,并关闭输出文件            } catch (Exception e) {                e.printStackTrace();            }        }   }

AnimatedGifEncoder1.java

public class AnimatedGifEncoder1 {   protected boolean closeStream;   protected int colorDepth;   protected byte[] colorTab;   protected int delay = 0;   protected int dispose;   protected boolean firstFrame;   protected int height;   protected Bitmap image;   protected byte[] indexedPixels;   protected OutputStream out;   protected int palSize;   protected byte[] pixels;   protected int repeat = -1;   protected int sample;   protected boolean sizeSet;   protected boolean started ;   protected int transIndex;   protected int transparent = 0;   protected boolean[] usedEntry;   protected int width;

  public AnimatedGifEncoder1()   {     boolean[] arrayOfBoolean = new boolean[256];     this.usedEntry = arrayOfBoolean;     this.palSize = 7;     this.dispose = -1;     this.closeStream = false;     this.firstFrame = true;     this.sizeSet = false;     this.sample = 10;   }

  public boolean addFrame(Bitmap paramBitmap)   {     boolean ok = true;     if(paramBitmap==null  || !started)     {      return false;     }         try       {        Log.i("AnimatedGifEncode...","AnimatedGifEncode is addFrame ="+paramBitmap);         if (!sizeSet)         {           int i = paramBitmap.getWidth();           int l = paramBitmap.getHeight();           setSize(i, l);         }         this.image = paramBitmap;         getImagePixels();         analyzePixels();       if(firstFrame)         {           writeLSD();           writePalette();           if(repeat>=0)             writeNetscapeExt();         }         writeGraphicCtrlExt();         writeImageDesc();           if (!firstFrame)           writePalette();         writePixels();         this.firstFrame = false;            }       catch (IOException localIOException1)       {        ok=false;                         }       return ok;       }

  protected void analyzePixels()   {     int len = this.pixels.length;     int nPix = len / 3;     byte[] arrayOfByte1 = new byte[nPix];     this.indexedPixels = arrayOfByte1;     byte[] arrayOfByte2 = this.pixels;     int k = this.sample;     NeuQuant nq = new NeuQuant(arrayOfByte2, len, k);     this.colorTab = nq.process();     int l = 0;     int i1 = this.colorTab.length;     Object localObject;     if (l >= i1)     {       l = 0;       localObject = null;     }           for (int i = 0; i < colorTab.length; i += 3) {                  byte temp = colorTab[i];                  colorTab[i] = colorTab[i + 2];                  colorTab[i + 2] = temp;                  usedEntry[i / 3] = false;              }           int k1 = 0;              for (int i = 0; i < nPix; i++) {                  int index =                      nq.map(pixels[k1++] & 0xff,                             pixels[k1++] & 0xff,                             pixels[k1++] & 0xff);                  usedEntry[index] = true;                  indexedPixels[i] = (byte) index;              }            pixels = null;              colorDepth = 8;              palSize = 7;              if (transparent != 0) {                  transIndex = findClosest(transparent);              }         }

  protected int findClosest(int paramInt)   {       if (colorTab == null)     {       return -1;     }     int r = Color.red(paramInt);     int g = Color.green(paramInt);     int b = Color.blue(paramInt);     int minpos = 0;       int dmin = 256 * 256 * 256;       int len = colorTab.length;          for (int i = 0; i < len;) {           int dr = r - (colorTab[i++] & 0xff);           int dg = g - (colorTab[i++] & 0xff);           int db = b - (colorTab[i] & 0xff);           int d = dr * dr + dg * dg + db * db;           int index = i / 3;           if (usedEntry[index] && (d < dmin)) {               dmin = d;               minpos = index;           }           i++;       }       return minpos;     }

      public boolean finish()   {    if (!started) return false;         boolean ok = true;         started = false;         try {             out.write(0x3b); // gif trailer             out.flush();             if (closeStream) {                 out.close();             }         } catch (IOException e) {             ok = false;         }  

      // reset for subsequent use         transIndex = 0;         out = null;         image = null;         pixels = null;         indexedPixels = null;         colorTab = null;         closeStream = false;         firstFrame = true;  

      return ok;     }

  protected void getImagePixels()   {     int w = this.image.getWidth();     int h = this.image.getHeight();     Bitmap.Config localConfig = Bitmap.Config.ARGB_8888;     Bitmap localBitmap1 = Bitmap.createBitmap(w, h, localConfig);     Canvas localCanvas = new Canvas(localBitmap1);     localCanvas.save();     Paint localPaint = new Paint();     localCanvas.drawBitmap(image, 0, 0, localPaint);     localCanvas.restore();        this.pixels =new byte[w * h * 3];     int[] arrayOfInt = new int[w * h];     int k = 0;     int l = 0;     int i1 = w;     localBitmap1.getPixels(arrayOfInt, 0, w, k, l, i1, h);     int localObject = 0;     while (true)     {           if (localObject >= arrayOfInt.length)         return;          pixels[localObject * 3] = (byte)Color.blue(arrayOfInt[localObject]);         pixels[localObject * 3+1] = (byte)Color.green(arrayOfInt[localObject]);       pixels[localObject * 3+2] = (byte)Color.red(arrayOfInt[localObject]);       ++localObject;     }   }

  public void setDelay(int ms) {         delay = Math.round(ms / 10.0f);     }  

      public void setDispose(int code) {         if (code >= 0) {             dispose = code;         }     }      

  public void setFrameRate(float fps) {         if (fps != 0f) {             delay = Math.round(100f / fps);         }     } 

  public void setQuality(int quality) {         if (quality < 1) quality = 1;         sample = quality;     }       public void setRepeat(int iter) {         if (iter >= 0) {           Log.i("AnimatedGifEncode...","AnimatedGifEncode is setRepeat..setRepeat =");           repeat = iter;         }     }  

  public void setSize(int w, int h) {         if (started && !firstFrame) return;         width = w;         height = h;         if (width < 1) width = 320;         if (height < 1) height = 240;         sizeSet = true;     }      

  public void setTransparent(int c)   {     this.transparent = c;   }

  public boolean start(OutputStream os)   {     if (os == null) return false;          boolean ok = true;          closeStream = false;          out = os;          Log.i("AnimatedGifEncode...","AnimatedGifEncode is start outputSteam");        try {              writeString("GIF89a"); // header          } catch (IOException e) {              ok = false;          }          return started = ok;     }

    public boolean start(String file) {         boolean ok = true;         try {             out = new BufferedOutputStream(new FileOutputStream(file));             ok = start(out);             Log.i("AnimatedGifEncode...","AnimatedGifEncode is start ="+file);           closeStream = true;         } catch (IOException e) {             ok = false;         }         return started = ok;     }  

  protected void writeGraphicCtrlExt() throws IOException {         out.write(0x21); // extension introducer         out.write(0xf9); // GCE label         out.write(4); // data block size         int transp, disp;         if (transparent == 0) {             transp = 0;             disp = 0; // dispose = no action         } else {             transp = 1;             disp = 2; // force clear if using transparent color         }         if (dispose >= 0) {             disp = dispose & 7; // user override         }         disp 8) & 0xff);     }       

  protected void writeString(String s) throws IOException {         for (int i = 0; i < s.length(); i++) {             out.write((byte) s.charAt(i));           Log.i("AnimatedGifEncode...","AnimatedGifEncode is read header!!!");       }     }  }

 

LZWEncoder.java

class LZWEncoder {

 private static final int EOF = -1;

 private int imgW, imgH;  private byte[] pixAry;  private int initCodeSize;  private int remaining;  private int curPixel;

 // GIFCOMPR.C       - GIF Image compression routines  //  // Lempel-Ziv compression based on 'compress'.  GIF modifications by  // David Rowley ([email protected])

 // General DEFINEs

 static final int BITS = 12;

 static final int HSIZE = 5003; // 80% occupancy

 // GIF Image compression - modified 'compress'  //  // Based on: compress.c - File compression ala IEEE Computer, June 1984.  //  // By Authors:  Spencer W. Thomas      (decvax!harpo!utah-cs!utah-gr!thomas)  //              Jim McKie              (decvax!mcvax!jim)  //              Steve Davies           (decvax!vax135!petsd!peora!srd)  //              Ken Turkowski          (decvax!decwrl!turtlevax!ken)  //              James A. Woods         (decvax!ihnp4!ames!jaw)  //              Joe Orost              (decvax!vax135!petsd!joe)

 int n_bits; // number of bits/code  int maxbits = BITS; // user settable max # bits/code  int maxcode; // maximum code, given n_bits  int maxmaxcode = 1   imgW = width;   imgH = height;   pixAry = pixels;   initCodeSize = Math.max(2, color_depth);  }    // Add a character to the end of the current packet, and if it is 254  // characters, flush the packet to disk.  void char_out(byte c, OutputStream outs) throws IOException {   accum[a_count++] = c;   if (a_count >= 254)    flush_char(outs);  }    // Clear out the hash table

 // table clear for block compress  void cl_block(OutputStream outs) throws IOException {   cl_hash(hsize);   free_ent = ClearCode + 2;   clear_flg = true;

  output(ClearCode, outs);  }    // reset code table  void cl_hash(int hsize) {   for (int i = 0; i < hsize; ++i)    htab[i] = -1;  }    void compress(int init_bits, OutputStream outs) throws IOException {   int fcode;   int i /* = 0 */;   int c;   int ent;   int disp;   int hsize_reg;   int hshift;

  // Set up the globals:  g_init_bits - initial number of bits   g_init_bits = init_bits;

  // Set up the necessary values   clear_flg = false;   n_bits = g_init_bits;   maxcode = MAXCODE(n_bits);

  ClearCode = 1     ent = codetab[i];     continue;    } else if (htab[i] >= 0) // non-empty slot     {     disp = hsize_reg - i; // secondary hash (after G. Knott)     if (i == 0)      disp = 1;     do {      if ((i -= disp) < 0)       i += hsize_reg;

     if (htab[i] == fcode) {       ent = codetab[i];       continue outer_loop;      }     } while (htab[i] >= 0);    }    output(ent, outs);    ent = c;    if (free_ent < maxmaxcode) {     codetab[i] = free_ent++; // code -> hashtable     htab[i] = fcode;    } else     cl_block(outs);   }   // Put out the final code.   output(ent, outs);   output(EOFCode, outs);  }    //----------------------------------------------------------------------------  void encode(OutputStream os) throws IOException {   os.write(initCodeSize); // write "initial code size" byte

  remaining = imgW * imgH; // reset navigation variables   curPixel = 0;

  compress(initCodeSize + 1, os); // compress and write the pixel data

  os.write(0); // write block terminator  }    // Flush the packet to disk, and reset the accumulator  void flush_char(OutputStream outs) throws IOException {   if (a_count > 0) {    outs.write(a_count);    outs.write(accum, 0, a_count);    a_count = 0;   }  }    final int MAXCODE(int n_bits) {   return (1   cur_accum &= masks[cur_bits];

  if (cur_bits > 0)        cur_accum |= (code = 8) {    char_out((byte) (cur_accum & 0xff), outs);    cur_accum >>= 8;    cur_bits -= 8;   }

  // If the next entry is going to be too big for the code size,   // then increase it, if possible.   if (free_ent > maxcode || clear_flg) {    if (clear_flg) {     maxcode = MAXCODE(n_bits = g_init_bits);     clear_flg = false;    } else {     ++n_bits;     if (n_bits == maxbits)      maxcode = maxmaxcode;     else      maxcode = MAXCODE(n_bits);    }   }

  if (code == EOFCode) {    // At EOF, write the rest of the buffer.    while (cur_bits > 0) {     char_out((byte) (cur_accum & 0xff), outs);     cur_accum >>= 8;     cur_bits -= 8;    }

   flush_char(outs);   }  } }

 

NeuQuant.java

public class NeuQuant {

  protected static final int netsize = 256; /* number of colours used */

  /* four primes near 500 - assume no image has a length so large */   /* that it is divisible by all four primes */   protected static final int prime1 = 499;   protected static final int prime2 = 491;   protected static final int prime3 = 487;   protected static final int prime4 = 503;

  protected static final int minpicturebytes = (3 * prime4);   /* minimum size for input image */

  /* Program Skeleton      ----------------      [select samplefac in range 1..30]      [read image from input file]      pic = (unsigned char*) malloc(3*width*height);      initnet(pic,3*width*height,samplefac);      learn();      unbiasnet();      [write output image header, using writecolourmap(f)]      inxbuild();      write output image using inxsearch(b,g,r)      */

  /* Network Definitions      ------------------- */

  protected static final int maxnetpos = (netsize - 1);   protected static final int netbiasshift = 4; /* bias for colour values */   protected static final int ncycles = 100; /* no. of learning cycles */

  /* defs for freq and bias */   protected static final int intbiasshift = 16; /* bias for fractions */   protected static final int intbias = (((int) 1) betashift); /* beta = 1/1024 */   protected static final int betagamma =    (intbias > 3); /* for 256 cols, radius starts */   protected static final int radiusbiasshift = 6; /* at 32.0 biased by 6 bits */   protected static final int radiusbias = (((int) 1)     network[i] = new int[4];     p = network[i];     p[0] = p[1] = p[2] = (i     int j = index[i];     map[k++] = (byte) (network[j][0]);     map[k++] = (byte) (network[j][1]);     map[k++] = (byte) (network[j][2]);    }    return map;   }     /* Insertion sort of network and building of netindex[0..255] (to do after unbias)      ------------------------------------------------------------------------------- */   public void inxbuild() {

   int i, j, smallpos, smallval;    int[] p;    int[] q;    int previouscol, startpos;

   previouscol = 0;    startpos = 0;    for (i = 0; i < netsize; i++) {     p = network[i];     smallpos = i;     smallval = p[1]; /* index on g */     /* find smallest in i..netsize-1 */     for (j = i + 1; j < netsize; j++) {      q = network[j];      if (q[1] < smallval) { /* index on g */       smallpos = j;       smallval = q[1]; /* index on g */      }     }     q = network[smallpos];     /* swap p (i) and q (smallpos) entries */     if (i != smallpos) {      j = q[0];      q[0] = p[0];      p[0] = j;      j = q[1];      q[1] = p[1];      p[1] = j;      j = q[2];      q[2] = p[2];      p[2] = j;      j = q[3];      q[3] = p[3];      p[3] = j;     }     /* smallval entry is now in position i */     if (smallval != previouscol) {      netindex[previouscol] = (startpos + i) >> 1;      for (j = previouscol + 1; j < smallval; j++)       netindex[j] = i;      previouscol = smallval;      startpos = i;     }    }    netindex[previouscol] = (startpos + maxnetpos) >> 1;    for (j = previouscol + 1; j < 256; j++)     netindex[j] = maxnetpos; /* really 256 */   }     /* Main Learning Loop      ------------------ */   public void learn() {

   int i, j, b, g, r;    int radius, rad, alpha, step, delta, samplepixels;    byte[] p;    int pix, lim;

   if (lengthcount < minpicturebytes)     samplefac = 1;    alphadec = 30 + ((samplefac - 1) / 3);    p = thepicture;    pix = 0;    lim = lengthcount;    samplepixels = lengthcount / (3 * samplefac);    delta = samplepixels / ncycles;    alpha = initalpha;    radius = initradius;

   rad = radius >> radiusbiasshift;    if (rad      if ((lengthcount % prime3) != 0)       step = 3 * prime3;      else       step = 3 * prime4;     }    }

   i = 0;    while (i < samplepixels) {     b = (p[pix + 0] & 0xff)

   int i, j, dist, a, bestd;    int[] p;    int best;

   bestd = 1000; /* biggest possible dist is 256*3 */    best = -1;    i = netindex[g]; /* index on g */    j = i - 1; /* start at netindex[g] and work outwards */

   while ((i < netsize) || (j >= 0)) {     if (i < netsize) {      p = network[i];      dist = p[1] - g; /* inx key */      if (dist >= bestd)       i = netsize; /* stop iter */      else {       i++;       if (dist < 0)        dist = -dist;       a = p[0] - b;       if (a < 0)        a = -a;       dist += a;       if (dist < bestd) {        a = p[2] - r;        if (a < 0)         a = -a;        dist += a;        if (dist < bestd) {         bestd = dist;         best = p[3];        }       }      }     }     if (j >= 0) {      p = network[j];      dist = g - p[1]; /* inx key - reverse dif */      if (dist >= bestd)       j = -1; /* stop iter */      else {       j--;       if (dist < 0)        dist = -dist;       a = p[0] - b;       if (a < 0)        a = -a;       dist += a;       if (dist < bestd) {        a = p[2] - r;        if (a < 0)         a = -a;        dist += a;        if (dist < bestd) {         bestd = dist;         best = p[3];        }       }      }     }    }    return (best);   }   public byte[] process() {    learn();    unbiasnet();    inxbuild();    return colorMap();   }     /* Unbias network to give byte values 0..255 and record position i to prepare for sort      ----------------------------------------------------------------------------------- */   public void unbiasnet() {

   int i, j;

   for (i = 0; i < netsize; i++) {     network[i][0] >>= netbiasshift;     network[i][1] >>= netbiasshift;     network[i][2] >>= netbiasshift;     network[i][3] = i; /* record colour no */    }   }     /* Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in radpower[|i-j|]      --------------------------------------------------------------------------------- */   protected void alterneigh(int rad, int i, int b, int g, int r) {

   int j, k, lo, hi, a, m;    int[] p;

   lo = i - rad;    if (lo < -1)     lo = -1;    hi = i + rad;    if (hi > netsize)     hi = netsize;

   j = i + 1;    k = i - 1;    m = 1;    while ((j < hi) || (k > lo)) {     a = radpower[m++];     if (j < hi) {      p = network[j++];      try {       p[0] -= (a * (p[0] - b)) / alpharadbias;       p[1] -= (a * (p[1] - g)) / alpharadbias;       p[2] -= (a * (p[2] - r)) / alpharadbias;      } catch (Exception e) {      } // prevents 1.3 miscompilation     }     if (k > lo) {      p = network[k--];      try {       p[0] -= (a * (p[0] - b)) / alpharadbias;       p[1] -= (a * (p[1] - g)) / alpharadbias;       p[2] -= (a * (p[2] - r)) / alpharadbias;      } catch (Exception e) {      }     }    }   }     /* Move neuron i towards biased (b,g,r) by factor alpha      ---------------------------------------------------- */   protected void altersingle(int alpha, int i, int b, int g, int r) {

   /* alter hit neuron */    int[] n = network[i];    n[0] -= (alpha * (n[0] - b)) / initalpha;    n[1] -= (alpha * (n[1] - g)) / initalpha;    n[2] -= (alpha * (n[2] - r)) / initalpha;   }     /* Search for biased BGR values      ---------------------------- */   protected int contest(int b, int g, int r) {

   /* finds closest neuron (min dist) and updates freq */    /* finds best neuron (min dist-bias) and returns position */    /* for frequently chosen neurons, freq[i] is high and bias[i] is negative */    /* bias[i] = gamma*((1/netsize)-freq[i]) */

   int i, dist, a, biasdist, betafreq;    int bestpos, bestbiaspos, bestd, bestbiasd;    int[] n;

   bestd = ~(((int) 1)      bestd = dist;      bestpos = i;     }     biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift));     if (biasdist < bestbiasd) {      bestbiasd = biasdist;      bestbiaspos = i;     }     betafreq = (freq[i] >> betashift);     freq[i] -= betafreq;     bias[i] += (betafreq



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有