bitmap 介绍

学习android,总感觉做了很多东西,回头望望又发现自己其实也没涉及多少方面,想想干脆总结或者说翻译下sdk的东东。

    讲到Bitmap,不能不提BItmapFactory,BItmapFactory在sdk上的简介是从包括文件,数据流,数组的资源中生成Bitmap对象.它的功能也的确实如此,它里边除了一个内部类BitmapFactory.Options之外就全是静态函数,全部是用来生成Bitmap的.

static Bitmap  decodeFile(String pathName)  
static Bitmap  decodeFile(String pathName, BitmapFactory.Options opts) 

这两个函数是从文件系统中读取图片,用法如下

       Bitmap b1;

       b1=BitmapFactory.decodeFile("/mnt/sdcard/audio/ic_launcher.png");
这是模拟器中的读取方法,在手机上读取sdcard上的文件应该是

       b1=BitmapFactory.decodeFile("/sdcard/audio/ic_launcher.png");

static Bitmap  decodeByteArray(byte[] data, int offset, int length)  
static Bitmap  decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options opts) 

这两个函数是从字节数组中生成Bitmap,函数调用没什么特别的,关键是字节数组怎么来,目前发现这两种方法生成:
       ByteArrayOutputStream os=new ByteArrayOutputStream();
       b1.compress(Bitmap.CompressFormat.JPEG, 10, os);
       byte data[]=os.toByteArray();
       b2=BitmapFactory.decodeByteArray(data, 0, data.length);
这种方法是把OutputStream转化成byte数组,另一种方法是把InputStream转化成OutputStream然后再转化成byte数组,因为从资源中读取出来的都是InputStream,然而BitmapFactory提供了从InputStream生成Bitmap的函数,所以这种方法其实没多少必要,但是也看一下:
       is=context.getResources().openRawResource(R.drawable.gallery_photo_5);
       ByteArrayOutputStream os2=new ByteArrayOutputStream(1024);
       byte buffer[]=new byte[1024];
       int len;
          try {
              while ((len = is.read(buffer)) >= 0) {
                  os2.write(buffer, 0, len);
              }
          } catch (java.io.IOException e) {
          }
          byte data2[]=os2.toByteArray();
          b3=BitmapFactory.decodeByteArray(data2, 0, data2.length);
中间的offset一般是0,但是有时候也不一定,要看数组data的内容,有时候data的可能不全是图片信息。

static Bitmap  decodeFileDescriptor(FileDescriptor fd)  
static Bitmap  decodeFileDescriptor(FileDescriptor fd, Rect outPadding, BitmapFactory.Options opts) 
这两个函数跟decodeFile是差不多的,都是从文件系统中获取图片,只不过一个是通过路径,一个是文件描述符,应用如下:
          FileInputStream fi;
          FileDescriptor fd=null;
          try{
          fi=new FileInputStream("/mnt/sdcard/audio/ic_launcher.png");
          fd=fi.getFD();
          }catch(java.io.IOException e)
          {
           
          }
        if(fd!=null)         
          b3=BitmapFactory.decodeFileDescriptor(fd);  
第2个函数多了一个Rect outPadding,这个矩形是用来给Bitmap与其他元素分开的间隔用的,就是padding.

static Bitmap  decodeResource(Resources res, int id, BitmapFactory.Options opts)  
static Bitmap  decodeResource(Resources res, int id) 

这两个函数的调用简单,如下:
          b1=BitmapFactory.decodeResource(context.getResources(), R.drawable.gallery_photo_5);

static Bitmap  decodeStream(InputStream is)       
static Bitmap  decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts) 

这两个函数调用跟上两个差不多,如下:
       is=context.getResources().openRawResource(R.drawable.gallery_photo_5);
       b1=BitmapFactory.decodeStream(is);
在讲byte数组如何生成的时候其实就已经可以用这个函数生成Bitmap了

