Omry Rozenfeld
Omry Rozenfeld

Reputation: 125

Android video and image resizing

I am looking for a way to lower the size of images and videos before I upload them to a server, at the moment I am sending files that are way too big and I cant seem to find any solution of how to compress the files, I know apps like whatsapp and facebook compress videos in a few seconds and cut them in 90% size, anyone got advice, direction I would be grateful.

Thank you.

Upvotes: 1

Views: 6558

Answers (2)

Mick
Mick

Reputation: 25501

You can use ffmpeg, an open source video library, to do the compression.

Be aware that video compression is generally quite compute intense so it is unlikely to take just 'a few seconds' except for small videos.

There are a number of ways to include ffmpeg in your application. Take a look at these 'wrapper' projects for examples to ether use or to help you build your own ffmpeg library:

As an example, the following code will compress an mp4 video file (default compression) once you have selected or built a ffmpeg wrapper (this code uses a custom ffmpeg library but it should give you an overview and you should be able to substitute one of the examples above):

public class VideoCompressionTask extends AsyncTask<String, String, String> {
/* This Class is an AsynchTask to compress a video on a background thread
 * 
 */

@Override
protected String doInBackground(String... params) {
    //Compress the video in the background

    //Get the the path of the video to compress
    String videoPath;
    String videoFileName;
    File videoFileToCompress;
    if (params.length == 1) {
        videoPath = params[0];
        videoFileToCompress = new File(videoPath);
        videoFileName = videoFileToCompress.getName();
    } else {
        //One or all of the params are not present - log an error and return
        Log.d("VideoCompressionTask","doInBackground wrong number of params");
        return null;
    }

    //Make sure the video to compress actually exists
    if(!videoFileToCompress.exists()) {
        Log.d("VideoCompressionTask","doInBackground video file to compress does not exist");
        return null;
    }

    //If the compressed file already exists then delete it first and let this task create a new one
    File compressedVideoFile = new File(compressedFilePath);
    if(compressedVideoFile.exists()) {
        compressedVideoFile.delete();
    }

    String argv[] = {"ffmpeg", "-i", videoPath, "-strict", "experimental", "-acodec", "aac", compressedFilePath};
    int ffmpegWrapperreturnCode = FfmpegJNIWrapper.call_ffmpegWrapper(appContext, argv);
    Log.d("VideoCompressionTask","doInBackground ffmpegWrapperreturnCode: " + ffmpegWrapperreturnCode);

    return(compressedFilePath);
}

Upvotes: 3

Karan
Karan

Reputation: 2130

I had exact need today so came up with this code. Send this function a bitmap and it will return a file path (local) of compressed image. Then create a File object with the returned file path and send it to server:

 public File compressImage(Bitmap bmp) {
        Bitmap scaledBitmap = null;

        int actualHeight = bmp.getHeight();
        int actualWidth = bmp.getWidth();

//      max Height and width values of the compressed image is taken as 816x612
        float imgRatio = actualWidth / actualHeight;
        float maxRatio = logoMaxWidth / logoMaxHeight;
//      width and height values are set maintaining the aspect ratio of the image
        if (actualHeight > logoMaxHeight || actualWidth > logoMaxWidth) {
            if (imgRatio < maxRatio) {
                imgRatio = logoMaxHeight / actualHeight;
                actualWidth = (int) (imgRatio * actualWidth);
                actualHeight = (int) logoMaxHeight;
            } else if (imgRatio > maxRatio) {
                imgRatio = logoMaxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) logoMaxWidth;
            } else {
                actualHeight = (int) logoMaxHeight;
                actualWidth = (int) logoMaxWidth;
            }
        }
        try {
            scaledBitmap = Bitmap.createScaledBitmap(bmp, actualWidth, actualHeight, true);
        } catch (OutOfMemoryError exception) {
            logoUploadFaied();
            exception.printStackTrace();
        }
        String uriSting = (System.currentTimeMillis() + ".jpg");
        File file = new File(Environment.getExternalStorageDirectory()
                + File.separator + uriSting);
        try {
            file.createNewFile();
        } catch (IOException e) {
            logoUploadFaied();
            e.printStackTrace();
        }

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            logoUploadFaied();
            e.printStackTrace();
        }
        try {
            fos.write(getBytesFromBitmap(scaledBitmap));
            fos.close();
            //recycling bitMap to overcome OutOfMemoryError
            if(scaledBitmap!=null){
                scaledBitmap.recycle();
                scaledBitmap=null;
            }
        } catch (IOException e) {
            logoUploadFaied();
            e.printStackTrace();
        }
        return file;
    }

Upvotes: 2

Related Questions