从相册和相机选择图片以及图片压缩和android7.0相机

从相册去图片

调用相机拍照

图片的压缩

 

布局

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/button_fith"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="相册" />

    <Button
        android:id="@+id/button_camber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="相机" />

    <ImageView
        android:id="@+id/iv"
        android:layout_width="250dp"
        android:layout_height="250dp" />
</LinearLayout>

 

 

 

 

代码

 

public class MainActivity extends AppCompatActivity {
    public static final int CAMERA = 1;
    public static final int PHONE = 2;
    private ImageView iv;
    private Uri imageuri;
    private File outPutImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button photo = (Button) findViewById(R.id.button_fith);
        Button camera = (Button) findViewById(R.id.button_camber);
        iv = (ImageView) findViewById(R.id.iv);
        photo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ContextCompat.checkSelfPermission(MainActivity.this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{
                            Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                } else {
                    openAibum();
                }
            }


        });
        assert camera != null;
        camera.setOnClickListener(new View.OnClickListener() {


            @Override
            public void onClick(View v) {
                //创建File对象,用于存储拍照后的图片
                outPutImage = new File(getExternalCacheDir(), "output_image.jpg");

                try {
                    if (outPutImage.exists()) {
                        outPutImage.delete();
                    }
                    outPutImage.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (Build.VERSION.SDK_INT >= 24) {//
                    imageuri = FileProvider.getUriForFile(MainActivity.this,
                            "com.example.cameraalbumtest.fileprovider", outPutImage);
                } else {
                    imageuri = Uri.fromFile(outPutImage);
                }
                //启动相机
                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri);
                startActivityForResult(intent, CAMERA);

            }
        });
    }

    /**
     * 打开相册
     */
    private void openAibum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        startActivityForResult(intent, PHONE);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    openAibum();
                } else {
                    Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case PHONE:

                if (resultCode == RESULT_OK) {
                    if (Build.VERSION.SDK_INT >= 19) {
                        handleImageKitKat(data);
                    } else {
                        handleImageBeforeKitKat(data);
                    }
                }
                break;
            case CAMERA:
                if (resultCode == RESULT_OK) {
                    try {
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageuri));
                        iv.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }

                }
                break;
            default:
                break;
        }
    }


    /**
     * 大于= API 19 de
     *
     * @param data
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    private void handleImageKitKat(Intent data) {
        String imagePath = null;
        Uri uri = data.getData();
        if (DocumentsContract.isDocumentUri(this, uri)) {
            //如果是document 类型的URI,则通过document Id处理;
            String docId = DocumentsContract.getDocumentId(uri);
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                String id = docId.split(":")[1];//解析出数字格式的id
                String selection = MediaStore.Images.Media._ID + "=" + id;
                imagePath = getImagetPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
            } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
                imagePath = getImagetPath(contentUri, null);
            }

        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            imagePath = getImagetPath(uri, null);

        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            imagePath = uri.getPath();
        }
        Log.d("TAG", "imagePath" + imagePath);
        displayImage(imagePath);//根据图片路径显示图片
    }

    /**
     * * 小于 API 19 de
     *
     * @param data
     */
    private void handleImageBeforeKitKat(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagetPath(uri, null);
        Log.d("TAG", "imagePath" + imagePath);
        displayImage(imagePath);//根据图片路径显示图片
    }


    private String getImagetPath(Uri uri, String selection) {
        String path = null;
        //通过Uri和selection来获取真实的图片路径
        Cursor cuesor = getContentResolver().query(uri, null, selection, null, null);
        if (cuesor != null) {
            if (cuesor.moveToFirst()) {
                path = cuesor.getString(cuesor.getColumnIndex(MediaStore.Images.Media.DATA));
            }
            cuesor.close();
        }
        return path;
    }

    private void displayImage(String imagePath) {
        if (imagePath != null) {

            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            Log.d("TAG1", "bitmap压缩前占用空间大小:" + bitmap.getByteCount() / 1024 / 1024 + "M"
                    + "  宽:" + bitmap.getWidth() + "  高:" + bitmap.getHeight());
            qualityCompression(bitmap, 30);
            SamplingRateCompression(imagePath);
            matrixCompression(bitmap);
            geshiCompression(imagePath);
            createScaledBitmapCompression(bitmap);
            iv.setImageBitmap(bitmap);
            Log.d("TAG", "bitmap:" + bitmap);
        } else {
            Toast.makeText(this, "failed to get image", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 可以用图片框架加载
     * @param imagePath
     */
    private void displayImage1(String imagePath) {
        if (imagePath != null) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(imagePath,options);
            int outHeight = options.outHeight;
            int outWidth = options.outWidth;
            options.inJustDecodeBounds = false;


        } else {
            Toast.makeText(this, "failed to get image", Toast.LENGTH_SHORT).show();
        }
    }


    /**
     * 中图片是以bitmap形式存在的,那么bitmap所占内存,直接影响到了应用所占内存大小,首先要知道bitmap所占内存大小计算方式:

     图片长度 x 图片宽度 x 一个像素点占用的字节数

     以下是图片的压缩格式:

     这里写图片描述

     其中,A代表透明度;R代表红色;G代表绿色;B代表蓝色。

     ALPHA_8
     表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度
     ARGB_4444
     表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节
     ARGB_8888
     表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节
     RGB_565
     表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节


     可以看到,图片的大小是没有变的,因为质量压缩不会减少图片的像素,它是在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的,这也是为什么该方法叫质量压缩方法。那么,图片的长,宽,像素都不变,那么bitmap所占内存大小是不会变的。

     但是我们看到bytes.length是随着quality变小而变小的。这样适合去传递二进制的图片数据,比如微信分享图片,要传入二进制数据过去,限制32kb之内。

     这里要说,如果是bit.compress(CompressFormat.PNG, quality, baos);这样的png格式,quality就没有作用了,bytes.length不会变化,因为png图片是无损的,不能进行压缩。
     */

    /**
     * 质量压缩
     *
     * @param bitmap
     * @param quality 30 压缩70%
     */
    private void qualityCompression(Bitmap bitmap, int quality) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        byte[] bytes = baos.toByteArray();
        Bitmap bit = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        Log.d("TAG1", "压缩后图片的大小:" + (bit.getByteCount() / 1024 / 1024)
                + "M  宽度为:" + bit.getWidth() + "  高度为:" + bit.getHeight()
                + "  bytes.length:" + (bytes.length / 1024) + "KB"
                + "  压缩率:" + quality);
    }

    /**
     * 设置inSampleSize的值(int类型)后,假如设为2,则宽和高都为原来的1/2,宽高都减少了,自然内存也降低了。

     我上面的代码没用过options.inJustDecodeBounds = true; 因为我是固定来取样的数据,为什么这个压缩方法叫采样率压缩,是因为配合inJustDecodeBounds,先获取图片的宽、高【这个过程就是取样】,然后通过获取的宽高,动态的设置inSampleSize的值。

     当inJustDecodeBounds设置为true的时候,BitmapFactory通过decodeResource或者decodeFile解码图片时,将会返回空(null)的Bitmap对象,这样可以避免Bitmap的内存分配,但是它可以返回Bitmap的宽度、高度以及MimeType。
     */
    /**
     * 采样率压缩
     * @param imagePath
     */
    private void SamplingRateCompression(String imagePath) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;

        Bitmap bit = BitmapFactory.decodeFile(imagePath, options);
        Log.d("TAG1", "压缩后图片的大小:" + (bit.getByteCount() / 1024 / 1024)
                + "M  宽度为:" + bit.getWidth() + "  高度为:" + bit.getHeight());
    }

    /**
     * 可以看出来,bitmap的长度和宽度分别缩小了一半,图片大小缩小了四分之一。
     * 缩放法压缩
     * @param bitmap
     */
    private void matrixCompression(Bitmap bitmap) {
        Matrix matrix = new Matrix();
        matrix.setScale(0.5f, 0.5f);
        Bitmap bit = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, true);
        Log.d("TAG1", "压缩后图片的大小:" + (bit.getByteCount() / 1024 / 1024)
                + "M  宽度为:" + bit.getWidth() + "  高度为:" + bit.getHeight());

    }

    /**
     * 我们看到图片大小直接缩小了一半,长度和宽度也没有变,相比argb_8888减少了一半的内存。

     注意:由于ARGB_4444的画质惨不忍睹,一般假如对图片没有透明度要求的话,可以改成RGB_565,相比ARGB_8888将节省一半的内存开销
     * .RGB_565法
     * @param imagePath
     */
    private void geshiCompression(String imagePath) {
        BitmapFactory.Options options2 = new BitmapFactory.Options();
        options2.inPreferredConfig = Bitmap.Config.RGB_565;

        Bitmap bit = BitmapFactory.decodeFile(imagePath, options2);
        Log.d("TAG1", "压缩后图片的大小:" + (bit.getByteCount() / 1024 / 1024)
                + "M  宽度为:" + bit.getWidth() + "  高度为:" + bit.getHeight());
    }
    private void createScaledBitmapCompression(Bitmap bitmap) {
        Bitmap bit = Bitmap.createScaledBitmap(bitmap, 150, 150, true);
        Log.d("TAG1", "压缩后图片的大小:" + (bit.getByteCount() / 1024 )
                + "k  宽度为:" + bit.getWidth() + "  高度为:" + bit.getHeight());
    }


}

 

适配7.0 FileUriExposeException 异常 https://blog.csdn.net/qq_35698774/article/details/107007405

 

权限

 

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

 

转发表明出处:https://blog.csdn.net/qq_35698774/article/details/74358793

android互助群:

感谢:郭霖的《第一行代码 第二版》

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大不懂

码字不易,一块也是爱,么么

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值