-3

Below is my edit profile activity where i give user an option to set the profile pic from gallery. When user clicks to edit profile pic, it opens up gallery, crop the selected image, cropped image will be saved at pre-defined location as well as temp location, cropped image will be set as profile pic. However, it always gets thumbnail or low quality image. The quality of image is same as of just like how we pass the image into the intent through uri and then get that image uri with getData and then setting up the image with setImageUri, because in such way it will give thumbnail and not the original image. That's why i tried first to save that cropped image and then get it from there. Even to avoid OOM (Out Of Memory) error, i tried to adjust the image quality and compression using inSampleSize, bitmap factory option and all... but at the end, what i get is always the same thumbnail type image quality!

What i want is as said in title, original cropped image to set for userImageView and not kind of thumbnail or low resolution image!

Also consider that i am new in android development as well as in programming, coding and all!

Any kind of help will be appreciated!

public class EditUserProfile extends AppCompatActivity {

    private CoordinatorLayout coordinatorLayout;

    public static final String Uimage = "Uimagepath";
    public static final String Name = "nameKey";
    public static final String UContact = "UContact";
    public static final String Uemail = "Uemail";

    private TextInputLayout inputLayoutName, inputLayoutEmail, inputLayoutContact;
    private EditText usernameTextView, userEmailTextView, userContactTextView;
    private ImageView userImageView;

    SharedPreferences sharedpreferences;
    private int PICK_IMAGE_REQUEST = 1;

