要想修改Bitmap图片的 R G B信息 首先 得先拿到这张图片每个点的Color值 然后根据这个Color值 就可以算出对应的R G B 值 我们都知道在计算机语言中在内存中加载一张图片实际上是把图片的每个点的RGB信息写入内存 如果动态的修改了这些颜色信息 那绘制出来的图片就会改变。
修改图片的颜色值其实在很多地方都有用处,我记得以前我做J2ME游戏开发的时候 因为手机本身内存比较低 不能同时在内存中加载过多的图片 比如 在打怪的时候 玩家肯定不希望每次看到的怪物都一样 在不加大内存的情况下可以选择修改图片的R G B信息 就会给玩家耳目一新的感觉 这就是游戏调色板的原理。
修改图片的颜色值其实在很多地方都有用处,我记得以前我做J2ME游戏开发的时候 因为手机本身内存比较低 不能同时在内存中加载过多的图片 比如 在打怪的时候 玩家肯定不希望每次看到的怪物都一样 在不加大内存的情况下可以选择修改图片的R G B信息 就会给玩家耳目一新的感觉 这就是游戏调色板的原理。
接下来我介绍一下代码。下面这两张图片中的话筒图片中间的颜色是白色 在这里我动态的修改图片中间的颜色值 让它动起来。
//启动activity
package cn.m15.demo; import android.app.Activity; import android.os.Bundle; import android.view.Window; public class demoActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); } }//布局文件 自定义了一个View 绘制 图片
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#888888" android:layout_height="150dip" android:layout_width="120dip" > <cn.m15.demo.RecordingView android:id="@+id/uvMeter" android:layout_height="wrap_content" android:layout_width="wrap_content" android:gravity="center" /> </RelativeLayout>//自定义View
package cn.m15.demo; import java.util.Random; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.BitmapDrawable; import android.util.AttributeSet; import android.view.View; public class RecordingView extends View{ Paint mPaint; Bitmap mBitmap; int mBitmapWidth = 0; int mBitmapHeight = 0; int mArrayColor[] = null; int mArrayColorLengh = 0; long startTime = 0; int mBackVolume = 0; public RecordingView(Context context) { super(context); init(context); } public RecordingView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } void init(Context context) { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //在这里创建了一张bitmap mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_vd_mic_on); //将这张bitmap设置为背景图片 setBackgroundDrawable(new BitmapDrawable(mBitmap)); mBitmapWidth = mBitmap.getWidth(); mBitmapHeight = mBitmap.getHeight(); mArrayColorLengh = mBitmapWidth * mBitmapHeight; mArrayColor = new int[mArrayColorLengh]; int count = 0; for (int i = 0; i < mBitmapHeight; i++) { for (int j = 0; j < mBitmapWidth; j++) { //获得Bitmap 图片中每一个点的color颜色值 int color = mBitmap.getPixel(j, i); //将颜色值存在一个数组中 方便后面修改 mArrayColor[count] = color; //如果你想做的更细致的话 可以把颜色值的R G B 拿到做响应的处理 笔者在这里就不做更多解释 int r = Color.red(color); int g = Color.green(color); int b = Color.blue(color); count++; } } startTime = System.currentTimeMillis(); } /** * 返回一个随机数 * * @param botton * @param top * @return */ int UtilRandom(int botton, int top) { return ((Math.abs(new Random().nextInt()) % (top + 1 - botton)) + botton); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //每隔100毫秒设置一下填充的颜色区域 if (System.currentTimeMillis() - startTime >= 100) { startTime = System.currentTimeMillis(); setVolume(UtilRandom(0, 100)); } //用于刷新屏幕 invalidate(); } public void setVolume(int volume) { int startY = 0; int endY = 0; boolean isAdd = false; //判断当前应该填充新区域 还是还原旧的区域 if (mBackVolume > volume) { isAdd = false; startY = getValue(mBackVolume); endY = getValue(volume); } else { isAdd = true; startY = getValue(volume); endY = getValue(mBackVolume); } //没必要每次都循环图片中的所有点,因为这样会比较耗时。 int count = startY * mBitmapWidth; //从图片须要填充或者还原 颜色的起始点 开始 到 终点 for (int i = startY; i < endY; i++) { for (int j = 0; j < mBitmapWidth; j++) { if (isAdd) { //将需要填充的颜色值如果不是 //在这说明一下 如果color 是全透明 或者全黑 返回值为 0 //getPixel()不带透明通道 getPixel32()才带透明部分 所以全透明是0x00000000 //而不透明黑色是0xFF000000 如果不计算透明部分就都是0了 int color = mBitmap.getPixel(j, i); if (color != 0) { mBitmap.setPixel(j, i, Color.BLACK); } } else { //如果是还原颜色 把现在点的颜色 赋值为之前保存颜色的数组 mBitmap.setPixel(j, i, mArrayColor[count]); } count++; } } mBackVolume = volume; } //通过百分比 根据图片宽高算出实际填充 高度 public int getValue(int volume) { return mBitmapHeight - (mBitmapHeight * volume / 100); } }