Намерение галереи Android: как я могу получить и установить оригинальное обрезанное изображение с полным размером и хорошим качеством вместо эскиза?

Ниже приведен мой вид деятельности по редактированию профиля, где я даю пользователю возможность установить изображение профиля из галереи. Когда пользователь щелкает, чтобы отредактировать изображение профиля, он открывает галерею, обрезает выбранное изображение, обрезанное изображение будет сохранено в заранее определенном месте, а также во временном местоположении, обрезанное изображение будет установлено как изображение профиля. Тем не менее, он всегда получает миниатюру или изображение низкого качества. Качество изображения такое же, как и то, как мы передаем изображение в намерение через URI, а затем получаем URI этого изображения с помощью getData, а затем настраиваем изображение с помощью setImageUri, потому что таким образом оно даст миниатюру, а не исходное изображение., Вот почему я попытался сначала сохранить это обрезанное изображение, а затем получить его оттуда. Даже чтобы избежать ошибки OOM (Out of Memory), я попытался отрегулировать качество изображения и сжатие, используя inSampleSize, опцию фабрики растровых изображений и все такое... но в конце я получаю всегда одинаковое качество миниатюрных изображений!

То, что я хочу, как сказано в заголовке, оригинальное обрезанное изображение для userImageView, а не вид миниатюры или изображения с низким разрешением!

Также учтите, что я новичок в разработке для Android, а также в программировании, кодировании и прочем!

Любая помощь будет оценена!

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;
    }

}

2 ответа

Решение

Посмотрите, поможет ли эта библиотека. https://github.com/IsseiAoki/SimpleCropView

Это может сохранить качество исходного изображения.

Редактировать:

Хм, они могли обновить библиотеку. Я использую старую библиотеку SimpleCropView. Вот моя реализация.

Для выбора картинки с устройства.:

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

Затем на Результат деятельности:

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();
            }
        }

Моя инициализация SimpleCropView в OnCreate:

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

И для получения обрезанного растрового изображения:

final Bitmap croppedImage = ProfilePic.getCroppedBitmap();

То, что мне нужно было сделать, это просто небольшое изменение, как показано ниже:

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

640 вместо 360 и готово! Мы все еще можем получить ширину и высоту на уровне 360 dp в атрибуте xml, но его настройка влияет на качество изображения. Замена 360 на 640, как уже упоминалось, дала мне желаемое качество изображения и намного лучше, чем то, что я получал ранее. Поэтому лучше сохранить среднее значение, которое может иметь большинство изображений. Однако, если значение, установленное здесь в намерении, как упомянуто выше, больше, чем исходное изображение, тогда есть вероятность наличия черного пиксельного пространства вокруг изображения, которое будет внутри просмотра изображения. Таким образом, мы должны указать среднее значение, которое может иметь большинство изображений, учитывая качество изображения.

Другие вопросы по тегам