static Bitmap  decodeResourceStream(Resources res, TypedValue value, InputStream is, Rect pad, BitmapFactory.Options opts)  
 这个函数跟 decodeStream差不多, res,value参数都是为了给opts赋值的,其参考代码如下
    public static Bitmap decodeResourceStream(Resources res, TypedValue value,
            InputStream is, Rect pad, Options opts) {

        if (opts == null) {
            opts = new Options();
        }

        if (opts.inDensity == 0 && value != null) {
            final int density = value.density;
            if (density == TypedValue.DENSITY_DEFAULT) {
                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
            } else if (density != TypedValue.DENSITY_NONE) {
                opts.inDensity = density;
            }
        }
        
        if (opts.inTargetDensity == 0 && res != null) {
            opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
        }
        
        return decodeStream(is, pad, opts);
    }
用法如下
        final TypedValue value = new TypedValue();  
        is=context.getResources().openRawResource(R.drawable.gallery_photo_5,value);
        b1=BitmapFactory.decodeResourceStream(context.getResources(), value, is, null, null);

BitmapFactory基本就这些函数,全是用来生成Bitmap的,不愧为它的字面意思,生产Bitmap的工厂。
全部代码如下

package com.android.blog;

import android.view.View;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.TypedValue;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileDescriptor;
public class BlogView extends View{
Bitmap b1,b2,b3;
InputStream is;
public BlogView(Context context)
{
       super(context);
       b1=BitmapFactory.decodeFile("/mnt/sdcard/audio/ic_launcher.png");
          b1=BitmapFactory.decodeResource(context.getResources(), R.drawable.gallery_photo_5);  
       ByteArrayOutputStream os=new ByteArrayOutputStream();
       b1.compress(Bitmap.CompressFormat.JPEG, 10, os);
       byte data[]=os.toByteArray();
       b2=BitmapFactory.decodeByteArray(data, 0, data.length);
       is=context.getResources().openRawResource(R.drawable.gallery_photo_5);
       b1=BitmapFactory.decodeStream(is);
       ByteArrayOutputStream os2=new ByteArrayOutputStream(1024);
       byte buffer[]=new byte[1024];
       int len;
          try {
              while ((len = is.read(buffer)) >= 0) {
                  os2.write(buffer, 0, len);
              }
          } catch (java.io.IOException e) {
          }
          byte data2[]=os2.toByteArray();
          b3=BitmapFactory.decodeByteArray(data2, 0, data2.length);
          FileInputStream fi;
          FileDescriptor fd=null;
          Rect r1=new Rect(10,10,20,20);
          try{
          fi=new FileInputStream("/mnt/sdcard/audio/ic_launcher.png");
          fd=fi.getFD();
          }catch(java.io.IOException e)
          {
           
          }
        if(fd!=null)         
          b3=BitmapFactory.decodeFileDescriptor(fd,r1,null);
        final TypedValue value = new TypedValue();  
        is=context.getResources().openRawResource(R.drawable.gallery_photo_5,value);
        b1=BitmapFactory.decodeResourceStream(context.getResources(), value, is, null, null);
}
@Override
protected void onDraw(Canvas canvas)
{
 Paint p=new Paint();
 canvas.drawColor(Color.WHITE);
 canvas.drawBitmap(b1, 10, 10, p);
 canvas.drawBitmap(b2, 50, 50, p);
 canvas.drawBitmap(b3, 100, 100, p); 

}
}



这节讲述Bitmap,首先可以看到它里边有两个枚举类,一个是Bitmap.CompressFormat,另一个是Bitmap.Config。第一个包含的是Bitmap可用于指定的压缩格式,有JPEG,PNG,WEBP三种格式。第二个包含的是Bitamap的有可能用到的颜色组合,有ALPHA_8 ,ARGB_4444,ARGB_8888,RGB_565。明显可以看出ARGB_4444是ARGB_8888的低质量组合状态,RGB_565是一种比较常用的颜色组合方式,尤其是在空间比较紧张又希望图片质量不太差的时候经常使用这种颜色组合。接下来有常量

intDENSITY_NONE
这个常量标示着Bitmap创建时用的是一个未知的density。

   下面开始看函数功能:

public boolean compress (Bitmap.CompressFormat format, int quality, OutputStream stream)

Bitmap在指定的输出流上写入一个压缩的版本,根据format,quality。quality比较压缩版本的质量,最大值为100,像png这样的无损耗的压缩格式,quality的值会被忽略。如果该函数返回true,那么Bitmap可以从BitmapFactory中重新读取一个输入流,变成另一个图片。注意不是所有的格式都支持所有的颜色组合方式,所以Bitmap通过BitmapFactory生成的时候可能就拥有不同的颜色组合方式,有可能会失去每个点的透明度(比如JPEG就只支持不透明的点)

