好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

(转)Android中实现区域平均算法在图片缩放里的应用(缩放图片抗锯齿)

摘要:
Android图片缩放效果较差,尤其是将大尺寸的图片缩放成小尺寸的图片时,即便是加了抗锯齿,锯齿现象也比较严重;而java sdk里的区域平均算法缩放图片,效果就比较完美了,因为jdk不能直接用于安卓项目中(类冲突),也没找到可以使用的替代的library,最终只好自己写,在此分享!

 

正文:

目前我知道的Android API中的传统的图片抗锯齿优化处理无非就是以下相关的设置:

 

//缩放抗锯齿
Bitmap.createScaledBitmap(bitmap, width, height, true);
Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);

 

//画布抗锯齿
PaintFlagsDrawFilter pfd = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); //画图片时设置画布抗锯齿
canvas.setDrawFilter(pfd);

 

//画笔抗锯齿
Paint p = new Paint(Paint.FILTER_BITMAP_FLAG);
p.setAntiAlias(true);

 

另外也无意发现了竟然还有这种缩放的api:ThumbnailUtils.extractThumbnail(bitmap, width, height);

以上都试过了,将图片缩放后效果都一样差!opengl、


经过测试,使用java sdk有较好的效果:
1、使用此方法,效果与安卓的缩放一样:
Image.getScaledInstance(width, height, java.awt.Image.SCALE_DEFAULT); //或java.awt.Image.SCALE_FAST等

2、使用此方法,效果很好:
Image.getScaledInstance(width, height, java.awt.Image.SCALE_SMOOTH); //或java.awt.Image.SCALE_AREA_AVERAGING


Android偏偏丢弃了java.awt.image,
因为jdk不能直接用于安卓项目中(类冲突),所以我进行了如下解决办法:

1、在stackoverflow上找到一个可以用于安卓的替代项目:https://code.google.com/p/awt-android-compat/
FQ下载下来后,该项目报错太多,仍有一些java类没有整合进来,不能使用;
2、尝试从java sdk源码中抽取,但类的继承、嵌套层级太深,试过几次都不行。

3、最后只好阅读java sdk缩放图片的相关源码,缩放时用了区域平均算法,大体就是取某个区域里像素点a\r\g\b的平均颜色值,作为缩放后的图片相应区域的颜色值,目前看来此算法缩放效果最优。
可参考java代码:
java.awt.Image#getScaledInstance()
java.awt.image.AreaAveragingScaleFilter

了解该算法之后,新写了一个图片缩放工具类,在Android中缩放效果已经比较好了,


至此已经解决。


区域平均算法缩放具体怎么好,请见图片:
原图是两张500x500像素的图片,缩放到40x40像素后的效果对比:

 

上面两张是安卓里的抗锯齿缩放,下面两张是使用区域平均算法缩放出的图片。

 


