Android入门——Bitmap和BitmapFactory

Posted brave-sailor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android入门——Bitmap和BitmapFactory相关的知识,希望对你有一定的参考价值。

我们都知道一个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的主要内容,如果未能解决你的问题,请参考以下文章

Android入门——Bitmap和BitmapFactory

Android BitmapFactory.Options 解决大图片加载OOM问题

ImageView学习

《Android开发艺术探索》之Bitmap的加载和Cache(十四)

Android:安卓学习笔记之Bitmap的简单理解和使用

Android:安卓学习笔记之Bitmap的简单理解和使用