Android Bitmap 载入与像素操作

一:载入与像素读写

在Android SDK中,图像的像素读写能够通过getPixel与setPixel两个Bitmap的API实现。

Bitmap API读取像素的代码例如以下:

int pixel = bitmap.getPixel(col, row);// ARGB
int red = Color.red(pixel); // same as (pixel >> 16) &0xff
int green = Color.green(pixel); // same as (pixel >> 8) &0xff
int blue = Color.blue(pixel); // same as (pixel & 0xff)
int alpha = Color.alpha(pixel); // same as (pixel >>> 24)

得到像素pixel是32位的整数,四个字节分别相应透明通道、红色、绿色、蓝色通道。

Bitmap API 写入像素,代码例如以下:

bm.setPixel(col, row, Color.argb(alpha, red, green, blue));

通过Color.argb又一次组装成一个int的像素值。

使用BitmapFactory.decodeFile或者decodeResource等方法实现载入图像的Bitmap对象时。这些方法就会为要构建的Bitmap对象分配合适大小的内存。假设原始的图像文件数据非常大,就会导致DVM不能分配请求的内存大小。从而导致OOM(out of memory)问题。而通过配置BitmapFactory.Option预先读取图像高度与宽带,图像进行适当的下採样,就能够避免OOM问题的发生。预先仅仅获取图像高度与宽带的代码例如以下:

        // 获取Bitmap图像大小与类型属性
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(),
R.drawable.shar_03, options);
int height = options.outHeight;
int width = options.outWidth;
String imageType = options.outMimeType;

基于下採样载入超大Bitmap图像的缩小版本号:

        // 下採样
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2;
final int halfWidth = width / 2; // Calculate the largest inSampleSize value
// that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
// 获取採样后的图像显示。避免OOM问题
options.inJustDecodeBounds = false;
srcImage = BitmapFactory.decodeResource(getResources(), R.drawable.shar_03, options);

二:像素操作

android彩色图像灰度化的三个简单方法

灰度化方法一:

灰度值GRAY = (max(red, green, blue) + min(red, green, blue))/2

灰度化方法二:

灰度值GRAY = (red + green + blue)/3

灰度化方法三:

灰度值GRAY = red*0.3 + green*0.59 + blue*0.11

代码实现例如以下:

public Bitmap gray(Bitmap bitmap, int schema)
{
Bitmap bm = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), bitmap.getConfig());
int width = bitmap.getWidth();
int height = bitmap.getHeight();
for(int row=0; row<height; row++){
for(int col=0; col<width; col++){
int pixel = bitmap.getPixel(col, row);// ARGB
int red = Color.red(pixel); // same as (pixel >> 16) &0xff
int green = Color.green(pixel); // same as (pixel >> 8) &0xff
int blue = Color.blue(pixel); // same as (pixel & 0xff)
int alpha = Color.alpha(pixel); // same as (pixel >>> 24)
int gray = 0;
if(schema == 0)
{
gray = (Math.max(blue, Math.max(red, green)) +
Math.min(blue, Math.min(red, green))) / 2;
}
else if(schema == 1)
{
gray = (red + green + blue) / 3;
}
else if(schema == 2)
{
gray = (int)(0.3 * red + 0.59 * green + 0.11 * blue);
}
bm.setPixel(col, row, Color.argb(alpha, gray, gray, gray));
}
}
return bm;
}

Bitmap图像镜像映射与亮度调整的代码实现例如以下:

public Bitmap brightness(Bitmap bitmap, double depth)
{
Bitmap bm = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), bitmap.getConfig());
int width = bitmap.getWidth();
int height = bitmap.getHeight();
for(int row=0; row<height; row++){
for(int col=0; col<width; col++){
int pixel = bitmap.getPixel(col, row);// ARGB
int red = Color.red(pixel); // same as (pixel >> 16) &0xff
int green = Color.green(pixel); // same as (pixel >> 8) &0xff
int blue = Color.blue(pixel); // same as (pixel & 0xff)
int alpha = Color.alpha(pixel); // same as (pixel >>> 24)
double gray = (0.3 * red + 0.59 * green + 0.11 * blue);
red += (depth * gray);
if(red > 255) { red = 255; } green += (depth * gray);
if(green > 255) { green = 255; } blue += (depth * gray);
if(blue > 255) { blue = 255; }
bm.setPixel(col, row, Color.argb(alpha, red, green, blue));
}
}
return bm;
} public Bitmap flip(Bitmap bitmap)
{
Bitmap bm = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), bitmap.getConfig());
int width = bitmap.getWidth();
int height = bitmap.getHeight();
for(int row=0; row<height; row++){
for(int col=0; col<width; col++){
int pixel = bitmap.getPixel(col, row);// ARGB
int red = Color.red(pixel); // same as (pixel >> 16) &0xff
int green = Color.green(pixel); // same as (pixel >> 8) &0xff
int blue = Color.blue(pixel); // same as (pixel & 0xff)
int alpha = Color.alpha(pixel); // same as (pixel >>> 24)
int ncol = width - col - 1;
bm.setPixel(ncol, row, Color.argb(alpha, red, green, blue));
}
}
return bm;
}