public Bitmap copy (Bitmap.Config config, boolean isMutable)

 按Bitmap的尺寸创建一个新的Bitmap,具体方法为指定一个颜色组合方式,然后将Bitmap中的点都复制到新Bitmap中,如果这种转变或者复制不成功的话将会返回null,   isMutable表示新生成的Bitmap中的点是否可以改变,true为可以,值得注意的是新生成的bitmap和老bitmap有相同的density

public void copyPixelsFromBuffer (Buffer src)

从buffer中复制点到Bitmap中,并且从初始位置开始会覆盖掉Bitmap中原来的点,复制过程中buffer的点不会以任何方式改变,不管原bitmap格式如何都会以32位的方式写入

public void copyPixelsToBuffer (Buffer dst)

将Bitmap中的点复制到指定的buffer当中,如果dst的空间不够大不能容下bitmap中的所有点,或者dst不是ByteBuffer, ShortBuffer, IntBuffer这三种之一,那么函数会抛出异常

 

public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)

静态函数,从目标bitmap中截取一段点集返回一个不可改变的bitmap,截取的范围由Matrix m来决定,返回的bitmap和目标有相同的density,x,y,width,height分别为目标的起点和宽高,filter表示目标是否需要过滤,只有在Matrix包含更多信息的时候才会用到。

public static Bitmap createBitmap (int width, int height, Bitmap.Config config)

返回一个指定了宽高的可以改变里边的点的内容的bitmap,它的density来源于当前屏幕的density。

public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height)

返回一个不可改变的bitmap,该bitmap与目标bitmap内容一样。

public static Bitmap createBitmap (int[] colors, int offset, int stride, int width, int height,Bitmap.Config config)

返回一个不可改变的bitmap,里边的点的值有colors数组一一对应的设定,offset表示colors数组中的颜色值是从哪个下标开始,stride表示colors数组中每一行有多少个颜色值,该值必须大于width。当width,height没有大于0,或者数组的长度小于bitmap的点的数量时就会抛出异常。

public static Bitmap createBitmap (Bitmap src)

创建一个目标bitmap的复制样本bitmap,并且该样本不可改变。

public static Bitmap createBitmap (int[] colors, int width, int height, Bitmap.Config config)

返回一个不可改变的bitmap,里边的点的值有colors数组一一对应的设定。

public static Bitmap createScaledBitmap (Bitmap src, int dstWidth, int dstHeight, boolean filter)

返回一个由目标bitmap按比例缩放了的新bitmap,该bitmap的宽高由dstWidth,dstHeight决定。

public int describeContents ()

返回一个标志位,标志着指定目标类型在包里边被整理的设置

public void eraseColor (int c)

将指定颜色填满到bitmap中,当该bitmap不可改变时将会抛出异常

public Bitmap extractAlpha ()

返回一个新的bitmap,该bitmap包含了目标bitmap的所有ARGB中的A值,它可以通过Canvas.drawBitmap()画出来,因为颜色值可以由paint补充到画布上

public Bitmap extractAlpha (Paint paint, int[] offsetXY)

返回一个新的bitmap,该bitmap包含了目标bitmap的所有ARGB中的A值,由于该bitmap的值会被paint所影响,比如paint有自己的A值,或者是存在着模糊不清的东东来改变该bitmap的尺寸,所以加入了offsetXY的参数,当offsetXY不为null时,它返回的是生成的bitmap能更好的符合目标bitmap的位移,比如paint包含一块半径为2的污迹,那么offsetXY包含-2,-2,然后画生成bitmap的时候从-2,-2开始画,能让paint的污迹在显示结果上跟目标bitmap更相近。

public final int getByteCount ()

返回有多少字节用来存储该bitmap的点

public final Bitmap.Config getConfig ()

如果目标bitmap的颜色组合方式是Bitmap.Config中的那几种之一,那么返回该组合方式,否则返回null

public int getDensity ()

