Resize image taken from gallery or camera, before being uploaded

回眸只為那壹抹淺笑 提交于 2019-12-31 02:35:25

问题


I have a form in my site that allows the user to upload a photo. My android app uses WebView to allow users access the site. On click of the upload button the app allows the user to choose between an image already existing in the gallery or take a new photo and upload that image. The code I have used for this is

showAttachmentDialog is called by the openFileChooser

private void showAttachmentDialog(ValueCallback<Uri> uploadMsg) {
        this.mUploadMessage = uploadMsg;

        File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp");
        // Create the storage directory if it does not exist
        if (! imageStorageDir.exists()){
            imageStorageDir.mkdirs();                  
        }
        File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");


        this.imageUri= Uri.fromFile(file);


        final List<Intent> cameraIntents = new ArrayList<Intent>();
        final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        final PackageManager packageManager = getPackageManager();
        final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
        for(ResolveInfo res : listCam) {
            final String packageName = res.activityInfo.packageName;
            final Intent intent = new Intent(captureIntent);
            intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
            intent.setPackage(packageName);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            cameraIntents.add(intent);
        }


       // mUploadMessage = uploadMsg; 
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);  
        intent.addCategory(Intent.CATEGORY_OPENABLE);  
        intent.setType("image/*"); 
        Intent chooserIntent = Intent.createChooser(intent,"Image Chooser");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
        this.startActivityForResult(chooserIntent,  FILECHOOSER_RESULTCODE);
    }

My onActivityResult

protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (requestCode == FILECHOOSER_RESULTCODE) {

            if (null == this.mUploadMessage) {
                return;
            }

            Uri result;
            if (resultCode != RESULT_OK) {
                result = null;
            } else {
                result = intent == null ? this.imageUri : intent.getData(); // retrieve from the private variable if the intent is null
            }

            this.mUploadMessage.onReceiveValue(result);
            this.mUploadMessage = null;



        }
    }

I would like to be able to change the size of the image before I upload it and I want this to be done on the phone , not in the webpage. I also want to delete the resized image from the phone when this is done and keep the prototype. Could you suggest me a way to do this? I show several cases in SO where it is suggested to create a bitmap and resize it in the desired size with createScaledBitmap but I am not sure which is the best way to do this in my case. Where should this take place? In my onActivityResult? Thanks in advance!

--------------------EDIT----------------------

private File imageStorageDir,file;

I declared these in my main Activity and added the following snippet in my onActivityResult

String newPath=file.getAbsolutePath();
            Bitmap bMap= BitmapFactory.decodeFile(newPath);
            Bitmap out = Bitmap.createScaledBitmap(bMap, 150, 150, false);
            File resizedFile = new File(imageStorageDir, "resized.png");

            OutputStream fOut=null;
            try {
                fOut = new BufferedOutputStream(new FileOutputStream(resizedFile));
                out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
                fOut.flush();
                fOut.close();
                bMap.recycle();
                out.recycle();

            } catch (Exception e) { // TODO

            }

Now the image is being resized and uploaded when taking a photo with the camera but when I am using the gallery I get a NullPointerException

05-23 10:12:50.354: E/BitmapFactory(1376): Unable to decode stream: java.io.FileNotFoundException: /storage/sdcard/Pictures/MyApp/IMG_1400854361171.jpg: open failed: ENOENT (No such file or directory)
05-23 10:12:50.364: D/AndroidRuntime(1376): Shutting down VM
05-23 10:12:50.414: W/dalvikvm(1376): threadid=1: thread exiting with uncaught exception (group=0x41465700)
05-23 10:12:50.494: E/AndroidRuntime(1376): FATAL EXCEPTION: main
05-23 10:12:50.494: E/AndroidRuntime(1376): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { dat=content://media/external/images/media/76 }} to activity {com.example.sinatra19/com.example.sinatra19.Sinatra22Activity}: java.lang.NullPointerException
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.app.ActivityThread.deliverResults(ActivityThread.java:3367)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.app.ActivityThread.handleSendResult(ActivityThread.java:3410)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.app.ActivityThread.access$1100(ActivityThread.java:141)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1304)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.os.Looper.loop(Looper.java:137)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.app.ActivityThread.main(ActivityThread.java:5103)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at java.lang.reflect.Method.invokeNative(Native Method)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at java.lang.reflect.Method.invoke(Method.java:525)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at dalvik.system.NativeStart.main(Native Method)
05-23 10:12:50.494: E/AndroidRuntime(1376): Caused by: java.lang.NullPointerException
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:482)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at com.example.sinatra19.Sinatra22Activity.onActivityResult(Sinatra22Activity.java:158)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.app.Activity.dispatchActivityResult(Activity.java:5322)
05-23 10:12:50.494: E/AndroidRuntime(1376):     at android.app.ActivityThread.deliverResults(ActivityThread.java:3363)
05-23 10:12:50.494: E/AndroidRuntime(1376):     ... 11 more

