也许说,图像算法很过时,那是许久以前的做法,可是作为Silverlight来说,我认为非常有用,这些有趣的处理就像是在Web上实现了一个Photoshop,大大扩展了发挥空间,很多算法不止PS在用,大多的图片软件也都在这样的算法,你甚至可以把它们变成你的Silverlight版本的图片处理软件,然而,我们只谈游戏中的应用,这些经典的算法可以各种特效的处理,甚至将一个游戏的资源成N个资源,下面只是一张图片,演示程序和源代码在最后面:)

Silverlight C# 游戏开发:资源的处理,图像算法(二)_silverlight

 

 

第一个:色相清除

Silverlight C# 游戏开发:资源的处理,图像算法(二)_休闲_02

 

色相清除,很简单,就是颜色值留下,将特定的颜色清除掉就能达到效果,上面这个效果RGB颜色分别只留下了一种,源代码如下,这个处理类似在Photoshop中颜色通道的显示,该应用较为广泛,如果你将下面的代码稍作修改,就能完成一个同一张图片的不同变化,比如说绿色小怪红色小怪蓝色小怪、甚至紫色小怪,哈哈。

  1.    
  2.  
  3. WriteableBitmap wb = new WriteableBitmap(Image0.Source as BitmapSource);  
  4.  
  5. WriteableBitmap wb1 = new WriteableBitmap(Image0.Source as BitmapSource);  
  6.  
  7. WriteableBitmap wb2 = new WriteableBitmap(Image0.Source as BitmapSource);  
  8.  
  9. //A R G B => [B, G, R, A]  
  10.  
  11. for (int y = 0; y < wb.PixelHeight; y++)  
  12.  
  13. {  
  14.  
  15. for (int x = 0; x < wb.PixelWidth; x++)  
  16.  
  17. {  
  18.  
  19. int pixel = wb.Pixels[y * wb.PixelWidth + x];  
  20.  
  21. byte[] dd = BitConverter.GetBytes(pixel);  
  22.  
  23. dd[0] = 0;  
  24.  
  25. dd[1] = 0;  
  26.  
  27. wb.Pixels[y * wb.PixelWidth + x] = BitConverter.ToInt32(dd, 0);  
  28.  
  29.  
  30.  
  31. pixel = wb1.Pixels[y * wb1.PixelWidth + x];  
  32.  
  33. dd = BitConverter.GetBytes(pixel);  
  34.  
  35. dd[1] = 0;  
  36.  
  37. dd[2] = 0;  
  38.  
  39. wb1.Pixels[y * wb1.PixelWidth + x] = BitConverter.ToInt32(dd, 0);  
  40.  
  41.  
  42.  
  43. pixel = wb2.Pixels[y * wb2.PixelWidth + x];  
  44.  
  45. dd = BitConverter.GetBytes(pixel);  
  46.  
  47. dd[2] = 0;  
  48.  
  49. dd[0] = 0;  
  50.  
  51. wb2.Pixels[y * wb2.PixelWidth + x] = BitConverter.ToInt32(dd, 0);  
  52.  
  53. }  
  54.  
  55. }  
  56.  
  57. Image1.Source = wb;  
  58.  
  59. Image2.Source = wb1;  
  60.  
  61. Image3.Source = wb2;  
  62.    
  63.  

第二个:Gamma值

 

 

Silverlight C# 游戏开发:资源的处理,图像算法(二)_图像处理技术  _03

 

伽马值,我们一般称之为颜色曲线,在以前电视机的显像就是这个来操纵的,当然了,gamma 校正是指更改 gamma 值以匹配监视器的中间灰度,校正补偿了不同输出设备存在的颜色显示差异,从而使图像在不同的监视器上呈现出相同的效果,这个方法在颜色区分中可以做多种不同的效果,例如梦境、恐惧等,部分源代码如下。

  1. private byte[] MakeGammaArray(double color)  
  2.  
  3. {  
  4.  
  5. byte[] gammaArray = new byte[256];  
  6.  
  7. for (int i = 0; i < 256; ++i)  
  8.  
  9. {  
  10.  
  11. gammaArray[i] =   
  12.  
  13. (byte)Math.Min(255, (int)((255.0 * Math.Pow(i / 255.0, 1.0 / color)) + 0.5));  
  14.  
  15. }  
  16.  
  17. return gammaArray;  
  18.  
  19. }  
  20.    
  21.  
第三个:亮度

 

 

 