获取该bitmap的density,默认的density跟当前屏幕的density是一样的,除非当前应用不支持多种屏幕density,不管什么情况都用系统默认的density,注意兼容方式由应用的开始的加载工序所决定--分享相同的工序,拥有相同的density,能确保大家明白无误的给bitmap设定一个正确的density。

public int getGenerationId ()

获取bitmap的当前id,当bitmap发生改变时,当前id会同时发生改变,这样判断bitmap有没有改变的一个有效的方法就是检查它的当前id。

public final int getHeight ()

获取高度

public byte[] getNinePatchChunk ()

返回一个选项数组,由UI系统应用在某些bitmap上,不会刻意的被应用所访问

public int getPixel (int x, int y)

返回该bitmap在当前点的颜色值,当x,y不在bitmap的范围内的时候会抛出异常

public void getPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)

获取bitmap的内容一个数组,pixels每个值都是该bitmap在对应点上的颜色值,参数stride表示要将bitmap中的行与行之间的颜色值也存储在数组中,不过一般情况下该值都是取width

public final int getRowBytes ()

计算bitmap中行与行之间所包含的字节数,注意这指的是bitmap一开始时存在的行间字节数,如果你用了getPixels和setPixels(),,那么该bitmap中的每一个点都变成32位的颜色值了

public int getScaledHeight (int targetDensity)

返回bitmap的比例高度,比例因子为画布的当前density除以bitmap的density

public int getScaledHeight (DisplayMetrics metrics)
public int getScaledHeight (Canvas canvas)
public int getScaledWidth (DisplayMetrics metrics)
public int getScaledWidth (int targetDensity)
public int getScaledWidth (Canvas canvas)

获取比例高度或者比例宽度,比例因子与给定的参数有关

public final int getWidth ()

获取宽度

public final boolean hasAlpha ()

判断该bitmap是否有透明点,如过为false,可以标记该bitmap不含有任何透明点,比如RGB_565的方式,就可以知道没有任何透明点

public final boolean isMutable ()

返回值表示该bitmap是否可被改变

public final boolean isRecycled ()

判断该bitmap是否被重复应用,如果是的话那么使用它的点会报错,并且它不会被画出来

public void prepareToDraw ()

重建任何跟画出ibtmap有关联的内存,对于要清除的bitmaps来说,该调用有利于确定它的每个点都被解码了,如果这个方法被好几个bitmap按顺序调用,那么它使用的优先级是先进后出,比如最后一个调用的拥有最高的优先级,如果bitmap没有跟它有关联的内存,那么这个调用也是无害的

public void recycle ()

释放与该bitmap相关联的对象,并且清除它的点数据的引用,但是不会同步的清除点数据,点数据会被简单的当成垃圾回收,当它没有任何引用的时候。该bitmap被标记死亡的话,调用getPixels() or setPixels()都会抛出异常,并且不会画出任何东西,该操作不可被逆转,所以当你要调用它时,你要确定该bitmap是不打算用了的,这是一个很超前的调用方法,正常是不需要调用的,因为垃圾回收器会自动将它回收,在该bitmap没有任何引用的时候

public boolean sameAs (Bitmap other)

判断该bitmap是否与other拥有相同的尺寸,颜色组合方式,点数据,,如果有一项不一样,就返回false,如果other为null,那就返回false

public void setDensity (int density)

给bitmap设置一个density,当画到canvas的时候,canvas也有一个density,那么bitmap会适当的缩放

public void setHasAlpha (boolean hasAlpha)

当知道该bitmap全不都是不透明的点或者知道它有部分透明点后,给它设置的一个标志,像RGB_565的编码方式,这个调用是被忽略的,因为它全是不透明点,这个标志在画bitmap的时候可以作为一个画的线索,当知道全部是不透明点时可以画得更快比有可能有透明点的时候

public void setPixel (int x, int y, int color)

设置x,y点的颜色值

public void setPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)

将bitmap中的点全部用pixels中的点相应的代替,参数与getPixels类似,当bitmap不可改变时,或者x,y,width,height超出了bitmap的边界时,或者pixels小于不能支持指定的点数目时都会抛出异常

public void writeToParcel (Parcel p, int flags)

将该bitmap和它的数据写到块里边去,该bitmap可以被重建,通过调用CREATOR.createFromParcel().

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值