-----------------------EDIT2------------------------

This snipet

           String newPath=getRealPathFromURI(getApplicationContext(), result);


            Bitmap bMap= BitmapFactory.decodeFile(newPath);
            Bitmap out = Bitmap.createScaledBitmap(bMap, 150, 150, false);
            File resizedFile = new File(imageStorageDir, "resize.png");

            OutputStream fOut=null;
            try {
                fOut = new BufferedOutputStream(new FileOutputStream(resizedFile));
                out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
                fOut.flush();
                fOut.close();
                bMap.recycle();
                out.recycle();

            } catch (Exception e) { // TODO

            }
this.mUploadMessage.onReceiveValue(Uri.fromFile(resizedFile));
        this.mUploadMessage = null;

calling

public String getRealPathFromURI(Context context, Uri contentUri) {
          Cursor cursor = null;
          try { 
            String[] proj = { MediaStore.Images.Media.DATA };
            cursor = context.getContentResolver().query(contentUri,  proj, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
          } finally {
            if (cursor != null) {
              cursor.close();
            }
          }
        }

works when the user chooses photo from gallery and crashes when taking photo from camera. I need the way to combine them


回答1:


Well all it needed was an if statement to check what method the user chose. file is created in the showAttachmentDialog and so the private imageUri allways has the Uri of that file. When the user chooses the camera option result also has that values whereas when he chooses gallery result has the Uri of the image chosen from the galery

if(result==this.imageUri){
            newPath=file.getAbsolutePath();}
            else{
            newPath=getRealPathFromURI(getApplicationContext(), result);}

The final code is

@Override
    //Receives the results of startActivityFromResult
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        String newPath;
        if (requestCode == FILECHOOSER_RESULTCODE) {

            if (null == this.mUploadMessage) {
                return;
            }

            Uri result;
            if (resultCode != RESULT_OK) {
                result = null;
            } else {
                result = intent == null ? this.imageUri : intent.getData(); // retrieve from the private variable if the intent is null
                Log.e("result",result.toString() );
                Log.e("intent",this.imageUri.toString() );

            }

            if(result==this.imageUri){
            newPath=file.getAbsolutePath();}
            else{
            newPath=getRealPathFromURI(getApplicationContext(), result);}

            Bitmap bMap= BitmapFactory.decodeFile(newPath);
            Bitmap out = Bitmap.createScaledBitmap(bMap, 150, 150, false);
            File resizedFile = new File(imageStorageDir, "resize.png");

            OutputStream fOut=null;
            try {
                fOut = new BufferedOutputStream(new FileOutputStream(resizedFile));
                out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
                fOut.flush();
                fOut.close();
                bMap.recycle();
                out.recycle();

            } catch (Exception e) { // TODO

            }


            this.mUploadMessage.onReceiveValue(Uri.fromFile(resizedFile));
            this.mUploadMessage = null;
            //resizedFile.delete();


        }
    }

    public String getRealPathFromURI(Context context, Uri contentUri) {
          Cursor cursor = null;
          try { 
            String[] proj = { MediaStore.Images.Media.DATA };
            cursor = context.getContentResolver().query(contentUri,  proj, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
          } finally {
            if (cursor != null) {
              cursor.close();
            }
          }
        }


来源:https://stackoverflow.com/questions/23813604/resize-image-taken-from-gallery-or-camera-before-being-uploaded

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!