我们都知道一个App的成败,首先取决于是否具有优秀的UI,而除了交互功能之外还需要丰富的图片背景和动画去支撑。在开发中我们应用到的图片不仅仅包括.png、.gif、.9.png、.jpg和各种Drawable系对象,还包括位图Bitmap,而且图片的处理也经常是影响着一个程序的高效性和健壮性。

一、Bitmap概述

Bitmap代表一张位图,扩展名可以是.bmp或者.dib。位图是Windows标准格式图形文件,它将图像定义为由点(像素)组成,每个点可以由多种色彩表示,包括2、4、8、16、24和32位色彩。例如,一幅1024×768分辨率的32位真彩图片,其所占存储字节数为:1024×768×32/8=3072KB,虽然位图文件图像效果好,但是非压缩格式的,需要占用较大存储空间,不利于在网络上传送Android系统当中,Bitmap是图像处理最重要的中转类之一。用它可以获取图像文件信息,借助Matrix进行图像剪切、旋转、缩放等操作,再以指定格式保存图像文件。

二、构造Bitmap对象

通常我们构造一个类的对象,都是可以通过其对应的构造方法。然而Bitmap是采用了工厂的设计模式,所以一般不会直接调用构造方法。

1、通过Bitmap的静态方法static Bitmap createBitmap()系

方法名(只列出部分方法) 用法说明
createBitmap(Bitmap src) 复制位图
createBitmap(Bitmap src,int x ,int y,int w,int h) 从源位图src的指定坐标(x,y)开始,截取宽w,高h的部分,用于创建新的位图对象
createScaledBitmap(Bitmap src,int w ,int h,boolean filter) 对源位图src缩放成宽为w,高为h的新位图
createBitmap(int w ,int h,Bitmap.Config config) 创建一个宽w,高h的新位图(config为位图的内部配置枚举类)
createBitmap(Bitmap src,int x ,int y,int w,int h,Matrix m,boolean filter) 从源位图src的指定坐标(x,y)开始,截取宽w,高h的部分,按照Matrix变换创建新的位图对象

2、通过BitmapFactory工厂类的static Bitmap decodeXxx()系

方法名(只列出部分方法) 参数及解释
decodeByteArray(byte[] data, int offset, int length) 从指定字节数组的offset位置开始,将长度为length的数据解析成位图
decodeFile(String pathName) 从pathName对应的文件解析成的位图对象
decodeFileDescriptor(FileDescriptor fd) 从FileDescriptor中解析成的位图对象
decodeResource(Resource res,int id) 根据给定的资源Id解析成位图
decodeStream(InputStream in) 把输入流解析成位图

三、Bitmap相关类之Path、Matrix

1、Path类的应用

有使用PS经验的都知道”路径”这么一个概念,可以把几个点连成一条“路径”,Android里的Path也是如此。在实际应用中我们可以调用Canvas的drawPath方法即可绘制图形,为了实现丰富的绘制效果,Android还定义了一个PathEffect系列类(ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect

1.1、Path类的构造方法

Path();
Path(Path src);

1.2、Path类的一些常用方法

部分方法 用法说明
public void addArc (RectF oval, float startAngle, float sweepAngle) 绘制弧形路径
public void addCircle (float x, float y, float radius, Path.Direction dir) 绘制圆形路径
public void addOval (RectF oval, Path.Direction dir) 绘制椭圆路径
public void lineTo (float x, float y) 把(x,y)连接到一起成为一条折线
public void moveTo (float x, float y)  

1.3、Path的实际应用

绘制跟随路径显示的字符串

package com.crazymo.graphicsdemo;

public class MyPathView extends View {
final String STR_TITLE="跟随路径显示的字符串";
Path[] paths=new Path[3];
Paint paint;
public MyPathView(Context ctx){
super(ctx);
paths[0]=new Path();
paths[0].moveTo(0,0);
for(int i=1;i<7;i++){
//随机生成7个点的Y坐标并将他们炼成一条路径
paths[0].lineTo(i*30,(float)Math.random()*30);
}
paths[1]=new Path();
RectF rectF=new RectF(0,0,200,120);
paths[1].addOval(rectF,Path.Direction.CCW); paths[2]=new Path();
paths[2].addArc(rectF,60,180);
//初始化画笔
paint=new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(1);
} @Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.translate(40, 40);
//从右边开始绘制即右对齐
paint.setTextAlign(Paint.Align.RIGHT);
paint.setTextSize(20);
//绘制路径
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(paths[0], paint);
paint.setStyle(Paint.Style.FILL);
canvas.drawTextOnPath(STR_TITLE, paths[0], -8, 20, paint);//沿着路径绘制文字
//画布下移120
canvas.translate(0,60);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(paths[1], paint);
paint.setStyle(Paint.Style.FILL);
canvas.drawTextOnPath(STR_TITLE, paths[1], -20,20,paint); canvas.translate(0,120);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(paths[2], paint);
paint.setStyle(Paint.Style.FILL);
canvas.drawTextOnPath(STR_TITLE,paths[2],-10,20,paint);
}
}

