Florian Mac Langlade
Florian Mac Langlade

Reputation: 1903

Android - Resize & crop picture before sending without saving it

Please excuse my bad English, I'm French !

In my Android App, I have to resize and crop a picture from the gallery before sending it to a server WITHOUT saving it.

Here my code to send to the server :

    HttpURLConnection connection = null;
    DataOutputStream outputStream = null;

    String pathToOurFile = imagePath;
    String urlServer = "http://ip/serverApp/upload/transfert.php";
    Log.e("UploadImage", urlServer);
    String lineEnd = "\r\n";
    String twoHyphens = "--";
    String boundary =  "*****";

    try
    {
        File file = new File(imagePath);
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] bytes = new byte[(int) file.length()];
        fileInputStream.read(bytes);
        fileInputStream.close();

        URL url = new URL(urlServer);
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
        connection.setDoOutput(true);
        outputStream = new DataOutputStream( connection.getOutputStream() );
        outputStream.writeBytes(twoHyphens + boundary + lineEnd);
        outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + pathToOurFile +"\"" + lineEnd);
        outputStream.writeBytes(lineEnd);

        int bufferLength = 1024;
        for (int i = 0; i < bytes.length; i += bufferLength) {
            int progress = (int)((i / (float) bytes.length) * 100);
            publishProgress(progress);
            if (bytes.length - i >= bufferLength) {
                outputStream.write(bytes, i, bufferLength);
            } else {
                outputStream.write(bytes, i, bytes.length - i);
            }
        }

        outputStream.writeBytes(lineEnd);
        outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

        outputStream.close();
        outputStream.flush();

        InputStream inputStream = connection.getInputStream();

        // read the response
        inputStream.close();

        int serverResponseCode = connection.getResponseCode();
        String serverResponseMessage = connection.getResponseMessage();


        Log.w("Upload image", "Response -> Code:"+serverResponseCode+" Message:"+serverResponseMessage);

        return serverResponseCode;
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }

Now I need to code to resize and crop the picture in order to have image of a size of 350px/350px.

Do you know how I could do that ?

Thanks a lot.

Upvotes: 1

Views: 7715

Answers (2)

This answer [is based on another answer][1], but I had some problems with that code, so I post the edited and working code.

I did it like this:

BitmapFactory.Options options = new BitmapFactory.Options();
options.outWidth = 50; //pixels
options.outHeight = 50; //pixels
InputStream in = context.getContentResolver().openInputStream(data.getData()); // here, you need to get your context.
Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] bitmapdata = baos.toByteArray();

Notice that, data is the returned data from the Intent you use to get the file. If you already have the file path, just use that...

And now, when you are creating the HTTP Entity, add:

 FormBodyPart fbp = new FormBodyPart("image", new ByteArrayBody(baos.toByteArray(), "image/jpeg", "image"));
 entity.addPart(fbp);

Also, notice that you need a MultipartEntity to upload files.

Upvotes: 0

VincentLamoute
VincentLamoute

Reputation: 810

OK !!!! For the correct way follow this this code !

BUT : becarful, it's an example ! -> YOU SHOULDN'T DO A INTERNET REQUEST IN THE MAIN THREAD

for execute this code, the function exec(); should to be put into a "doInBackground()" of an asyncTask<Object, Object, Object>();

the startActivityForResult() and the override of onActivityResult() should to be into an activity class

tell me if it's correct !!!!

private int ACTIVITY_ID_PICK_PHOTO = 42;
private int maxWidth = 350;
private int maxHeight = 350;
private String url = "http://ip/serverApp/upload/transfert.php"

//Call the activity for select photo into the gallery
private void SelectPhoto(){
    Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
    photoPickerIntent.setType("image/*");
    startActivityForResult(photoPickerIntent, ACTIVITY_ID_PICK_PHOTO);
}

// check the return of the result
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
//check th id of the result
    if (requestCode == ACTIVITY_ID_PICK_PHOTO)
        selectPhotoControl(data);
}

//Working data
private void selectPhotoControl(Intent data) {
//check if any photo is selected
    if (data == null)
        return;
//get the uri of the picture selected
    Uri photoUri = data.getData();
    if (photoUri != null) {
//decode the Uri
        String[] filePathColumn = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(photoUri,
                filePathColumn, null, null, null);
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
//get the uri of the image
        String filePath = cursor.getString(columnIndex);
        cursor.close();
//get the image in the bitmap and resize the image
        Bitmap bp = resize(filePath);
        if (bp != null)
            postImage(bp, filePath);
    }
}

public static HttpResponse postImage(Bitmap bp, String uristr) throws ClientProtocolException, IOException {
//initialization of the postrequest
        HttpPost httpPost = new HttpPost(url);
//create the multipart entitiy (if you want send another content)
        MultipartEntity entity = new MultipartEntity(
//the boundary for separate the informations
        HttpMultipartMode.BROWSER_COMPATIBLE, "------CustomBoundary", null);
        if (bp != null) {
//create the bytes array for send the image
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
//if you want to compress the image -> write the result into bos
            bp.compress(CompressFormat.JPEG, 100, bos);
//get the filename of the image
            String filename = uristr.substring(uristr.lastIndexOf("/") + 1,
                    uristr.length());
//put the picture into the body of this part
            FormBodyPart fbp = new FormBodyPart("photo", new ByteArrayBody(
                    bos.toByteArray(), "image/jpeg", filename));
//add the part to the entity
            entity.addPart(fbp);
        }
//set the entity into the request
            httpPost.setEntity(entity);
//execute the request
        return exec(httpPost);
    }

protected synchronized static HttpResponse exec(HttpRequestBase base) throws ClientProtocolException, IOException{
    if (base != null)
//Execute the request
        return mHttpClient.execute(base);
    else
        return null;
}

private Bitmap resize(String path){
// create the options
    BitmapFactory.Options opts = new BitmapFactory.Options();

//just decode the file
    opts.inJustDecodeBounds = true;
    Bitmap bp = BitmapFactory.decodeFile(path, opts);

//get the original size
    int orignalHeight = opts.outHeight;
    int orignalWidth = opts.outWidth;
//initialization of the scale
    int resizeScale = 1;
//get the good scale
    if ( orignalWidth > maxWidth || orignalHeight > maxHeight ) {
       final int heightRatio = Math.round((float) orignalHeight / (float) maxHeight);
       final int widthRatio = Math.round((float) orignalWidth / (float) maxWidth);
       resizeScale = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
//put the scale instruction (1 -> scale to (1/1); 8-> scale to 1/8)
    opts.inSampleSize = resizeScale;
    opts.inJustDecodeBounds = false;
//get the futur size of the bitmap
    int bmSize = (orignalWidth / resizeScale) * (orignalHeight / resizeScale) * 4;
//check if it's possible to store into the vm java the picture
    if ( Runtime.getRuntime().freeMemory() > bmSize ) {
//decode the file
        bp = BitmapFactory.decodeFile(path, opts);
    } else
        return null;
    return bp;
}

Upvotes: 2

Related Questions