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

Android : How to convert the compressed images to string with minimum size

在我的 android 应用程序中,我使用类似图像压缩的 whatsapp,然后我使用 Base64 编码将压缩图像位图转换为字符串,我注意到当我压缩 5mb 图像并将其保存在另一个位置它只有 60kb 或 70kb 之类的东西,而 Base64 编码的字符串对于同一图像占用 500kb 或 600kb,为什么会这样?有什么方法可以将压缩图像转换为字符串,其相同 size.Below 是我的代码。

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.How 我可以将具有相同大小的压缩位图转换为字符串吗?

虽然你的图片有一个很大的不同。

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

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

而 Base64 编码的字符串是 PNG

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

这可以解释大小差异。另一件事可能是,bitmapImg 也改变了两次压缩之间的内容。