我们都知道一个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. python3 时间处理

    1 标记当前时间 import datetime from dateutil import tz #标记当前时间为中国时间 注意(replace 只有标记的意思没有转化的意思) datetime.da ...

  2. 引用 Windows Server 2003 FTP服务器配置详解

    引用 昆神之星 的 Windows Server 2003 FTP服务器配置详解 1.FTP文件传输协议,主要用于计算机之间文件传输,是互联网上仅次于www的第二大服务.本文主要演示如何在Window ...

  3. 阿姆达尔定律(Amdahl's law)

    首先给出阿姆达尔定律的数学公式描述: S(N)=1(1−p)+pN p:程序中可并行部分的程序在单核上执行时间的占比: N:处理器的数目(总的核心数) S(N):程序在 N 个处理器(总核心数)相对在 ...

  4. diff命令具体解释

    diff命令參数: diff - 找出两个文件的不同点 总览 diff [选项] 源文件 目标文件 以下是 GNU所接受的 diff 的全部选项的概要. 大多数的选项有两个同样的名字,一个是单个的跟在 ...

  5. Myeclipse的默认工作区间怎么恢复提示框?

    好久一直使用默认工作空间.现在,回过头来想让那个提示框回来. 该如何做呢? 1.找到我们的myeclipse安装目录下的 2.false是关闭. 3.改成true 4.同时,新增新的工作区间和之前旧的 ...

  6. ORACLE10g R2【单实例 FS→单实例FS】

    ORACLE10g R2[单实例FS→单实例FS] 本演示案例所用环境:   primary standby OS Hostname pry std OS Version RHEL5.8 RHEL5. ...

  7. sql server中新增一条数据后返回该数据的ID

    开发中遇到的问题:在新增一条数据后往往不需要返回该数据的ID,但是有的时候可能需要返回该数据的ID以便后面的编程使用. 在这里介绍两种方法: 其一:使用存储过程: create procedure a ...

  8. c++ 常识

    1)  功能:格式化字符串输出    说明:format指定输出格式,后面跟要输出的变量        目前printf支持以下格式:          %c        单个字符          ...

  9. 洛谷——U10206 Cx的治疗

    https://www.luogu.org/problem/show?pid=U10206 题目背景 「Cx的故事」众所周知,Cx是一个宇宙大犇.由于Cx在空中花园失足摔下,导致他那蕴含着无穷智慧的大 ...

  10. 使用 STL 辅助解决算法问题

    不要重复制造轮子,而且你造的轮子未必比得上别人的: <numeric>⇒ accumulate,累积容器中区间的和,可以指定初值: 为什么 STL 中的容器和算法一定关于区间的操作一定是左 ...