执行截图:



布局XML文件内容例如以下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.imageprocess1.MainActivity" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/button_gray_3"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@string/process" /> <Button
android:id="@+id/button_inverse"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/button_gray_3"
android:layout_alignTop="@+id/button_gray_3"
android:text="@string/inverse" /> <Button
android:id="@+id/button_gray_1"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/button_inverse"
android:layout_alignTop="@+id/button_gray_3"
android:text="@string/nored" /> <Button
android:id="@+id/button_gray_2"
android:layout_width="100dp"
android:layout_below="@+id/button_gray_3"
android:layout_height="wrap_content"
android:text="@string/noblue" /> <Button
android:id="@+id/button_flip"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_below="@+id/button_inverse"
android:layout_toRightOf="@+id/button_gray_2"
android:text="@string/flip" />
<Button
android:id="@+id/button_save"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_below="@+id/button_gray_3"
android:layout_toRightOf="@+id/button_flip"
android:text="@string/save" />
</RelativeLayout> <ImageView
android:id="@+id/image_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitCenter"
android:src="@drawable/ic_launcher" /> </LinearLayout>

MainActivity中的onCreate方法的代码例如以下:

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView iView = (ImageView) this.findViewById(R.id.image_content);
Bitmap b = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
Canvas c = new Canvas(b);
c.drawText("Load Image from here...", 50, 200, paint);
iView.setImageBitmap(b);
Button saveBtn = (Button) this.findViewById(R.id.button_save);
saveBtn.setOnClickListener(new OnClickListener() { @Override
public void onClick(View view) {
Toast toast = Toast.makeText(getApplicationContext(), "Please load the image firstly...", Toast.LENGTH_SHORT);
toast.show();
loadImage();
ImageView iView = (ImageView) findViewById(R.id.image_content);
iView.setImageBitmap(srcImage);
if(srcImage != null)
{
//saveFile(srcImage);
}
} });
Button processBtn = (Button) this.findViewById(R.id.button_gray_3);
processBtn.setOnClickListener(new OnClickListener() { @Override
public void onClick(View view) {
if(srcImage == null)
{
loadImage();
}
ImagePixelsProcessor processor = new ImagePixelsProcessor();
Bitmap bm = processor.gray(srcImage, 2); // 有不同的灰度化策略
final ImageView iView = (ImageView) findViewById(R.id.image_content);
iView.setImageBitmap(bm);
} }); Button inverseBtn = (Button) this.findViewById(R.id.button_inverse);
inverseBtn.setOnClickListener(new OnClickListener() { @Override
public void onClick(View view) {
if(srcImage == null)
{
loadImage();
}
ImagePixelsProcessor processor = new ImagePixelsProcessor();
Bitmap bm = processor.brightness(srcImage, 0.3);
final ImageView iView = (ImageView) findViewById(R.id.image_content);
iView.setImageBitmap(bm);
}
}); Button noRedBtn = (Button) this.findViewById(R.id.button_gray_1);
noRedBtn.setOnClickListener(new OnClickListener() { @Override
public void onClick(View view) {
if(srcImage == null)
{
loadImage();
}
ImagePixelsProcessor processor = new ImagePixelsProcessor();
Bitmap bm = processor.gray(srcImage, 0); // 有不同的灰度化策略
final ImageView iView = (ImageView) findViewById(R.id.image_content);
iView.setImageBitmap(bm);
}
}); Button gray2Btn = (Button) this.findViewById(R.id.button_gray_2);
gray2Btn.setOnClickListener(new OnClickListener() { @Override
public void onClick(View view) {
if(srcImage == null)
{
loadImage();
}
ImagePixelsProcessor processor = new ImagePixelsProcessor();
Bitmap bm = processor.gray(srcImage, 1); // 有不同的灰度化策略
final ImageView iView = (ImageView) findViewById(R.id.image_content);
iView.setImageBitmap(bm);
}
}); Button flipBtn = (Button) this.findViewById(R.id.button_flip);
flipBtn.setOnClickListener(new OnClickListener() { @Override
public void onClick(View view) {
if(srcImage == null)
{
loadImage();
}
ImagePixelsProcessor processor = new ImagePixelsProcessor();
Bitmap bm = processor.flip(srcImage);
final ImageView iView = (ImageView) findViewById(R.id.image_content);
iView.setImageBitmap(bm);
}
});

