3分钟教你图解Bitmap编码传输

在Android的图片传输的流程为:

Created with Raphaël 2.1.2 Bitmap 二进制流 Byte数组 Base64编码 String进行传输 Base64解码 还原为原来的Byte数组,然后转换为原来的String
Bitmap的转换为二进制流:
//将bitmap转换为二进制流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);

其中,我们知道compress的方法是进行压缩的,其中方法里面的三个参数,分别代表:图片格式、压缩比例、字节流(节数组输出流在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中)。

其实这个时候我想到了一个问题,当压缩比例为100的时候,也就是没有进行压缩,那这一步的代码意义何在呢? 经过研究下面源码:

 /**
     * Write a compressed version of the bitmap to the specified outputstream.
     * If this returns true, the bitmap can be reconstructed by passing a
     * corresponding inputstream to BitmapFactory.decodeStream(). Note: not
     * all Formats support all bitmap configs directly, so it is possible that
     * the returned bitmap from BitmapFactory could be in a different bitdepth,
     * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque
     * pixels).
     *
     * @param format   The format of the compressed image
     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
     *                 small size, 100 meaning compress for max quality. Some
     *                 formats, like PNG which is lossless, will ignore the
     *                 quality setting
     * @param stream   The outputstream to write the compressed data.
     * @return true if successfully compressed to the specified stream.
     */
    public boolean compress(CompressFormat format, int quality, OutputStream stream) {
        checkRecycled("Can't compress a recycled bitmap");
        // do explicit check before calling the native method
        if (stream == null) {
            throw new NullPointerException();
        }
        if (quality < 0 || quality > 100) {
            throw new IllegalArgumentException("quality must be 0..100");
        }
        StrictMode.noteSlowCall("Compression of a bitmap is slow");
        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");
        boolean result = nativeCompress(mNativePtr, format.nativeInt,
                quality, stream, new byte[WORKING_COMPRESS_STORAGE]);
        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
        return result;
    }

其中最重要的一句代码是这个:

nativeCompress(mNativePtr, format.nativeInt,
                quality, stream, new byte[WORKING_COMPRESS_STORAGE]);

再深入发现调用的是这个方法:

private static native boolean nativeCompress(long nativeBitmap, int format,
                                            int quality, OutputStream stream,
                                            byte[] tempStorage);

我们最后发现它最后是调用到了JNI,直接使用.cpp方法里面的C++函数了。这个大家有兴趣可以去参考这篇文章:Bitmap压缩原理解析与Android 7.0之前通过NDK使用libjpeg库高质量压缩图片
所以回到我们的第一个源码那,看注释,第一句是 Write a compressed version of the bitmap to the specified outputstream. 意思就是将压缩后的Bitmap写入到指定的输出流里面。这样我就弄懂了,其实这个压缩如果是100的话,其最终的目的也就是去将bitmap写入到流里面。流(Stream)二进制数据流,内存中电信号转换,写入到磁盘的存储颗粒上,记录电信号。

二进制流转换为Byte[]数组
  • 这个就涉及到了编码的知识了。在最早期的时候,大家的编码方式都使用的是ASCII码的编码方式,而我们要知道的是在计算机中,所有的信息都是以0和1来进行存储的,指定的二进制代表了字母、标点符号、控制字符。譬如存储在计算机上的01000001代表了大写字母A。ASCII码一共有256个,但是常用的也就前128个,标准ASCII码(0~127)。
  • 简而言之,对于字符而言,直接用ASCII码对应的数字表示,ASCII码就是用来将字符存储到计算机的,例如“3” 的ASCII码的十进制为51 ,二进制为 0011 0011 。则是将二进制的值存储到了计算机。
  • 那么,由此延伸的一个问题是:当本身就是十进制的51,其二进制也为0011 0011 ,存储进了计算机。那么在计算机中的二进制 0011 0011,表现到内存中到底是字符还是数字呢? 我自我理解是计算机中既然存储了0011 0011 那么在内存中表示出来的值,只与其定义的数有关,如果你定义的是int 那么就是51;如果你定义的是String 那么就是“3”。
  • 而Byte里面存储为8bit,可以存储所有ASCII所有字符(这是它包含8bits的初衷)。也就是说1Byte里面有8bit的二进制,那么将二进制流每8bit存储于一个Byte,就可以得到最后转换的Byte[]数组了。
Byte[]数组转Base64编码
什么是Base64编码

漫画:什么是Base64算法?

为什么要进行Base64编码

因为Http协议(超文本传输协议)中,Byte里面的二进制可能为0000 0001B,如果直接转换为String的话,明显是不可能的,因为这个不是可打印字符,那么传输过程中可能就会出现乱码,而Base64也就是64个可打印的字符串。

ValueCharValueCharValueCharValueChar
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+
15P31f47v63/
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值