You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发中如何将设备拍摄的照片转换为base64且保证画质

安卓拍照获取全尺寸原图转Base64解决方案

问题原因

你当前代码中通过data.getExtras().get("data")获取的Bitmap是系统返回的拍照缩略图,本身分辨率极低,所以不管怎么调整压缩参数都无法得到高清画质,这是导致画质差的核心原因。

实现方案

要获取全尺寸原图,需要给相机Intent指定输出Uri,让相机直接将全尺寸照片写入你预设的临时文件,后续直接读取该文件的字节流转Base64即可,全程无需经过Bitmap处理,完全保留原图画质。

完整实现代码

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Base64;
import android.widget.Button;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends Activity {
    ImageView imageV, imageV2;
    Button btn, btn2;
    static final int IMAGE_REQUEST = 1;
    static final int IMAGE_REQUEST2 = 2;
    private Uri currentPhotoUri1, currentPhotoUri2; // 存储全尺寸照片的输出Uri

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageV = findViewById(R.id.image_view);
        imageV2 = findViewById(R.id.image_view_2);
        btn = findViewById(R.id.button);
        btn2 = findViewById(R.id.button2);

        btn.setOnClickListener(view -> {
            Intent takePhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (takePhoto.resolveActivity(getPackageManager()) != null) {
                File photoFile = null;
                try {
                    photoFile = createImageFile();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                if (photoFile != null) {
                    currentPhotoUri1 = FileProvider.getUriForFile(this,
                            getPackageName() + ".fileprovider",
                            photoFile);
                    takePhoto.putExtra(MediaStore.EXTRA_OUTPUT, currentPhotoUri1);
                    startActivityForResult(takePhoto, IMAGE_REQUEST);
                }
            }
        });

        btn2.setOnClickListener(view -> {
            Intent takePhoto2 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (takePhoto2.resolveActivity(getPackageManager()) != null) {
                File photoFile = null;
                try {
                    photoFile = createImageFile();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                if (photoFile != null) {
                    currentPhotoUri2 = FileProvider.getUriForFile(this,
                            getPackageName() + ".fileprovider",
                            photoFile);
                    takePhoto2.putExtra(MediaStore.EXTRA_OUTPUT, currentPhotoUri2);
                    startActivityForResult(takePhoto2, IMAGE_REQUEST2);
                }
            }
        });
    }

    // 创建临时照片文件
    private File createImageFile() throws IOException {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        return File.createTempFile(
                imageFileName,
                ".jpg",
                storageDir
        );
    }

    // 直接从Uri读取文件转Base64,不经过Bitmap处理
    private String uriToBase64(Uri uri) throws IOException {
        File file = new File(uri.getPath());
        FileInputStream fis = new FileInputStream(file);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = fis.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        fis.close();
        byte[] imageBytes = bos.toByteArray();
        return Base64.encodeToString(imageBytes, Base64.DEFAULT);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            try {
                if (requestCode == IMAGE_REQUEST) {
                    String imageB64 = uriToBase64(currentPhotoUri1);
                    // 此处可直接将imageB64上传至数据库
                    imageV.setImageURI(currentPhotoUri1); // 可选:显示全尺寸图片
                } else if (requestCode == IMAGE_REQUEST2) {
                    String image2B64 = uriToBase64(currentPhotoUri2);
                    // 此处可直接将image2B64上传至数据库
                    imageV2.setImageURI(currentPhotoUri2); // 可选:显示全尺寸图片
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

补充注意事项

  • 安卓7.0及以上版本需要在AndroidManifest.xml中配置FileProvider,示例配置如下:
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
    
    同时在res/xml目录下创建file_paths.xml文件:
    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-files-path name="pictures" path="Pictures/" />
    </paths>
    
  • 如果确实需要经过Bitmap处理再转Base64,可以在压缩时将quality参数设为100,同时加载Bitmap时使用inSampleSize=1不做采样压缩,也能最大程度保留画质。
  • 临时照片文件如果不需要长期保留,上传完成后可以手动删除,避免占用用户存储空间。

内容的提问来源于stack exchange,提问作者Rick V

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 02:06:11