    String stringUri;
    Uri outputFileUri;
    Uri uriString;
    Uri picUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_edit_user_profile);
        Toolbar userProfileToolbar = (Toolbar) findViewById(R.id.my_toolbar);
        setSupportActionBar(userProfileToolbar);

        inputLayoutName = (TextInputLayout) findViewById(R.id.input_layout_username);
        inputLayoutEmail = (TextInputLayout) findViewById(R.id.input_layout_useremail);
        inputLayoutContact = (TextInputLayout) findViewById(R.id.input_layout_usercontact);

        userImageView = (ImageView) findViewById(R.id.userImage);
        usernameTextView = (EditText) findViewById(R.id.username);
        userContactTextView = (EditText) findViewById(R.id.usercontact);
        userEmailTextView = (EditText) findViewById(R.id.useremail);

        Button btnSave = (Button) findViewById(R.id.action_save);


        sharedpreferences = getSharedPreferences(Uimage, Context.MODE_PRIVATE);
        sharedpreferences = getSharedPreferences(Name, Context.MODE_PRIVATE);
        sharedpreferences = getSharedPreferences(UContact, Context.MODE_PRIVATE);
        sharedpreferences = getSharedPreferences(Uemail, Context.MODE_PRIVATE);

        if (sharedpreferences.contains(Uimage)) {
            String imagepath = sharedpreferences.getString(Uimage, "");
            uriString = Uri.parse(imagepath);
            userImageView.setImageURI(uriString);
        }

        if (sharedpreferences.contains(Name)) {
            usernameTextView.setText(sharedpreferences.getString(Name, ""));
        }
        if (sharedpreferences.contains(UContact)) {
            userContactTextView.setText(sharedpreferences.getString(UContact, ""));
        }
        if (sharedpreferences.contains(Uemail)) {
            userEmailTextView.setText(sharedpreferences.getString(Uemail, ""));
        }

        usernameTextView.addTextChangedListener(new MyTextWatcher(usernameTextView));
        userEmailTextView.addTextChangedListener(new MyTextWatcher(userEmailTextView));
        userContactTextView.addTextChangedListener(new MyTextWatcher(userContactTextView));

        coordinatorLayout = (CoordinatorLayout) findViewById(R.id
                .coordinatorLayout);

        final ImageButton button = (ImageButton) findViewById(R.id.editImage);
        assert button != null;
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // Perform action on click

                Intent intent = new Intent();
                // start the activity - we handle returning in onActivityResult
                intent.setAction(Intent.ACTION_GET_CONTENT);
                // Show only images, no videos or anything else
                intent.setDataAndType(picUri, "image/*");
                // set crop properties
                intent.putExtra("crop", "true");
                // indicate aspect of desired crop
                intent.putExtra("aspectX", 1);
                intent.putExtra("aspectY", 1);
                // indicate output X and Y
                intent.putExtra("outputX", 360);
                intent.putExtra("outputY", 360);
                // retrieve data on return
                intent.putExtra("return-data", false);
                File file = new File(Environment.getExternalStorageDirectory() + File.separator + "image.jpg");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
                // Always show the chooser (if there are multiple options available)
                startActivityForResult(Intent.createChooser(intent, "Select Pic from"), PICK_IMAGE_REQUEST);
            }
        });
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == PICK_IMAGE_REQUEST) {

            //Get our saved file into a bitmap object:
            File file = new File(Environment.getExternalStorageDirectory() + File.separator + "image.jpg");
            Bitmap Croppedbitmap = decodeSampledBitmapFromFile(file.getAbsolutePath(), 1000, 700);

            userImageView.setImageBitmap(Croppedbitmap);

            String root = Environment.getExternalStorageDirectory().toString();
            File myDir = new File(root + "/MyApp");

            if (!myDir.exists())
                myDir.mkdirs();

            Random generator = new Random();
            int n = 100;
            n = generator.nextInt(n);
            String fname = "Image_" + n + 1 + ".png";
            File file2 = new File(myDir, fname);
            outputFileUri = Uri.fromFile(file2);
            stringUri = outputFileUri.toString();

            SharedPreferences.Editor editor = sharedpreferences.edit();
            editor.putString(Uimage, stringUri);
            editor.apply();

            if (file2.exists())
                file2.delete();

            try {
                FileOutputStream out = new FileOutputStream(file2);
                assert Croppedbitmap != null;
                Croppedbitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight)
    { // BEST QUALITY MATCH

        //First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);

        // Calculate inSampleSize, Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        int inSampleSize = 1;

        if (height > reqHeight)
        {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        }
        int expectedWidth = width / inSampleSize;

        if (expectedWidth > reqWidth)
        {
            //if(Math.round((float)width / (float)reqWidth) > inSampleSize) // If bigger SampSize..
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }

        options.inSampleSize = inSampleSize;

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;

        return BitmapFactory.decodeFile(path, options);
    }



    /**
     * Validating form
     */

    private boolean submitForm() {
        if (!validateName()) {
            return false;
        }

        if (!validateContact()) {
            return false;
        }

        if (!validateEmail()) {
            return false;
        }

        Snackbar snackbar = Snackbar
                .make(coordinatorLayout, "Saved!", Snackbar.LENGTH_LONG);

        snackbar.show();

        return true;
    }

    private boolean validateName() {
        if (usernameTextView.getText().toString().trim().isEmpty()) {
            inputLayoutName.setError(getString(R.string.err_msg_name));
            requestFocus(usernameTextView);
            return false;
        } else {
            inputLayoutName.setError(null);
        }

        return true;
    }

    private boolean validateEmail() {
        String email = userEmailTextView.getText().toString().trim();

        if (email.isEmpty() || !isValidEmail(email)) {
            inputLayoutEmail.setError(getString(R.string.err_msg_email));
            requestFocus(userEmailTextView);
            return false;
        } else {
            inputLayoutEmail.setError(null);
        }

        return true;
    }

    private boolean validateContact() {
        if (userContactTextView.getText().toString().trim().isEmpty()) {
            inputLayoutContact.setError(getString(R.string.err_msg_contact));
            requestFocus(userContactTextView);
            return false;
        } else {
            inputLayoutContact.setError(null);
        }

        return true;
    }

    private static boolean isValidEmail(String email) {
        return !TextUtils.isEmpty(email) && android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches();
    }

    private void requestFocus(View view) {
        if (view.requestFocus()) {
            getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        }
    }

    private class MyTextWatcher implements TextWatcher {

        private View view;

        private MyTextWatcher(View view) {
            this.view = view;
        }

        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        public void afterTextChanged(Editable editable) {
            switch (view.getId()) {
                case R.id.username:
                    validateName();
                    break;
                case R.id.useremail:
                    validateEmail();
                    break;
                case R.id.usercontact:
                    validateContact();
                    break;
            }
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.editprofile_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_save:

                if (!submitForm()) {

                    return false;
                }

                SharedPreferences.Editor editor = sharedpreferences.edit();

                TextView usernameTextView = (TextView) findViewById(R.id.username);
                String usernameString = usernameTextView.getText().toString();

                editor.putString(Name, usernameString);
                editor.apply();

                TextView ucontactTV = (TextView) findViewById(R.id.usercontact);
                String uContactS = ucontactTV.getText().toString();

                editor.putString(UContact, uContactS);
                editor.apply();

                TextView uEmailTV = (TextView) findViewById(R.id.useremail);
                String uEmailS = uEmailTV.getText().toString();

                editor.putString(Uemail, uEmailS);
                editor.apply();

                Snackbar snackbar = Snackbar
                        .make(coordinatorLayout, "Saved!", Snackbar.LENGTH_LONG);

                snackbar.show();

                Intent userProfileIntent = new Intent(EditUserProfile.this, UserProfile.class);

                userProfileIntent.putExtra(Name, usernameString);
                userProfileIntent.putExtra(UContact, uContactS);
                userProfileIntent.putExtra(Uemail, uEmailS);

                if (sharedpreferences.contains(stringUri)) {
                    userProfileIntent.putExtra(Uimage, stringUri);
                }

                setResult(RESULT_OK, userProfileIntent);
                finish();

        }
        return true;
    }

}
Sagar Patel
  • 506
  • 1
  • 8
  • 23

