Android游戏Graphics绘图之图像像素操作

我们在玩游戏时经常会看到一些图像的特效,比如半透明等效果。要实现这些效果并不难,只需要对图像本身的像素执行操作。Android中的 Bitmap同样提供了操作像素的方法,可以通过getPixels方法来获得该图像的像素并放到一个数组中,我们处理这个像素数组就可以了,最后通过 setPixels设置这个像素数组到Bitmap中。

在Android中,每一个图像像素通过一个4字节整数来展现:最高位字节用作Alpha通道,即用来实现透明与不透明控制,255代表完全不透明,0则代表完全透明;接下来的一个字节是Red红色通道,255代表完全是红色。依次类推,接下来的两个字节相应地实现绿色和蓝色通道。

下面的示例通过对图像像素的操作来模拟水纹效果,如图5-11所示。

实现代码如下所示:

package com.yarin.android.Examples_05_10;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
 
public class GameView extends View implements Runnable
{
    int BACKWIDTH;
 
    int BACKHEIGHT;
 
    short[] buf2;
 
    short[] buf1;
 
    int[] Bitmap2;
 
    int[] Bitmap1;
     
    public GameView(Context context)
    {
        super(context);
         
        /** 装载图片 */
        Bitmap      image = BitmapFactory.decodeResource(this.getResources(),R.drawable.qq);
        BACKWIDTH = image.getWidth();
        BACKHEIGHT = image.getHeight();
         
        buf2 = new short[BACKWIDTH * BACKHEIGHT];
        buf1 = new short[BACKWIDTH * BACKHEIGHT];
        Bitmap2 = new int[BACKWIDTH * BACKHEIGHT];
        Bitmap1 = new int[BACKWIDTH * BACKHEIGHT];
 
        /** 加载图片的像素到数组中 */
        image.getPixels(Bitmap1, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT);
         
        new Thread(this).start();
    }
     
     
    void DropStone(int x,// x坐标
                   int y,// y坐标
                   int stonesize,// 波源半径
                   int stoneweight)// 波源能量
    {
        for (int posx = x - stonesize; posx < x + stonesize; posx++)
            for (int posy = y - stonesize; posy < y + stonesize; posy++)
                if ((posx - x) * (posx - x) + (posy - y) * (posy - y) < stonesize * stonesize)
                    buf1[BACKWIDTH * posy + posx] = (short) -stoneweight;
    }
     
     
    void RippleSpread()
    {
        for (int i = BACKWIDTH; i < BACKWIDTH * BACKHEIGHT - BACKWIDTH; i++)
        {
            // 波能扩散
            buf2[i] = (short) (((buf1[i - 1] + buf1[i + 1] + buf1[i - BACKWIDTH] + buf1[i + BACKWIDTH]) >> 1) - buf2[i]);
            // 波能衰减
            buf2[i] -= buf2[i] >> 5;
        }
 
        // 交换波能数据缓冲区
        short[] ptmp = buf1;
        buf1 = buf2;
        buf2 = ptmp;
    }
 
    /** 渲染你水纹效果 */
    void render()
    {
        int xoff, yoff;
        int k = BACKWIDTH;
        for (int i = 1; i < BACKHEIGHT - 1; i++)
        {
            for (int j = 0; j < BACKWIDTH; j++)
            {
                // 计算偏移量
                xoff = buf1[k - 1] - buf1[k + 1];
                yoff = buf1[k - BACKWIDTH] - buf1[k + BACKWIDTH];
 
                // 判断坐标是否在窗口范围内
                if ((i + yoff) < 0)
                {
                    k++;
                    continue;
                }
                if ((i + yoff) > BACKHEIGHT)
                {
                    k++;
                    continue;
                }
                if ((j + xoff) < 0)
                {
                    k++;
                    continue;
                }
                if ((j + xoff) > BACKWIDTH)
                {
                    k++;
                    continue;
                }
 
                // 计算出偏移象素和原始象素的内存地址偏移量
                int pos1, pos2;
                pos1 = BACKWIDTH * (i + yoff) + (j + xoff);
                pos2 = BACKWIDTH * i + j;
                Bitmap2[pos2++] = Bitmap1[pos1++];
                k++;
            }
        }
    }
     
    public void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
         
        /** 绘制经过处理的图片效果 */
        canvas.drawBitmap(Bitmap2, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT, false, null);
    }
     
    // 触笔事件
    public boolean onTouchEvent(MotionEvent event)
    {
         
        return true;
    }
 
 
    // 按键按下事件
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        return true;
    }
 
 
    // 按键弹起事件
    public boolean onKeyUp(int keyCode, KeyEvent event)
    {
        DropStone(BACKWIDTH/2, BACKHEIGHT/2, 10, 30);
        return false;
    }
 
 
    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)
    {
        return true;
    }
     
    /**
     * 线程处理
     */
    public void run()
    {
        while (!Thread.currentThread().isInterrupted())
        {
            try
            {
                Thread.sleep(50);
            }
            catch (InterruptedException e)
            {
                Thread.currentThread().interrupt();
            }
            RippleSpread();
            render();
            //使用postInvalidate可以直接在线程中更新界面
            postInvalidate();
        }
    }
}

最后,我们就可以用上面的方法实现Android图像像素操作了,谢谢阅读!

参考   http://www.oschina.net/question/54100_32462

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值