深入学习Bitmap-android的图片扫描

来源:互联网 发布:淘宝宝贝详情尺寸大小 编辑:程序博客网 时间:2024/05/16 10:14
我这个实例是将一个位图用几秒钟扫描,然后得到它的反色图。做这个实例主要是想研究下Bitmap类和Color类,重点是getPixe和setPix的这两个方法的用法。
先上图看效果

相关代码:

public class SkanBitmap extends Activity {
    /** Called when the activity is first created. */
        private Bitmap bm;//要扫描的图片
        private Bitmap pm;//扫描后得到的图片
        private int width,height;//图片的宽和高
        private Button button;
        private ImageView imageview;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        button=(Button)findViewById(R.id.button);
        imageview=(ImageView)findViewById(R.id.imageView);
        bm=BitmapFactory.decodeResource(getResources(), R.drawable.sssd);//从资源文件中得到一个位图
            width=bm.getWidth();//获取位图的宽
            height=bm.getHeight();//获取位图的高
            button.setOnClickListener(new OnClickListener(){
                        @Override
                        public void onClick(View arg0) {
                                // TODO Auto-generated method stub
                                //新建一个宽是width,高是height,图片格式是RGB_565的空位图。
                                pm=Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
                                imageview.setImageBitmap(pm);
                                new thread().start();//开始扫描图片的线程
                        }
                });
    }
   
    // 扫描图片的线程
    class thread extends Thread{
                 public void run() {
                        button.setClickable(false);//暂时将按钮的点击事件屏蔽掉,保证一次只开启一个线程
                        int[] colors=new int[width];//取一行图片的像素点
                         for(int i=0;i<height;i++){
                                 //将位图bm的第i行的像素放入到数组 colors中去
                            bm.getPixels(colors, 0, width, 0, i, width, 1);
                            for(int j=0;j<colors.length;j++){
                            //将颜色数组中的RGB值取反,255减去当前颜色值就获得当前颜色的反色
                                        colors[j]=Color.rgb(255-Color.red(colors[j]),
                                                        255-Color.green(colors[j]), 255-Color.blue(colors[j]));
                                        }
                            pm.setPixels(colors, 0, width, 0, i, width, 1);//颜色取反后,将像素加入到pm的第i行中去
                            imageview.postInvalidate();//刷新图片
                         }
                        button.setClickable(true);//重新监听按钮的点击事件

                       
          }
       }
   

}


bm.getPixels(colors, 0, width, 0, i, width, 1);
colors是用于存放像素的数组,参数中i是取第i行的像素,第二个width是每行去width个像素,我就是取整行的像素,1是只选择取一列。
colors[j]=Color.rgb(255-Color.red(colors[j]), 255-Color.green(colors[j]), 255-Color.blue(colors[j]));
分别取得颜色值得R、G、B通道值,然后取反后封装成一个新的颜色值。

其实本实例的效果有多种方法可以实现,可以用getPixel(int x, int y)与        setPixel(int x, int y, int color)去实现,也可以用getPixels(int[] pixels, int offset, int stride, int x, int y, int width, int height)与setPixels(int[] pixels, int offset, int stride, int x, int y, int width, int height)去实现。
要说明的是,获取像素和设置像素是一个比较耗时的操作。我尝试了多种方法,发现一个点一个点去获取像素和设置像素的话,非常耗时,而一行行的区操作像素效果最好。其实我本来想一竖排一竖排去获取并设置像素的,可是发现用getPixels(int[] pixels, int offset, int stride, int x, int y, int width, int height)与setPixels(int[] pixels, int offset, int stride, int x, int y, int width, int height)去实现并不适用,它并不能像一行行那样类似的去操作,我也纳闷android的这个地方怎么就行不通,或许是自己还没有找对方法。


Color类android.graphics.Color

此类 定义了一些方法来创建和转换颜色值。颜色被表示为封装的数值,这个数值由四个字节组成,分别是:alpha、red、green、blue,这些值是非自 左乘的,也就是说任何透明性只存储在alpha部分,而不是在颜色组成部分。每一部分按照如下的顺序保存:(alpha<<24)| (red<<16)|<green<<8)|blue.每一部分的取值范围在0-255之间,0意味着这部分不起作 用,255表示100%的起作用。因此不透明的黑色应该是0xFF000000,不透明的白色应该是0xFFFFFFFF 。
Color类提供了12个常量值来代表不同的颜色值,我们在开发工程中可以直接调用这些常量值来设置我们所要修饰的文本、图形等对象。

public int getPixel (int x, int y)

返回指定位置的像素颜色值。如果x或y越界(负数,或各自大于等于宽度或高度值),讲抛出一个异常。

参数

x        待返回像素的x坐标值(0-width-1)。

                 y        待返回像素的y坐标值(0-height-1)

    返回值

                   指定坐标的argb颜色值。

  异常

                   如果x,y越界,IilegalArgumentExcepiton将被抛出。



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

把位图的数据拷贝到pixels[]中。每一个都由一个表示颜色值的int值来表示。幅度参数表明调用者允许的像素数组行间距。对通常的填充结果,只要传递宽度值给幅度参数。

参数

pixels       接收位图颜色值的数组

offset      写入到pixels[]中的第一个像素索引值

stride        pixels[]中的行间距个数值(必须大于等于位图宽度)。不能为负数

x          从位图中读取的第一个像素的x坐标值。

                 y             从位图中读取的第一个像素的y坐标值

                 width       从每一行中读取的像素宽度

                 height   读取的行数               

  异常

                   IilegalArgumentExcepiton       如果x,y,width,height越界或stride的绝对值小于位图宽度时将被抛出。

                   ArrayIndexOutOfBoundsException          如果像素数组太小而无法接收指定书目的像素值时将被抛出

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

把指定的颜色写入到位图中x,y的坐标值的位置(假设该位图是可变的)。

参数

X               待替换像素的x坐标(0到width-1)。

Y               待替换像素的y坐标(0到height-1)

color         写入到位图的颜色值

抛出

         IilegalStateException                      如果这个位图不可改变

IIlegalArgumentException   如果x,y的值超出位图的边界



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

用数组中的颜色值替换位图的像素值。数组中的每个元素是包装的整型,代表了颜色值。

参数

      pixels        写到位图中的颜色值

offset        从pixels[]中读取的第一个颜色值的索引

stride        位图行之间跳过的颜色个数。通常这个值等于位图宽度,但它可以更更大(或负数)

X               被写入位图中第一个像素的x坐标。

Y               被写入位图中第一个像素的y坐标

width        从pixels[]中拷贝的每行的颜色个数

height       写入到位图中的行数

异常

      IilegalStateException                      如果这个位图不可改变

IIlegalArgumentException   如果x,y,width,height的值超出位图的边界

ArrayIndexOutOfBoundsException 如果像素队列太小以致不能接受指定的像素位数。


源码在我的这一篇博客上有:

http://www.eoeandroid.com/thread-151806-1-1.html





原创粉丝点击