I am creating a video from the static images present in the external storage of my phone. The video will be like an automatic slideshow of the images. I have used JCodec for it.
Below is my code.
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.jcodec.common.model.ColorSpace;
import org.jcodec.common.model.Picture;
import java.io.File;
import java.io.IOException;
public class VideoActivity extends AppCompatActivity{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
video();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Video Created") //
.setMessage("Hi this video is created") //
.setPositiveButton("Play", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// TODO
Log.d("dee","On Click on the play button");
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+ "/output97.mp4"));
intent.setDataAndType(Uri.parse(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+"/output97.mp4"), "video/mp4");
startActivity(intent);
dialog.dismiss();
}
}) //
.setNegativeButton(("Share"), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
Uri uri = Uri.fromFile(GetSDPathToFile("","output67.mp4"));
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setDataAndType(uri, "video/*");
intent.setType("video/mp4");
startActivity(intent);
dialog.dismiss();
}
});
builder.show();
}
public void video() {
try {
//Harsh bhaiya change the directory name in the GetSdToPath() Function in the belwo 1 lines
File file = this.GetSDPathToFile("", "output97.mp4");
NewSequenceEncoder encoder = new NewSequenceEncoder(file);
File folder = new File(Environment.getExternalStorageDirectory() +"/numeros/fshhaq/") ;
File[] listFile = folder.listFiles();
// only 5 frames in total
String text = "Numero";
for (int i = 1; i <= listFile.length; i++) {
String _path=listFile[i-1].getAbsolutePath();
Log.d("dee","pathhhhhhhhhhhh12"+_path);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(_path, options);
Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
//Log.d("dee","reached here");
Log.d("dee","image " + i);
Typeface tf = Typeface.create("Helvitica", Typeface.NORMAL);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setTypeface(tf);
Log.d("dee","reached before the typface");
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(convertToPixels(getApplicationContext(),16));
Rect textRect = new Rect();
Log.d("dee","created the rectange");
paint.getTextBounds(text, 0, text.length(), textRect);
// Log.d("dee","reached here2");
Canvas canvas = new Canvas(mutableBitmap);
Log.d("dee","reached here3");
//If the text is bigger than the canvas , reduce the font size
if (textRect.width() >= (canvas.getWidth() - 4)) //the padding on either sides is considered as 4, so as to appropriately fit in the text
{
Log.d("dee", "Let us know");
paint.setTextSize(convertToPixels(getApplicationContext(), 7)); //Scaling needs to be used for different dpi's
}
//Calculate the positions
int xPos= (canvas.getWidth() -105); //-2 is for regulating the x position offset
Log.d("dee","reached the jesus");
Log.d("dee",canvas.getWidth() + "");
Log.d("dee",canvas.getWidth() + " sbjgbsdj " + canvas.getHeight());
//"- ((paint.descent() + paint.ascent()) / 2)" is the distance from the baseline to the center.
int yPos = (int) ((canvas.getHeight())-50);
canvas.drawText("00O", xPos, yPos, paint);
//int bitmapResId = this.getB.getIdentifier("image" + (i),"drawable", this.getPackageName());
//Log.d("dee", this.getResources().getIdentifier("image" + (i), "drawable", this.getPackageName()) + " " +" is the no");
Log.d("dee","image "+i+"This is the required image number");
//Log.d("dee",this.getBitmapFromResources(getApplicationContext().getResources(),bitmapResId).toString());
// Bitmap bitmap = getBitmapFromResources(this.getResources(), bitmapResId);
//Log.d("dee",R.drawable.class.getResource().l +" fields in drawable");
//BitmapDrawable bitmap1 = this.writeTextOnDrawable(bitmapResId,"NUMERO",getApplicationContext());
Picture pic = this.fromBitmap(mutableBitmap);
//Toast.makeText(getApplicationContext(),"Image +" + i,Toast.LENGTH_SHORT).show();
Log.d("dee",pic.getColor() +" "+pic.createCompatible());
encoder.encodeNativeFrame(pic);
Log.d("dee","reached here4");
}
Log.d("dee","reached here5");
// int bitmapResId = this.getResources().getIdentifier("image6", "drawable", this.getPackageName());
//Log.d("dee",this.getBitmapFromResources(getApplicationContext().getResources(),bitmapResId).toString());
//Bitmap bitmapp = getBitmapFromResources(this.getResources(), bitmapResId);
Log.d("dee","reached here6");
// Picture pic = this.fromBitmap((bitmapp));
//Log.d("dee",pic.getWidth() + " " + pic.getHeight());
Log.d("dee","reached here7");
//encoder.encodeNativeFrame(pic);
Log.d("dee","reached here9");
encoder.finish();
Log.d("dee","reached here8");
} catch (IOException e) {
e.printStackTrace();
}
}
private Bitmap getBitmapFromResources(Resources resources, int bitmapResId) {
return BitmapFactory.decodeResource(resources, bitmapResId);
}
//Change the path in the below function harsh bhaiya
protected File GetSDPathToFile(String filePatho, String fileName) {
File extBaseDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
Log.d("dee", Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).toString());
if (filePatho == null || filePatho.length() == 0 || filePatho.charAt(0) != '/')
filePatho = "/" + filePatho;
createDirIfNotExists(filePatho);
File file = new File(extBaseDir.getAbsoluteFile() + filePatho);
return new File(file.getAbsolutePath() + "/" + fileName);// file;
}
//cahnge in this one too
public static boolean createDirIfNotExists(String path) {
boolean ret = true;
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), path);
if (!file.exists()) {
if (!file.mkdirs()) {
Log.e("TravellerLog :: ", "Problem creating Image folder");
ret = false;
}
}
return ret;
}
public Picture fromBitmap(Bitmap src) {
Picture dst = Picture.create(src.getWidth(), src.getHeight(), ColorSpace.RGB);
fromBitmap(src, dst);
Log.d("dee", dst.getWidth() + "");
return dst;
}
public void fromBitmap(Bitmap src, Picture dst) {
int[] dstData = dst.getPlaneData(0);
int[] packed = new int[src.getWidth() * src.getHeight()*4];
src.getPixels(packed, 0, src.getWidth(), 0, 0, src.getWidth(), src.getHeight());
for (int i = 0, srcOff = 0, dstOff = 0; i < src.getHeight(); i++) {
for (int j = 0; j < src.getWidth(); j++, srcOff++, dstOff += 3) {
int rgb = packed[srcOff];
dstData[dstOff] = (rgb >> 16) & 0xff;
dstData[dstOff + 1] = (rgb >> 8) & 0xff;
dstData[dstOff + 2] = rgb & 0xff;
}
}
}
public static int convertToPixels(Context context, int nDP)
{
final float conversionScale = context.getResources().getDisplayMetrics().density;
return (int) ((nDP * conversionScale) + 0.5f) ;
}
}
I am getting the ArrayIndexOutOfBoundsException error. Following is the logcat
Process: org.example.android.numero, PID: 8567 java.lang.RuntimeException: Unable to start activity ComponentInfo{org.example.android.numero/org.example.android.numero.VideoActivity}: java.lang.ArrayIndexOutOfBoundsException: length=589824; index=589824
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2365)
at android.app.ActivityThread.access$800(ActivityThread.java:147)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1283)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5237)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=589824; index=589824
at org.jcodec.scale.RgbToYuv420j.rgb2yuv(RgbToYuv420j.java:72)
at org.jcodec.scale.RgbToYuv420j.transform(RgbToYuv420j.java:38)
at org.example.android.numero.NewSequenceEncoder.encodeNativeFrame(NewSequenceEncoder.java:68)
at org.example.android.numero.VideoActivity.video(VideoActivity.java:124)
at org.example.android.numero.VideoActivity.onCreate(VideoActivity.java:36)
at android.app.Activity.performCreate(Activity.java:5982)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2258)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2365)
at android.app.ActivityThread.access$800(ActivityThread.java:147)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1283)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5237)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)
Can anyone suggest me where i am going wrong? I feel there is some problem with the resolution of the picture.
Edit: I have overridden a method in JCodec (sequenceEncoder) to newSequenceEncoder, in order to control the frames per second on the video.
Because in below loop you are going equal to the length of the array but array starts from 0 and goes length-1
for(int i = 1; i <= listFile.length; i++)
it suppose to be this
for(int i = 1; i < listFile.length; i++)
plus you are missing the first file name by starting loop from 1 so it should be
for(int i = 0; i < listFile.length; i++)