【发布时间】: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