设计稿、切图
tinypng压缩
一张bitmap所占内存计算
代码获取:bitmap.getByteCount
手动计算
densitydpi
屏幕像素密度一般计算公式为,由屏幕长宽的分辨率,根据勾股定律求出对角线的像素数,再除以屏幕的尺寸
densityDpi
- drawable—160
- hdpi—240
- 2x—xhdpi—320dpi—高清屏—720p
- 3x—xxhdpi—480dpi—超清—1080p
format
- ARGB-8888 foamat=4byte
- RGB_565 foamat=2byte
float scale = deviceDensityDpi/densityDpi//缩放比例
int scaledWith = (imgWidth*scale + 0.5f)
int scaleheight = (imgHeight*scale + 0.5f)
int byteCount = scaledWidth * scaleheight*format
我的手机是屏幕密度是440
图片位置:drawable-hdpi
图片格式:ARGB-8888
图片大小:400 * 400
宽度:int(400 * (440 / 240) + 0.5)
高度:int(400 * (440 / 240) + 0.5)
内存大小:2149156
png/jpg只是图片的容器,它们是经过相对应的压缩算法将原图的每个像素点转换用另外一种数据格式表示,以此达到压缩目的,减少图片文件大小
位于res的不同资源目录中的图片,当加载进内存时,会先经过一次分辨率的转换,然后再计算大小
当通过代码将图片加载进内存,会分析图片文件本身的数据格式,然后还原为bitmap,bitmap对象的大小取决于像素点的数据格式以及分辨率
一张png/jpg格式的图片大小,跟这张图片加载进内存所占用的大小完全是两回事
UI稿@2x,@3x的区别?
造成图片模糊的原因是位图的像素总数和对应的物理像素个数不一致,那么只需要增加图片的位图像素数目,使其接近于设备物理像素就解决了这个问题
因此我们采用@2x@3x的图片,就是为了使图片的位图像素和设备位图像素的数目接近于1:1,就能使图片清晰显示不模糊
位图像素数目大于物理像素的情况,会对图片进行压缩,清晰度不会发生变化,但是会有一些色差及锐利度的减少
适配不同的设备
针对不同的设备采用相应的图片,使得图片的位图像素等于物理像素
设备像素比为1的设备使用@1x
2使用@2x—xhdpi—320dpi—高清屏—720p
3使用@3x—xxhdpi—480dpi—超清—1080p
Bitmap的复用?
Bitmap尽量使用inBitmap
Glide内部也使用了inBitmap作为缓存复用的一种方式。
bitmap对象申请和释放会引起频繁的GC操作,从而引起界面卡顿
BitmapRegionDecode 分块加载
比方说加载图片左上角一个大小块
图片压缩算法
哈夫曼
gif编码里面是算法?
EasyPhotos
相册加载图片使用
Luban
压缩图片,然后上传
断点续传实现?
在本地下载过程中要使用数据库实时存储到底存储到文件的哪个位置了,这样点击开始继续传递时,才能通过HTTP的GET请求中的setRequestProperty(“Range”,“bytes=startIndex-endIndex”);方法可以告诉服务器,数据从哪里开始,到哪里结束。
同时在本地的文件写入时,RandomAccessFile的seek()方法也支持在文件中的任意位置进行写入操作。最后通过广播或事件总线机制将子线程的进度告诉Activity的进度条。
关于断线续传的HTTP状态码是206,即HttpStatus.SC_PARTIAL_CONTENT。
android studio上右键图片,选择Convert to WebP
图片压缩原理
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
options.inScaled = false;//禁止图片缩放
return BitmapFactory.decodeResource(res, resId, options);
}
public static 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 halfHeight = height / 2;
final int halfWidth = width / 2;
//计算最大的inSampleSize值,即2的幂,并保留这两个值
//高度和宽度大于要求的高度和宽度
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
尽量不在Button上使用selector来设置点击与正常时背景图,因为在button初始化时会将选中状态与正常状态的两张图都加载都内存中,无疑在无意中加大了内存的占用,可xml中设置正常的背景,在setOnTouchListener监听中通过代码动态改变,在按下时显示选中状态北京,抬起恢复
final Button button=new Button(this);
button.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//手指按下
button.setBackgroundResource(R.mipmap.down);
break;
case MotionEvent.ACTION_UP:
//手指抬起,恢复
button.setBackgroundResource(R.mipmap.up);
break;
}
//为了监听事件的分发,返回false
return false;
}
});
图标一般是要做成矢量的,若公司UI实力强劲,可以维护一个iconfont库
https://blog.csdn.net/guofudong2/article/details/81299137
getByteCount():API12 加入,代表存储 Bitmap 的像素需要的最少内存。
getAllocationByteCount():API19 加入,代表在内存中为 Bitmap 分配的内存大小,代替了 getByteCount() 方法。
在不复用 Bitmap 时,getByteCount() 和 getAllocationByteCount 返回的结果是一样的。在通过复用 Bitmap 来解码图片时,
那么 getByteCount() 表示新解码图片占用内存的大 小,getAllocationByteCount() 表示被复用 Bitmap 真实占用的内存大小(即 mBuffer 的长度)
ScaleType.FIX_XY:不考虑原图的比例,拉伸或者压缩使得它等于控件的宽高
下面三种都会维持原图的比例,使得它们的x,y都小于等于控件的宽高,只是最终的图形放的位置不同。
ScaleType.FIT_START:放置在左上角。
ScaleType.FIT_CENTER:放置在中间。
ScaleType.FIT_END:放置在右下角
ScaleType.CENTER
要求一点:
原图的中心和控件的中心重合
ScaleType.CENTER_CROP
要求三点:
整个控件能够被填满
原图的比例不变
原图的中心和控件的中心重合。
保证原图的x,y轴上的元素至少有一个在控件中能被完全展示,那么有一下两种情况,在下面的操作做完之后,裁剪掉多余的部分:
如果原图没有填满控件,那么会慢慢按比例放大,直到填满控件;
如果原图已经填满控件,那么它会慢慢缩小,直到某一边和控件重合
ScaleType.CENTER_INSIDE
要求三点:
原图的所有像素位于控件内部
原图的比例不变
图片的中心和控件的中心重合。
它不要求原始图片填满x,y轴的任意一个,因此,如果原图的长宽都小于等于控件的长宽,不会进行放大操作,这也是它和ScaleType.FIT_CENTER的区别
整个scaleType的原理就是在configureBounds中配置了mDrawMatrix,而在onDraw当中会根据mDrawMatrix来对图层进行变换,在这个变换之后的图层上进行绘制mDrawable,之后再恢复图层
src的图片一定会绘制在backgroud之上
WebP是一种支持有损压缩和无损压缩的图片文件格式,派生自图像编码格式VP8。根据Google的测试,无损压缩后的WebP比PNG文件少了45%的文件大小,即使这些PNG文件经过其他压缩工具压缩之后,WebP还是可以减少28%的文件大小。
对于PNG这种图像存储格式,它有两个特点:无损压缩和支持透明效果。
由于PNG文件采用LZ77算法的派生算法进行压缩,其结果是获得高的压缩比,不损失数据。它利用特殊的编码方法标记重复出现的数据,因而对图像的颜色没有影响,也不可能产生颜色的损失,这样就可以重复保存而不降低图像质量。
PNG可以为原图像定义256个透明层次,使得彩色图像的边缘能与任何背景平滑地融合,从而彻底地消除锯齿边缘。这种功能是GIF和JPEG没有的
矢量图形的想法就被提出了:它包含的不是图片中的各个像素点的描述,而是对于图片的绘制命令,当我们解析图片的时候,会运行这一系列的绘制命令来最终得到光栅图像。
SVG 和 VectorDrawable
SVG就是矢量图形的一种具体实现,它包含了一系列的绘制命令,例如下图,我们使用xml文件的多个标签进行组合,最终把图像描述出来
适用于较小的图片
适用于较为简单的图片
在Android当中,VectorDrawable到光栅图像的栅格化处理是通过CPU进行的。而这一光栅处理的时间和图片的大小成正比,因此,如果图片很大,那么加载的时间将会很长,这种情况就不适合使用VectorDrawable了。
https://www.jianshu.com/p/4043efd5b944
https://www.jianshu.com/p/abc756158cf6
安卓加载本地大图的时候,不能直接用setImageResource和setBackgroundResource,
图片内存=图片宽图片高每个像素占用字节数,这样很大概率内存溢出
需要用glide加载,封装了两个方法加载本地静图和动图
动图ImageLoaderImpl.loadGifByResId
静图ImageLoaderImpl.loadBitmapByResId