47

I am looking for a simple way to create an animated GIF in a native Android application. The source files should be JPEG (from camera or what ever) and the output should be saved as GIF on the device.

I do not want to know how to play animations or animated GIF files.

To be clear: I want to know how to put single images frame by frame into a "movie" and then save it as a .gif file.

e.g. This App can do want I want to do.

Mischa
  • 1,073
  • 2
  • 13
  • 23

6 Answers6

59

See this solution.

https://github.com/nbadal/android-gif-encoder

It's an Android version of this post.

http://www.jappit.com/blog/2008/12/04/j2me-animated-gif-encoder/

To use this class, here is an example helper method to generate GIF byte array. Note here the getBitmapArray() function is a method to return all the Bitmap files in an image adapter at once. So the input is all the Bitmap files in one adapter, the output is a byte array which you can write to the file.

public byte[] generateGIF() {
    ArrayList<Bitmap> bitmaps = adapter.getBitmapArray();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    AnimatedGifEncoder encoder = new AnimatedGifEncoder();
    encoder.start(bos);
    for (Bitmap bitmap : bitmaps) {
        encoder.addFrame(bitmap);
    }
    encoder.finish();
    return bos.toByteArray();
}

To use this function, do the following then you can save the file into SDcard.

FileOutputStream outStream = null;
        try{
            outStream = new FileOutputStream("/sdcard/generate_gif/test.gif");
            outStream.write(generateGIF());
            outStream.close();
        }catch(Exception e){
            e.printStackTrace();
        }
Fanglin
  • 2,132
  • 1
  • 21
  • 26
  • Does this compute a gif with 8-bit or 24-bit colors? – Michael Jul 03 '14 at 07:06
  • 1
    encoder.addFrame(bitmap); but addFrame looking for image path right ?The method addFrame(Image) in the type AnimatedGifEncoder is not applicable for the arguments (Bitmap) – Achayan Nov 02 '14 at 05:45
  • @Achayan it should take Bitmap as argument. – Fanglin Nov 03 '14 at 17:09
  • @lifelogger yeah it is and I was using worng one which is the J2ME version. Thanks – Achayan Nov 03 '14 at 18:09
  • thanks. I used this class. how can I use many frames without OutOfMemoryError? – Hamidreza Samadi Feb 02 '15 at 11:45
  • Thanks for sharing this code. When I run it though I just get an image, though it says it's a GIF. I've tested by trying to embed it elsewhere. Are there any other settings you have to run? – scientiffic Jul 18 '16 at 20:57
  • @scientiffic GIF is a image file as well. If you cannot display it on your phone, you probably need to check this answer down below. http://stackoverflow.com/a/16331504/3047840 – Fanglin Jul 19 '16 at 16:48
  • 1
    There is an image processing library, akin to http://square.github.io/picasso/ which uses the very same AnimatedGifEncoder class mentioned by Lifelogger- http://bumptech.github.io/glide/javadocs/latest/index.html, https://github.com/bumptech/glide – Nevermore Aug 02 '16 at 00:08
  • 3
    this is very slow for me. about 6 seconds for a frame on my nexus 5x. each frame is 1800x1000 – amarkovits Aug 03 '16 at 23:45
  • How to declare adapter in adapter.getBitmapArray(); ? – djac Nov 03 '17 at 18:20
  • @djac If you're not already using an adapter, you can just pass a `Bitmap[]` or `Bitmap...` into the method instead and work with that. – ban-geoengineering Dec 06 '17 at 16:15
  • After creating the `encoder`, you may also need to call `encoder.setDelay(YOUR_FRAME_DELAY_MILLIS);` and/or `animatedGifEncoder.setRepeat(0);` - see source code for documentation: https://raw.githubusercontent.com/nbadal/android-gif-encoder/master/GifEncoder.java – ban-geoengineering Dec 06 '17 at 16:18
  • Hello, I successfully used this view in my app but when I am setting GIF by using InputStream only first image is displayed. Please any suggestion... – Ghanshyam Bagul Apr 14 '18 at 14:49
7

This might help you. It's a class which is used to generate gif files.

http://elliot.kroo.net/software/java/GifSequenceWriter/

