【问题标题】:Best practices and code to upload image to firebase storage将图像上传到 Firebase 存储的最佳做法和代码
【发布时间】:2018-01-31 11:15:31
【问题描述】:

我使用了 3 种不同的代码来测试上传到 Firebase 存储的图像文件的大小。 (图片的原始大小为 12.3 MB)

first 代码将 uri 转换为位图并将其放置在 ImageView 上,将其压缩为 PNG 格式,最后将图像上传到 firebase 存储。

上传格式:.PNG。上传后大小:14.82 MB。

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 2 && resultCode == RESULT_OK) {

            Uri uri = data.getData();

            try {
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), uri);
                mImageView.setImageBitmap(bitmap);
            } catch (IOException e) {
                e.printStackTrace();
            }

            String randomName = UUID.randomUUID().toString() + ".png";

            StorageReference filePath = mStorage.child("feed_photos").child(randomName);

            mImageView.setDrawingCacheEnabled(true);
            mImageView.buildDrawingCache();
            Bitmap bitmap2 = ((BitmapDrawable) mImageView.getDrawable()).getBitmap();

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            bitmap2.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
            mImageView.setDrawingCacheEnabled(false);
            byte[] data2 = outputStream.toByteArray();

            UploadTask uploadTask = filePath.putBytes(data2);

            progressDialog.setMessage("uploading...");
            progressDialog.show();

            uploadTask.addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception exception) {
                    Toast.makeText(getContext(), "UPLOAD FAILED", Toast.LENGTH_SHORT).show();
                }
            }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                    progressDialog.dismiss();
                }
            });
        }
    }

第二个代码与第一个代码相同,但将其转换为 JPEG。

上传的格式为 .JPEG。上传后大小为 5.58 MB。

第二个代码与第一个代码的区别:

bitmap2.compress(Bitmap.CompressFormat.JPEG, 100, outputStream); //JPEG this time!

第三个代码直接将图片从手机存储上传到firebase存储。

上传的格式为 .JPEG。上传后大小为 3.41 MB。

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 2 && resultCode == RESULT_OK) {

            Uri uri = data.getData();

            String randomName = UUID.randomUUID().toString() + ".png";

            StorageReference filePath = mStorage.child("feed_photos").child(randomName);

            UploadTask uploadTask = filePath.putFile(uri);

            progressDialog.setMessage("uploading...");
            progressDialog.show();

            uploadTask.addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception exception) {
                    Toast.makeText(getContext(), "UPLOAD FAILED", Toast.LENGTH_SHORT).show();
                }
            }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                    progressDialog.dismiss();
                }
            });
        }

上传后,我对比了firebase storage中的三张图片,三张图片的质量似乎没有什么区别。这就提出了一个问题,为什么在较小的 JPEG 图像尺寸(Q1)的情况下上传 PNG?此外,即使是 3.41 MB 的最小文件大小也相当大,特别是如果该应用程序拥有大量用户群并定期上传图像。在这种情况下,保持图像质量可与 Whatsapp (Q2) 相媲美的普遍接受的要存储的图像大小是多少。

另外,在第三个代码中,我没有写任何压缩代码。但是,无论如何,它似乎以最小的图像大小上传。那么为什么教程边界甚至首先压缩图像(Q3)? (原始图像大小为 12.3 MB)

这些问题让我很困惑,我应该使用什么代码和最佳实践将图像上传到 Firebase 存储。

我希望我的应用做什么(主要问题):

用户从手机的图片库中选择图片,图片会弹出到 ImageView 上,这样用户就可以为其添加标题作为元数据。当用户确认后,图像及其元数据将上传到 Firebase 存储。 ImageView 和下载后的图像质量可能与 Whatsapp 的图像相当。因此,实现这一目标的正确代码和最佳实践是什么?如果在主要问题之前先回答前 3 个问题(Q1、2 和 3)会很有帮助。很抱歉,因为我是 android 开发的新手并且是自学的。提前致谢!

补充:我还没有谈到从 firebase 存储中下载图像,但我打算使用带有 glide 的 firebaseui 来完成。希望没问题。

【问题讨论】:

    标签: android image file-upload bitmap firebase-storage


    【解决方案1】:

    1)PNG 是无损的。 jpg是有损压缩。这意味着 PNG 可以精确地解码为原始图像,而 jpg 则不能(数据和质量会在压缩中丢失)。如果您有想要保持最高质量的文件,则需要 PNG。请注意,根据您保存 jpg 的 Q 因子和图像类型,您可能看不到明显的质量差异。

    2)您将其保存为 JPG 和 PNG。这些已经是压缩文件格式。完全解压的 bmp 文件更大。

    3)上传任务用什么Q因子保存数据?我的猜测相当低。这对于某些类型的图像很好。但是 Q 因子越低,文件越小(但压缩损失越大)。不知道这一点,你就不是在比较相同的东西。

    【讨论】:

    • 但是为什么我手动压缩的 JPEG 和 PNG 图像比我直接从图库存储上传的 JPEG 大?这是因为Q因子吗?这个我不太明白。
    • 您是否使用与手动压缩相同的 Q 因子进行压缩?预计 PNG 比 JPG 更大,甚至比 JPG 大得多 - 无损压缩比相同数据的有损更大。另外,您是压缩相同的原始图像还是解压缩并重新压缩(对于 JPG,这实际上每次都会更改图像,因为有损压缩的有损压缩会导致更多的数据丢失)。
    • 我每次从存储中选择相同的图像。这是我知道的全部。另外,我不知道什么或如何使用 Q 因子。
    • Q 因子是量化因子,缩放质量因子,1 到 100 之间的值。越高,jpg 越准确(但文件越大)。在 itmap2.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);它是中间变量。可以在en.wikipedia.org/wiki/JPEG 找到不同 Q 和结果大小的图像示例
    • 有时差别不大。这取决于图像是什么,以及它与压缩算法的配合程度(这是我的工资等级以上的数学来解释)。但是,是的,如果 JPG 神奇地从 12 MB 跃升至 3MB,它会以更高的压缩率重新压缩。没有其他方法可以做到这一点。
    猜你喜欢
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 2017-09-25
    • 2021-09-18
    相关资源
    最近更新 更多