-第一次尝试用CSDN-markdown编辑器写文章。发现这个东西真好用!赞。。!

-gloomyfish@2015-07-02

Android Bitmap 载入与像素操作的更多相关文章

  1. android bitmap的 一些简单操作

    /** 获取 drawable 的图片 可以循环 1.图名 2.drawable 3.包名 **/ int imgid = getResources().getIdentifier("ic_ ...

  2. [Android]通过JNI访问并操作Bitmap的元素,支持RGB565和ARGB8888

    [Android]通过JNI访问并操作Bitmap的元素,支持RGB565和ARGB8888 标签: androidbitmapjni 2014-05-09 20:35 2985人阅读 评论(1) 收 ...

  3. Android Bitmap 常见的几个操作:缩放,裁剪,旋转,偏移

    Android Bitmap 相关操作 常见的几个操作:缩放,裁剪,旋转,偏移      很多操作需要 Matrix 来支持:Matrix 通过矩阵来处理位图,计算出各个像素点的位置,从而把bitma ...

  4. [翻译]开发文档:android Bitmap的高效使用

    内容概述 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently",包括大尺寸Bitmap的高效加载,图片的异步加载和数据缓存 ...

  5. Android bitmap图片处理

    一.View转换为Bitmap         在Android中所有的控件都是View的直接子类或者间接子类,通过它们可以组成丰富的UI界面.在窗口显示的时候Android会把这些控件都加载到内存中 ...

  6. Android图片载入框架最全解析(一),Glide的基本使用方法

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/53759439 本文同步发表于我的微信公众号.扫一扫文章底部的二维码或在微信搜索 郭 ...

  7. Android异步载入全解析之大图处理

    Android异步载入全解析之大图处理 异步载入中很重要的一部分就是对图像的处理,这也是我们前面用异步载入图像做示例的原因. 一方面是由于图像处理不好的话会很占内存,并且easyOOM,还有一方面,图 ...

  8. Android异步载入全解析之使用AsyncTask

    Android异步载入全解析之使用AsyncTask 概述 既然前面提到了多线程,就不得不提到线程池,通过线程池,不仅能够对并发线程进行管理.更能够提高他们运行的效率.优化整个App.当然我们能够自己 ...

  9. Android异步载入全解析之开篇瞎扯淡

    Android异步载入 概述 Android异步载入在Android中使用的很广泛,除了是由于避免在主线程中做网络操作.更是为了避免在显示时由于时间太长而造成ANR,添加显示的流畅性,特别是像List ...

随机推荐

  1. 解决Java compiler level does not match the version of the installed Java project facet.问题

    其实之前遇到过Java compiler level does not match the version of the installed Java project facet.这个问题,因为当时没 ...

  2. Swift - 类和结构体的区别

    类和结构体有许多相同之处,也有许多不同之处. 二者区别如下: 1,类可以继承和扩展,结构体不可以 2,可以让一个类的实例来反初始化,释放存储空间,结构体做不到 3,类的对象是引用类型,而结构体是值类型 ...

  3. swt,jface,rcp

    //swt-jface-rcp,基本结构:display类,shell类,组件:widget窗口控件,control控件,composites面板,button,label,text文本框,list列 ...

  4. Postfix+Amavisd-new+Spamassassin+ClamAV整合安装

    1. 安装软件和依赖包 apt-get install amavisd-new spamassassin clamav-daemon mysql-client mysql-server apt-get ...

  5. ACM-简单题之Factorial——poj1401

    转载请注明出处:http://blog.csdn.net/lttree Factorial Time Limit: 1500MS   Memory Limit: 65536K Total Submis ...

  6. DELPHI学习---类和对象(五篇)

    Classes and objects(类和对象) 类(或者类类型)定义了一个结构,它包括字段(也称为域).方法和属性:类的实例叫做对象:类的字段.方法和属性被称为它的部件(components)或成 ...

  7. Modular Fibonacci

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=30506#problem/U fib数列对2^m取模的循环节为3*(2^(m-1)) #i ...

  8. POJ2828 Buy Tickets 【线段树】+【单点更新】+【逆序】

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 12296   Accepted: 6071 Desc ...

  9. XMPP协议简介

    XMPP(息处理现场协议)是基于可扩展标记语言(XML)的协议.它用于即时消息(IM)以及在线现场探測.XMPP协议採用的是client-server架构,全部从一个client发到还有一个clien ...

  10. 沙朗javascript总结一下(一)---基础知识

    我也听说过Javascript这东西.我一直感觉很神奇,但它并没有去太懂.今天,牛腩哥哥随后的初步研究,一些浅显的认识.就先总结一下. 首先,什么是javascript? javascript是一种直 ...