Hello Gif 之 制作与拆分

Gif的简单实战

开发过程中需要自己对Gif处理合成与分解,之前都是一直在使用Glide加载。记录一下。

使用到的总体代码

在这里插入图片描述

抽取自Glide部分您可以自己去Glide中获取代码,也可以在这里下载:
点击下载资源.

主要是文件太多,所以放到下载里了,如果你的积分少,可以私信我
获取。

预览效果

在这里插入图片描述

上图其实就是有3张图片生成的,代码如下:

    /**
     * 生成gif
     *
     * @param view
     */
    public void encoderGif(View view) {
        GifMaker gifMaker = new GifMaker();
        try {
            gifMaker.makeGif(getResources(),
                    new int[]{R.drawable.dance1, R.drawable.dance2, R.drawable.dance3},
                    BitmapUtil.getFileDir(this, "dance.gif").getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

而将如果将上面的gif图拆分,同样你将获得3张图片
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码如下:

    /**
     * 拆分Gif
     *
     * @param view
     */
    public void decoderGif(View view) {
        GifSplitter gifSplitter = new GifSplitter();
        try {
            InputStream inputStream;
            //从app下Assets文件夹读取
            inputStream = getResources().getAssets().open("dance.gif");
            //从文件内读取
//            inputStream = new FileInputStream(BitmapUtil.getFileDir(this, "dance.gif").getAbsolutePath());
            List<Bitmap> bitmapList = gifSplitter.decoderGifToBitmaps(inputStream);
            int size = bitmapList.size();
            for (int i = 0; i < size; i++) {
                Bitmap bitmap = bitmapList.get(i);
                BitmapUtil.saveBitmap(this, bitmap, "dance" + i + ".webp");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

最后放出自己实现那部分的工具类

GifMaker

/**
 * Gif制作
 */
public class GifMaker {

    public GifMaker() {

    }

    public boolean makeGif(List<Bitmap> bitmapList, String outputPath) throws IOException {
        //AnimatedGifEncoder具体参数,可自行查看,这里为了演示,只简单使用。
        AnimatedGifEncoder encoder = new AnimatedGifEncoder();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        encoder.start(bos);
//        encoder.setDelay(300);
//        encoder.setRepeat(0);
        int size = bitmapList.size();
        for (int i = 0; i < size; i++) {
            Bitmap bmp = bitmapList.get(i);
            if (bmp == null) {
                continue;
            }
            try {
                //可在此处对bmp进行处理(如压缩,缩放等等)
                encoder.addFrame(bmp);
            } catch (Exception e) {
                e.printStackTrace();
                System.gc();
                break;
            }
        }
        encoder.finish();
        //bitmapList清理看情况,如外部不再使用,就clear
        bitmapList.clear();


        //写入文件xxx.gif
        byte[] data = bos.toByteArray();

        File file = new File(outputPath);
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write(data);
        fileOutputStream.flush();
        fileOutputStream.close();
        return file.exists();
    }

    public boolean makeGifFromPath(List<String> sourcePathList, String outputPath) throws IOException {
        List<Bitmap> bitmaps = new ArrayList<Bitmap>();
        final int length = sourcePathList.size();
        for (int i = 0; i < length; i++) {
            bitmaps.add(BitmapFactory.decodeFile(sourcePathList.get(i)));
        }
        return makeGif(bitmaps, outputPath);
    }

    public boolean makeGifFromFile(List<File> sourceFileList, String outputPath) throws IOException {
        List<String> pathArray = new ArrayList<String>();
        final int length = sourceFileList.size();
        for (int i = 0; i < length; i++) {
            pathArray.add(sourceFileList.get(i).getAbsolutePath());
        }
        return makeGifFromPath(pathArray, outputPath);
    }

    public boolean makeGif(Resources resources, @DrawableRes int[] sourceDrawableId, String outputPath) throws IOException {
        List<Bitmap> bitmaps = new ArrayList<Bitmap>();
        for (int i = 0; i < sourceDrawableId.length; i++) {
            bitmaps.add(BitmapFactory.decodeResource(resources, sourceDrawableId[i]));
        }
        return makeGif(bitmaps, outputPath);
    }
}

GifSplitter

/**
 * Gif拆分
 */
public class GifSplitter {

    /**
     * 将gif分解成多张Bitmap
     *
     * @param inputStream
     * @throws IOException
     */
    public List<Bitmap> decoderGifToBitmaps(InputStream inputStream) throws IOException {
        List<Bitmap> bitmapList = new ArrayList<>();

        byte[] data = isToBytes(inputStream);

        MockProvider provider = new MockProvider();
        GifHeaderParser headerParser = new GifHeaderParser();
        headerParser.setData(data);
        GifHeader header = headerParser.parseHeader();

        StandardGifDecoder decoder = new StandardGifDecoder(provider);
        decoder.setData(header, data);
        //帧数
        int frameCount = decoder.getFrameCount();
        for (int i = 0; i < frameCount; i++) {
            decoder.advance();
            Bitmap nextFrame = decoder.getNextFrame();
            bitmapList.add(nextFrame);
        }
        return bitmapList;
    }

    private static byte[] isToBytes(@NonNull InputStream is) throws IOException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int read;
        try {
            while ((read = is.read(buffer)) != -1) {
                os.write(buffer, 0, read);
            }
        } finally {
            is.close();
        }
        return os.toByteArray();
    }

    /**
     * 私有实现获取Bitmap
     */
    private static class MockProvider implements StandardGifDecoder.BitmapProvider {

        @NonNull
        @Override
        public Bitmap obtain(int width, int height, @NonNull Bitmap.Config config) {

            return Bitmap.createBitmap(width, height, config);
        }

        @Override
        public void release(@NonNull Bitmap bitmap) {
            // Do nothing.
        }

        @NonNull
        @Override
        public byte[] obtainByteArray(int size) {
            return new byte[size];
        }

        @Override
        public void release(@NonNull byte[] bytes) {
            // Do nothing.
        }

        @NonNull
        @Override
        public int[] obtainIntArray(int size) {
            return new int[size];
        }

        @Override
        public void release(@NonNull int[] array) {
            // Do Nothing
        }
    }
}

BitmapUtil

public class BitmapUtil {

    public static boolean saveBitmap(Context context, Bitmap bitmap, String fileName) {
        try {
            File imageFile = getFileDir(context, fileName);
            FileOutputStream fos = new FileOutputStream(imageFile);
            //这里配置生bitmap的格式与压缩率(0-100)
            bitmap.compress(Bitmap.CompressFormat.PNG, 70, fos);
            fos.flush();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    @NonNull
    public static File getFileDir(Context context, String name) {
        File externalFilesDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (!externalFilesDir.exists()) {
            boolean isSuccess = externalFilesDir.mkdirs();
            if (!isSuccess) {
                externalFilesDir.mkdirs();
            }
        }
        return new File(externalFilesDir, name);
    }
}

妥妥的干货,还可以-->点击链接进行跳转去Github查看这个项目
https://github.com/CoderDaMing/HelloGif
,自己运行一下,后续如有更新就在此项目中.

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值