JavaME UI设计之图像特效二

 
上一篇我们分析了处理图片特效的原理,通常是将图像数据转换为一个int[]数组,然后再操作这个int[]数组,最后将操作之后的int[]数组转换为一个Image即可。本文我们接着分析另外几种常用特效的实现原理。
负片特效
要在图像处理软件中将图片处理为负片特效,非常简单,但是这些图像处理软件也是通过程序来实现的,其实现原理通常是用255来减去图像数据的r,g,b值,得到一个新的r,g,b值,再将新的数值合成图片即可,具体实现代码如下:
/*
 * 图片特效负片
 */
public Image effect_negative(Image src) {
       int srcW = src.getWidth();
       int srcH = src.getHeight();
       int[] srcPixels = getPixels(src);
       int r = 0;
       int g = 0;
       int b = 0;
       int a = 0;
       int argb;
       for (int i = 0; i < srcH; i++) {
              for (int ii = 0; ii < srcW; ii++) {
                     argb = srcPixels[i * srcW + ii];
                     a = ((argb & 0xff000000) >> 24); // alpha channel
                     r = 255 - ((argb & 0x00ff0000) >> 16); // red channel
                     g = 255 - ((argb & 0x0000ff00) >> 8); // green channel
                     b = 255 - (argb & 0x000000ff); // blue channel
                     srcPixels[i * srcW + ii] = ((a << 24) | (r << 16) | (g << 8) | b);
              }
       }
       return drawPixels(srcPixels, srcW, srcH);
}
在JavaME中一个像素都是一个int数据,要分别取得其a,r,g,b通道直接使用移位操作即可,如下所示。在其他更复杂的特效处理中夜经常这样来提取一个像素的a,r,g,b数值。
a = ((argb & 0xff000000) >> 24);
r = ((argb & 0x00ff0000) >> 16);
g = ((argb & 0x0000ff00) >> 8);
b = (argb & 0x000000ff);
对于负片特效的演示效果,如下图所示。
 

 
黑白特效
图像的黑白特效实现的原理是将图像的a,r,g,b通道的值都降低一定的比例,因此实现过程即为先取出每个像素的a,r,g,b通道数据,然后分别乘以一个颜色的比例(该比例可以根据实际实现进行调整),然后将个通道数据按照((a << 24) | (r << 16) | (g << 8) | b)方式合成一个int值,具体实现代码如下所示。
/*
 * 图片特效黑白
 */
public Image effect_black_white(Image src) {
       int srcW = src.getWidth();
       int srcH = src.getHeight();
       int[] srcPixels = getPixels(src);
       int r = 0;
       int g = 0;
       int b = 0;
       int a = 0;
       int argb;
       int temp;
       for (int i = 0; i < srcH; i++) {
              for (int ii = 0; ii < srcW; ii++) {
                     argb = srcPixels[i * srcW + ii];
                     a = ((argb & 0xff000000) >> 24); // alpha channel
                     r = ((argb & 0x00ff0000) >> 16); // red channel
                     g = ((argb & 0x0000ff00) >> 8); // green channel
                     b = (argb & 0x000000ff); // blue channel
                     temp = (int) (.299 * (double) r + .587 * (double) g + .114 * (double) b);
                     r = temp;
                     g = temp;
                     b = temp;
                     srcPixels[i * srcW + ii] = ((a << 24) | (r << 16) | (g << 8) | b);
              }
       }
       return drawPixels(srcPixels, srcW, srcH);
}
这里我们对r,g,b通道分别乘了0.299,0.587,0.114,该数值可以进行调整,具体效果如下图所示。
 

 
粉笔画特效
粉笔画大家都见得很多了,这里就不作过多的介绍了,要通过程序实现粉笔画的可以通过以下公式进行实现:
R=255-(Math. sqrt((2*(r-r1)*(r-r1)+(r-r2)*(r-r2))))
G=255-(Math. sqrt((2*(g-g1)*(g-g1)+(g-g2)*(g-g2))))
B=255-(Math. sqrt((2*(b-b1)*(b-b1)+(b-b2)*(b-b2))))
其中r1和r2分别为当前像素的右边一个像素和下边一个像素的r值,g1、g2、b1、b2同理。
有关粉笔画的效果具体实现代码如下:
/*
 * 图片特效粉笔画
 */
public Image effect_crayon(Image src)
{
       int srcW = src.getWidth();
       int srcH = src.getHeight(); 
       int[] srcPixels = getPixels(src);
       int r = 0;
       int g = 0;
       int b = 0;
       int a = 0;
       int argb;  
       int r1 = 0;
       int g1 = 0;
       int b1 = 0;
       int r2 = 0;
       int g2 = 0;
       int b2 = 0;
       for (int i = 0; i < srcH; i++)
       {
              for(int ii=0;ii<srcW;ii++)
              {
                     argb = srcPixels[i*srcW+ii];
                     a = ((argb & 0xff000000) >> 24); // alpha channel
                     r = ((argb & 0x00ff0000) >> 16); // red channel
                     g = ((argb & 0x0000ff00) >> 8); // green channel
                     b = (argb & 0x000000ff); // blue channel
              if(i+1 == srcH)
              {
                     r1= 0;
                     g1= 0;
                     b1=0;
              }
              else
              {
                     argb = srcPixels[(i+1)*srcW+ii];
                     r1 = ((argb & 0x00ff0000) >> 16); // red channel
                     g1 = ((argb & 0x0000ff00) >> 8); // green channel
                     b1 = (argb & 0x000000ff); // blue channel
              }
              if(ii+1 == srcW){
                     r2= 0;
                     g2= 0;
                     b2=0;
              }
              else
              {
                     argb = srcPixels[i*srcW+ii+1];
                     r2 = ((argb & 0x00ff0000) >> 16); // red channel
                     g2 = ((argb & 0x0000ff00) >> 8); // green channel
                     b2 = (argb & 0x000000ff); // blue channel
              }
             // rr1=(r1-r2)^2 rr2=(r1-r3)^2
           r = (int)Math.sqrt((double)(2*(r-r1)*(r-r1)+(r-r2)*(r-r2)));
           g = (int)Math.sqrt((double)(2*(g-g1)*(g-g1)+(g-g2)*(g-g2)));
           b = (int)Math.sqrt((double)(2*(b-b1)*(b-b1)+(b-b2)*(b-b2)));
           r =255-r; // red channel
           g =255-g; // green channel
           b =255-b; // blue channel
           srcPixels[i*srcW+ii] = ((a << 24) | (r << 16) | (g << 8) | b);
           }
    }
    return drawPixels(srcPixels, srcW, srcH);
}
通过该函数实现的粉笔画效果如下图所示。
 

你可能感兴趣的:(JavaME UI设计之图像特效二)