本帖最后由 mwdr3000 于 2021-5-8 14:26 编辑
之前发了一贴因为“未能明确发现原创因素”而被删除,现在重新编辑发布一贴。App支持MP4转GIF,可以自由旋转角度,可以查看历史转化记录,也可以进行查看与分享,没有任何的广告!
注意:1.请给予App读取文件的权限没有此权限将无法获取你的MP4资源,无法写入GIF文件到你的手机中;2.删除APP后你所有转化的GIF图片都将会被删除!!!
先上App的使用图后最后为代码。开发工具为AndroidStudion。
历史记录中点击一下为查看,长按为 分享或删除提示框。
主要代码:
[Java] 纯文本查看 复制代码 /**
* [url=home.php?mod=space&uid=952169]@Param[/url] gifPath gif图片的存储路径
* @param begin 开始时间
* @param end 结束时间
* @param fps
* @param speed
* @param gifWidth gif的导出宽度
* @param gifHeight gif的导出长度
* @param videoState 视频是横屏还是竖屏的
* @param needRoate 是否需要旋转
* @param rotateAngle 旋转角度
*/
public void encoder(final String gifPath, final long begin, final long end, final int fps,
final int speed, final int gifWidth, final int gifHeight, final int videoState, final boolean needRoate, final int rotateAngle) {
if (begin > duration) {
// throw new RuntimeException("开始时间不能大于视频时长");
callBack.erroCallBack("开始时间不能大于视频时长");
return;
}
if (end <= begin) {
// throw new RuntimeException("开始时间大于结束时间");
callBack.erroCallBack("开始时间大于结束时间");
return;
}
Thread thread = new Thread() {
@Override
public void run() {
super.run();
long endTime = duration;
if (end < duration) {
endTime = end;
}
long time1 = System.currentTimeMillis();
videoExtractor.seekTo(begin * 1000, trackIndex); // 精确定位到指定帧(定位到指定开始时间帧)
FastYUVtoRGB fastYUVtoRGB = new FastYUVtoRGB(context);
String mime = format.getString(MediaFormat.KEY_MIME);
MediaCodec videoDecoder = null;
try {
videoDecoder = MediaCodec.createDecoderByType(mime);
} catch (IOException e) {
e.printStackTrace();
}
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
int width = format.getInteger(MediaFormat.KEY_WIDTH);
int height = format.getInteger(MediaFormat.KEY_HEIGHT);
videoDecoder.configure(format, null, null, 0);
videoDecoder.start();
GIFEncoder encoder = null;
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int f = fps;
if (f <= 0) {
f = 15;
}
int s = speed;
if (s <= 0) {
s = f;
}
long frameTime = 1000 / f;
long startTime = begin;
while (true) {
int run = extractorVideoInputBuffer(videoExtractor, videoDecoder);
if (run == 1) {
int outIndex = videoDecoder.dequeueOutputBuffer(info, 500000);
if (outIndex >= 0) {
long time = info.presentationTimeUs / 1000;
if (time >= begin && time <= endTime) {
if (time >= startTime) {
Image image = videoDecoder.getOutputImage(outIndex); // 输出
Bitmap bitmap = fastYUVtoRGB.convertYUVtoRGB(getDataFromImage(image), width, height);
int videoImageState = MImageUtil.getPicDirection(image.getHeight(), image.getWidth());
if (needRoate) { // 是否需要旋转,解决自动旋转错误的问题
bitmap = PhotoBitmapUtils.rotateBitmap(bitmap, rotateAngle);
} else {
// LogUtil.i("视频导出图片:" + videoImageState);
// LogUtil.i("原视频图片:" + videoState);
if (videoImageState != videoState) { // 横竖屏不一致,默认自动旋转90°
bitmap = PhotoBitmapUtils.rotateBitmap(bitmap, 90);
}
}
if (gifWidth != -1 && gifHeight != -1) { // 创建新的位图
bitmap = Bitmap.createScaledBitmap(bitmap, gifWidth, gifHeight, true);
} else {
bitmap = Bitmap.createScaledBitmap(bitmap, width / 4, height / 4, true);
}
if (encoder == null) {
encoder = new GIFEncoder();
encoder.setFrameRate(s);
encoder.init(bitmap);
encoder.start(gifPath);
} else {
encoder.addFrame(bitmap);
}
int p = (int) ((startTime - begin) * 100 / (endTime - begin));
LogUtil.d("p = " + p);//进度
if (callBack != null) {
callBack.currentProgress(p);
}
startTime += frameTime;
}
}
videoDecoder.releaseOutputBuffer(outIndex, true /* Surface init */);
if (time >= endTime) {
break;
}
}
} else if (run == -1) {
break;
}
}
if (encoder != null) {
encoder.finish();
}
LogUtil.d("encoder->time = " + (System.currentTimeMillis() - time1));
LogUtil.d("over");
LogUtil.d("gif_path:" + gifPath);
if (callBack != null) {
callBack.onSuccess(System.currentTimeMillis() - time1, gifPath);
}
videoDecoder.stop();
videoDecoder.release();
MFileUtil.clearAllCache(context); // 清除缓存
}
};
thread.start();
}
暂未开放的项目有:设置帧率与速度以及导出的质量。后期会逐渐进行开发的请放心。
使用的是MediaExtractor对视频文件进行帧抽取抽取到的第一帧用于创建文件的头信息,while循环中不断的向GIF文件中设置帧,最后输出到app的存储路径下。(注意这个存储路径会随着App的删除而删除!!!)
请放心使用APP因为我只使用的一条文件读取权限,没有任何上传个人隐私的权限,甚至没有网络访问....
因为Android手机品牌过多并未进行逐一测试,如果有使用问题请在评论区进行反馈。备注上自己的手机品牌以及Android系统版本!
=========分割线===========
这个是初代版本,1.0,有的小伙伴的手机无法安装,就直击使用1.2版本吧!
奉上下载链接:https://pan.baidu.com/s/1nP6Y5zS3d4tOtIcISIi5yg
提取码:a1t9
=========分割线===========
当前最新为1.2版本 (1.解决部分手机安装报错的问题,2.提示框修改)
下载链接:https://pan.baidu.com/s/1CxTITrQHQ6vToH4HAbBRNQ
提取码:dldz
哦,对了APP我已经加固处理了,想反编译的同学可就要辛苦了。。。(1.2没有加固了!因为有些小伙伴的手机加固后就不能安装了,所以就不加固了)
|