现在的位置: 首页 > 综合 > 正文

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

2013年09月20日 ⁄ 综合 ⁄ 共 4894字 ⁄ 字号 评论关闭

 

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

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

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

实现代码如下所示:

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图像像素操作了,谢谢阅读!

抱歉!评论已关闭.