【问题标题】:How to take a photo in Android, using full image size(not thumbnail) and compress the image to bytes?如何在 Android 中拍照,使用完整图像大小(不是缩略图)并将图像压缩为字节?
【发布时间】:2020-06-01 18:14:13
【问题描述】:

我不知道我是否做错了什么,也许我根本没有使用图像,或者我以错误的方式压缩图像,因为当我试图将它发送到服务器时,它回复我说大小超过 10 MB我的手机拍照 jpg 大约 7-9 MB(在 Edit.java 中我有一条评论,我之前使用缩略图但需要更改它,因为当我尝试在桌面上查看缩略图时,缩略图质量很差)

这是我的代码:

AndroidManifest.xml

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

    <uses-feature android:name="android.hardware.camera"></uses-feature>

<provider
            android:authorities="cam.com.example.fileprovider"
            android:name="android.support.v4.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_path"/>
        </provider>

file_path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">

    <external-path
        name="external"
        path="/"/>
    <external-files-path
        name="external_files"
        path="/"/>
    <cache-path
        name="cache"
        path="/"/>
    <external-cache-path
        name="external_cache"
        path="/"/>
    <files-path
        name="files"
        path="/"/>

</paths>

Edit.java

btn_image.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    REQUEST_IMAGE_CAPTURE = 1;
                    Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                    if (cameraIntent.resolveActivity(getPackageManager()) != null) {

                        File imageFile = null;
                        try{
                            imageFile=getImageFile();
                        }catch (IOException e){
                            e.printStackTrace();
                        }
                        if(imageFile!=null){
                            Uri imageUri = FileProvider.getUriForFile(Edit.this,"cam.com.example.fileprovider",imageFile);
                            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
                            startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);

                        }

                    }
                } catch (Exception e) {
                        Toasty.warning(getApplicationContext(), IC, Toast.LENGTH_SHORT, true).show();

                }
            }

        });



public File getImageFile() throws IOException{
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageName = "jpg_"+timeStamp+"_";
        File storageDir = getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);

        File imageFile = File.createTempFile(imageName,".jpg",storageDir);
        currentImagePath = imageFile.getAbsolutePath();
        return imageFile;
    }



    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            if (imagenString == null) {

                File imgFile = new File(currentImagePath);
                String path = imgFile.getAbsolutePath();
                Bitmap mybitmap = BitmapFactory.decodeFile(path);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                mybitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
                byte[] byteArray = byteArrayOutputStream.toByteArray();
                imagenString = Base64.encodeToString(byteArray, Base64.DEFAULT);

/* **Before I was doing this, but the thumbnail has such a bad quality so needed to change it**

                Bundle extras = data.getExtras();
                Bitmap imageBitmap = (Bitmap) extras.get("data");
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
                byte[] byteArray = byteArrayOutputStream.toByteArray();
                imagenString = Base64.encodeToString(byteArray, Base64.DEFAULT);*/
            }
        }
    }

【问题讨论】:

    标签: java android android-studio photo image-compression


    【解决方案1】:

    您正在使用用户选择的相机应用程序拍照。通常,这将保存为 JPEG 图像。 JPEG 图像是压缩图像格式,针对照片等“真实世界”图像进行了优化。

    然后您尝试将其全部读入内存。这不是一个好计划,因为您可能没有足够的内存来处理全尺寸照片。

    然后您尝试获取生成的Bitmap 并将其编码为PNG。 PNG 是一种压缩图像格式,但它是为图标和其他艺术品设计的。一张照片在 PNG 中几乎总是比在 JPEG 中占用更多空间。更糟糕的是,您正试图将其作为 PNG 编码到内存中——同样,您可能没有足够的内存来执行此操作。

    然后您尝试将编码的 PNG 转换为 base-64。这将占用比编码的 PNG 更多的空间,而且您可能没有足够的内存来处理它。

    我希望您的应用程序会因OutOfMemoryError 而崩溃很多。

    最好的解决方案是去掉大部分内容,直接从磁盘上传 JPEG。不要将其加载到内存中,不要将其转换为 PNG,也不要将其转换为 base-64。

    【讨论】:

      【解决方案2】:

      这是因为您将图像转换为 Base64 编码字符串,这使得数据的大小更大。

      在以下代码中,您使用值 100 进行压缩,100 是最小压缩和高质量。

      mybitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
      

      您可以尝试压缩更多图像,但它会降低质量:

      mybitmap.compress(Bitmap.CompressFormat.PNG, 70, byteArrayOutputStream);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-24
        • 2015-11-28
        • 2012-01-06
        • 2016-01-29
        • 2013-09-03
        相关资源
        最近更新 更多