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. 慎得慌二u赫然共和任务i个屁

    http://www.huihui.cn/share/8424421 http://www.huihui.cn/share/8424375 http://www.huihui.cn/share/842 ...

  2. 积累的VC编程小技巧之标题栏和菜单

    1.窗口最大最小化按纽的控制 ①怎样在程序开始的时候让它最大化? ②vc++做出来的exe文件在窗体的右上方是没有最大化和最小化按钮的,怎样实现这一功能? ③如何在显示窗口时,使最大化按钮变灰?   ...

  3. Shell 基本运算符

    Shell 和其他编程语言一样,支持多种运算符,包括: 算数运算符 关系运算符 布尔运算符 字符串运算符 文件测试运算符 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 ...

  4. ExtJs4 笔记(10) Ext.tab.Panel 选项卡

    本篇讲解选项卡控件. 一.基本选项卡 首先我们来定义一个基本的选项卡控件,其中每个Tab各有不同,Tab的正文内容可以有三种方式获取: 1.基本方式:通过定义html和items的方式. 2.读取其他 ...

  5. CURD特性

    本节课大纲: 一.ThinkPHP 3 的CURD介绍 (了解) 二.ThinkPHP 3 读取数据 (重点) 对数据的读取 Read $m=new Model('User'); ##返回一个实例 $ ...

  6. iOS学习笔记(十五)——数据库操作(SQLite)

    SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库.SQLite最初的设计目标是用于嵌入式系统,它占用资源非常少,在嵌入式设备中,只需要几百K的 ...

  7. pwd的实现

    #include <string.h> #include <stdlib.h> #include <dirent.h> #include <sys/types ...

  8. SuSE(SLES)安装配置syslog-ng日志server,可整合splunk

    Update History 2014年04月25日 - 撰写初稿 引言 在自己主动化部署AutoYast.自己主动化监控BMC Patrol双方面形成雏形后.日志的收集.管理.分析也顺势成为我们须要 ...

  9. HDU4719-Oh My Holy FFF(DP线段树优化)

    Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) T ...

  10. Hibernate学习之createSQLQuery与createQuery的区别及使用

    hibernate中createQuery与createSQLQuery:前者用的hql语句进行查询,后者可以用sql语句查询,前者以hibernate生成的Bean为对象装入list返回,后者则是以 ...