【问题标题】:Different number of bytes when storing images to Android Q vs previous versions将图像存储到 Android Q 时的字节数与以前的版本不同
【发布时间】:2021-09-17 12:49:29
【问题描述】:

我们有一个我们不完全了解的情况。在我们的应用程序中,用户选择图像,这些图像保存到光盘并映射到他们的图片文件夹。然后当用户准备好上传选中的图片时,我们使用ByteArrayOutputStream将它们分别变成一个字节数组,然后再变成一串十六进制字符。到目前为止,即使在数据覆盖率低的领域,这种方法也很有效。

我们将图像保存到光盘的过程(为清晰起见,通常在 Stack Overflow 中找到)是:

ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
            imageDir = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "temp", null);
            bytes.close();

由于MediaStore.Images.Media.insertImage 已被弃用,我们已开始查看Android Q 及更高版本的代码:

ContentValues values = new ContentValues();
            values.put(MediaStore.Images.Media.DISPLAY_NAME, "location_image.jpg");
            values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
            values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);

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

            OutputStream imageOutStream = inContext.getContentResolver().openOutputStream(uri);

            imageDir = String.valueOf( uri );
            Boolean b = inImage.compress(Bitmap.CompressFormat.JPEG, 100, imageOutStream);

            imageOutStream.close();

但是,当我们使用ByteArrayOutputStream 来上传使用 Q 及更高版本的这个新进程存储的图像时,数组是 3-4 大,这反过来又会扰乱我们的数据上传过程。例如,在旧进程 (=Q) 中它会膨胀到 1.4M。

这是为什么呢??

我们可以将新进程中的 JPEG 质量降低到 80-90%,并且会得到与旧进程相同长度的字节数组。

【问题讨论】:

  • 仅根据您的描述,我的猜测是以前的 Android 版本将质量参数限制在 ~80-90,而较新的版本实际上在超过 100 时使用 100。普通 1080x1080 的 JPEG 照片质量为 100应该在至少 1.4M 的数量级上,这似乎是合理的。如果你之前有 380k,那么这表明 100 并没有真正使用。
  • insertImage() 方法将图像保存为 50%:android.googlesource.com/platform/frameworks/base/+/…。一直都是这样,AFAIK。
  • @MikeM.:这很有意义。它表明原始代码中的 100 是无关紧要的(实际上在这种情况下整个 compress 调用毫无意义),如果 OP 希望在新版本中具有相同的质量,他们也应该使用 50 的质量值。跨度>
  • @user3398945:据我所知compress 根本不会影响inImage 本身。它所做的只是将压缩的 JPEG 版本写入bytes(然后您似乎没有做任何事情)。因此,在上面的代码中,它似乎完全没有意义,应该在不替换的情况下删除。
  • 好的。但是,一旦您创建了调整大小的文件,就无需使用中间位图来上传调整大小的文件。而且我也不会在上传时对文件进行十六进制编码,因为你必须传输两倍的字节。

标签: java android mediastore


【解决方案1】:

@Mike M 在上述 cmets 中提供的答案。

insertImage 总是将质量设置为 50%,新代码只需要匹配即可:

Boolean b = inImage.compress(Bitmap.CompressFormat.JPEG, 50, imageOutStream);

最好在旧(已弃用)代码中删除:

inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

因为它没有真正的功能。

在这两种情况下,某些运行 Android 10 的机型可能会遇到图片标题不唯一的问题。所以它有助于将它们更改为:

"image_" + System.currentTimeMillis()+".jpg"

【讨论】:

    猜你喜欢
    • 2014-03-28
    • 1970-01-01
    • 2022-12-18
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 2015-06-25
    • 2020-08-19
    相关资源
    最近更新 更多