diff --git a/app/src/main/java/com/frank/ffmpeg/gif/HighQualityGif.java b/app/src/main/java/com/frank/ffmpeg/gif/HighQualityGif.java deleted file mode 100644 index 808a757..0000000 --- a/app/src/main/java/com/frank/ffmpeg/gif/HighQualityGif.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.frank.ffmpeg.gif; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Environment; -import android.text.TextUtils; -import android.util.Log; - -import com.frank.ffmpeg.FFmpegCmd; -import com.frank.ffmpeg.util.FFmpegUtil; -import com.frank.ffmpeg.util.FileUtil; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -/** - * @author frank - * @date 2020-09-25 20:11 - * @desc Extract frames, and convert to GIF - */ - -public class HighQualityGif { - - private final static String TAG = HighQualityGif.class.getSimpleName(); - - private final static int TARGET_WIDTH = 320; - - private final static int TARGET_HEIGHT = 180; - - private int mWidth; - private int mHeight; - private int mRotateDegree; - - public HighQualityGif(int width, int height, int rotateDegree) { - mWidth = width; - mHeight = height; - mRotateDegree = rotateDegree; - } - - private int chooseWidth(int width, int height) { - if (width <= 0 || height <= 0) { - return TARGET_WIDTH; - } - int target; - if (mRotateDegree == 0 || mRotateDegree == 180) {//landscape - if (width > TARGET_WIDTH) { - target = TARGET_WIDTH; - } else { - target = width; - } - } else {//portrait - if (height > TARGET_HEIGHT) { - target = TARGET_HEIGHT; - } else { - target = height; - } - } - return target; - } - - private byte[] generateGif(String filePath, int startTime, int duration, int frameRate) throws IllegalArgumentException { - if (TextUtils.isEmpty(filePath)) { - return null; - } - String folderPath = Environment.getExternalStorageDirectory() + "/gif_frames/"; - FileUtil.deleteFolder(folderPath); - int targetWidth = chooseWidth(mWidth, mHeight); - String[] commandLine = FFmpegUtil.videoToImageWithScale(filePath, startTime, duration, frameRate, targetWidth, folderPath); - FFmpegCmd.executeSync(commandLine); - File fileFolder = new File(folderPath); - if (!fileFolder.exists() || fileFolder.listFiles() == null) { - return null; - } - File[] files = fileFolder.listFiles(); - - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BeautyGifEncoder gifEncoder = new BeautyGifEncoder(); - gifEncoder.setFrameRate(10); - gifEncoder.start(outputStream); - - for (File file:files) { - Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); - if (bitmap != null) { - gifEncoder.addFrame(bitmap); - } - } - gifEncoder.finish(); - return outputStream.toByteArray(); - } - - private boolean saveGif(byte[] data, String gifPath) { - if (data == null || data.length == 0 || TextUtils.isEmpty(gifPath)) { - return false; - } - boolean result = true; - FileOutputStream outputStream = null; - try { - outputStream = new FileOutputStream(gifPath); - outputStream.write(data); - outputStream.flush(); - } catch (IOException e) { - result = false; - } finally { - if (outputStream != null) { - try { - outputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - return result; - } - - /** - * convert video into GIF - * @param gifPath gifPath - * @param filePath filePath - * @param startTime where starts from the video(Unit: second) - * @param duration how long you want to convert(Unit: second) - * @param frameRate how much frames you want in a second - * @return convert GIF success or not - */ - public boolean convertGIF(String gifPath, String filePath, int startTime, int duration, int frameRate) { - byte[] data; - try { - data = generateGif(filePath, startTime, duration, frameRate); - } catch (IllegalArgumentException | OutOfMemoryError e) { - Log.e(TAG, "generateGif error=" + e.toString()); - return false; - } - return saveGif(data, gifPath); - } - -} diff --git a/app/src/main/java/com/frank/ffmpeg/gif/HighQualityGif.kt b/app/src/main/java/com/frank/ffmpeg/gif/HighQualityGif.kt new file mode 100644 index 0000000..7d47fb1 --- /dev/null +++ b/app/src/main/java/com/frank/ffmpeg/gif/HighQualityGif.kt @@ -0,0 +1,138 @@ +package com.frank.ffmpeg.gif + +import android.graphics.BitmapFactory +import android.os.Environment +import android.text.TextUtils +import android.util.Log +import com.frank.ffmpeg.FFmpegCmd +import com.frank.ffmpeg.util.FFmpegUtil +import com.frank.ffmpeg.util.FileUtil +import java.io.ByteArrayOutputStream +import java.io.File +import java.io.FileOutputStream +import java.io.IOException + +/** + * @author frank + * @date 2020-11-08 23:45 + * @desc Extract frames, and convert to GIF + */ +class HighQualityGif(width: Int, height: Int, rotateDegree: Int) { + + companion object { + private val TAG = HighQualityGif::class.java.simpleName + + private const val TARGET_WIDTH = 320 + + private const val TARGET_HEIGHT = 180 + } + + private var mWidth: Int = 0 + private var mHeight: Int = 0 + private var mRotateDegree: Int = 0 + + init { + this.mWidth = width + this.mHeight = height + this.mRotateDegree = rotateDegree + } + + private fun chooseWidth(width: Int, height: Int): Int { + if (width <= 0 || height <= 0) { + return TARGET_WIDTH + } + return if (mRotateDegree == 0 || mRotateDegree == 180) {//landscape + if (width > TARGET_WIDTH) { + TARGET_WIDTH + } else { + width + } + } else {//portrait + if (height > TARGET_HEIGHT) { + TARGET_HEIGHT + } else { + height + } + } + } + + @Throws(IllegalArgumentException::class) + private fun generateGif(filePath: String, startTime: Int, duration: Int, frameRate: Int): ByteArray? { + if (TextUtils.isEmpty(filePath)) { + return null + } + val folderPath = Environment.getExternalStorageDirectory().toString() + "/gif_frames/" + FileUtil.deleteFolder(folderPath) + val targetWidth = chooseWidth(mWidth, mHeight) + val commandLine = FFmpegUtil.videoToImageWithScale(filePath, startTime, duration, frameRate, targetWidth, folderPath) + FFmpegCmd.executeSync(commandLine) + val fileFolder = File(folderPath) + if (!fileFolder.exists() || fileFolder.listFiles() == null) { + return null + } + val files = fileFolder.listFiles() + + val outputStream = ByteArrayOutputStream() + val gifEncoder = BeautyGifEncoder() + gifEncoder.setFrameRate(10f) + gifEncoder.start(outputStream) + + for (file in files) { + val bitmap = BitmapFactory.decodeFile(file.absolutePath) + if (bitmap != null) { + gifEncoder.addFrame(bitmap) + } + } + gifEncoder.finish() + return outputStream.toByteArray() + } + + private fun saveGif(data: ByteArray?, gifPath: String): Boolean { + if (data == null || data.isEmpty() || TextUtils.isEmpty(gifPath)) { + return false + } + var result = true + var outputStream: FileOutputStream? = null + try { + outputStream = FileOutputStream(gifPath) + outputStream.write(data) + outputStream.flush() + } catch (e: IOException) { + result = false + } finally { + if (outputStream != null) { + try { + outputStream.close() + } catch (e: IOException) { + e.printStackTrace() + } + + } + } + return result + } + + /** + * convert video into GIF + * @param gifPath gifPath + * @param filePath filePath + * @param startTime where starts from the video(Unit: second) + * @param duration how long you want to convert(Unit: second) + * @param frameRate how much frames you want in a second + * @return convert GIF success or not + */ + fun convertGIF(gifPath: String, filePath: String, startTime: Int, duration: Int, frameRate: Int): Boolean { + val data: ByteArray? + try { + data = generateGif(filePath, startTime, duration, frameRate) + } catch (e: IllegalArgumentException) { + Log.e(TAG, "generateGif error=$e") + return false + } catch (e: OutOfMemoryError) { + Log.e(TAG, "generateGif error=$e") + return false + } + + return saveGif(data, gifPath) + } +} \ No newline at end of file