Android:如何将压缩图像转换为最小大小的字符串

2024-06-27

在我的android应用程序中,我使用whatsapp之类的图像压缩,之后我使用Base64编码将压缩图像位图转换为字符串,我注意到当我压缩5mb图像并将其保存在另一个位置时,它只是60kb或70kb的东西就像这样,同一张图像的 Base64 编码字符串需要 500kb 或 600kb,为什么会这样呢?有什么方法可以将压缩图像转换为具有相同大小的字符串。下面是我的代码。

Bitmap bitmapImg;

    if (requestCode == FILE_SELECT_CODE) {
        if(data!= null) {
            try {
                Uri selectedImageUri = data.getData();
                String mimeType = getContentResolver().getType(selectedImageUri);

                compressImage(selectedImageUri);

            // Converting compressed bitmap to string
                ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
                bitmapImg.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOS);
                String strBitmap = Base64.encodeToString(byteArrayOS.toByteArray(), Base64.DEFAULT);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    private String compressImage(Uri selImageUri) {
        String fileStrName = null;
        bitmapImg = null;
        try {
            String filePath = getRealPathFromURI(selImageUri);
            BitmapFactory.Options options = new BitmapFactory.Options();

    //      by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
    //      you try the use the bitmap here, you will get null.
            options.inJustDecodeBounds = true;
            Bitmap bmpTemp = BitmapFactory.decodeFile(filePath, options);

            int actualHeight = options.outHeight;
            int actualWidth = options.outWidth;

    //      max Height and width values of the compressed image is taken as 816x612

            float maxHeight = 816.0f;
            float maxWidth = 612.0f;
            float imgRatio = actualWidth / actualHeight;
            float maxRatio = maxWidth / maxHeight;

    //      width and height values are set maintaining the aspect ratio of the image

            if (actualHeight > maxHeight || actualWidth > maxWidth) {
                if (imgRatio < maxRatio) {
                    imgRatio = maxHeight / actualHeight;
                    actualWidth = (int) (imgRatio * actualWidth);
                    actualHeight = (int) maxHeight;
                } else if (imgRatio > maxRatio) {
                    imgRatio = maxWidth / actualWidth;
                    actualHeight = (int) (imgRatio * actualHeight);
                    actualWidth = (int) maxWidth;
                } else {
                    actualHeight = (int) maxHeight;
                    actualWidth = (int) maxWidth;
                }
            }

    //      setting inSampleSize value allows to load a scaled down version of the original image

            options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
    //      inJustDecodeBounds set to false to load the actual bitmap

            options.inJustDecodeBounds = false;

    //      this options allow android to claim the bitmap memory if it runs low on memory

            options.inPurgeable = true;
            options.inInputShareable = true;
            options.inTempStorage = new byte[16 * 1024];

            try {
    //          load the bitmap from its path

                bmpTemp = BitmapFactory.decodeFile(filePath, options);
            } catch (OutOfMemoryError exception) {
                exception.printStackTrace();
            }
            try {
                bitmapImg = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
            } catch (OutOfMemoryError exception) {
                exception.printStackTrace();
            }

            float ratioX = actualWidth / (float) options.outWidth;
            float ratioY = actualHeight / (float) options.outHeight;
            float middleX = actualWidth / 2.0f;
            float middleY = actualHeight / 2.0f;

            Matrix scaleMatrix = new Matrix();
            scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);

            Canvas canvas = new Canvas(bitmapImg);
            canvas.setMatrix(scaleMatrix);
            canvas.drawBitmap(bmpTemp, middleX - bmpTemp.getWidth() / 2, middleY - bmpTemp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));

    //      check the rotation of the image and display it properly

            ExifInterface exif;
            try {
                exif = new ExifInterface(filePath);

                int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
                Matrix matrix = new Matrix();
                if (orientation == 6) {
                    matrix.postRotate(90);
                } else if (orientation == 3) {
                    matrix.postRotate(180);
                } else if (orientation == 8) {
                    matrix.postRotate(270);
                }
                bitmapImg = Bitmap.createBitmap(bitmapImg, 0, 0, bitmapImg.getWidth(), bitmapImg.getHeight(), matrix, true);
            } catch (IOException e) {
                e.printStackTrace();
            } 
            FileOutputStream out = null;
            String filename = getFilename();
            try {
                out = new FileOutputStream(filename);

    //          write the compressed bitmap at the destination specified by filename.
                bitmapImg.compress(Bitmap.CompressFormat.JPEG, 80, out);

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return fileStrName;
    }

    public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height/ (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        final float totalPixels = width * height;
        final float totalReqPixelsCap = reqWidth * reqHeight * 2;
        while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
            inSampleSize++;
        }

        return inSampleSize;
    }

    private String getRealPathFromURI(Uri contentUri) {
        Cursor cursor = getContentResolver().query(contentUri, null, null, null, null);
        if (cursor == null) {
            return contentUri.getPath();
        } else {
            cursor.moveToFirst();
            int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
            return cursor.getString(index);
        }
    }

    public String getFilename() {
        File file = new File(Environment.getExternalStorageDirectory().getPath(), "MyFolder/Images");
        if (!file.exists()) {
            file.mkdirs();
        }
        String uriSting = (file.getAbsolutePath() + "/" + System.currentTimeMillis() + ".jpg");
        return uriSting;

    }

这里压缩图像的大小为 60kb 或 70kb,但是当我将 strBitmap 保存到数据库时,它需要 500kb 或 600kb。如何将具有相同大小的压缩位图转换为字符串。


不过,您的图像有一个很大的差异。

您存储为文件的图像将存储为 JPEG

bitmapImg.compress(Bitmap.CompressFormat.JPEG, 80, out);

而 Base64 编码的字符串是 PNG

bitmapImg.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOS);