Silverlight C# 游戏开发:资源的处理,图像算法(二)_图像处理技术  _04

 

 

亮度的原理很简单,只是将颜色数值增加一个偏移,虽然以正负255来计算,无非就是-1.0和+1.0的问题,颜色加值最后得到一张图片的亮度减暗或者加深,这个用法在很多游戏中很有用,你可以做一些微调,设置一些特别的效果,例如被电击之后的感觉,或者遭到暗属性的Debuff,算法就在下面,并不难,只需要传入参数brightness就行了。

 

  1.  
  2.  
  3. private void SetBrightness(int brightness)  
  4.  
  5. {  
  6.  
  7. if (brightness < -255brightness = -255;  
  8.  
  9. if (brightness > 255) brightness = 255;  
  10.  
  11.  
  12.  
  13. WriteableBitmap wb = new WriteableBitmap(Image0.Source as BitmapSource);  
  14.  
  15. for (int y = 0; y < wb.PixelHeight; y++)  
  16.  
  17. {  
  18.  
  19. for (int x = 0; x < wb.PixelWidth; x++)  
  20.  
  21. {  
  22.  
  23. int pixel = wb.Pixels[y * wb.PixelWidth + x];  
  24.  
  25. byte[] dd = BitConverter.GetBytes(pixel);  
  26.  
  27. int B = (int)dd[0] + brightness;  
  28.  
  29. int G = (int)dd[1] + brightness;  
  30.  
  31. int R = (int)dd[2] + brightness;  
  32.  
  33. if (B < 0B = 0;  
  34.  
  35. if (B > 255) B = 255;  
  36.  
  37. if (G < 0G = 0;  
  38.  
  39. if (G > 255) G = 255;  
  40.  
  41. if (R < 0R = 0;  
  42.  
  43. if (R > 255) R = 255;  
  44.  
  45. dd[0] = (byte)B;  
  46.  
  47. dd[1] = (byte)G;  
  48.  
  49. dd[2] = (byte)R;  
  50.  
  51. wb.Pixels[y * wb.PixelWidth + x] = BitConverter.ToInt32(dd, 0);  
  52.  
  53. }  
  54.  
  55. }  
  56.  
  57. Image1.Source = wb;  
  58.  
  59. }  
  60.    
  61.  

 

第四个:对比度

 

 

Silverlight C# 游戏开发:资源的处理,图像算法(二)_silverlight技术_05

 

与亮度一样,是一个常用的算法,将颜色的亮度和饱和度同时增加,以达到黑的更黑,白的更白,这种方法在处理特效时相当有用, 依据不同的情况使用不同的效果,算法给出如下,它是一个设置型的处理方案,与亮度一样,传入一个参数即可。

  1. private void SetContrast(double contrast)  
  2.  
  3. {  
  4.  
  5. if (contrast < -100contrast = -100;  
  6.  
  7. if (contrast > 100) contrast = 100;  
  8.  
  9. contrast = (100.0 + contrast) / 100.0;  
  10.  
  11. contrast *= contrast;  
  12.  
  13.  
  14.  
  15. WriteableBitmap wb = new WriteableBitmap(Image0.Source as BitmapSource);  
  16.  
  17. for (int y = 0; y < wb.PixelHeight; y++)  
  18.  
  19. {  
  20.  
  21. for (int x = 0; x < wb.PixelWidth; x++)  
  22.  
  23. {  
  24.  
  25. int pixel = wb.Pixels[y * wb.PixelWidth + x];  
  26.  
  27. byte[] dd = BitConverter.GetBytes(pixel);  
  28.  
  29. double pR = (double)dd[2] / 255.0;  
  30.  
  31. pR -0.5;  
  32.  
  33. pR *= contrast;  
  34.  
  35. pR += 0.5;  
  36.  
  37. pR *= 255;  
  38.  
  39. if (pR < 0pR = 0;  
  40.  
  41. if (pR > 255) pR = 255;  
  42.  
  43.  
  44.  
  45. double pG = (double)dd[1] / 255.0;  
  46.  
  47. pG -0.5;  
  48.  
  49. pG *= contrast;  
  50.  
  51. pG += 0.5;  
  52.  
  53. pG *= 255;  
  54.  
  55. if (pG < 0pG = 0;  
  56.  
  57. if (pG > 255) pG = 255;  
  58.  
  59.  
  60.  
  61. double pB = (double)dd[0] / 255.0;  
  62.  
  63. pB -0.5;  
  64.  
  65. pB *= contrast;  
  66.  
  67. pB += 0.5;  
  68.  
  69. pB *= 255;  
  70.  
  71. if (pB < 0pB = 0;  
  72.  
  73. if (pB > 255) pB = 255;  
  74.  
  75.  
  76.  
  77. dd[2] = (byte)pR;  
  78.  
  79. dd[1] = (byte)pG;  
  80.  
  81. dd[0] = (byte)pB;  
  82.  
  83.  
  84.  
  85. wb.Pixels[y * wb.PixelWidth + x] = BitConverter.ToInt32(dd, 0);  
  86.  
  87. }  
  88.  
  89. }  
  90.  
  91. Image1.Source = wb;  
  92.  
  93. }  
第五个:灰度

 

 

Silverlight C# 游戏开发:资源的处理,图像算法(二)_silverlight_06

 

我以前一直认为是取RGB的平均值,后来实验之后才知道,这样得到的效果很不好,原来颜色也占有不同的比重,知道比重值之后,我们就能将一张颜色漂亮的图片变成灰度图了,这个用法非常普遍,比如说死亡的效果,不需要再准备一套同样的灰度图片,下面是源代码,均值分别为0.299,0.587,0.114。

  1. WriteableBitmap wb = new WriteableBitmap(Image0.Source as BitmapSource);  
  2.  
  3. for (int y = 0; y < wb.PixelHeight; y++)  
  4.  
  5. {  
  6.  
  7. for (int x = 0; x < wb.PixelWidth; x++)  
  8.  
  9. {  
  10.  
  11. int pixel = wb.Pixels[y * wb.PixelWidth + x];  
  12.  
  13. byte[] dd = BitConverter.GetBytes(pixel);  
  14.  
  15. double R = dd[2];  
  16.  
  17. double G = dd[1];  
  18.  
  19. double B = dd[0];  
  20.  
  21. byte gray = (byte)(0.299 * R + 0.587 * G + 0.114 * B);  
  22.  
  23. dd[0] = dd[1] = dd[2] = gray;  
  24.  
  25.  
  26.  
  27. wb.Pixels[y * wb.PixelWidth + x] = BitConverter.ToInt32(dd, 0);  
  28.  
  29. }  
  30.  
  31. }  
  32.  
  33. Image1.Source = wb;  
  34.    
  35.  
第六个:反色

 

 

Silverlight C# 游戏开发:资源的处理,图像算法(二)_silverlight技术_07

 

反色的效果应用不甚广泛,它很简单,有的时候用在让人觉得诡异的地方比较好,我记得动漫中常有这样的尴尬环境表示方法,或者过场,反正算法并不难,参看下述源代码,公式为FF=FF-0:

  1. WriteableBitmap wb = new WriteableBitmap(Image0.Source as BitmapSource);  
  2.  
  3. for (int y = 0; y < wb.PixelHeight; y++)  
  4.  
  5. {  
  6.  
  7. for (int x = 0; x < wb.PixelWidth; x++)  
  8.  
  9. {  
  10.  
  11. int pixel = wb.Pixels[y * wb.PixelWidth + x];  
  12.  
  13. byte[] dd = BitConverter.GetBytes(pixel);  
  14.  
  15.  
  16.  
  17. dd[2] = (byte)(255 - dd[2]);  
  18.  
  19. dd[1] = (byte)(255 - dd[1]);  
  20.  
  21. dd[0] = (byte)(255 - dd[0]);  
  22.  
  23.  
  24.  
  25. wb.Pixels[y * wb.PixelWidth + x] = BitConverter.ToInt32(dd, 0);  
  26.  
  27. }  
  28.  
  29. }  
  30.  
  31. Image1.Source = wb;  
综述:

我们今天一起搞了六种常见的图像算法,其实都是在操作像素点,将像素做了一些修改,但是c#里运算速度不是很理想,主要是我的水平还是很低级,只好用暴力的方法解决,以前在C++中,我们可以使用汇编对内存进行操作,处理速度非常的快,我们在Silverlight中做到同等的处理可能要做一些优化工作,比如预先载入,提前处理,或者弄个另外线程搞定,不过不论怎么说,性能和效率都是我们最关注的点,游戏是非常要求速度的交互程序,所以,我们需要考虑的更多,到底是用性能换空间,还是用空间换性能,都是游戏开发者们一直在挑战的题目。

下面是本篇节的Silverlight程序:)需要源代码的在这里下载:源代码在这里