2 Answers2

2

See if this library helps. https://github.com/IsseiAoki/SimpleCropView

It can keep the quality of the original image.

Edit:

Hmm they may have updated the library. I am using the older library of SimpleCropView. Here is my Implementation.

For selecting picture from device.:

Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);

Then on Activity Result:

if (requestCode == PICK_IMAGE_REQUEST && data != null && data.getData() != null) {


            try {
                String selectedImagePath = null;
                Uri selectedImageUri = data.getData();

                if (selectedImageUri.toString().contains("%")) {
                    if (selectedImageUri.toString().startsWith("content://com.google.android.apps.photos.content")) {
                        Log.v("esty", "URI: " + selectedImageUri.toString());
                        selectedImagePath = getPath.getImageUrlWithAuthority(this, selectedImageUri);

                    } else {


                        Log.v("esty", "URI: " + selectedImageUri.toString());
                        String[] UriArray = selectedImageUri.toString().split("%3A");

                        String newURIString = "content://media/external/images/media/" + UriArray[1];
                        Uri newURI = Uri.parse(newURIString);
                        Log.v("esty", "URI: " + newURI);
                        selectedImagePath = getPath.getPath(newURI, this);
                    }
                } else {
                    selectedImagePath = getPath.getPath(selectedImageUri, this);
                }

                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                bitmap1 = BitmapFactory.decodeFile(selectedImagePath, options);

                // MessageBox.Show(this, selectedImagePath);
                finalFile = new File(selectedImagePath);
                ProfilePic.setImageBitmap(bitmap1);
                filename=selectedImagePath.substring(selectedImagePath.lastIndexOf("/")+1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

My SimpleCropView Initialization in OnCreate:

CropImageView ProfilePic = (CropImageView) findViewById(R.id.cropImageView);

And for getting the Cropped Bitmap:

final Bitmap croppedImage = ProfilePic.getCroppedBitmap();
Shafayat Mamun
  • 439
  • 1
  • 6
  • 22
  • I have updated my answer. There are some methods that I used in the code for getting the accurate file path but you don't need them for right now. Just set the image to your cropimageview and get the cropped bitmap. – Shafayat Mamun Apr 17 '16 at 12:27
  • 1
    The image quality is considerably better than what i was getting earlier. The lib is really good. However, i will have to do some more work as i am getting crop tool inside the imageview instead of in the gallery on the selected pic and also sometimes i am unable to drag the handle of crop. But all in all, this lib really improved the quality of image! – Sagar Patel Apr 17 '16 at 14:05
-1

What i needed to do is just a little change as below:

intent.putExtra("outputX", 640);
                intent.putExtra("outputY", 640);

640 instead of 360 and it is done! We can still get width and height as of 360 dp in xml attribute but adjusting it here affects image quality. Replacing the 360 with 640 as mentioned, gave me desired image quality and way better than what i was getting earlier. So better to keep an average value here most images can have. However, if the value set here in intent as mentioned above is bigger than the original image, then there is a chance of having black pixel space surrounding the image that would be inside the imageview. So, we have to put the average value most images can have considering image quality as well.

Sagar Patel
  • 506
  • 1
  • 8
  • 23