-3

下面是我的编辑个人资料活动,我为用户提供了从图库中设置个人资料图片的选项。当用户单击编辑个人资料图片时,它会打开图库,裁剪所选图像,裁剪后的图像将保存在预定义的位置以及临时位置,裁剪后的图像将设置为个人资料图片。但是,它总是得到缩略图或低质量的图像。图像的质量与我们如何通过 uri 将图像传递到意图中然后使用 getData 获取该图像 uri 然后使用 setImageUri 设置图像一样,因为这样它会给出缩略图而不是原始图像. 这就是为什么我首先尝试保存裁剪后的图像,然后从那里获取它。甚至为了避免 OOM(内存不足)错误,我尝试使用 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;
    }

}
4

2 回答 2

4

看看这个库是否有帮助。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();
            }
        }

我在 OnCreate 中的 SimpleCropView 初始化:

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

并获取裁剪位图:

final Bitmap croppedImage = ProfilePic.getCroppedBitmap();
于 2016-04-17T10:35:12.703 回答
-1

我需要做的只是一点点改变,如下所示:

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

640 代替 360 就完成了!我们仍然可以在 xml 属性中获取 360 dp 的宽度和高度,但在这里调整它会影响图像质量。如前所述,用 640 替换 360,给了我想要的图像质量,并且比我之前得到的要好得多。所以最好在这里保持大多数图像可以具有的平均值。但是,如果在上面提到的意图中设置的值大于原始图像,则有可能在图像周围存在黑色像素空间,该空间将位于 imageview 内部。因此,我们必须将大多数图像的平均值也考虑到图像质量。

于 2016-04-18T17:54:35.873 回答