对于缩放质量要求高的可以使用,下面共享代码:

 import   android.graphics.Bitmap;
  import   android.graphics.Bitmap.Config;

  /**  
 * 区域平均算法缩放图片,500x500的图,缩放成小图时;若使用安卓提供的api,无论怎么抗锯齿,缩放出的图片也是带有较明显锯齿的。此缩放效果提升
 * 
 * @Author zhuanggy  欢迎加入安卓开发交流qq群 88130145
 * @Date:2014-12-5
 * @Copyright 原创:  http://www.eoeandroid.com/thread-556407-1-1.html 
  */ 
 public   class   AreaAveragingScale {
          protected   int  [] colorArray;
          private   int   srcWidth;
          private   int   srcHeight;

          private   int   destWidth;
          private   int   destHeight;

          float  [] reds;
          float  [] greens;
          float  [] blues;
          float  [] alphas;

          public   AreaAveragingScale(Bitmap src) {
                srcWidth  =  src.getWidth();
                srcHeight  =  src.getHeight();

                colorArray  =  new   int [srcWidth *  srcHeight];
                src.getPixels(colorArray,  0, srcWidth, 0, 0 , srcWidth, srcHeight);
                  int   a, r, g, b;
                  for  ( int  y = 0; y < srcHeight; y++ ) {
                          for  ( int  x = 0; x < srcWidth; x++ ) {
                                  int  index = y * srcWidth +  x;
                                a  = (colorArray[index] >> 24) & 0xff ;
                                r  = (colorArray[index] >> 16) & 0xff ;
                                g  = (colorArray[index] >> 8) & 0xff ;
                                b  = colorArray[index] & 0xff ;
                                colorArray[index]  = (a << 24) | (r << 16) | (g << 8) |  b;
                        }
                }
        }

          public  Bitmap getScaledBitmap( int  width,  int   height) {
                destWidth  =  width;
                destHeight  =  height;
                reds  =  new   float  [srcWidth];
                greens  =  new   float  [srcWidth];
                blues  =  new   float  [srcWidth];
                alphas  =  new   float  [srcWidth];

                Bitmap bitmap  =  Bitmap.createBitmap(destWidth, destHeight, Config.ARGB_8888);
                accumPixels( 0, 0 , srcWidth, srcHeight, bitmap);

                  return   bitmap;
        }

          private   void  accumPixels( int  x,  int  y,  int  w,  int   h, Bitmap bitmap) {
                  int  sy =  y;
                  int  syrem =  destHeight;
                  int   dy, dyrem;
                dy  = 0 ;
                dyrem  = 0 ;
                  while  (sy < y +  h) {
                          int   amty;
                          if  (dyrem == 0 ) {
                                  for  ( int  i = 0; i < destWidth; i++ ) {
                                        alphas[i]  = reds[i] = greens[i] = blues[i] =  0f;
                                }
                                dyrem  =  srcHeight;
                        }
                          if  (syrem <  dyrem) {
                                amty  =  syrem;
                        }   else   {
                                amty  =  dyrem;
                        }
                          int  sx = 0 ;
                          int  dx = 0 ;
                          int  sxrem = 0 ;
                          int  dxrem =  srcWidth;
                          float  a = 0f, r = 0f, g = 0f, b =  0f;
                          while  (sx <  w) {
                                  if  (sxrem == 0 ) {
                                        sxrem  =  destWidth;

                                        a  =  getAComponent(sx, sy);
                                        r  =  getRComponent(sx, sy);
                                        g  =  getGComponent(sx, sy);
                                        b  =  getBComponent(sx, sy);

                                          if  (a != 255.0f ) {
                                                  float  ascale = a / 255.0f ;
                                                r  *=  ascale;
                                                g  *=  ascale;
                                                b  *=  ascale;
                                        }
                                }
                                  int   amtx;
                                  if  (sxrem <  dxrem) {
                                        amtx  =  sxrem;
                                }   else   {
                                        amtx  =  dxrem;
                                }
                                  float  mult = (( float ) amtx) *  amty;
                                alphas[dx]  += mult *  a;
                                reds[dx]  += mult *  r;
                                greens[dx]  += mult *  g;
                                blues[dx]  += mult *  b;
                                  if  ((sxrem -= amtx) == 0 ) {
                                        sx ++ ;
                                }
                                  if  ((dxrem -= amtx) == 0 ) {
                                        dx ++ ;
                                        dxrem  =  srcWidth;
                                }
                        }
                          if  ((dyrem -= amty) == 0 ) {
                                  do   {
                                        calcRow(dy, bitmap);
                                        dy ++ ;
                                }   while  ((syrem -= amty) >= amty && amty ==  srcHeight);
                        }   else   {
                                syrem  -=  amty;
                        }
                          if  (syrem == 0 ) {
                                syrem  =  destHeight;
                                sy ++ ;
                        }
                }
        }

          private   void  calcRow( int   dy, Bitmap bitmap) {

                  //   Log.e("", "calcRow" + dy); 

                 float  origmult = (( float ) srcWidth) *  srcHeight;
                  for  ( int  x = 0; x < srcWidth; x++ ) {
                          float  mult =  origmult;
                          int  a = Math.round(alphas[x] /  mult);
                          if  (a <= 0 ) {
                                a  = 0 ;
                        }   else   if  (a >= 255 ) {
                                a  = 255 ;
                        }   else   {
                                mult  = alphas[x] / 255 ;
                        }
                          int  r = Math.round(reds[x] /  mult);
                          int  g = Math.round(greens[x] /  mult);
                          int  b = Math.round(blues[x] /  mult);

                          if  (r < 0 ) {
                                r  = 0 ;
                        }   else   if  (r > 255 ) {
                                r  = 255 ;
                        }
                          if  (g < 0 ) {
                                g  = 0 ;
                        }   else   if  (g > 255 ) {
                                g  = 255 ;
                        }
                          if  (b < 0 ) {
                                b  = 0 ;
                        }   else   if  (b > 255 ) {
                                b  = 255 ;
                        }
                        setPixelColor(bitmap, x, dy, r, g, b, a);
                }
        }

          private   void  setPixelColor(Bitmap bitmap,  int  x,  int  y,  int  c0,  int  c1,  int  c2,  int   a) {
                  int  rgbcolor = (a << 24) + (c0 << 16) + (c1 << 8) +  c2;
                colorArray[((y  * srcWidth + x))] =  rgbcolor;
                  if  (x >= destWidth || y >=  destHeight) {

                }   else   {
                        bitmap.setPixel(x, y, colorArray[((y  * srcWidth +  x))]);
                }

        }

          //   获得像素点的透明度 A 
         private   int  getAComponent( int  x,  int   y) {
                  return  (colorArray[((y * srcWidth + x))] & 0xFF000000) >>> 24 ;
        }

          //   获得像素点的红色值 R 
         private   int  getRComponent( int  x,  int   y) {
                  return  (colorArray[((y * srcWidth + x))] & 0x00FF0000) >>> 16 ;
        }

          //   获得像素点的绿色值 G 
         private   int  getGComponent( int  x,  int   y) {
                  return  (colorArray[((y * srcWidth + x))] & 0x0000FF00) >>> 8 ;
        }

          //   获得像素点的蓝色值 B 
         private   int  getBComponent( int  x,  int   y) {
                  return  (colorArray[((y * srcWidth + x))] & 0x000000FF );
        }
} 

 

 

原文地址:http://www.eoeandroid.com/thread-556407-1-1.html

 

查看更多关于(转)Android中实现区域平均算法在图片缩放里的应用(缩放图片抗锯齿)的详细内容...

  阅读:47次

上一篇: FFT算法的verilog实现

下一篇:HOG算法基础