繁体   English   中英

Android 将 bitmap 保存到图像文件

[英]Android save bitmap to image file

如何将 bitmap 保存到图像文件? (png/jpg 任何类型都不在乎...)

我正在运行设备(海思)和 android 应用程序。
Android 和设备正在通过 sockets 进行通信。
设备发送图像 (h.264) 并在 TextureView 上的 Android 上显示。
我可以使用textureView.getBitmap()从 TextureView 获取 Bitmap 。


我做了一个按钮按钮来保存图片, textureView.getBitmap()

<Button
  android:id="@+id/btnSavePng"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:onClick="onBtnSavePng"
  android:text="savePicture" />

并且,onclick function 如下。


public String getCurrentTimeString() {
  int yyyy = Calendar.getInstance().get(Calendar.YEAR);
  int MM = Calendar.getInstance().get(Calendar.MONTH) + 1;
  int dd = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
  int hh = Calendar.getInstance().get(Calendar.HOUR);
  int mm = Calendar.getInstance().get(Calendar.MINUTE);
  int ss = Calendar.getInstance().get(Calendar.SECOND);
  
  String result = yyyy+"-"+MM+"-"+dd+" "+hh+":"+mm+":"+ss;
  return result;
}

public void onBtnSavePng(View view) {
  try {
    File storage = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
    String fname = getCurrentTimeString() + ".jpg";
    File tp = new File(storage, fname);
    Bitmap bm = textureView.getBitmap();
    tp.createNewFile(); // Result of File.createNewFile() ignored

    FileOutputStream ot = new FileOutputStream(tp);
    bm.compress(Bitmap.CompressFormat.JPEG, 100, ot);
    ot.close();
  } catch(Exception e) {
    Log.d("onBtnSavePng", e.toString()); // java.io.IOException: Operation not permitted
  }
}

我允许使用权限AndroidManifest.xml如下,并且android:requestLegacyExternalStorage="true"正在申请中。

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

我的代码有问题吗?

如果是这样,如何将 bitmap 保存为 png 或 jpg 文件?

我想,我的应用程序无法访问目录。

感谢您阅读我的问题。


自我解决。


public void onBtnSavePng(View view) {
  try {
    String root = Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES).toString();
    File myDir = new File(root + "/saved_images");
    myDir.mkdirs();
    String fname = getCurrentTimeString() + ".jpg";
    File file = new File(myDir, fname);

    FileOutputStream out = new FileOutputStream(file);
    Bitmap bm = textureView.getBitmap();
    bm.compress(Bitmap.CompressFormat.JPEG, 100, out);
    out.flush();
    out.close();
  } catch( Exception e) {
    Log.d("onBtnSavePng", e.toString());
  }

我不明白为什么我的代码还没有工作。
无论如何,感谢所有帮助我的人。
我会尝试所有的回复代码。

谢谢你。

1.如果您还没有请求运行时权限,请检查它: https://developer.android.com/training/permissions/requesting

2.或者如果您的 android 高于 10: https://developer.android.com/about/versions/11/privacy/storage#scoped

  • 在您更新应用程序以定位 Android 11 后,系统将忽略 requestLegacyExternalStorage 标志。

然后您必须使用 SAF 或 MediaStore API 将 bitmap 存储在“公共目录”中。

SAF: https://developer.android.com/guide/topics/providers/document-provider

MediaStore API: https://developer.android.com/reference/android/provider/MediaStore

public void onBtnSavePng(View view) {
    try {
        String fileName = getCurrentTimeString() + ".jpg";

        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/");
            values.put(MediaStore.MediaColumns.IS_PENDING, 1);
        } else {
            File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
            File file = new File(directory, fileName);
            values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
        }

        Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

        try (OutputStream output = getContentResolver().openOutputStream(uri)) {
            Bitmap bm = textureView.getBitmap();
            bm.compress(Bitmap.CompressFormat.JPEG, 100, output);
        }
    } catch (Exception e) {
        Log.d("onBtnSavePng", e.toString()); // java.io.IOException: Operation not permitted
    }
}
 String myDir =new File (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)+pdfDirectoryImage);
            fileName = filename + ".png";
            androidElevenPath = saveImages(mContext,finalBitmap,filename);

 private static Uri saveImages(Context mContext, Bitmap bitmap, @NonNull String name) throws IOException {
        boolean saved;
        OutputStream fos;
        File image = null;
        Uri imageUri = null;
        String imagesDir = null;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ContentResolver resolver = mContext.getContentResolver();
            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
            contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
            contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM" + pdfDirectoryImage);
             imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
            fos = resolver.openOutputStream(imageUri);
        } else {
             imagesDir = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DCIM).toString() + File.separator + pdfDirectoryImage;

            File file = new File(imagesDir);

            if (!file.exists()) {
                file.mkdir();
            }

             image = new File(imagesDir, name + ".png");
            fos = new FileOutputStream(image);

        }

        saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
        return imageUri;
    }

如果您使用的是 Android11+ 并且您已授予存储管理器权限并直接处理文件(而不是 MediaStore API),则原因可能是创建文件名称中的“:”字符(通常来自时间戳)。 Android 11(与旧的 Android 版本不同)不允许这样做。

在 kotlin这对我有用->

fun saveMediaToStorage(bitmap: Bitmap, context: Context, onUriCreated: (Uri) -> Unit) {
var fos: OutputStream? = null

//Generating a file name
val filename = "${System.currentTimeMillis()}.jpg"

try {
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
        val resolver = context.contentResolver
        val contentValues = ContentValues()
        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "$filename.jpg")

        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
        val imageUri =
            resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
        fos = Objects.requireNonNull(imageUri)?.let {
            resolver.openOutputStream(it)
        }

        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
        Objects.requireNonNull(fos)

        imageUri?.let { onUriCreated(it) }
    } else {
        //These for devices running on android < Q
        val imagesDir =
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
        val image = File(imagesDir, filename)
        fos = FileOutputStream(image)

        fos.use {
            //Finally writing the bitmap to the output stream that we opened
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)
        }

        onUriCreated(Uri.fromFile(image))
    }
} catch (e: Exception) {
    Log.d("error", e.toString())
}

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM