`
ranlic
  • 浏览: 46793 次
社区版块
存档分类
最新评论

Bitmap类getPixels()方法中参数stride理解

阅读更多
  在学习Graphics中遇到位图(Bitmap)中getPixels()方法,对该方法的用法大体理解,但对其中的stride参数却不明白具体的用法以及用意,经过一番折腾后,有些明了,现记述过程如下:

行文有些详细,请赶时间的同学直接跳到红字总结处查看!!
getPixels()方法的用处为获取位图(Bitmap)中的根据方法参数所决定的像素值(颜色值),存入类型为int的pixels数组中,至于从RGB转换为int数值的算法是什么,暂时不知,存疑!!

Android英文SDK中有关getPixels()方法的介绍如下
(引自Android SDK官网,链接请见附后1)

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

Since: API Level 1
Returns in pixels[] a copy of the data in the bitmap. Each value is a packed int representing a Color. The stride parameter allows the caller to allow for gaps in the returned pixels array between rows. For normal packed results, just pass width for the stride value.
Parameters

pixels The array to receive the bitmap's colors
offset The first index to write into pixels[]
stride The number of entries in pixels[] to skip between rows (must be >= bitmap's width). Can be negative.
x The x coordinate of the first pixel to read from the bitmap
y The y coordinate of the first pixel to read from the bitmap
width The number of pixels to read from each row
height The number of rows to read
Throws

IllegalArgumentException if x, y, width, height exceed the bounds of the bitmap, or if abs(stride) < width.
ArrayIndexOutOfBoundsException if the pixels array is too small to receive the specified number of pixels. 


看完英文文档仍然不甚明白,于是去搜了下中文Android文档相应内容,如下(引自农民伯伯博客,链接请见附后2)

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          如果像素数组太小而无法接收指定书目的像素值时将被抛出。

看完后仍然对Stride解释中的"行间距"不太明白,去查了下Stride在英语中的原义
Stride在柯林斯中的英英释义如下


1 If you stride somewhere, you walk there with quick, long steps.
  stride意为"大踏步快速前进"
2 A stride is a long step which you take when you are walking or running.
  stride在此做名词,意为"大步"
3 Someone's stride is their way of walking with long steps.
  指代某人具体迈大步的方式.

于是可以把stride理解为人行走过程中所迈大步的一段距离,而在此方法中可以理解为每行的像素数,至于用处是什么,还要继续寻找答案.

然后去StackOverFlow去搜了搜"getPixels() stride"关键字,查找到如下信息

1  In most cases the stride is the same as the width. The stride is useful if you are trying to copy/draw a sub-region of a Bitmap. For instance, if you have a 100x100 bitmap and you want to draw the 50x50 top-right corner, you can use a width of 50px and a stride of 100px.(链接请见附后3)

2  Stride is number of bytes used for storing one image row.

Stride can be different from the image width.

Most of the images are 4 byte aligned.

For ex. a 24 bit (RGB) image with width of 50 pixels. The total bytes required will be 150 (3(RGB)*50). As image will be 4 byte aligned, in this case the byte required will become 154.

So you will see stride as 154, width 50 and image alignment as 4 byte.(链接请见附后3)

上面内容表示stride参数有两种用处

第一种
可以截取图片中部分区域或者图片拼接.

截图:假设读取像素值的原图片宽为w,高为h,此时设置参数pixels[w*h], 参数stride为 w ,参数offset为0,参数x ,y为截图的起点位置,参数width和height为截图的宽度和高度,则此方法运行后,返回的pixels[]数组中从pixels[0]至pixels[width*height-1]里存储的是从图片( x , y )处起读取的截图大小为width * height的像素值.
示例:修改Android SDK自带的AipDemo程序中BitmapDecode示例,更换图像为自制四角四色图:


图像大小为100*100,想截取图片右上1/4图像(图上黄色部分)修改程序部分代码为:

mBitmap2.getPixels(pixels, 0, w, 50, 0, w/2, h/2);
            String text = String.valueOf(pixels[10]);
            Log.i(SampleView.VIEW_LOG_TAG,text);
            mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h,
                                           Bitmap.Config.ARGB_8888);
            mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h,
                                           Bitmap.Config.ARGB_4444);

运行后得到如下结果:





现在我们看到右边两副ARGB_8888,ARGB_4444图像隐约只在左上角显示原图右上的1/4黄色部分,其余部分为背景色白色,那么问题又来了,此时ARGB_8888,ARGB_4444图像大小为多少?还是原图的大小(100*100)吗,或者是(50*50)了,不然背景色为何是画布的背景色呢?那么把
pixels[100*100]数组设初始值看下情况(通过Log.i()我查到了pixels中存储的像素值为百万左右的负整数,所以这里胡乱取个数-2578654做为初始值,颜色不太好,请见谅),修改后代码如下:
int[] pixels = new int[w*h];
            for(int i=0; i < w*h; i++){
            	pixels[i] = -2578654;
            }
            mBitmap2.getPixels(pixels, 0, w, 50, 0, w/2, h/2);
            String text = String.valueOf(pixels[10]);
            Log.i(SampleView.VIEW_LOG_TAG,text);
            mBitmap3 = Bitmap.createBitmap(pixels, 0, w, w, h,
                                           Bitmap.Config.ARGB_8888);
            mBitmap4 = Bitmap.createBitmap(pixels, 0, w, w, h,
                                           Bitmap.Config.ARGB_4444);

运行后结果为:






这样我们就可以看到结果了,如果pixels[]中的数值为int默认值(0)的话,图片相应的部分就为背景色,如果设置为别的初始值而在运行中没有被修改的话就还是原样.


下面设置下getPixels[]方法中offset,使得黄色部分截图出现在它在原图中的位置,
offset = x + y*w ,本例代码如下:
mBitmap2.getPixels(pixels, 50, w, 50, 0, w/2, h/2);

运行结果如下





当然可以用这个方法进行更复杂的运算,诸如截取素材图片修改目标图片(已存储至pixels数组中)的指定区域!!


图片拼接:

假设两张图片大小都为 w * h ,getPixels()方法中设置参数pixels[2*w*h],参数offset = 0,stride = 2*w读取第一张图片,再次运行getPixels()方法,设置参数offset = w,stride = 2*w,读取第二张图片,再将pixels[]绘制到画布上就可以看到两张图片已经拼接起来了.
示例如下:
int w = mBitmap2.getWidth();
            int h = mBitmap2.getHeight();
            int n = 2*w;
            Log.i(SampleView.VIEW_LOG_TAG,String.valueOf(w*h));
            int[] pixels = new int[n*h];
            for(int i=0; i < n*h; i++){
            	pixels[i] = -2578654;
            }
            mBitmap2.getPixels(pixels, 0, n, 0, 0, w, h);
            mBitmap2.getPixels(pixels, w, n, 0, 0, w, h);
            mBitmap3 = Bitmap.createBitmap(pixels, 0, n, n, h,
                                           Bitmap.Config.ARGB_8888);

运行结果如下
 




第二种: 
stride表示数组pixels[]中存储的图片每行的数据,在其中可以附加信息,即
stride = width + padding,如下图所示(图片引自链接请见附后4)





这样可以不仅仅存储图片的像素信息,也可以储存相应每行的其它附加信息.


最后,stride参数的意义及用处总结如下:

1 用来表示pixels[]数组中每行的像素个数,用于行与行之间区分,绝对值必须大于参数width,但不必大于所要读取图片的宽度w(在width < w 时成立).(stride负数有何作用不知,存疑).另,pixels.length >= stride * height,否则会抛出ArrayIndexOutOfBoundsException 异常

2 stride > width时,可以在pixels[]数组中添加每行的附加信息,可做它用.

附后:
1, int, int, int, int, int, int)]Android英文文档getPixels()方法介绍

2 Android中文文档getPixels()方法介绍

3 StackOverflow中关于getPixels()问答.

4 图片来源
  • 大小: 351 Bytes
  • 大小: 3.6 KB
  • 大小: 22.5 KB
  • 大小: 31.3 KB
  • 大小: 34 KB
  • 大小: 34.7 KB
分享到:
评论
6 楼 舒马赫 2013-04-19  
流弊火火  
5 楼 水木清华77 2013-01-24  
推测stride为负数的时候,应该是从图片的末尾读,倒着读图片
4 楼 hsz001 2012-07-27  
你好,请问下系统提供的 getPixels()方法里面的int[] pixel参数,在取得值之后是按照类似int[width][height]的顺序存储还是按照int[height][width]方式存储呢?
3 楼 lovexp2010 2012-06-20  
  
2 楼 smilett12345 2012-04-01  
受益匪浅
1 楼 renpeng301 2012-03-27  
透彻

相关推荐

    Android Bitmap.getPixels的正确理解演示源码

    Android Bitmap.getPixels的正确理解演示源码,参考文章《Android Bitmap入门:getPixels的正确理解》

    c#Bitmap类和Graphics类

    在本节中,我们将详细介绍Bitmap类和Graphics类的概念、方法和应用场景。 一、Bitmap类 Bitmap类是C#中用于图像处理的基本类,它提供了多种方法来操作图像,包括图像的创建、编辑、显示和保存。Bitmap类的实例可以...

    c#.net Bitmap类的基本使用方法

    在C#.NET编程环境中,`Bitmap`类是用于...通过以上内容,我们可以理解`Bitmap`类在C#.NET中的基本用法,包括创建、加载、显示和操作图像。这为开发者提供了一种灵活的方式,以便在应用程序中实现丰富的图像处理功能。

    Bitmap类和图像像素值获取方法

    C#下读取、修改位置Bitmap,以及几种不同方法修改位图数据

    Android利用BitMap获得图片像素数据的方法

    `getPixels()` 是一个静态方法,用于将Bitmap对象中的像素数据复制到一个整数数组中。其基本用法如下: ```java int[] pixels = new int[bit.getWidth() * bit.getHeight()]; bit.getPixels(pixels, 0, bit....

    Bitmap类和PictureBox控件实现显示,保存

    在C#编程中,`Bitmap`类和`PictureBox`控件是Windows Forms应用程序中用于处理图像的核心组件。本文将深入探讨这两个元素的功能、用法以及如何利用它们来显示和保存图像。 1. `Bitmap`类 `Bitmap`是.NET Framework...

    Android bitmap工具类

    在Android开发中,Bitmap是用于处理图像的基本类,它提供了对像素级别的操作。BitmapUtils工具类是为了方便开发者在处理图片时进行各种操作,比如转换、压缩、存储等。本篇文章将详细探讨`Android bitmap工具类`,...

    Android canvas drawBitmap方法详解及实例

    `drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)`是`drawBitmap()`方法的一个重载版本,其参数含义如下: 1. **Bitmap bitmap**: 这是你要绘制的位图对象,通常是从资源文件、内存缓存或者直接创建的...

    Android bitmap图片压缩工具类

    在BitmapCompressUtils中,可能存在一个`compressToJPEG(Bitmap bitmap, int quality, OutputStream out)`方法,它使用JPEG格式进行压缩,其中quality参数表示质量,范围是0到100,数值越小,压缩程度越大,图片质量...

    Android下利用Bitmap切割图片

    在Android开发中,Bitmap是处理图像的基本类,用于在内存中表示位图图像。当我们需要对图片进行裁剪、缩放或进行其他操作时,Bitmap提供了丰富的功能。本篇文章将详细探讨如何在Android环境下利用Bitmap来切割图片。...

    Android中使用Bitmap类的简要介绍.pdf

    Bitmap类在Android系统中扮演着图像处理的核心角色,它提供了加载、操作和保存图像的功能。由于Bitmap构造函数是私有的,我们无法直接实例化,而是通过BitmapFactory类来创建Bitmap对象。BitmapFactory提供了多种...

    bitmap理解学习例子

    Bitmap是Android系统中用于处理图像的核心类,它在Android应用开发中扮演着至关重要的角色。Bitmap对象代表了图像数据,可以是位图(如PNG、JPEG或BMP格式)或者是可绘制对象(如通过Canvas绘制的图形)。在这个...

    Android中把bitmap存成BMP格式图片的方法

    在示例代码中,我们先通过`getDrawingCache()`方法获取View的绘制缓存,然后调用`getPixels()`方法得到Bitmap的像素数据。像素数据通常存储在一个整型数组中,每个像素由红、绿、蓝三原色的值表示。 2. **处理BMP...

    Android bitmap

    如果图像存储在设备的文件系统中,可以通过`decodeFile()`方法来创建Bitmap。例如,从SD卡上的一个JPEG文件加载Bitmap: ```java Bitmap bmp = BitmapFactory.decodeFile("/sdcard/dcim/tianjin.jpeg"); ``` 3....

    C#中bitmap、stream、byte类型转换实例

    1. **Bitmap**: Bitmap是System.Drawing命名空间中的一个类,它代表了一个像素图,可以是位图或矢量图。Bitmap对象可以直接显示在窗体上,也可以保存为图像文件。 2. **Stream**: Stream是System.IO命名空间中的...

    MFC学习bitmap的代码类

    在Microsoft Foundation Classes (MFC) 中,Bitmap 是一个重要的图形对象,用于在应用程序中显示和处理位图图像。MFC 提供了一个 CBitmap 类来封装Windows API中的位图操作。这个"BitmapDemo"可能是一个教学示例,...

    bitmap工具类

    Bitmap工具类是Android开发中非常关键的一个部分,主要用于处理图像数据,尤其是在内存管理上起着至关重要的作用。在Android系统中,Bitmap对象是用于存储像素数据的,它消耗大量的内存,如果处理不当,很容易引发...

    android中对Bitmap图片设置任意角为圆角

    1. 创建一个圆形Bitmap,可以通过Bitmap.createBitmap方法,传入宽度、高度和配置参数,再使用BitmapShader的TileMode.CLAMP模式来填充圆形区域。然后,创建一个Paint对象,并设置其颜色过滤器(colorFilter)为...

    Bitmap类源文件

    java实现的Bitmap类 用于自动生成Bitmap文件头和填充调色板等,目前只支持8位256色的Bitmap

    android bitmap outOfMemory解决方法

    在Android开发中,Bitmap对象是用于处理图像的主要类,但如果不正确管理,它可能导致应用程序运行时出现`OutOfMemoryError`。这是因为Bitmap占用大量的内存,尤其是当加载大尺寸或高分辨率图片时。这个问题在低内存...

Global site tag (gtag.js) - Google Analytics