如何将图像转换为带有gzip的base64字符串-Android

3

我正在尝试将从Android文件路径中获取的图像转换并压缩为base64的gzip格式(我使用这种格式是因为我的Java桌面版本也在使用相同的格式)。以下是我目前的压缩代码:

Bitmap bm = BitmapFactory.decodeFile(imagePath);              
ByteArrayOutputStream baos = new ByteArrayOutputStream();     
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);           
byte[] data = baos.toByteArray();                                                               
String base64Str = null;                                      

ByteArrayOutputStream out_bytes = new ByteArrayOutputStream();
OutputStream out = new Base64.OutputStream(out_bytes);

try {
    out.write(data);
    out.close();                                                         
    byte[] encoded = out_bytes.toByteArray();                 

    base64Str = Base64.encodeBytes(encoded, Base64.GZIP);     
    baos.close();                                             
} catch (Exception e) {}

1
你确定你不是想要 byte[] encoded = baos.toByteArray() 吗?out_bytes 是空的,看起来是不必要的。 - Lone nebula
好的,发现了。我以为我在使用更新的代码。我会再看一下。 - Vnge
请检查编辑,我相信那就是它的样子。 - Vnge
在压缩位图后,从baos编辑的data字节数组。 - Vnge
1个回答

4
这是您当前代码的功能:
//1. Decode data from image file
Bitmap bm = BitmapFactory.decodeFile(imagePath);
...
//2. Compress decoded image data to JPEG format with max quality
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
...
//3. Encode compressed image data to base64
out.write(data);
...
//4. Compress to gzip format, before encoding gzipped data to base64
base64Str = Base64.encodeBytes(encoded, Base64.GZIP);

我不知道你们的桌面版本是如何做的,但第三步是不必要的,因为你在第四步中已经完成了相同的操作。
(回答的一部分被删除)
编辑:以下代码将从文件中读取字节,对字节进行gzip压缩并将其编码为base64。它适用于所有小于2 GB的可读文件。传递给Base64.encodeBytes的字节将与文件中的字节相同,因此不会丢失任何信息(与上面的代码不同,在那里你首先将数据转换为JPEG格式)。
/*
 * imagePath has changed name to path, as the file doesn't have to be an image.
 */
File file = new File(path);
long length = file.length();
BufferedInputStream bis = null;
try {
    bis = new BufferedInputStream(new FileInputStream(file));
    if(length > Integer.MAX_VALUE) {
        throw new IOException("File must be smaller than 2 GB.");
    }
    byte[] data = new byte[(int)length];
    //Read bytes from file
    bis.read(data);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if(bis != null)
        try { bis.close(); }
        catch(IOException e) {}
}
//Gzip and encode to base64
String base64Str = Base64.encodeBytes(data, Base64.GZIP);

编辑2:这将解码base64 字符串并将解码后的数据写入文件:

    //outputPath is the path to the destination file.

    //Decode base64 String (automatically detects and decompresses gzip)
    byte[] data = Base64.decode(base64str);
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(outputPath);
        //Write data to file
        fos.write(data);
    } catch(IOException e) {
        e.printStackTrace();
    } finally {
        if(fos != null)
            try { fos.close(); }
            catch(IOException e) {}
    }

我的桌面版本使用缓冲图像和ImageIO完成了同样的功能。这正是我所需要的。我想我一直在寻找可能的解决方案,不知道该使用什么,不该使用什么。非常感谢!这对我来说很有效。 - Vnge
顺便说一下,原始图像数据通常可以比最高质量的JPEG版本更压缩。在这种情况下,如果您直接对原始图像数据使用Base64.encodeBytes(data, Base64.GZIP),则会获得更短的base64字符串。 你所指的是什么意思? - Vnge
@Vnge 假设您选择了一张PNG图像。如果该图像颜色较少,则文件大小将较小。当您将其转换为JPEG格式时,最终的字节数会比存储在图像文件中的字节数更多。在这种情况下,如果您直接对PNG格式数据执行第4步骤,您将获得一个较短的base64“字符串”,而不是先解码并压缩为JPEG。此外,如果您以这种方式执行操作,不会丢失任何信息。 - Lone nebula
能否提供一下第4步之前的base64示例?并且在该步骤中我也可以使用其他图片吗? - Vnge
@Vnge 编码和解码应该在安卓和普通电脑上都能正常工作。 - Lone nebula
这正是我想的。我测试了编码,它运行得非常好。我只是不知道是否有其他解码方式。感谢您的帮助! - Vnge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接