从 gif / 视频保存位图
Save bitmaps from gif / video
我想保存 GIF 文件和视频文件的单个图像(位图)。我想要每个文件的 5 张图片。根据文件的长度(秒),图片要每隔一定时间拍照,这样就有5张了。希望有人能帮帮我,谢谢!
您可以使用 Android-Ndk-Gif 库来处理您的需求,这里有一个完整的示例,说明如何从 GIF 中获取每个位图,您可以将 gifDecoder.frameNum()
更改为 4,以便获取前 5 个来自您的 GIF 的帧
GifDecoder gifDecoder = new GifDecoder();
boolean isSucceeded = gifDecoder.load(Path); // PATH OF YOUR IMAGE
ArrayList<BitmapGIFUtil> arrayListBitmaps = new ArrayList<>();
for (int i = 0; i < gifDecoder.frameNum(); ++i) {
Bitmap bitmap = gifDecoder.frame(i);
int GIFDelay = gifDecoder.delay(i);
arrayListBitmaps.add(new BitmapGIFUtil(bitmap, GIFDelay));
}
BitmapGIFUtil.java
public class BitmapGIFUtil {
private Bitmap bitmap;
private int Delay;
public BitmapGIFUtil() {
}
public BitmapGIFUtil(Bitmap bitmap, int delay) {
this.bitmap = bitmap;
Delay = delay;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getDelay() {
return Delay;
}
public void setDelay(int delay) {
Delay = delay;
}
}
填写完 arrayListBitmaps
后,您可以将每个 bitmap
保存到您的图库中
我用 Glide 找到了一个很好的解决方案(对于 gif):
Glide.with(Activity.this)
.asGif()
.load(picturePath)
.into(new SimpleTarget<GifDrawable>() {
@Override
public void onResourceReady(@NonNull GifDrawable resource, @Nullable Transition<? super GifDrawable> transition) {
try {
Object GifState = resource.getConstantState();
Field frameLoader = GifState.getClass().getDeclaredField("frameLoader");
frameLoader.setAccessible(true);
Object gifFrameLoader = frameLoader.get(GifState);
Field gifDecoder = gifFrameLoader.getClass().getDeclaredField("gifDecoder");
gifDecoder.setAccessible(true);
StandardGifDecoder standardGifDecoder = (StandardGifDecoder) gifDecoder.get(gifFrameLoader);
for (int i = 0; i < standardGifDecoder.getFrameCount(); i++) {
standardGifDecoder.advance();
if (i == 4) {
bitmap1 = standardGifDecoder.getNextFrame();
} else if (i == standardGifDecoder.getFrameCount() / 3) {
bitmap2 = standardGifDecoder.getNextFrame();
} else if (i == standardGifDecoder.getFrameCount() / 2) {
bitmap3 = standardGifDecoder.getNextFrame();
} else if (i == standardGifDecoder.getFrameCount() - 4) {
bitmap4 = standardGifDecoder.getNextFrame();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
这是一个使用 MediaMetadataRetriever 的解决方案(针对视频):
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(videoFile.getAbsolutePath());
MediaPlayer mp = MediaPlayer.create(getBaseContext(), vidUri);
mp.release();
String strLength = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long time=Long.valueOf(strLength)*1000;
bitmap1 = retriever.getFrameAtTime(time/10*2,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
bitmap2 = retriever.getFrameAtTime(time/10*4,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
bitmap3 = retriever.getFrameAtTime(time/10*6,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
bitmap4 = retriever.getFrameAtTime(time/10*8,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
我想保存 GIF 文件和视频文件的单个图像(位图)。我想要每个文件的 5 张图片。根据文件的长度(秒),图片要每隔一定时间拍照,这样就有5张了。希望有人能帮帮我,谢谢!
您可以使用 Android-Ndk-Gif 库来处理您的需求,这里有一个完整的示例,说明如何从 GIF 中获取每个位图,您可以将 gifDecoder.frameNum()
更改为 4,以便获取前 5 个来自您的 GIF 的帧
GifDecoder gifDecoder = new GifDecoder();
boolean isSucceeded = gifDecoder.load(Path); // PATH OF YOUR IMAGE
ArrayList<BitmapGIFUtil> arrayListBitmaps = new ArrayList<>();
for (int i = 0; i < gifDecoder.frameNum(); ++i) {
Bitmap bitmap = gifDecoder.frame(i);
int GIFDelay = gifDecoder.delay(i);
arrayListBitmaps.add(new BitmapGIFUtil(bitmap, GIFDelay));
}
BitmapGIFUtil.java
public class BitmapGIFUtil {
private Bitmap bitmap;
private int Delay;
public BitmapGIFUtil() {
}
public BitmapGIFUtil(Bitmap bitmap, int delay) {
this.bitmap = bitmap;
Delay = delay;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getDelay() {
return Delay;
}
public void setDelay(int delay) {
Delay = delay;
}
}
填写完 arrayListBitmaps
后,您可以将每个 bitmap
保存到您的图库中
我用 Glide 找到了一个很好的解决方案(对于 gif):
Glide.with(Activity.this)
.asGif()
.load(picturePath)
.into(new SimpleTarget<GifDrawable>() {
@Override
public void onResourceReady(@NonNull GifDrawable resource, @Nullable Transition<? super GifDrawable> transition) {
try {
Object GifState = resource.getConstantState();
Field frameLoader = GifState.getClass().getDeclaredField("frameLoader");
frameLoader.setAccessible(true);
Object gifFrameLoader = frameLoader.get(GifState);
Field gifDecoder = gifFrameLoader.getClass().getDeclaredField("gifDecoder");
gifDecoder.setAccessible(true);
StandardGifDecoder standardGifDecoder = (StandardGifDecoder) gifDecoder.get(gifFrameLoader);
for (int i = 0; i < standardGifDecoder.getFrameCount(); i++) {
standardGifDecoder.advance();
if (i == 4) {
bitmap1 = standardGifDecoder.getNextFrame();
} else if (i == standardGifDecoder.getFrameCount() / 3) {
bitmap2 = standardGifDecoder.getNextFrame();
} else if (i == standardGifDecoder.getFrameCount() / 2) {
bitmap3 = standardGifDecoder.getNextFrame();
} else if (i == standardGifDecoder.getFrameCount() - 4) {
bitmap4 = standardGifDecoder.getNextFrame();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
这是一个使用 MediaMetadataRetriever 的解决方案(针对视频):
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(videoFile.getAbsolutePath());
MediaPlayer mp = MediaPlayer.create(getBaseContext(), vidUri);
mp.release();
String strLength = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long time=Long.valueOf(strLength)*1000;
bitmap1 = retriever.getFrameAtTime(time/10*2,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
bitmap2 = retriever.getFrameAtTime(time/10*4,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
bitmap3 = retriever.getFrameAtTime(time/10*6,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
bitmap4 = retriever.getFrameAtTime(time/10*8,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);