2、使用Matrix控制图片和View的平移、旋转、缩放等。

2.1、构造Matrix对象

public Matrix();
public Matrix(Matrix src);

2.2、Matrix一些常用的方法

部分方法 用法说明
public void setTranslate(float dx, float dy) 绘制弧形路径
public void setSkew(float kx, float ky, float px, float py) 控制Matrix以(px,py)为轴心进行倾斜,kx,ky为X,Y方向上的倾斜距离
public void setSkew(float px, float py) kx,ky为X,Y方向上的倾斜距离
public void setRotate(float degree) 控制Matrix旋转degree度
public void setRotate(float degree,float px,float py) 控制Matrix以轴心(px,py)旋转degree度
setScale(float sx, float sy, float px, float py) 控制Matrix以(px,py)为轴心缩放,sx,sy为X,Y方向上的缩放距离
void setScale(float sx, float sy)  

2.3、Marix的简单应用

自定义一个使用Matrix的View

/**
* Created by cmo on 16-4-1.
*/
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet; public class CostomView extends View { private Bitmap mBitmap;
private Matrix matrix; public CostomView(Context context) {
super(context);
matrix = new Matrix();
} public CostomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
matrix = new Matrix();
} public CostomView(Context context, AttributeSet attrs) {
super(context, attrs);
matrix = new Matrix();
} public Bitmap getmBitmap() {
return mBitmap;
} public void setmBitmap(Bitmap mBitmap) {
this.mBitmap = mBitmap;
invalidate();
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mBitmap != null) {
canvas.drawBitmap(mBitmap, matrix, null);
}
} public void rotate(float degree) {
if (mBitmap != null) {
matrix.preRotate(degree, mBitmap.getWidth() / 2,
mBitmap.getHeight() / 2);
invalidate();
} }
//平移
public void translate(float dx, float dy) {
if (mBitmap != null) {
matrix.postTranslate(dx, dy);
invalidate();
}
}
//缩放
public void scale(float sx, float sy) {
if (mBitmap != null) {
matrix.postScale(sx, sy);
invalidate();
}
}
//镜像(相当于是照镜子里的自己)
public void mirror() {
if (mBitmap != null) {
matrix.postScale(-1, 1);
matrix.postTranslate(mBitmap.getWidth(), 0);
invalidate();
}
}
//倒影
public void shadow() {
if (mBitmap != null) {
matrix.postScale(1, -1);
matrix.postTranslate(0, mBitmap.getHeight());
invalidate();
}
}
public void skew(float kx, float ky){
if (mBitmap != null) {
matrix.postSkew(kx, ky);
invalidate();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.crazymo.matrixdemo.CostomView
android:id="@+id/costomview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_translate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="平移"/>
<Button
android:id="@+id/btn_scale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="缩放"/>
<Button
android:id="@+id/btn_rotate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="旋转"/> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_skew"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="倾斜"/>
<Button
android:id="@+id/btn_mirro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="镜像"/>
<Button
android:id="@+id/btn_shadow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="倒影"/>
</LinearLayout>
</LinearLayout>
package com.crazymo.matrixdemo;
/**
* Created by cmo on 16-4-1.
*/
public class CostViewActivity extends Activity {
private CostomView mCostomView; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cotomview);
mCostomView = (CostomView) findViewById(R.id.costomview);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.mipmap.bcg);
mCostomView.setmBitmap(bitmap); ((Button) findViewById(R.id.btn_rotate))
.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mCostomView.rotate(15);
}
});
((Button) findViewById(R.id.btn_scale))
.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mCostomView.scale(1.8f, 1.8f);
}
});
((Button) findViewById(R.id.btn_translate))
.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mCostomView.translate(100, 100);
}
});
((Button) findViewById(R.id.btn_skew))
.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mCostomView.skew(-0.3f, 0.3f);
}
});
((Button) findViewById(R.id.btn_mirro))
.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mCostomView.mirror();
}
});
((Button) findViewById(R.id.btn_shadow))
.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mCostomView.shadow();
}
});
}
}