Jatin Malwal
  • 5,133
  • 2
  • 23
  • 26
  • There is a way of doing what you want. First make a byte array of images. Then add header information of gif file then save this file. – Jatin Malwal Nov 22 '13 at 19:31
  • Do you have an example? I managed it to save a file from byte array, but I don't know the header information. – Mischa Nov 22 '13 at 22:13
  • http://www.w3.org/Graphics/GIF/spec-gif89a.txt FOLLOW THIS. It consists all the header info a gif required. Or wiki git format and find all the header byte info. Then just add those values in your byte array. – Jatin Malwal Nov 23 '13 at 06:59
  • This is not the perfect answer because I haven't a working solution jet, but it is the closest answer to get the bounty... – Mischa Nov 28 '13 at 19:42
  • Thanks :) I'll try to do the same thing. The ans of this question by user3047840 is just perfect. – Jatin Malwal Nov 30 '13 at 07:15
  • @Jatin Malwal-can you post link for same? – Sameer Z. Apr 01 '14 at 05:17
6

It did very well for me, It create file fast and good quality images

//True for dither. Will need more memory and CPU
AnimatedGIFWriter writer = new AnimatedGIFWriter(true);
OutputStream os = new FileOutputStream("animated.gif");
Bitmap bitmap; // Grab the Bitmap whatever way you can
// Use -1 for both logical screen width and height to use the first frame dimension
writer.prepareForWrite(os, -1, -1)
writer.writeFrame(os, bitmap);
// Keep adding frame here
writer.finishWrite(os);
// And you are done!!!

https://github.com/dragon66/android-gif-animated-writer

Đăng Huân
  • 139
  • 1
  • 9
4

If you only want to display these bitmaps like an animated gif, you can create an AnimatedDrawable using this code:

AnimationDrawable animation = new AnimationDrawable();
animation.addFrame(getResources().getDrawable(R.drawable.image1), 10);
animation.addFrame(getResources().getDrawable(R.drawable.image2), 50);
animation.addFrame(getResources().getDrawable(R.drawable.image3), 30);
animation.setOneShot(false);

ImageView imageAnim =  (ImageView) findViewById(R.id.imageView);
imageAnim.setImageDrawable(animation);

// start the animation!
animation.start();
ban-geoengineering
  • 18,324
  • 27
  • 171
  • 253
Abeer Iqbal
  • 1,256
  • 10
  • 10
1

Solution 1

Have you seen this article? ..... it's with source code..

As I know, I think android won't play gif animation image. You should use webview that will play gif animation..

http://droid-blog.net/2011/10/14/tutorial-how-to-use-animated-gifs-in-android-part-1/

and if you can..

http://androidosbeginning.blogspot.in/2010/09/gif-animation-in-android.html

Solution 2

Android provides Drawable Animation.

Bhavesh Hirpara
  • 22,255
  • 15
  • 63
  • 104
  • 1
    Hm... Thanks, but this is just how to play GIFs. But I want to create a new GIF file out of files from my device. I want to know how to but single images frame by frame into a "movie" and then save it as a .gif file. I did not find something like that in your links. Or am I blind? :) – Mischa May 02 '13 at 13:26
  • You should've put this explanation in an EDIT to the original question ;) – Azder Jun 18 '13 at 09:33
0

Gif is basically a set of images with a constant time delay in frames. You can not directly play gif in android. I've worked lot on playing gif animation in android.

  • When playing gif we also handle all calls of playing frames by our self. So this is not a best approach

  • If you have set of images just play them by a delay in frames. That would be the all you want.

  • You can not make gif in application by native code as well. There are some drawbacks as well for using gif format. Which I had faced in my game.

  • If you have set of drawables you can use AnimationDrawable for showing aanimation like gif as well. It can also set the any View.

I had also made a custom view to play gif animations. First I load gif and convert it into InputStream then I pass it to my custom view class to play the gif.

 public class GifWebView extends View {
    private Movie mMovie;
    InputStream mStream;
    long mMoviestart;
    private boolean play;

public GifWebView(Context context, InputStream stream) {
    super(context);
    mStream = stream;
    setPlay(true);
    mMovie = Movie.decodeStream(mStream);
}

@Override
protected void onDraw(Canvas canvas) {

    canvas.drawColor(Color.TRANSPARENT);
    super.onDraw(canvas);
    final long now = SystemClock.uptimeMillis();

    if (mMoviestart == 0) {
        mMoviestart = now;
    }
    final int relTime = (int) ((now - mMoviestart) % mMovie.duration());

    mMovie.setTime(relTime);
    mMovie.draw(canvas, 20, 20);
    if (play) {
        Log.i("reltime", "" + relTime + ",duration:" + mMovie.duration());
        this.invalidate();
    }
}

@Override
public boolean onTouchEvent(android.view.MotionEvent event) {
    return true;
};

public boolean isPlay() {
    return play;
}
Jatin Malwal
  • 5,133
  • 2
  • 23
  • 26