Bitmap 类

2018-08-07  本文已影响0人  _VITA

图像格式

首先Bitmap本质而言,是图片一种存储方式。
位图(Bitmap)格式其实并不能说是一种很常见的格式(从我们日常的使用频率上来讲,远不如 .jpg .png .gif 等),因为其数据没有经过压缩,其内部存储的色彩信息(灰度图,RGB 或 ARGB)直接以二进制的形式暴露在外,也十分方便借助计算机软件进行简单或深入的分析.
Bitmap的结构可以分三部分:位图文件头,位图信息数据头,原始位图数据。

数据按照像素行进行包装,便于读取。但是这并不是全部,因为其中还可能会有补零(zero-padding)。这涉及到计算机的数据结构对齐(data structure alignment)的问题。

主流的 CPU 每次从内存中读取并处理数据块(chunk),且通常为 32 比特(4 字节)。因此,为了提升读取效率,位图每行的数据(字节)都需要是 4 的倍数。不可避免地,有些时候每行的结尾就会出现补零(其实补其他任意数字也是可以的,但常见都是补 0)。
对于每行补零的个数,是有计算方法的。公式如下(知乎的 LaTeX 公式不能很好地支持中文,因此无法进行翻译,抱歉):

即,每行的字节数等于:每像素比特数乘以图片宽度31 的和除以 32,并向下取整,最后乘以4

得到了每行的字节数,进而就能够得到原始位图数据,或者说存储图片的所有像素的色彩信息的数据,的大小了:


即,原始位图数据大小等于:每行的字节数乘以图像高度(也就是总行数)

再加上之前说的文件头的数据大小(通常为 54 字节),就能够得到文件大小了。

在Android程序里Bitmap多大呢?

density:The logical density of the display. This is a scaling factor for the Density Independent Pixel unit, where one DIP is one pixel on an approximately 160 dpi screen (for example a 240x320, 1.5”x2” screen), providing the baseline of the system’s display. Thus on a 160dpi screen this density value will be 1; on a 120 dpi screen it would be .75; etc.
This value does not exactly follow the real screen size (as given by xdpi and ydpi, but rather is used to scale the size of the overall UI in steps based on gross changes in the display dpi. For example, a 240x320 screen will have a density of 1 even if its width is 1.8”, 1.3”, etc. However, if the screen resolution is increased to 320x480 but the screen size remained 1.5”x2” then the density would be increased (probably to 1.5).
densityDpi:The screen density expressed as dots-per-inch.

density densityDpi
1 160
1.5 240
2 320
3 480
3.5 560
4 640

SkBitmap.cpp

size_t SkBitmap::ComputeRowBytes(Config c, int width) {
    return SkColorTypeMinRowBytes(SkBitmapConfigToColorType(c), width);
}
SkImageInfo.h
 
static int SkColorTypeBytesPerPixel(SkColorType ct) {
   static const uint8_t gSize[] = {
    0,  // Unknown
    1,  // Alpha_8
    2,  // RGB_565
    2,  // ARGB_4444
    4,  // RGBA_8888
    4,  // BGRA_8888
    1,  // kIndex_8
  };
  SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gSize) == (size_t)(kLastEnum_SkColorType + 1),
                size_mismatch_with_SkColorType_enum);
 
   SkASSERT((size_t)ct < SK_ARRAY_COUNT(gSize));
   return gSize[ct];
}
 
static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {
    return width * SkColorTypeBytesPerPixel(ct);
}

ARGB_8888(也就是我们最常用的 Bitmap 的格式)的一个像素占用 4byte,那么 rowBytes 实际上就是 4width bytes。
那么结论出来了,一张 ARGB_8888 的 Bitmap 占用内存的计算公式
bitmapInRam = bitmapWidth
bitmapHeight *4 bytes

Bitmap 与Drawable的关系

Bitmap是用来显示的实际数据,它在概念上隶属于Drawable,但是与Drawable之间不是继承关系。
可以简单地理解为 Bitmap 储存的是 像素信息,Drawable 储存的是 对 Canvas 的一系列操作。而 BitmapDrawable 储存的是「把 Bitmap 渲染到 Canvas 上」这个操作。

参考资料:

上一篇 下一篇

猜你喜欢

热点阅读