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,自己运行一下,后续如有更新就在此项目中.