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

 

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

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

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

Android游戏Graphics绘图之图像像素操作_第1张图片

实现代码如下所示:

view source
print ?
001 package com.yarin.android.Examples_05_10;
002    
003 import android.content.Context;
004 import android.graphics.Bitmap;
005 import android.graphics.BitmapFactory;
006 import android.graphics.Canvas;
007 import android.view.KeyEvent;
008 import android.view.MotionEvent;
009 import android.view.View;
010    
011 public class GameView extends View implements Runnable
012 {
013     int BACKWIDTH;
014    
015     int BACKHEIGHT;
016    
017     short[] buf2;
018    
019     short[] buf1;
020    
021     int[] Bitmap2;
022    
023     int[] Bitmap1;
024        
025     public GameView(Context context)
026     {
027         super(context);
028            
029         /** 装载图片 */
030         Bitmap      image = BitmapFactory.decodeResource(this.getResources(),R.drawable.qq);
031         BACKWIDTH = image.getWidth();
032         BACKHEIGHT = image.getHeight();
033            
034         buf2 = new short[BACKWIDTH * BACKHEIGHT];
035         buf1 = new short[BACKWIDTH * BACKHEIGHT];
036         Bitmap2 = new int[BACKWIDTH * BACKHEIGHT];
037         Bitmap1 = new int[BACKWIDTH * BACKHEIGHT];
038    
039         /** 加载图片的像素到数组中 */
040         image.getPixels(Bitmap1, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT);
041            
042         new Thread(this).start();
043     }
044        
045        
046     void DropStone(int x,// x坐标
047                    int y,// y坐标
048                    int stonesize,// 波源半径
049                    int stoneweight)// 波源能量
050     {
051         for (int posx = x - stonesize; posx < x + stonesize; posx++)
052             for (int posy = y - stonesize; posy < y + stonesize; posy++)
053                 if ((posx - x) * (posx - x) + (posy - y) * (posy - y) < stonesize * stonesize)
054                     buf1[BACKWIDTH * posy + posx] = (short) -stoneweight;
055     }
056        
057        
058     void RippleSpread()
059     {
060         for (int i = BACKWIDTH; i < BACKWIDTH * BACKHEIGHT - BACKWIDTH; i++)
061         {
062             // 波能扩散
063             buf2[i] = (short) (((buf1[i - 1] + buf1[i + 1] + buf1[i - BACKWIDTH] + buf1[i + BACKWIDTH]) >> 1) - buf2[i]);
064             // 波能衰减
065             buf2[i] -= buf2[i] >> 5;
066         }
067    
068         // 交换波能数据缓冲区
069         short[] ptmp = buf1;
070         buf1 = buf2;
071         buf2 = ptmp;
072     }
073    
074     /** 渲染你水纹效果 */
075     void render()
076     {
077         int xoff, yoff;
078         int k = BACKWIDTH;
079         for (int i = 1; i < BACKHEIGHT - 1; i++)
080         {
081             for (int j = 0; j < BACKWIDTH; j++)
082             {
083                 // 计算偏移量
084                 xoff = buf1[k - 1] - buf1[k + 1];
085                 yoff = buf1[k - BACKWIDTH] - buf1[k + BACKWIDTH];
086    
087                 // 判断坐标是否在窗口范围内
088                 if ((i + yoff) < 0)
089                 {
090                     k++;
091                     continue;
092                 }
093                 if ((i + yoff) > BACKHEIGHT)
094                 {
095                     k++;
096                     continue;
097                 }
098                 if ((j + xoff) < 0)
099                 {
100                     k++;
101                     continue;
102                 }
103                 if ((j + xoff) > BACKWIDTH)
104                 {
105                     k++;
106                     continue;
107                 }
108    
109                 // 计算出偏移象素和原始象素的内存地址偏移量
110                 int pos1, pos2;
111                 pos1 = BACKWIDTH * (i + yoff) + (j + xoff);
112                 pos2 = BACKWIDTH * i + j;
113                 Bitmap2[pos2++] = Bitmap1[pos1++];
114                 k++;
115             }
116         }
117     }
118        
119     public void onDraw(Canvas canvas)
120     {
121         super.onDraw(canvas);
122            
123         /** 绘制经过处理的图片效果 */
124         canvas.drawBitmap(Bitmap2, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT, false, null);
125     }
126        
127     // 触笔事件
128     public boolean onTouchEvent(MotionEvent event)
129     {
130            
131         return true;
132     }
133    
134    
135     // 按键按下事件
136     public boolean onKeyDown(int keyCode, KeyEvent event)
137     {
138         return true;
139     }
140    
141    
142     // 按键弹起事件
143     public boolean onKeyUp(int keyCode, KeyEvent event)
144     {
145         DropStone(BACKWIDTH/2, BACKHEIGHT/2, 10, 30);
146         return false;
147     }
148    
149    
150     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)
151     {
152         return true;
153     }
154        
155     /**
156      * 线程处理
157      */
158     public void run()
159     {
160         while (!Thread.currentThread().isInterrupted())
161         {
162             try
163             {
164                 Thread.sleep(50);
165             }
166             catch (InterruptedException e)
167             {
168                 Thread.currentThread().interrupt();
169             }
170             RippleSpread();
171             render();
172             //使用postInvalidate可以直接在线程中更新界面
173             postInvalidate();
174         }
175     }
176 }

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

你可能感兴趣的:(图像视频开发,Android,android,游戏,import,image,class,null)