如何在Android(开发)中从JPEG文件创建动画GIF

47
我正在寻找一种在本地Android应用程序中创建动画GIF的简单方法。源文件应为JPEG(来自相机或其他),输出应保存为设备上的GIF。
我不想知道如何播放动画或动画GIF文件。
明确一点:我想知道如何逐帧将单个图像放入“电影”中,然后将其保存为.gif文件。
例如此应用程序可以做我想做的事情。

2
这是我为 Android 开发的独立动态 GIF 编写器。它速度快,并且您可以选择使用抖动以获得更好的质量。 - dragon66
@dragon66,您能否添加一个发布标签,以便我们可以使用JitPack? - TheRealChx101
@TheRealChx101 目前还没有发布。 - dragon66
@dragon66 那你就自己做一个吧 :) - TheRealChx101
6个回答

59

看这个解决方案:

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

它是这篇文章的 Android 版本:

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

要使用这个类,这里有一个生成 GIF 字节数组的示例帮助方法。请注意,getBitmapArray() 函数是一种将图像适配器中的所有位图文件一次性返回的方法。因此,输入是一个适配器中的所有位图文件,输出是一个字节数组,您可以将其写入文件。

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();
}

要使用此功能,请按照以下步骤执行,然后您可以将文件保存到SD卡中。

FileOutputStream outStream = null;
        try{
            outStream = new FileOutputStream("/sdcard/generate_gif/test.gif");
            outStream.write(generateGIF());
            outStream.close();
        }catch(Exception e){
            e.printStackTrace();
        }

1
encoder.addFrame(bitmap); 但是addFrame需要图片路径,对吗?类型AnimatedGifEncoder中的方法addFrame(Image)不适用于参数(Bitmap)。 - Achayan
1
有一个图像处理库,类似于http://square.github.io/picasso/,它使用Lifelogger提到的同样的AnimatedGifEncoder类- http://bumptech.github.io/glide/javadocs/latest/index.html,https://github.com/bumptech/glide - Nevermore
3
对我来说这很慢,在我的Nexus 5X上每帧大约需要6秒钟。每帧的分辨率为1800x1000。 - amarkovits
如何在adapter.getBitmapArray()中声明适配器? - djac
创建encoder之后,您可能还需要调用encoder.setDelay(YOUR_FRAME_DELAY_MILLIS);和/或animatedGifEncoder.setRepeat(0); - 有关文档,请参见源代码:https://raw.githubusercontent.com/nbadal/android-gif-encoder/master/GifEncoder.java - ban-geoengineering
显示剩余8条评论

7

有一种做你想要的事情的方法。首先,制作一个图像的字节数组。然后添加 GIF 文件的头部信息,然后保存此文件。 - Jatin Malwal
你有例子吗?我成功地从字节数组中保存了一个文件,但是我不知道头信息。 - Mischa
请按照此链接:http://www.w3.org/Graphics/GIF/spec-gif89a.txt,其中包含GIF所需的所有标头信息。或者在维基百科上查找GIF格式并找到所有标头字节信息。然后只需将这些值添加到您的字节数组中即可。 - Jatin Malwal
这不是完美的答案,因为我还没有一个可行的解决方案,但它是获得悬赏最接近的答案... - Mischa
谢谢 :) 我会尝试做同样的事情。用户3047840对这个问题的答案非常完美。 - Jatin Malwal
@Jatin Malwal,你能发布相应的链接吗? - Sameer Z.

6

它对我来说表现得非常好,可以快速创建文件并生成高质量的图像。

//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


这个编码器的一个特点是它可以逐帧写入动画GIF,以减少内存消耗。 - dragon66
它也会保存 GIF 文件吗? - A. N
是的,它将gif保存为animated.gif的文件名。 - dragon66

4

如果你只想像动态gif一样显示这些位图,你可以使用以下代码创建一个 AnimatedDrawable

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();

1

1
嗯...谢谢,但这只是如何播放GIF的方法。但我想从我的设备文件中创建一个新的GIF文件。我想知道如何逐帧将单个图像放入“电影”中,然后将其保存为.gif文件。我在你提供的链接中没有找到类似的东西。或者我是瞎了吗? :) - Mischa
你应该将这个解释放在原问题的编辑中 ;) - Azder

0

Gif基本上是一组具有帧间恒定时间延迟的图像。您无法直接在Android中播放gif动画。我曾经在Android平台上花费了很多时间来研究播放gif动画。

  • 当播放gif时,我们还会自己处理所有播放帧的调用。因此,这不是最佳方法

  • 如果您有一组图像,请通过帧延迟播放它们。这就是您想要的全部内容。

  • 您也无法通过本机代码在应用程序中制作gif。使用gif格式也有一些缺点。这是我在游戏中遇到的问题之一。

  • 如果您有一组可绘制对象,您还可以使用AnimationDrawable来显示类似gif的动画。它还可以设置任何视图。

我还制作了一个自定义视图来播放gif动画。首先,我加载gif并将其转换为InputStream,然后将其传递给我的自定义视图类以播放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;
}

5
谢谢,但我并没有询问如何播放GIF文件,而是询问如何创建GIF文件。请问您需要的是什么样的帮助呢? - Mischa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接