四、Bitmap的简单应用

1、从资源文件中获取Bitmap

Bitmap rawBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.bcg); 

2、从SD卡里获取Bitmap

String SDCarePath=Environment.getExternalStorageDirectory().toString();
String filePath=SDCarePath+"/"+"demo.jpg";
Bitmap rawBitmap1 = BitmapFactory.decodeFile(filePath, null);
InputStream inputStream=getBitmapInputStreamFromSDCard("demo.jpg");
Bitmap rawBitmap2 = BitmapFactory.decodeStream(inputStream);

3、设置图片的圆角,返回设置后的Bitmap

public Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
Bitmap roundCornerBitmap = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(roundCornerBitmap);
int color = 0xff424242;// int color = 0xff424242;
Paint paint = new Paint();
paint.setColor(color);
// 防止锯齿
paint.setAntiAlias(true);
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
RectF rectF = new RectF(rect);
float roundPx = pixels;
// 相当于清屏
canvas.drawARGB(0, 0, 0, 0);
// 先画了一个带圆角的矩形
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
// 再把原来的bitmap画到现在的bitmap!!!注意这个理解
canvas.drawBitmap(bitmap, rect, rect, paint);
return roundCornerBitmap;
}

4、将图片高宽和的大小kB压缩

//得到图片原始的高宽
int rawHeight = rawBitmap.getHeight();
int rawWidth = rawBitmap.getWidth();
// 设定图片新的高宽
int newHeight = 500;
int newWidth = 500;
// 计算缩放因子
float heightScale = ((float) newHeight) / rawHeight;
float widthScale = ((float) newWidth) / rawWidth;
// 新建立矩阵
Matrix matrix = new Matrix();
matrix.postScale(heightScale, widthScale);
// 设置图片的旋转角度
// matrix.postRotate(-30);
// 设置图片的倾斜
// matrix.postSkew(0.1f, 0.1f);
// 将图片大小压缩
// 压缩后图片的宽和高以及kB大小均会变化
Bitmap newBitmap = Bitmap.createBitmap(rawBitmap, 0, 0, rawWidth,rawWidth, matrix, true);

5、将Bitmap转换为Drawable Drawable转Bitmap

Drawable newBitmapDrawable = new BitmapDrawable(Bitmap);
//如果要获取BitMapDrawable中所包装的BitMap对象,可以用getBitMap()方法;
Bitmap bitmap = newBitmapDrawable.getBitmap();