这可以解释尺寸差异。另一件事可能是,bitmapImg在两次压缩之间也更改了它的内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android:如何将压缩图像转换为最小大小的字符串 的相关文章

随机推荐

  • 无法执行 Cookie 身份验证:SignInAsync 和 AuthenticateAsync 不成功

    我正在尝试构建一个非常简单的游乐场服务器 以供我研究一些 ASP NET Core 身份验证 授权概念 基本上是一个带有一个非常简单的控制器的网络应用程序 可以使用 Postman 进行测试 我提出了代码的缩小版本 由单个登录端点组成 该端
  • 适用于 Python 的旧版本 Windows 二进制库 Wheel 的存储库?

    作为很多用户 我使用很棒的Christopher 的 Windows 二进制轮子 http www lfd uci edu gohlke pythonlibs vlfd当尝试在 Windows 上安装一些 python 包 例如 GDAL
  • 从线程中停止龙卷风

    我正在运行龙卷风 并从一个单独的线程监视各种数据源等 在这种情况下 如果用户关闭浏览器 则关闭 Web 服务器非常重要 我只是依赖于浏览器的心跳请求 然后想要停止龙卷风 ioloop 事实证明这是非常困难的 Start the main p
  • Ember Cli Inflector 调整

    我在哪里 如何调整Ember Inflector http emberjs com guides models the rest adapter toc pluralization customization类 创建一个 ember cli
  • 根据绘图单击事件对数据框进行子集化

    我有下面的数据框 Name lt c John Bob Jack Number lt c 3 3 5 NN lt data frame Name Number 还有一个简单闪亮的应用程序 可以从中创建一个绘图直方图 我的目标是单击直方图的一
  • Javascript显示/隐藏div onclick

    我有一个页面 其中包含三个 div 每个 div 是一个段落 我想使用 javascript 在用户从导航栏中按下每个 div 时仅在页面中显示这是导航栏 https i stack imgur com 1LnsS png WebDev 只
  • Instagram 如何使用 Amazon S3?

    在将文件上传到 Amazon S3 时 我需要深入了解 Instagram 的工程 我刚刚开始使用 S3 我认为 Instagram 是一个值得效仿的好模式 因为他们每天上传数千张图片 我的应用程序有点相似 用户上传图片 可以删除自己的图片
  • 如何在 Maven 中为依赖项指定存储库

    在具有多个依赖项和存储库的项目中 Maven 下载依赖项的试错方法有点麻烦且缓慢 所以我想知道是否有任何方法可以为某些声明的依赖项设置特定的存储库 例如 我希望 bouncycastle 直接检查 BouncyCastle 的 Maven
  • 无法使用 JHipster 访问 API 文档

    我一直在尝试访问 JHipster 生成的 Spring 应用程序生成的 Swagger UI 我尝试通过 swagger ui html 进行访问 因为这在其他项目中效果很好 但这次不行 我还查找了安全配置类并尝试了所有引用 swagge
  • MySQL 多个 IN 条件对同一个表进行子查询

    我有多个带有子查询的 IN 条件 SELECT S name S email FROM something S WHERE 1 NOT IN SELECT id FROM tags WHERE somethingId S id AND 2
  • 如何在 Java 中监听按键时使图像移动。

    我开始学习java编程 我认为通过游戏开发来学习java很酷 我知道如何绘制图像并听按键然后移动该图像 但是 当窗口监听按键时 是否可以使图像在窗口中来回移动 例如 当图像或物体 如宇宙飞船 在窗口中从左向右移动时 如果我按空格键 激光将在
  • bash - 从文本文件中删除多行不同的文本

    我正在处理大量日志文件 并且大多数日志文件都有大量被记录多次的重复字符串 为了使与此类事情没有太多关系的其他人 也为我自己 轻松查看日志 我想制作一个脚本来删除一些可能对其他人造成 误报 的文本行 嘿管理员 我多次出现这些错误 gt 叹息
  • iOS 显示 UIImage 全屏并启用缩放(捏合和双击)

    我有一个UIImage从相机捕获UIImagePickerController 现在 在用户单击它之后 我希望它显示全屏 并且能够使用捏合手势进行放大和缩小 还可以使用双击手势来放大特定区域 换句话说 我想模拟ios默认图像浏览器的功能 我
  • LINQ-to-SQL 是否支持组合查询?

    作为一名不懂 C 的程序员 我对 LINQ 查询的求值语义很好奇 如下所示 var people from p in Person where p age lt 18 select p var otherPeople from p in p
  • 如何在同一视图中渲染两个分页且可 ajax 的集合?

    在 Rails 3 2 索引视图中 我正在渲染两个部分 并且在部分 Show some fields 分页不起作用 如果我改变will paginate要获取实例变量 分页可以工作 但是集合错误 当调用部分时 如何将
  • Java - 罗马 rss 阅读器?

    我正在尝试阅读 rss 我将 jar 文件复制到我的 libs 文件夹中 并将该 jar 文件作为库添加到我的 eclipse 项目中 为了导出并导出 我检查了我的 jar 文件 现在我正在尝试使用罗马提供的RSS阅读器 import co
  • 工厂模式数据库连接

    我正在尝试使用 MySQL 实现数据库连接上的工厂模式 SQL Server 面临奇怪的错误 你调用的对象是空的 在 SQL 命令对象上 internal class SqlServerDB IDatabase private SqlCon
  • GCC、字符串化和内联 GLSL?

    我想使用宏字符串化来声明内联 GLSL 着色器字符串 define STRINGIFY A A const GLchar vert STRINGIFY version 120 n attribute vec2 position void m
  • PHP/MySQL:检索邻接列表模型中的单个路径

    有没有什么有效的方法可以在不限制深度的情况下根据节点的ID检索邻接列表模型中的单个路径 就像如果我有一个名为 Banana 的节点的 ID 我可以获得以下路径 Food gt Fruits gt Banana 如果不可能的话也不是什么大问题
  • Android:如何将压缩图像转换为最小大小的字符串

    在我的android应用程序中 我使用whatsapp之类的图像压缩 之后我使用Base64编码将压缩图像位图转换为字符串 我注意到当我压缩5mb图像并将其保存在另一个位置时 它只是60kb或70kb的东西就像这样 同一张图像的 Base6