
一、基础概念:
px:像素(pixel),指的是屏幕上的物理点,最小的独立显示单位。
ppi:指的是水平方向或者竖直方向上每英寸的像素值,每英寸像素点(就是每英寸像素点的数量),通过屏幕长宽计算出对角线的长度,再除以屏幕对角线英寸值。X/x = Y/y = ppi,这里X为水平像素值,x为水平英寸值,Y为竖直像素值,y为竖直英寸值。所以ppi=√(X²+Y²)/对角线英寸
dpi:每英寸点(mdpi:150,hdpi:240),每英寸的像素点的数量
dp:与像素点无关,虚拟像素,px = dp (dpi/160)
densityDpi:是屏幕每英寸对应多少个点(不是像素点)density = densityDpi/160
in:英寸,等于254厘米。
二、计算:
1、像素的计算
px = dp (dpi/160)
以Nexus6为例,一张180 180的,放在设置了wrap-content的ImageView中,当这张,分别放在drawable-nodpi,drawable-mdpi,drawable-hdpi,drawable-xhdpi,drawable-xxhdpi,drawable-xxxhdpi的资源目录下,在屏幕上显示多大像素的?
hdpi:int(180560/240)+05f)=420px
xhdpi:int(180 (560/320)+05f) = 315px
xxhdpi:int(180 (560/480)+05f) = 210px
2、内存的计算:
ALPHA8,RGB565,ARGB_4444,ARGB8888,Android系统默认ARGB8888(分别占的字节数为1,2,2,4Byte)
hdpi的内存:4204204=705600byte = 689kb
xhdpi的内存:3153154= 396900byte = 3876kb
xxhdpi的内存:2102104=176400byte = 1722kb
drawable-ldpi (dpi=120, density=075)
drawable-mdpi (dpi=160, density=1)
drawable-hdpi (dpi=240, density=15)
drawable-xhdpi (dpi=320, density=2)
drawable-xxhdpi (dpi=480, density=3)
3、bitmap的内存占用:Bitmap 在内存当中占用的大小其实取决于:
色彩格式,如果是 ARGB8888 那么就是一个像素4个字节,如果是 RGB565 那就是2个字节
原始文件存放的资源目录(是 hdpi 还是 xxhdpi )等
目标屏幕的密度(所以同等条件下,红米在资源方面消耗的内存肯定是要小于三星S6的)
4、内存计算:
720 720px的放到手机屏幕是320dpi,缩放的文件夹是mdpi,采用默认的存储格式,则占用的内存是:
(720 (160/320)+05f)^2
HBITMAP bmpHandle = (HBITMAP)LoadImage(NULL);
CBitmap bitmap;
bitmapAttach(bmpHandle); //关联位图对象
BITMAP bmp;
bitmapGetBitmap(&bmp); //获取位图信息
CString s;
sFormat("宽度=%d 高度=%d", bmpbmWidth, bmpbmHeight);
HBITMAP hBmp;
//
BITMAP bmpInfo;
GetObject((HGDIOBJ)hBmp, sizeof(bmpInfo), &bmpInfo);
//bmpInfobmWidth和bmpInfobmHeight应该是你想要的
各点像素:
先创建一个DC(比如CreateDC("DISPLAY", 0, 0, 0)这样?),然后SelectObject把你的HBITMAP选进去,之后用GetPixel函数可以获取上面的像素点
用到的不仅仅包括png、gif、9png、jpg和各种Drawable系对象,还包括位图Bitmap
的处理也经常是影响着一个程序的高效性和健壮性。
为什么不直接用Bitmap传输?
位图文件虽好,但是非压缩格式,占用较大存储空间。
Bitmap主要方法有:获取图像宽高、释放,判断是否已释放和是否可修改,压缩、创建制定位图等功能
用于从不同的数据源(如文件、输入流、资源文件、字节数组、文件描述符等)解析、创建Bitmap对象
允许我们定义以何种方式如何读到内存。
推荐阅读: Android - Bitmap-内存分析
注意事项:
decodeFileDescriptor比decodeFile高效
查看源码可以知道
替换成
建议采用decodeStream代替decodeResource。
因为BitmapFactorydecodeResource 加载的可能会经过缩放,该缩放目前是放在 java 层做的,效率比较低,而且需要消耗 java 层的内存。因此,如果大量使用该接口加载,容易导致OOM错误,BitmapFactorydecodeStream 不会对所加载的进行缩放,相比之下占用内存少,效率更高。
这两个接口各有用处,如果对性能要求较高,则应该使用 decodeStream;如果对性能要求不高,且需要 Android 自带的自适应缩放功能,则可以使用 decodeResource。
推荐阅读:[ BitmapFactorydecodeResource加载缩小的原因及解决方法
canvas和Matrix可对Bitmap进行旋转、放缩、平移、切错等 *** 作
可以用BitmaponCreateBitmap、Canvas的clipRect和clipPath等等方式
推荐阅读: android自定义View学习4--图像剪切与变换
对初始化Bitmap对象过程中可能发生的OutOfMemory异常进行了捕获。如果发生了OutOfMemory异常,应用不会崩溃,而是得到了一个默认的Bitmap图。
如果不进行缓存,尽管看到的是同一张文件,但是使用BitmapFactory类的方法来实例化出来的Bitmap,是不同的Bitmap对象。缓存可以避免新建多个Bitmap对象,避免内存的浪费。
如果像素过大,使用BitmapFactory类的方法实例化Bitmap的过程中,需要大于8M的内存空间,就必定会发生OutOfMemory异常。
可以将缩小,以减少载入过程中的内存的使用,避免异常发生。
推荐阅读:
Bitmap详解与Bitmap的内存优化
/
@param path 路径
@param displayWidth 需要显示的宽度
@param displayHeight 需要显示的高度
@return Bitmap
/
public static Bitmap decodeBitmap(String path, int displayWidth, int displayHeight) {
BitmapFactoryOptions op = new BitmapFactoryOptions();
opinJustDecodeBounds = true;
// opinJustDecodeBounds = true;表示我们只读取Bitmap的宽高等信息,不读取像素。
Bitmap bmp = BitmapFactorydecodeFile(path, op); // 获取尺寸信息
// opoutWidth表示的是图像真实的宽度
// opinSamplySize 表示的是缩小的比例
// opinSamplySize = 4,表示缩小1/4的宽和高,1/16的像素,android认为设置为2是最快的。
// 获取比例大小
int wRatio = (int) Mathceil(opoutWidth / (float) displayWidth);
int hRatio = (int) Mathceil(opoutHeight / (float) displayHeight);
// 如果超出指定大小,则缩小相应的比例
if (wRatio > 1 && hRatio > 1) {
if (wRatio > hRatio) {
// 如果太宽,我们就缩小宽度到需要的大小,注意,高度就会变得更加的小。
opinSampleSize = wRatio;
} else {
opinSampleSize = hRatio;
}
}
opinJustDecodeBounds = false;
bmp = BitmapFactorydecodeFile(path, op);
// 从原Bitmap创建一个给定宽高的Bitmap
return BitmapcreateScaledBitmap(bmp, displayWidth, displayHeight, true);
}
是本地的吗
如果是本地,可以通过BitmapFactorydecodeResource(res,id);
来获取到这个Bitmap,获取到这个Bitmap,你要的大小都出来了啊
如果是网络,也可以通过BitmapFactory的获取
在ImageView中的image,可以使用getWidth()和getHeight()来获取宽度和高度,但是获得的image宽度和高度不是很精确的;对于背景,你首先要获取背景的Drawable对象,然后将Drawable对象转换为BitmapDrawable,这样你就可以将背景作为Bitmap对象并获取其宽度和高度了。代码如下:Bitmap b = ((BitmapDrawble)imageViewgetBackground())getBitmap(); int w = bgetWidth(); int h = bgetHeight(); or do like this wayimageViewsetDrawingCacheEnabled(true); Bitmap b = imageViewgetDrawingCache(); int w = bgetWidth(); int h = bgetHeight(); 或者也可以像下面这样:imageViewsetDrawingCacheEnabled(true); Bitmap b = imageViewgetDrawingCache(); int w = bgetWidth(); int h = bgetHeight(); 上面的代码仅仅可以为你获取当前ImageView的大小:imageViewgetWidth(); imageViewgetHeight(); 如果你要获取Drawable image对象的大小,可用如下代码:Drawable d = getResources()getDrawable(Rdrawableyourimage); int h = dgetIntrinsicHeight(); int w = dgetIntrinsicWidth();
字符的正确绘制位置
首先在创建好FTFace,Freetype推荐使用基线作为绘制基准,但是通常都是设置字符左上角的位置开始绘制。需要获得基线到字符轮廓最高点的距离,这个信息放在
Ascender = FTFace->size->metricsascender >> 6; // 基线到字符轮廓最高点的距离, 由于是266的定点数,因此获取整数部分需要除以64
然后每个字符的高度是不同的,Freetype生成的bitmap一般刚刚好包围到字符,比如a和l的bitmap图高度是不同的。因此还需要获得每个字符的偏移宽度和高度,这两个信息放在
bitmap_left = FTFace->glyph->bitmap_left; // 字符距离左边界的距离
bitmap_top = FTFace->glyph->bitmap_top; // 字符最高点距离基线的距离
好了,现在假设要在(posx, posy)处绘制字符,(charposx, charposy)表示字符的正确绘制位置
charposx = posx + bitmap_left;
charposy = posy - Ascender + bitmap_top;
以上就是关于Bitmap的内存计算方式全部的内容,包括:Bitmap的内存计算方式、VC++ 获取图片的尺寸大小、如何获得一个HBITMAP指向的BMP图片的尺寸和各点的像素谢谢!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)