Android入门——Bitmap和BitmapFactory的更多相关文章

  1. android图像与图像处理系列(一、Bitmap和BitmapFactory)

    1.Drawable对象 Android应用添加了Drawabe资源之后,Android SDK会为这份资源文件在R清单文件中创建一个索引项:R.drawable.file_name,接着我们可以在x ...

  2. Android学习之——图形图像处理(Bitmap、BitmapFactory)(一)

    转载自http://blog.csdn.net/csxwc/article/details/10345235 Bitmap是Android系统中的图像处理的最重要的类之一.用它可以获取图像文件信息,对 ...

  3. [Android学习笔记]Bitmap,BitmapDrawable,BitmapFactory学习笔记

    Bitmap:图片文件的封装,可以看做是一张位图此类中的静态方法可以通过源Bitmap创建新的Bitmap对象此类封装了位图的一些信息Bitmap文档 BitmapFactory:一个工具类,用于创建 ...

  4. Android 使用Bitmap将自身保存为文件,BitmapFactory从File中解析图片并防止OOM

    1.使用Bitmap将自身保存为文件 public boolean saveBitmapAsFile(String name, Bitmap bitmap) { File saveFile = new ...

  5. zxing学习笔记 android入门

    对于刚开始学习android开发的童鞋们来说,若有一个简单而又全面的android工程能来剖析,那就是再好不过了,zxing就是不错得例子.    zxing的源码可以到google code上下载, ...

  6. Android入门(十六)调用摄像头相册

    原文链接:http://www.orlion.ga/665/ 一.调用摄像头 创建一个项目ChoosePicDemo,修改activity_main.xml: <LinearLayout xml ...

  7. android 入门-android自定义控件

    第一种:继承View 实现自己的属性 <com.cc.imagewithmarkersample.MyView android:id="@+id/myviewid" andr ...

  8. Android处理Bitmap的一些方法

    http://www.it165.net/pro/html/201305/5795.html # 文件与Bitmap间的方法 1. 从文件载入Bitmap 01./** 02.* @brief 从文件 ...

  9. Android中Bitmap, Drawable, Byte,ID之间的转化

    Android中Bitmap, Drawable, Byte,ID之间的转化 1.  Bitmap 转化为 byte ByteArrayOutputStream out = new ByteArray ...

随机推荐

  1. ArcGIS “Error HRESULT E_FAIL has been returned from a call to a COM component.” 异常的解决

    错误提示内容: {System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been ret ...

  2. [PWA] Deal with caches in PWA

    The takeway is to know when we should cache the content? When we should clean the caches? 1. When sh ...

  3. [Express] Upload Files with Express

    In this lesson we create a new Express web server app for handling file uploads and persisting them ...

  4. 运行 CMD 时,參数加引號常见问题

    在调用 CMD 时.如脚本中用 WScript.Shell 调用. 假设參数中有包括空格的长路径名时,必需要加引號才干正确被识别. 是的,大家都知道要加引號.但怎么加却easy被误解.这个问题,不时地 ...

  5. widget-移除底部小部件内容

    今天有一个要求,就是在调出手机窗口小部件的时候,让其中的某些小部件不显示.折腾了好久,虽然不知道原理,最终还是实现了屏蔽其中个别小部件的方法.记录下来 要想屏蔽底部小部件的显示,只需要把相关的类跟广播 ...

  6. 《三》Java IO 字节输入输出流

    那么这篇博客我们讲的是字节输入输出流:InputStream.OutputSteam(下图红色长方形框内),红色椭圆框内是其典型实现(FileInputSteam.FileOutStream)     ...

  7. CISP/CISA 每日一题 九(2017-11-30 09:25)

    电子银行风险管理责任: 1.风险管理是董事会和高级管理层的责任 2.实施技术是信息技术高级管理层的责任 3.测量和监控风险是经营管理层的责任     管理层在实施一个新的电子银行应用程序之前要 ___ ...

  8. 数学定理证明机械化的中国学派(II)

    所谓"学派"是指:存在一帮人,具有同样或接近的学术观点或学术立场,採用某种特定的"方法"(或途径),在一个学术方向上共同开展工作.而且做出了相当有迎影响的学术成 ...

  9. OR1200指令Cache使用举例

    下面内容摘自<步步惊芯--软核处理器内部设计分析>一书 12.4 ICache中的特殊寄存器 通过ICache的接口可知其具有特殊寄存器,而且是不可读的特殊寄存器,OR1200处理器中IC ...

  10. c3p0的经常使用配置方式

    1:第一种方式很easy c3p0.driverClass=com.mysql.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql://localhost:3308/databas ...