2016-04-08 10:30:15 DIDO222 阅读数 0

一、常用的图片处理方法:http://gundumw100.iteye.com/blog/849729

Java代码  收藏代码
  1. //压缩图片大小  
  2.     public static Bitmap compressImage(Bitmap image) {  
  3.   
  4.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  5.         image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中  
  6.         int options = 100;  
  7.         while ( baos.toByteArray().length / 1024>100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩         
  8.             baos.reset();//重置baos即清空baos  
  9.             image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中  
  10.             options -= 10;//每次都减少10  
  11.         }  
  12.         ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中  
  13.         Bitmap bitmap = BitmapFactory.decodeStream(isBm, nullnull);//把ByteArrayInputStream数据生成图片  
  14.         return bitmap;  
  15.     }  

Java代码  收藏代码
  1. /**  
  2.      * 将彩色图转换为灰度图  
  3.      * @param img 位图  
  4.      * @return  返回转换好的位图  
  5.      */    
  6.     public Bitmap convertGreyImg(Bitmap img) {    
  7.         int width = img.getWidth();         //获取位图的宽    
  8.         int height = img.getHeight();       //获取位图的高    
  9.             
  10.         int []pixels = new int[width * height]; //通过位图的大小创建像素点数组    
  11.             
  12.         img.getPixels(pixels, 0, width, 00, width, height);    
  13.         int alpha = 0xFF << 24;     
  14.         for(int i = 0; i < height; i++)  {    
  15.             for(int j = 0; j < width; j++) {    
  16.                 int grey = pixels[width * i + j];    
  17.                     
  18.                 int red = ((grey  & 0x00FF0000 ) >> 16);    
  19.                 int green = ((grey & 0x0000FF00) >> 8);    
  20.                 int blue = (grey & 0x000000FF);    
  21.                     
  22.                 grey = (int)((float) red * 0.3 + (float)green * 0.59 + (float)blue * 0.11);    
  23.                 grey = alpha | (grey << 16) | (grey << 8) | grey;    
  24.                 pixels[width * i + j] = grey;    
  25.             }    
  26.         }    
  27.         Bitmap result = Bitmap.createBitmap(width, height, Config.RGB_565);    
  28.         result.setPixels(pixels, 0, width, 00, width, height);    
  29.         return result;    
  30.     }    




将一个图片切割成多个图片
有种场景,我们想将一个图片切割成多个图片。比如我们在开发一个拼图的游戏,就首先要对图片进行切割。
以下是封装好的两个类,可以实现图片的切割。仅供参考和学习。
一个是ImagePiece类,此类保存了一个Bitmap对象和一个标识图片的顺序索引的int变量。
Java代码  收藏代码
  1. import android.graphics.Bitmap;   
  2. public class ImagePiece {     
  3.     public int index = 0;          
  4.     public Bitmap bitmap = null;    
  5. }  

一个是ImageSplitter类,有一个静态方法split,传入的参数是要切割的Bitmap对象,和横向和竖向的切割片数。比如传入的是3、3,则横竖向都切割成3片,最终会将整个图片切割成3X3=9片。
Java代码  收藏代码
  1. import java.util.ArrayList;    
  2. import java.util.List;    
  3.     
  4. import android.graphics.Bitmap;    
  5.     
  6. public class ImageSplitter {    
  7.     
  8.     public static List<ImagePiece> split(Bitmap bitmap, int xPiece, int yPiece) {    
  9.     
  10.         List<ImagePiece> pieces = new ArrayList<ImagePiece>(xPiece * yPiece);    
  11.         int width = bitmap.getWidth();    
  12.         int height = bitmap.getHeight();    
  13.         int pieceWidth = width / 3;    
  14.         int pieceHeight = height / 3;    
  15.         for (int i = 0; i < yPiece; i++) {    
  16.             for (int j = 0; j < xPiece; j++) {    
  17.                 ImagePiece piece = new ImagePiece();    
  18.                 piece.index = j + i * xPiece;    
  19.                 int xValue = j * pieceWidth;    
  20.                 int yValue = i * pieceHeight;    
  21.                 piece.bitmap = Bitmap.createBitmap(bitmap, xValue, yValue,    
  22.                         pieceWidth, pieceHeight);    
  23.                 pieces.add(piece);    
  24.             }    
  25.         }    
  26.     
  27.         return pieces;    
  28.     }    
  29.     
  30. }  


1、图标加灰色过滤;
2、android的图片资源默认是静态的,单实例;如果两个IM好友的头像一样,最简单的都是用的软件自带头像,有一个在线,一个离线,直接改变头像的灰度,则两个用户的头像都会变灰或者在线,答案是:Drawable.mutate()。
Java代码  收藏代码
  1. Drawable mDrawable = context.getResources().getDrawable(R.drawable.face_icon);    
  2. //Make this drawable mutable.    
  3. //A mutable drawable is guaranteed to not share its state with any other drawable.    
  4. mDrawable.mutate();    
  5. ColorMatrix cm = new ColorMatrix();    
  6. cm.setSaturation(0);    
  7. ColorMatrixColorFilter cf = new ColorMatrixColorFilter(cm);    
  8. mDrawable.setColorFilter(cf);  


生成缩略图,抠自android launcher源码:
Java代码  收藏代码
  1. /* 
  2.  * Copyright (C) 2008 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.android.launcher;  
  18.   
  19. import android.graphics.drawable.BitmapDrawable;  
  20. import android.graphics.drawable.Drawable;  
  21. import android.graphics.drawable.PaintDrawable;  
  22. import android.graphics.Bitmap;  
  23. import android.graphics.PixelFormat;  
  24. import android.graphics.Canvas;  
  25. import android.graphics.PaintFlagsDrawFilter;  
  26. import android.graphics.Paint;  
  27. import android.graphics.Rect;  
  28. import android.content.res.Resources;  
  29. import android.content.Context;  
  30.   
  31. /** 
  32.  * Various utilities shared amongst the Launcher's classes. 
  33.  */  
  34. final class Utilities {  
  35.     private static int sIconWidth = -1;  
  36.     private static int sIconHeight = -1;  
  37.   
  38.     private static final Paint sPaint = new Paint();  
  39.     private static final Rect sBounds = new Rect();  
  40.     private static final Rect sOldBounds = new Rect();  
  41.     private static Canvas sCanvas = new Canvas();  
  42.   
  43.     static {  
  44.         sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,  
  45.                 Paint.FILTER_BITMAP_FLAG));  
  46.     }  
  47.   
  48.     /** 
  49.      * Returns a Drawable representing the thumbnail of the specified Drawable. 
  50.      * The size of the thumbnail is defined by the dimension 
  51.      * android.R.dimen.launcher_application_icon_size. 
  52.      * 
  53.      * This method is not thread-safe and should be invoked on the UI thread only. 
  54.      * 
  55.      * @param icon The icon to get a thumbnail of. 
  56.      * @param context The application's context. 
  57.      * 
  58.      * @return A thumbnail for the specified icon or the icon itself if the 
  59.      *         thumbnail could not be created.  
  60.      */  
  61.     static Drawable createIconThumbnail(Drawable icon, Context context) {  
  62.         if (sIconWidth == -1) {  
  63.             final Resources resources = context.getResources();  
  64.             sIconWidth = sIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size);  
  65.         }  
  66.   
  67.         int width = sIconWidth;  
  68.         int height = sIconHeight;  
  69.   
  70.         float scale = 1.0f;  
  71.         if (icon instanceof PaintDrawable) {  
  72.             PaintDrawable painter = (PaintDrawable) icon;  
  73.             painter.setIntrinsicWidth(width);  
  74.             painter.setIntrinsicHeight(height);  
  75.         } else if (icon instanceof BitmapDrawable) {  
  76.             // Ensure the bitmap has a density.  
  77.             BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;  
  78.             Bitmap bitmap = bitmapDrawable.getBitmap();  
  79.             if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {  
  80.                 bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics());  
  81.             }  
  82.         }  
  83.         int iconWidth = icon.getIntrinsicWidth();  
  84.         int iconHeight = icon.getIntrinsicHeight();  
  85.   
  86.         if (width > 0 && height > 0) {  
  87.             if (width < iconWidth || height < iconHeight || scale != 1.0f) {  
  88.                 final float ratio = (float) iconWidth / iconHeight;  
  89.   
  90.                 if (iconWidth > iconHeight) {  
  91.                     height = (int) (width / ratio);  
  92.                 } else if (iconHeight > iconWidth) {  
  93.                     width = (int) (height * ratio);  
  94.                 }  
  95.   
  96.                 final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ?  
  97.                             Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;  
  98.                 final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);  
  99.                 final Canvas canvas = sCanvas;  
  100.                 canvas.setBitmap(thumb);  
  101.                 // Copy the old bounds to restore them later  
  102.                 // If we were to do oldBounds = icon.getBounds(),  
  103.                 // the call to setBounds() that follows would  
  104.                 // change the same instance and we would lose the  
  105.                 // old bounds  
  106.                 sOldBounds.set(icon.getBounds());  
  107.                 final int x = (sIconWidth - width) / 2;  
  108.                 final int y = (sIconHeight - height) / 2;  
  109.                 icon.setBounds(x, y, x + width, y + height);  
  110.                 icon.draw(canvas);  
  111.                 icon.setBounds(sOldBounds);  
  112.                 icon = new FastBitmapDrawable(thumb);  
  113.             } else if (iconWidth < width && iconHeight < height) {  
  114.                 final Bitmap.Config c = Bitmap.Config.ARGB_8888;  
  115.                 final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);  
  116.                 final Canvas canvas = sCanvas;  
  117.                 canvas.setBitmap(thumb);  
  118.                 sOldBounds.set(icon.getBounds());  
  119.                 final int x = (width - iconWidth) / 2;  
  120.                 final int y = (height - iconHeight) / 2;  
  121.                 icon.setBounds(x, y, x + iconWidth, y + iconHeight);  
  122.                 icon.draw(canvas);  
  123.                 icon.setBounds(sOldBounds);  
  124.                 icon = new FastBitmapDrawable(thumb);  
  125.             }  
  126.         }  
  127.   
  128.         return icon;  
  129.     }  
  130.   
  131.     /** 
  132.      * Returns a Bitmap representing the thumbnail of the specified Bitmap. 
  133.      * The size of the thumbnail is defined by the dimension 
  134.      * android.R.dimen.launcher_application_icon_size. 
  135.      * 
  136.      * This method is not thread-safe and should be invoked on the UI thread only. 
  137.      * 
  138.      * @param bitmap The bitmap to get a thumbnail of. 
  139.      * @param context The application's context. 
  140.      * 
  141.      * @return A thumbnail for the specified bitmap or the bitmap itself if the 
  142.      *         thumbnail could not be created. 
  143.      */  
  144.     static Bitmap createBitmapThumbnail(Bitmap bitmap, Context context) {  
  145.         if (sIconWidth == -1) {  
  146.             final Resources resources = context.getResources();  
  147.             sIconWidth = sIconHeight = (int) resources.getDimension(  
  148.                     android.R.dimen.app_icon_size);  
  149.         }  
  150.   
  151.         int width = sIconWidth;  
  152.         int height = sIconHeight;  
  153.   
  154.         final int bitmapWidth = bitmap.getWidth();  
  155.         final int bitmapHeight = bitmap.getHeight();  
  156.   
  157.         if (width > 0 && height > 0) {  
  158.             if (width < bitmapWidth || height < bitmapHeight) {  
  159.                 final float ratio = (float) bitmapWidth / bitmapHeight;  
  160.       
  161.                 if (bitmapWidth > bitmapHeight) {  
  162.                     height = (int) (width / ratio);  
  163.                 } else if (bitmapHeight > bitmapWidth) {  
  164.                     width = (int) (height * ratio);  
  165.                 }  
  166.       
  167.                 final Bitmap.Config c = (width == sIconWidth && height == sIconHeight) ?  
  168.                         bitmap.getConfig() : Bitmap.Config.ARGB_8888;  
  169.                 final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);  
  170.                 final Canvas canvas = sCanvas;  
  171.                 final Paint paint = sPaint;  
  172.                 canvas.setBitmap(thumb);  
  173.                 paint.setDither(false);  
  174.                 paint.setFilterBitmap(true);  
  175.                 sBounds.set((sIconWidth - width) / 2, (sIconHeight - height) / 2, width, height);  
  176.                 sOldBounds.set(00, bitmapWidth, bitmapHeight);  
  177.                 canvas.drawBitmap(bitmap, sOldBounds, sBounds, paint);  
  178.                 return thumb;  
  179.             } else if (bitmapWidth < width || bitmapHeight < height) {  
  180.                 final Bitmap.Config c = Bitmap.Config.ARGB_8888;  
  181.                 final Bitmap thumb = Bitmap.createBitmap(sIconWidth, sIconHeight, c);  
  182.                 final Canvas canvas = sCanvas;  
  183.                 final Paint paint = sPaint;  
  184.                 canvas.setBitmap(thumb);  
  185.                 paint.setDither(false);  
  186.                 paint.setFilterBitmap(true);  
  187.                 canvas.drawBitmap(bitmap, (sIconWidth - bitmapWidth) / 2,  
  188.                         (sIconHeight - bitmapHeight) / 2, paint);  
  189.                 return thumb;  
  190.             }  
  191.         }  
  192.   
  193.         return bitmap;  
  194.     }  
  195. }  


Java代码  收藏代码
  1. //Android Matrix类实现镜像方法  
  2. public void drawRegion(Image image_src,  
  3.   
  4. int x_src, int y_src,  
  5.   
  6. int width, int height,  
  7.   
  8. int transform,  
  9.   
  10. int x_dest, int y_dest,  
  11.   
  12. int anchor){  
  13.   
  14. if((anchor&VCENTER) != 0){  
  15.   
  16. y_dest -= height/2;  
  17.   
  18. }else if((anchor&BOTTOM) != 0){  
  19.   
  20. y_dest -= height;  
  21.   
  22. }  
  23.   
  24. if((anchor&RIGHT) != 0){  
  25.   
  26. x_dest -= width;  
  27.   
  28. }else if((anchor&HCENTER) != 0){  
  29.   
  30. x_dest -= width/2;  
  31.   
  32. }  
  33.   
  34. Bitmap newMap = Bitmap.createBitmap(image_src.getBitmap(), x_src, y_src, width, height);  
  35.   
  36. Matrix mMatrix = new Matrix();  
  37.   
  38. Matrix temp = new Matrix();  
  39.   
  40. Matrix temp2 = new Matrix();  
  41.   
  42. float[] mirrorY = {  
  43.   
  44. -100,  
  45. 010,  
  46. 001  
  47.   
  48. };  
  49.   
  50. temp.setValues(mirrorY);  
  51.   
  52. switch(transform){  
  53.   
  54. case Sprite.TRANS_NONE:  
  55.   
  56. break;  
  57.   
  58. case Sprite.TRANS_ROT90:  
  59.   
  60. mMatrix.setRotate(90,width/2, height/2);  
  61.   
  62. break;  
  63.   
  64. case Sprite.TRANS_ROT180:  
  65.   
  66. mMatrix.setRotate(180,width/2, height/2);  
  67.   
  68. break;  
  69.   
  70. case Sprite.TRANS_ROT270:  
  71.   
  72. mMatrix.setRotate(270,width/2, height/2);  
  73.   
  74. break;  
  75.   
  76. case Sprite.TRANS_MIRROR:  
  77.   
  78. mMatrix.postConcat(temp);  
  79.   
  80. break;  
  81.   
  82. case Sprite.TRANS_MIRROR_ROT90:  
  83.   
  84. mMatrix.postConcat(temp);  
  85.   
  86. mMatrix.setRotate(90,width/2, height/2);  
  87.   
  88. break;  
  89.   
  90. case Sprite.TRANS_MIRROR_ROT180:  
  91.   
  92. mMatrix.postConcat(temp);  
  93.   
  94. mMatrix.setRotate(180,width/2, height/2);  
  95.   
  96. break;  
  97.   
  98. case Sprite.TRANS_MIRROR_ROT270:  
  99.   
  100. mMatrix.postConcat(temp);  
  101.   
  102. mMatrix.setRotate(270,width/2, height/2);  
  103.   
  104. break;  
  105.   
  106. }  
  107.   
  108. mMatrix.setTranslate(x_dest, y_dest);  
  109.   
  110. canvas.drawBitmap(newMap, mMatrix, mPaint);  
  111.   
  112. }  


Java代码  收藏代码
  1. //图片Url保存为位图并进行缩放操作  
  2. //通过传入图片url获取位图方法  
  3. public Bitmap returnBitMap(String url) {  
  4.         URL myFileUrl = null;  
  5.         Bitmap bitmap = null;  
  6.         try {  
  7.             myFileUrl = new URL(url);  
  8.         } catch (MalformedURLException e) {  
  9.             e.printStackTrace();  
  10.         }  
  11.         try {  
  12.             HttpURLConnection conn = (HttpURLConnection) myFileUrl  
  13.                     .openConnection();  
  14.             conn.setDoInput(true);  
  15.             conn.connect();  
  16.             InputStream is = conn.getInputStream();  
  17.             bitmap = BitmapFactory.decodeStream(is);  
  18.             is.close();  
  19.         } catch (IOException e) {  
  20.             e.printStackTrace();  
  21.         }  
  22.         Log.v(tag, bitmap.toString());  
  23.   
  24.         return bitmap;  
  25.     }  
  26. //通过传入位图,新的宽.高比进行位图的缩放操作  
  27. public static Drawable resizeImage(Bitmap bitmap, int w, int h) {  
  28.   
  29.         // load the origial Bitmap  
  30.         Bitmap BitmapOrg = bitmap;  
  31.   
  32.         int width = BitmapOrg.getWidth();  
  33.         int height = BitmapOrg.getHeight();  
  34.         int newWidth = w;  
  35.         int newHeight = h;  
  36.   
  37.         Log.v(tag, String.valueOf(width));  
  38.         Log.v(tag, String.valueOf(height));  
  39.   
  40.         Log.v(tag, String.valueOf(newWidth));  
  41.         Log.v(tag, String.valueOf(newHeight));  
  42.   
  43.         // calculate the scale  
  44.         float scaleWidth = ((float) newWidth) / width;  
  45.         float scaleHeight = ((float) newHeight) / height;  
  46.   
  47.         // create a matrix for the manipulation  
  48.         Matrix matrix = new Matrix();  
  49.         // resize the Bitmap  
  50.         matrix.postScale(scaleWidth, scaleHeight);  
  51.         // if you want to rotate the Bitmap  
  52.         // matrix.postRotate(45);  
  53.   
  54.         // recreate the new Bitmap  
  55.         Bitmap resizedBitmap = Bitmap.createBitmap(BitmapOrg, 00, width,  
  56.                 height, matrix, true);  
  57.   
  58.         // make a Drawable from Bitmap to allow to set the Bitmap  
  59.         // to the ImageView, ImageButton or what ever  
  60.         return new BitmapDrawable(resizedBitmap);  
  61.   
  62.     }  


Java代码  收藏代码
  1. 1.图片加载方法,方便用户加载图片  
  2. /*** 
  3. * 加载本地图片 
  4. * @param context:主运行函数实例 
  5. * @param bitAdress:图片地址,一般指向R下的drawable目录 
  6. * @return 
  7. */  
  8. public final Bitmap CreatImage(Context context, int bitAdress) {  
  9. Bitmap bitmaptemp = null;  
  10. bitmaptemp = BitmapFactory.decodeResource(context.getResources(),  
  11. bitAdress);  
  12. return bitmaptemp;  
  13. }  
  14. 2.图片平均分割方法,将大图平均分割为N行N列,方便用户使用  
  15. /*** 
  16. * 图片分割 
  17. * 
  18. * @param g 
  19. * :画布 
  20. * @param paint 
  21. * :画笔 
  22. * @param imgBit 
  23. * :图片 
  24. * @param x 
  25. * :X轴起点坐标 
  26. * @param y 
  27. * :Y轴起点坐标 
  28. * @param w 
  29. * :单一图片的宽度 
  30. * @param h 
  31. * :单一图片的高度 
  32. * @param line 
  33. * :第几列 
  34. * @param row 
  35. * :第几行 
  36. */  
  37. public final void cuteImage(Canvas g, Paint paint, Bitmap imgBit, int x,  
  38. int y, int w, int h, int line, int row) {  
  39. g.clipRect(x, y, x + w, h + y);  
  40. g.drawBitmap(imgBit, x – line * w, y – row * h, paint);  
  41. g.restore();  
  42. }  
  43. 3.图片缩放,对当前图片进行缩放处理  
  44. /*** 
  45. * 图片的缩放方法 
  46. * 
  47. * @param bgimage 
  48. * :源图片资源 
  49. * @param newWidth 
  50. * :缩放后宽度 
  51. * @param newHeight 
  52. * :缩放后高度 
  53. * @return 
  54. */  
  55. public Bitmap zoomImage(Bitmap bgimage, int newWidth, int newHeight) {  
  56. // 获取这个图片的宽和高  
  57. int width = bgimage.getWidth();  
  58. int height = bgimage.getHeight();  
  59. // 创建操作图片用的matrix对象  
  60. Matrix matrix = new Matrix();  
  61. // 计算缩放率,新尺寸除原始尺寸  
  62. float scaleWidth = ((float) newWidth) / width;  
  63. float scaleHeight = ((float) newHeight) / height;  
  64. // 缩放图片动作  
  65. matrix.postScale(scaleWidth, scaleHeight);  
  66. Bitmap bitmap = Bitmap.createBitmap(bgimage, 00, width, height,  
  67. matrix, true);  
  68. return bitmap;  
  69. }  
  70. 4.绘制带有边框的文字,一般在游戏中起文字的美化作用  
  71. /*** 
  72. * 绘制带有边框的文字 
  73. * 
  74. * @param strMsg 
  75. * :绘制内容 
  76. * @param g 
  77. * :画布 
  78. * @param paint 
  79. * :画笔 
  80. * @param setx 
  81. * ::X轴起始坐标 
  82. * @param sety 
  83. * :Y轴的起始坐标 
  84. * @param fg 
  85. * :前景色 
  86. * @param bg 
  87. * :背景色 
  88. */  
  89. public void drawText(String strMsg, Canvas g, Paint paint, int setx,  
  90. int sety, int fg, int bg) {  
  91. paint.setColor(bg);  
  92. g.drawText(strMsg, setx + 1, sety, paint);  
  93. g.drawText(strMsg, setx, sety – 1, paint);  
  94. g.drawText(strMsg, setx, sety + 1, paint);  
  95. g.drawText(strMsg, setx – 1, sety, paint);  
  96. paint.setColor(fg);  
  97. g.drawText(strMsg, setx, sety, paint);  
  98. g.restore();  
  99. }  
  100. 5.Android 图片透明度处理代码  
  101. /** 
  102. * 图片透明度处理 
  103. * 
  104. * @param sourceImg 
  105. *            原始图片 
  106. * @param number 
  107. *            透明度 
  108. * @return 
  109. */  
  110. public static Bitmap setAlpha(Bitmap sourceImg, int number) {  
  111. int[] argb = new int[sourceImg.getWidth() * sourceImg.getHeight()];  
  112. sourceImg.getPixels(argb, 0, sourceImg.getWidth(), 00,sourceImg.getWidth(), sourceImg.getHeight());// 获得图片的ARGB值  
  113. number = number * 255 / 100;  
  114. for (int i = 0; i < argb.length; i++) {  
  115. argb = (number << 24) | (argb & 0×00FFFFFF);// 修改最高2位的值  
  116. }  
  117. sourceImg = Bitmap.createBitmap(argb, sourceImg.getWidth(), sourceImg.getHeight(), Config.ARGB_8888);  
  118. return sourceImg;  
  119. }  
  120. 6.图片翻转  
  121. Resources res = this.getContext().getResources();  
  122. img = BitmapFactory.decodeResource(res, R.drawable.slogo);  
  123. Matrix matrix = new Matrix();  
  124. matrix.postRotate(90);        /*翻转90度*/  
  125. int width = img.getWidth();  
  126. int height = img.getHeight();  
  127. r_img = Bitmap.createBitmap(img, 00, width, height, matrix, true);  

Java代码  收藏代码
  1. import android.graphics.Bitmap;  
  2. import android.graphics.Canvas;  
  3. import android.graphics.LinearGradient;  
  4. import android.graphics.Matrix;  
  5. import android.graphics.Paint;  
  6. import android.graphics.PixelFormat;  
  7. import android.graphics.PorterDuffXfermode;  
  8. import android.graphics.Rect;  
  9. import android.graphics.RectF;  
  10. import android.graphics.Bitmap.Config;  
  11. import android.graphics.PorterDuff.Mode;  
  12. import android.graphics.Shader.TileMode;  
  13. import android.graphics.drawable.Drawable;  
  14. /** 
  15.  
  16. * @author superdev 
  17. * @version 1.0 
  18. * 
  19. */  
  20. public class ImageUtil {  
  21.   
  22. /** 
  23. * 放大缩小图片 
  24. */  
  25. public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {  
  26.    int width = bitmap.getWidth();  
  27.    int height = bitmap.getHeight();  
  28.    Matrix matrix = new Matrix();  
  29.    float scaleWidht = ((float) w / width);  
  30.    float scaleHeight = ((float) h / height);  
  31.    matrix.postScale(scaleWidht, scaleHeight);  
  32.    Bitmap newbmp = Bitmap.createBitmap(bitmap, 00, width, height, matrix, true);  
  33.    return newbmp;  
  34. }  
  35.   
  36. /** 
  37. * 将Drawable转化为Bitmap 
  38. */  
  39. public static Bitmap drawableToBitmap(Drawable drawable) {  
  40.    int width = drawable.getIntrinsicWidth();  
  41.    int height = drawable.getIntrinsicHeight();  
  42.    Bitmap bitmap = Bitmap.createBitmap(width, height, drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);  
  43.    Canvas canvas = new Canvas(bitmap);  
  44.    drawable.setBounds(00, width, height);  
  45.    drawable.draw(canvas);  
  46.    return bitmap;  
  47.   
  48. }  
  49.   
  50. /** 
  51. * 获得圆角图片的方法 
  52. */  
  53. public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {  
  54.   
  55.    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);  
  56.    Canvas canvas = new Canvas(output);  
  57.   
  58.    final int color = 0xff424242;  
  59.    final Paint paint = new Paint();  
  60.    final Rect rect = new Rect(00, bitmap.getWidth(), bitmap.getHeight());  
  61.    final RectF rectF = new RectF(rect);  
  62.   
  63.    paint.setAntiAlias(true);  
  64.    canvas.drawARGB(0000);  
  65.    paint.setColor(color);  
  66.    canvas.drawRoundRect(rectF, roundPx, roundPx, paint);  
  67.   
  68.    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));  
  69.    canvas.drawBitmap(bitmap, rect, rect, paint);  
  70.   
  71.    return output;  
  72. }  
  73.   
  74. /** 
  75. * 获得带倒影的图片方法 
  76. */  
  77. public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {  
  78.    final int reflectionGap = 4;  
  79.    int width = bitmap.getWidth();  
  80.    int height = bitmap.getHeight();  
  81.   
  82.    Matrix matrix = new Matrix();  
  83.    matrix.preScale(1, -1);  
  84.   
  85.    Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2, width, height / 2, matrix, false);  
  86.   
  87.    Bitmap bitmapWithReflection = Bitmap.createBitmap(width, (height + height / 2), Config.ARGB_8888);  
  88.   
  89.    Canvas canvas = new Canvas(bitmapWithReflection);  
  90.    canvas.drawBitmap(bitmap, 00null);  
  91.    Paint deafalutPaint = new Paint();  
  92.    canvas.drawRect(0, height, width, height + reflectionGap, deafalutPaint);  
  93.   
  94.    canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);  
  95.   
  96.    Paint paint = new Paint();  
  97.    LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff0x00ffffff, TileMode.CLAMP);  
  98.    paint.setShader(shader);  
  99.    // Set the Transfer mode to be porter duff and destination in  
  100.    paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));  
  101.    // Draw a rectangle using the paint with our linear gradient  
  102.    canvas.drawRect(0, height, width, bitmapWithReflection.getHeight() + reflectionGap, paint);  
  103.    return bitmapWithReflection;  
  104. }  
  105. }  

Java代码  收藏代码
  1. private byte[] Bitmap2Bytes(Bitmap bm){  
  2.    ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  3.    bm.compress(Bitmap.CompressFormat.PNG, 100, baos);  
  4.    return baos.toByteArray();  
  5. }  
  6. private Bitmap Bytes2Bimap(byte[] b){  
  7.             if(b.length!=0){  
  8.                 return BitmapFactory.decodeByteArray(b, 0, b.length);  
  9.             }  
  10.             else {  
  11.                 return null;  
  12.             }  
  13.       }  
  14.   
  15.  /** 
  16.      * create the bitmap from a byte array 
  17.      *生成水印图片 
  18.      * @param src the bitmap object you want proecss 
  19.      * @param watermark the water mark above the src 
  20.      * @return return a bitmap object ,if paramter's length is 0,return null 
  21.      */  
  22.     private Bitmap createBitmap( Bitmap src, Bitmap watermark )  
  23.     {  
  24.         String tag = "createBitmap";  
  25.         Log.d( tag, "create a new bitmap" );  
  26.         if( src == null )  
  27.         {  
  28.             return null;  
  29.         }  
  30.    
  31.         int w = src.getWidth();  
  32.         int h = src.getHeight();  
  33.         int ww = watermark.getWidth();  
  34.         int wh = watermark.getHeight();  
  35.         //create the new blank bitmap  
  36.         Bitmap newb = Bitmap.createBitmap( w, h, Config.ARGB_8888 );//创建一个新的和SRC长度宽度一样的位图  
  37.         Canvas cv = new Canvas( newb );  
  38.         //draw src into  
  39.         cv.drawBitmap( src, 00null );//在 0,0坐标开始画入src  
  40.         //draw watermark into  
  41.         cv.drawBitmap( watermark, w - ww + 5, h - wh + 5null );//在src的右下角画入水印  
  42.         //save all clip  
  43.         cv.save( Canvas.ALL_SAVE_FLAG );//保存  
  44.         //store  
  45.         cv.restore();//存储  
  46.         return newb;  
  47.     }  
  48.    /** 重新编码Bitmap 
  49.    *  
  50.    * @param src 
  51.    *          需要重新编码的Bitmap 
  52.    * 
  53.    * @param format 
  54.    *          编码后的格式(目前只支持png和jpeg这两种格式) 
  55.    * 
  56.    * @param quality 
  57.    *          重新生成后的bitmap的质量 
  58.    * 
  59.    * @return 
  60.    *          返回重新生成后的bitmap 
  61.    */  
  62.  private static Bitmap codec(Bitmap src, Bitmap.CompressFormat format,  
  63.                                     int quality) {  
  64.             ByteArrayOutputStream os = new ByteArrayOutputStream();  
  65.             src.compress(format, quality, os);              
  66.   
  67.             byte[] array = os.toByteArray();  
  68.             return BitmapFactory.decodeByteArray(array, 0, array.length);  
  69.         }  
  70.   
  71. //Stream转换成Byte  
  72. static byte[] streamToBytes(InputStream is) {  
  73.       ByteArrayOutputStream os = new ByteArrayOutputStream(1024);  
  74.       byte[] buffer = new byte[1024];  
  75.       int len;  
  76.       try {  
  77.              while ((len = is.read(buffer)) >= 0) {  
  78.              os.write(buffer, 0, len);  
  79.              }  
  80.           } catch (java.io.IOException e) {  
  81.   
  82.           }  
  83.           return os.toByteArray();  
  84. }  
  85. //把View转换成Bitmap  
  86.   
  87.     /** 
  88.      * 把一个View的对象转换成bitmap 
  89.      */  
  90.     static Bitmap getViewBitmap(View v) {  
  91.           
  92.         v.clearFocus();  
  93.         v.setPressed(false);  
  94.   
  95.         //能画缓存就返回false  
  96.         boolean willNotCache = v.willNotCacheDrawing();  
  97.         v.setWillNotCacheDrawing(false);   
  98.         int color = v.getDrawingCacheBackgroundColor();  
  99.         v.setDrawingCacheBackgroundColor(0);  
  100.         if (color != 0) {  
  101.             v.destroyDrawingCache();  
  102.         }  
  103.         v.buildDrawingCache();  
  104.         Bitmap cacheBitmap = v.getDrawingCache();  
  105.         if (cacheBitmap == null) {  
  106.             Log.e(TAG, "failed getViewBitmap(" + v + ")"new RuntimeException());  
  107.             return null;  
  108.         }  
  109.         Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);  
  110.         // Restore the view  
  111.         v.destroyDrawingCache();  
  112.         v.setWillNotCacheDrawing(willNotCache);  
  113.         v.setDrawingCacheBackgroundColor(color);  
  114.         return bitmap;  
  115.     }  

Java代码  收藏代码
  1. 读取raw资源文件中的mp3文件,然后通过音乐播放器播放:  
  2.   
  3.     /** 
  4.      * 把mp3文件写入卡 
  5.      *  
  6.      * @param fileName 
  7.      *             输出的文件名(全路径) 
  8.      * @param context 
  9.          *             context对象 
  10.      */  
  11.     private void writeMP3ToSDcard(String fileName, Context context) {  
  12.         byte[] buffer = new byte[1024 * 8];  
  13.         int read;  
  14.         BufferedInputStream bin = new BufferedInputStream(context.getResources().openRawResource(R.raw.ring));  
  15.         try {  
  16.             BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(fileName));  
  17.             while ((read = bin.read(buffer)) > -1) {  
  18.                 bout.write(buffer, 0, read);  
  19.             }  
  20.             bout.flush();  
  21.             bout.close();  
  22.             bin.close();  
  23.         } catch (FileNotFoundException e) {  
  24.             e.printStackTrace();  
  25.         } catch (IOException e) {  
  26.             e.printStackTrace();  
  27.         }  
  28.     }  
  29.   
  30.   
  31. Intent intent = new Intent();  
  32. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  33. intent.setAction(android.content.Intent.ACTION_VIEW);  
  34. intent.setDataAndType(Uri.fromFile(newFile("XXXXmp3的文件全路径")),"audio/*");  
  35. startActivity(intent);  


绘制图像倒影
Java代码  收藏代码
  1. private void    
  2. _Init()     
  3. {     
  4.   m_paint = new Paint(Paint.ANTI_ALIAS_FLAG);     
  5.   LinearGradient lg = new LinearGradient(     
  6.     000, m_nShadowH,      
  7.     0xB0FFFFFF0x00000000,     
  8.     Shader.TileMode.CLAMP);     
  9.   m_paint.setShader(lg);     
  10.   m_paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));     
  11. }     
  12.     
  13. @Override protected void      
  14. onDraw(Canvas canvas)     
  15. {     
  16.   super.onDraw(canvas);     
  17.     
  18.   int nX = 0;     
  19.   int nY = 20;     
  20.     
  21.   _DrawNormalImg(canvas, nX, nY);     
  22.   _DrawMirror(canvas, nX, nY);     
  23. }      
  24.     
  25. private void    
  26. _DrawNormalImg(Canvas canvas, int nX, int nY)     
  27. {     
  28.   canvas.save(Canvas.MATRIX_SAVE_FLAG);     
  29.   canvas.translate(nX, nY);        
  30.   m_dw.draw(canvas);     
  31.   canvas.restore();     
  32. }     
  33.     
  34. private void    
  35. _DrawMirror(Canvas canvas, int nX, int nY)     
  36. {     
  37.   int nW = m_dw.getIntrinsicWidth();     
  38.   int nH = m_dw.getIntrinsicHeight();     
  39.     
  40.   ///////////////////////////////////     
  41.   //draw mirror image     
  42.   canvas.save(Canvas.MATRIX_SAVE_FLAG);     
  43.   canvas.scale(1.0f, -1.0f);     
  44.   canvas.translate(nX, -(nY + nH * 2));     
  45.   canvas.clipRect(0, nH, nW, nH - m_nShadowH);     
  46.   m_dw.draw(canvas);     
  47.   canvas.restore();     
  48.     
  49.   //////////////////////////////     
  50.   //draw mask     
  51.   canvas.save();     
  52.   canvas.translate(nX, nY + nH);     
  53.   canvas.drawRect(00, nW, m_nShadowH, m_paint);     
  54.   canvas.restore();     
  55. }    

Android 繪圖座標體系預設的原點在左上角,X 軸往右是越來越大的正值,而 Y 軸往下,則是越來越大的正值。要畫出垂直翻轉的圖片,其實也就是要垂直翻轉整個繪圖座標體系。在 Android 中,要如何做?答案就是 canvas.scale(1.0f, -1.0f)。很簡單吧,沒想到給 scale() 函式一個負值,就可以翻轉相對應的軸。
在 Photoshop 中,做鏡像特效的第二步是要對這翻轉的圖片,加個由灰到黑的漸層 mask。
在 Android 中,要畫漸層色,那就一定得用 LinearGradient 這個類別。至於要對背景圖加上個 mask,就請參考一下 Paint 的 setXfermode() 函式。_Init() 這個函式,就是負責生成一個由灰到黑漸層 mask 的 m_paint 物件。



http://blog.csdn.net/Android_Tutor/archive/2010/11/02/5981753.aspx

http://www.cnblogs.com/TerryBlog/archive/2012/01/08/2316482.html

android常用图片特效处理
http://www.eoeandroid.com/thread-170526-1-1.html

相机(Camera)实时滤镜效果
http://www.eoeandroid.com/thread-171528-1-1.html

Android, WindowsPhone7, IOS ,vc2010平台40多套图片滤镜开源
http://www.cnblogs.com/daizhj/archive/2012/05/15/2501406.html

Android实现获取本机中所有图片
http://www.cnblogs.com/hanyonglu/archive/2012/05/10/2494908.html



Android 图片处理工具类封装
http://www.open-open.com/lib/view/open1386682905126.html


2018-09-18 15:39:23 qq_21556263 阅读数 0

Android图像处理—图像色彩处理探究

本文章主要探究了Android的图像处理中的色彩处理部分的使用

RGBA模型

RGBA是一种缩写,其含义分别是Red、Green、Blue、Aplha。即红、绿、蓝三原色以及透明度四个选项。我们平时所见到的各种颜色不过是这三原色通过不同的比例混合所得,而alpha则可以控制图片的透明度。

下面介绍一些图像处理中重要的三个概念:

  • 色调/色相:物体传递的颜色
  • 饱和度:颜色的纯度,从0%(灰)到100%(饱和)来进行描述
  • 亮度/明度:颜色的相对明暗程度

Android中,系统提供类ColorMatrix来帮助调整图像的三个重要属性

色调

通过setRotate方法来设定整个图像的色调,第一个是需要设定的颜色,其中,0对应R,1对应G,2对应B。这里为了简单,给它设定一样的值hue。

ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0,hue);     //0=&gt;R
hueMatrix.setRotate(1,hue);     //1=&gt;G

饱和度

通过setSaturation方法来给图像设置饱和度,通过设置值,就可以控制图片的饱和度。

ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);

亮度

通过setScale方法来给图像设定亮度,四个参数分别是R亮度,G亮度,B亮度以及透明度亮度。

ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum,lum,lum,1);

通过ColorMatrix的方法调整图像效果

下面建立一个Android工程,来开始学习使用图像处理。

主界面

首先,建立一个主菜单,来选择对图片进行的修改。

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="40dp"
        android:textSize="40sp"
        android:text="美图秀秀"/>

    <Button
        android:id="@+id/btn_primary_color"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="PRIMARY COLOR"/>

    <Button
        android:id="@+id/btn_color_matrix"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="COLOR MATRIX"/>

    <Button
        android:id="@+id/btn_3"
       	android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="等待实现"/>
</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {
	private Button primaryButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        primaryButton = (Button)findViewById(R.id.btn_primary_color);
        primaryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                primaryColorEvent();
            }
        });
    }

    public void primaryColorEvent(){
        Intent intent = new Intent(MainActivity.this,PrimaryColorActivity.class);
        startActivity(intent);
    }
}

三原色调整界面

可以大致分析一下,如果要调整一张图片,要经过这三个步骤:

  1. 获取一张图片
  2. 对图片进行一系列修改
  3. 返回一张图片

因此,不妨设计一个工具类,来进行图像相关的处理,这样可以提高代码的复用性。

public class ImageUtils {
    public static Bitmap handleImageEffect(Bitmap bitmap,float hue,float saturation,float lum){
        //由于不能直接在原图上修改,所以创建一个图片,设定宽度高度与原图相同。为32位ARGB图片
        Bitmap currentBitmap = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        //创建一个和原图相同大小的画布
        Canvas canvas = new Canvas(currentBitmap);
        //创建笔刷并设置抗锯齿
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //色相ColorMatrix
        ColorMatrix hueMatrix = new ColorMatrix();
        hueMatrix.setRotate(0,hue);
        hueMatrix.setRotate(1,hue);
        hueMatrix.setRotate(2,hue);
        //饱和度ColorMatrix
        ColorMatrix saturationMatrix = new ColorMatrix();
        saturationMatrix.setSaturation(saturation);
        //亮度ColorMatrix
        ColorMatrix lumMatrix = new ColorMatrix();
        lumMatrix.setScale(lum,lum,lum,1);
        //将三种效果融合起来
        ColorMatrix imageMatrix = new ColorMatrix();
        imageMatrix.postConcat(hueMatrix);
        imageMatrix.postConcat(saturationMatrix);
        imageMatrix.postConcat(lumMatrix);

        paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
        canvas.drawBitmap(bitmap,0,0,paint);

        return currentBitmap;
    }
}

这里,用到了Canvas类,canvas类是一个画布类,后面进行的操作都会在画布上进行,而不是在原图上。建立了三个ColorMatrix,进行了不同方面的操作,并用postConcat方法将这些Matrix进行融合。通过setColorFilter方法来修改paint的相关属性,然后在canvas上将图片绘制出来。最后将修改后的图片返回出来。

回到我们的界面。设计是用三个Seekbar来分别控制色相、饱和度、亮度三个属性。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:scaleType="centerCrop"
        android:layout_marginTop="24dp"
        android:layout_marginBottom="24dp"
        android:layout_centerHorizontal="true"/>

    <SeekBar
        android:id="@+id/seekbar_hue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_below="@id/image_view"/>

    <SeekBar
        android:id="@+id/seekbar_saturation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
      	android:layout_margin="10dp"
        android:layout_below="@id/seekbar_hue"/>

    <SeekBar
        android:id="@+id/seekbar_lum"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
       	android:layout_below="@id/seekbar_saturation"/>
</RelativeLayout>

然后编辑PrimaryColorActivity。这里我们定义了一个最大值及中间值,可以让它从中间值开始变化,然后通过一系列方法来分别获取色相、饱和度、亮度的值。

public class PrimaryColorActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener{
    private ImageView mImageView;
    private SeekBar mSeekbarHue,mSeekbarSaturation,mSeekbarLum;
    private final static int MAX_VALUE = 255;   //最大值
    private final static int MID_VALUE = 127;   //中间值

    private float mHue,mSaturation,mLum;

    private Bitmap bitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_primary_color);

        //获取图片
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test1);

        mImageView = (ImageView)findViewById(R.id.image_view);

        mImageView.setImageBitmap(bitmap);

        mSeekbarHue = (SeekBar)findViewById(R.id.seekbar_hue);
        mSeekbarSaturation = (SeekBar)findViewById(R.id.seekbar_saturation);
        mSeekbarLum = (SeekBar)findViewById(R.id.seekbar_lum);

        mSeekbarHue.setOnSeekBarChangeListener(this);
        mSeekbarSaturation.setOnSeekBarChangeListener(this);
        mSeekbarLum.setOnSeekBarChangeListener(this);

        mSeekbarHue.setMax(MAX_VALUE);
        mSeekbarSaturation.setMax(MAX_VALUE);
        mSeekbarLum.setMax(MAX_VALUE);

        mSeekbarHue.setProgress(MID_VALUE);
        mSeekbarSaturation.setProgress(MID_VALUE);
        mSeekbarLum.setProgress(MID_VALUE);

    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        switch (seekBar.getId()){
            case R.id.seekbar_hue:
                //将0-255的值转换为色调值
                mHue = (progress - MID_VALUE)*1.0F/MID_VALUE*180;
                break;
            case R.id.seekbar_saturation:
                //将0-255值转换为饱和度值
                mSaturation = progress*1.0F/MID_VALUE;
                break;
            case R.id.seekbar_lum:
                //将0-255的值转换为亮度值
                mLum = progress*1.0F/MID_VALUE;
                break;
        }
        mImageView.setImageBitmap(ImageUtils.handleImageEffect(bitmap,
                mHue,mSaturation,mLum));
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }
}

运行后,拖动Seekbar,可以发现,我们成功地改变了图片的各项属性


原理分析——矩阵变换

我们之前用到了ColorMatrix类,众所周知,Matrix是矩阵的意思,所以这里实际上我们是通过操作矩阵来处理图像。Android中提供了如图的颜色矩阵,来帮助我们进行图像效果的处理, 图像中的每一个点都是一个矩阵分量,是由R、G、B、A和1组成:

我们用这个颜色矩阵乘上像素点对应的颜色矩阵分量,就能得到一个新的矩阵R1G1B1A1。如图:

这样,我们就把一个像素点通过颜色矩阵变换成了新的像素点(颜色调整后的效果)。

我们把如图的矩阵称为初始化矩阵,因为它乘上原来的像素点后,仍不变。

下面我们看一下这个矩阵,它在原来矩阵的基础上把两个地方的0变为了100,导致的后果就是原来的R G的值变为了它们加上100的值,也就是每个像素点的R G值都增加了100:

同样的,我们可以看一下这样的一个矩阵,它在原来的初始化矩阵的基础上,把矩阵G上的一个1变为了2,带入后可发现,G变为了原来的两倍,效果就是将整个图像的Green增加了两倍

我们可以发现,颜色矩阵的四行分别控制着像素点的R G B A四个属性,而颜色矩阵的第五列,我们称它为颜色偏移量,它不会直接改变某个颜色的系数,而是在原来的基础上调整整个颜色。

我们要改变一个颜色,不仅仅可以改变偏移量,还可以改变颜色的系数。

用矩阵变换来调整图像效果

我们基于原来的工程,增加一个Activity,并让MainActivity的第二个按钮跳转到此Activity。

首先是布局,我们制作如下的布局,准备在GridLayout中添加20个EditText来代表矩阵,用按钮来应用矩阵。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"/>

    <GridLayout
        android:id="@+id/group"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="3"
       	android:rowCount="4"
        android:columnCount="5"
    </GridLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        
        <Button
            android:id="@+id/btn_change"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="改变"/>

        <Button
            android:id="@+id/btn_reset"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="重置"/>

    </LinearLayout>
</LinearLayout>

<

然后,我们修改Activity的代码,动态将EditText添加到GridText,来映射我们的ColorMatrix。通过改变EditText来改变我们的ColorMatrix,使图片效果变化。

public class ColorMatrixActivity extends AppCompatActivity {
    private ImageView mImageView;
    private GridLayout mGroup;
    private Bitmap bitmap;
    private int mEtWidth,mEtHeight;
    private EditText[] mEditTexts = new EditText[20];
    private float[] mColorMatrix = new float[20];   //对应矩阵
    private Button changeButton;
    private Button resetButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_color_matrix);

        bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.test1);
        mImageView = (ImageView) findViewById(R.id.image_view);
        mImageView.setImageBitmap(bitmap);

        mGroup = (GridLayout) findViewById(R.id.group);
        //动态创建EditText,填充GridLayout

        //由于在onCreate中,mGroup还没有创建完成,无法获取宽高
        //所以通过post方法,在控件绘制完毕后,执行Runnable的具体方法
        mGroup.post(new Runnable() {
            @Override
            public void run() {
                mEtWidth = mGroup.getWidth()/5;
                mEtHeight = mGroup.getHeight()/4;
                addEditText();
                initMatrix();
            }
        });

        changeButton = (Button)findViewById(R.id.btn_change);
        changeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                changeButtonEvent();
            }
        });

        resetButton = (Button)findViewById(R.id.btn_reset);
        resetButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                resetButtonEvent();
            }
        });
    }

    private void addEditText(){
        for (int i=0;i&lt;20;i++){
            EditText editText = new EditText(ColorMatrixActivity.this);
            mEditTexts[i] = editText;
            mGroup.addView(editText,mEtWidth,mEtHeight);
        }
    }

    private void initMatrix(){
        for (int i=0;i&lt;20;i++){
            if (i%6 == 0){
                //i为第0、6、12、18位时
                mColorMatrix[i]=1;
                mEditTexts[i].setText(String.valueOf(1));
            }else{
                mColorMatrix[i]=0;
                mEditTexts[i].setText(String.valueOf(0));
            }
        }
    }

    private void getMatrix(){
        for (int i=0;i&lt;20;i++){
            mColorMatrix[i] = Float.valueOf(mEditTexts[i].getText().toString());
        }
    }

    private void setImageMatrix(){
        Bitmap currentBitmap = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        ColorMatrix colorMatrix = new ColorMatrix();
        colorMatrix.set(mColorMatrix);
        Canvas canvas = new Canvas(currentBitmap);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
        canvas.drawBitmap(bitmap,0,0,paint);
        mImageView.setImageBitmap(currentBitmap);
    }

    public void changeButtonEvent(){
        getMatrix();
        setImageMatrix();
    }

    public void resetButtonEvent(){
        initMatrix();
        setImageMatrix();
    }
}

可以看到,成功改变了图片效果,效果如图

学到这里,我们便可以解答之前为什么要用这样的参数来改变色相、饱和度和亮度了。以亮度为例,我们来看看setScale方法的源码。可以发现,ColorMatrix在内部也是使用这样一个颜色数组,同时将6的倍数位设置为相应的值,以此来改变亮度,说明我们如果在颜色矩阵中想要改变亮度,只需要将每个颜色的值同时提高即可。

  /**
    * Set this colormatrix to scale by the specified values.
    */
    public void setScale(float rScale, float gScale, float bScale,float aScale) {
        final float[] a = mArray;
       	for (int i = 19; i &gt; 0; --i) {
            a[i] = 0;
        }
        a[0] = rScale;
        a[6] = gScale;
        a[12] = bScale;
        a[18] = aScale;
    }

通过这些研究,我们可以这样总结:

图像处理,实际上就是研究不同颜色矩阵对图像的处理效果

比如我们在一些图像处理app中常见的怀旧效果,通过下图的设置方法即可得到


通过像素点进行图像处理

图像经过放大后,会呈现一个个点阵,每一个点实际上就是一个像素点。通过RGB的颜色配比,就可以显示出不同的颜色。

下面是一些对像素点处理形成图像特效的例子:

底片效果

对于ABC三个像素点,求B点的底片效果的算法如下。实际上就是对每个坐标点计算它的反色,即可得到

B.r = 255 - B.r;
B.g = 255 - B.g;
B.b = 255 - B.b;

老照片效果

求老照片效果对像素点的算法如下,其中pixR就是当前像素点的R值,以此类推。

newR = (int)(0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
newG = (int)(0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
newB = (int)(0.272 * pixR + 0.534 * pixG + 0.131 * pixB);

浮雕效果

对于ABC三个点,求B点的浮雕效果的算法如下。

B.r = C.r - B.r + 127;
B.g = C.g - B.g + 127;
B.b = C.b - B.b + 127;

下面,我们就通过对像素点的修改来改变图像的显示效果。

先新建一个新的Activity,并在MainActivity的第三个按钮中加上跳转到它的方法。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">        
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        
        <ImageView
            android:id="@+id/image_view1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>

        <ImageView
            android:id="@+id/image_view2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <ImageView
            android:id="@+id/image_view3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>

        <ImageView
            android:id="@+id/image_view4"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>
</LinearLayout>

加入相应特效方法

我们在ImageUtils中加入几个新方法,分别做不同的处理

反色效果

代码如下,我们在里面新建了一个对应图片的像素的数组,然后通过getPixels方法获取所有像素。
getPixels的第二个参数是代表起点的偏移量,第三个参数是控制读取数组时的行距,一般使用width,后面两个参数代表第一次读取像素点的坐标,倒数第二个参数代表我们从bitmap中读取的宽度,最后一个是读取的高度。
然后我们分别对每个像素点通过Color类的red green blue alpha方法来获取r g b a四个值,并通过算法改变它的rgb值,并通过Color的argb方法转换为新的像素数组。需要注意的是,改变它的rgb值时,需要判断一下有没有超过0-255的限制,有的话则赋值为255或0

    
    Bitmap currentBitmap = Bitmap.createBitmap(width,height,
            Bitmap.Config.ARGB_8888);
        int[] oldPx = new int[width*height];    //存储像素点数组
        int[] newPx = new int[width*height];
        bitmap.getPixels(oldPx,0,width,0,0,width,height);
        for (int i=0;i&lt;width*height;i++){
            color = oldPx[i];
            r = Color.red(color);
            g = Color.green(color);
            b = Color.blue(color);
            a = Color.alpha(color);
            //通过算法计算新的rgb值
            r = 255 - r;
            g = 255 - g;
            b = 255 - b;

            if (r &gt; 255) r=255;
            else if (r &lt; 0) r=0;

            if (g &gt; 255) g=255;
            else if (g &lt; 0) g=0;

            if (b &gt; 255) b=255;
            else if (b &lt; 0) b=0;

            newPx[i] = Color.argb(a,r,g,b);
        }
        currentBitmap.setPixels(newPx,0,width,0,0,width,height);
		return currentBitmap;
	}
老照片效果

其他代码基本与之前的一样,只是算法稍作变动,并且不能在原来的rgb基础上改动:

`    

```java
    public static Bitmap handleImageOldpicture(Bitmap bitmap){
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int color;
        int r,g,b,a;

        Bitmap currentBitmap = Bitmap.createBitmap(width,height,
                Bitmap.Config.ARGB_8888);
        int[] oldPx = new int[width*height];    //存储像素点数组
        int[] newPx = new int[width*height];
        bitmap.getPixels(oldPx,0,width,0,0,width,height);
        for (int i=0;i<width*height;i++){
            color = oldPx[i];
            r = Color.red(color);
            g = Color.green(color);
            b = Color.blue(color);
            a = Color.alpha(color);

            int r1,g1,b1;
            r1 = (int)(0.393 * r + 0.769 * g + 0.189 * b);
            g1 = (int)(0.349 * r + 0.686 * g + 0.168 * b);
            b1 = (int)(0.272 * r + 0.534 * g + 0.131 * b);

            if (r1 > 255) r1=255;
            else if (r1 < 0) r1=0;

            if (g1 > 255) g1=255;
            else if (g1 < 0) g1=0;

            if (b1 > 255) b1=255;
            else if (b1 < 0) b1=0;

            newPx[i] = Color.argb(a,r1,g1,b1);
        }
        currentBitmap.setPixels(newPx,0,width,0,0,width,height);

        return currentBitmap;
    }
```
##### 浮雕效果

与之前的差不多,唯一需要注意的是,我们需要用到前一个像素点的颜色,所以需要从1开始循环,然后通过相应算法,获取图片

```java
    public static Bitmap handleImagePixelsRelief(Bitmap bitmap){
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int color,colorBefore;
        int r,g,b,a;
        int r1,g1,b1;

        Bitmap currentBitmap = Bitmap.createBitmap(width,height,
                Bitmap.Config.ARGB_8888);

        int[] oldPx = new int[width*height];    //存储像素点数组
        int[] newPx = new int[width*height];
        bitmap.getPixels(oldPx,0,width,0,0,width,height);
        for (int i=1;i<width*height;i++){
            //取出前一个点的颜色
            colorBefore = oldPx[i-1];
            r = Color.red(colorBefore);
            g = Color.green(colorBefore);
            b = Color.blue(colorBefore);
            a = Color.alpha(colorBefore);

            color = oldPx[i];
            r1 = Color.red(color);
            g1 = Color.green(color);
            b1 = Color.blue(color);

            r = (r - r1 + 127);
            g = (g - g1 + 127);
            b = (b - b1 + 127);

            if (r1 > 255) r1=255;

            if (g1 > 255) g1=255;

            if (b1 > 255) b1=255;

            newPx[i] = Color.argb(a,r,g,b);
        }
        currentBitmap.setPixels(newPx,0,width,0,0,width,height);

        return currentBitmap;
    }
```
#### 查看效果

我们在Activity中调用相应方法,查看效果。

```java
public class PixelEffectActivity extends AppCompatActivity {
    private ImageView imageView1,imageView2,imageView3,imageView4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pixel_effect);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test1);
        imageView1 = (ImageView) findViewById(R.id.image_view1);
        imageView2 = (ImageView) findViewById(R.id.image_view2);
        imageView3 = (ImageView) findViewById(R.id.image_view3);
        imageView4 = (ImageView) findViewById(R.id.image_view4);

        imageView1.setImageBitmap(bitmap);
        imageView2.setImageBitmap(ImageUtils.handleImageNegative(bitmap));
        imageView3.setImageBitmap(ImageUtils.handleImageOldpicture(bitmap));
        imageView4.setImageBitmap(ImageUtils.handleImagePixelsRelief(bitmap));
    }
}
```


效果如图

![](http://193.112.164.83/wp-content/uploads/2018/04/2f5f6a2520a613e2a7f268b7e687cfa6.png)

* * *
---
**广告时间**
我是N0tExpectErr0r,一名广东工业大学的大二学生
欢迎来到我的个人博客,所有文章均在个人博客中同步更新哦
[http://blog.N0tExpectErr0r.cn](http://blog.N0tExpectErr0r.cn)
2018-05-07 19:09:41 huangxin388 阅读数 4926

Android数字图像处理之二值化

下面blabla一段废话心急的同志们可以跳过。

        一幅图像包括目标物体,背景还有噪声,怎样从多值的数字图像中取出目标物体,最常用的方法就是设定某一阈值T,用T将图像的数据分成两大部分:大于T的像素群和小于T的像素群。这是研究灰度变换最特殊的方法,成为图像的二值化。二值化处理就是把图像f(x,y)分成目标物体和背景两个区域,然后求其阈值。二值化是数字图像处理中一项最基本的变换方法,通过非0取1、固定阈值、双固定阈值等不同的阈值化变换方法,使一幅灰度图变成了黑白二值图像,将所需的目标部分从复杂的图像背景中脱离出来,以利于以后的研究。

一、非0即1

思路:

 

  1. 传入需要处理的图像
  2. 遍历整个图像取出图像中每个点的像素值存到一个数组中(oldPix)
  3. 在循环中获取每个像素点的颜色值,并抽取每个像素中的r,g,b,a分量准备处理
  4. 利用灰度公式计算出每个点的灰度值(范围0-255),并做溢出处理
  5. 如果某点的灰度值为0则不做处理
  6. 如果某点的灰度值大于0,则将其灰度值置为255(非0即1)
  7. 将处理后的灰度值合成像素点的颜色值,存到一个新数组中(newPix)
  8. 创建一个高度、宽度和原图完全一样的新图
  9. 将存新数组中的颜色值赋给新图
  10. 将新图像返回

用于处理图像的函数如下

    private Bitmap zeroAndOne(Bitmap bm) {
        int width = bm.getWidth();//原图像宽度
        int height = bm.getHeight();//原图像高度
        int color;//用来存储某个像素点的颜色值
        int r, g, b, a;//红,绿,蓝,透明度
        //创建空白图像,宽度等于原图宽度,高度等于原图高度,用ARGB_8888渲染,这个不用了解,这样写就行了
        Bitmap bmp = Bitmap.createBitmap(width, height
                , Bitmap.Config.ARGB_8888);

        int[] oldPx = new int[width * height];//用来存储原图每个像素点的颜色信息
        int[] newPx = new int[width * height];//用来处理处理之后的每个像素点的颜色信息
        /**
         * 第一个参数oldPix[]:用来接收(存储)bm这个图像中像素点颜色信息的数组
         * 第二个参数offset:oldPix[]数组中第一个接收颜色信息的下标值
         * 第三个参数width:在行之间跳过像素的条目数,必须大于等于图像每行的像素数
         * 第四个参数x:从图像bm中读取的第一个像素的横坐标
         * 第五个参数y:从图像bm中读取的第一个像素的纵坐标
         * 第六个参数width:每行需要读取的像素个数
         * 第七个参数height:需要读取的行总数
         */
        bm.getPixels(oldPx, 0, width, 0, 0, width, height);//获取原图中的像素信息

        for (int i = 0; i < width * height; i++) {//循环处理图像中每个像素点的颜色值
            color = oldPx[i];//取得某个点的像素值
            r = Color.red(color);//取得此像素点的r(红色)分量
            g = Color.green(color);//取得此像素点的g(绿色)分量
            b = Color.blue(color);//取得此像素点的b(蓝色分量)
            a = Color.alpha(color);//取得此像素点的a通道值

            //此公式将r,g,b运算获得灰度值,经验公式不需要理解
            int gray = (int)((float)r*0.3+(float)g*0.59+(float)b*0.11);
            //下面前两个if用来做溢出处理,防止灰度公式得到到灰度超出范围(0-255)
            if(gray > 255) {
                gray = 255;
            }

            if(gray < 0) {
                gray = 0;
            }

            if (gray != 0) {//如果某像素的灰度值不是0(黑色)就将其置为255(白色)
                gray = 255;
            }

            newPx[i] = Color.argb(a,gray,gray,gray);//将处理后的透明度(没变),r,g,b分量重新合成颜色值并将其存储在数组中
        }
        /**
         * 第一个参数newPix[]:需要赋给新图像的颜色数组//The colors to write the bitmap
         * 第二个参数offset:newPix[]数组中第一个需要设置给图像颜色的下标值//The index of the first color to read from pixels[]
         * 第三个参数width:在行之间跳过像素的条目数//The number of colors in pixels[] to skip between rows.
         * Normally this value will be the same as the width of the bitmap,but it can be larger(or negative).
         * 第四个参数x:从图像bm中读取的第一个像素的横坐标//The x coordinate of the first pixels to write to in the bitmap.
         * 第五个参数y:从图像bm中读取的第一个像素的纵坐标//The y coordinate of the first pixels to write to in the bitmap.
         * 第六个参数width:每行需要读取的像素个数The number of colors to copy from pixels[] per row.
         * 第七个参数height:需要读取的行总数//The number of rows to write to the bitmap.
         */
        bmp.setPixels(newPx, 0, width, 0, 0, width, height);//将处理后的像素信息赋给新图
        return bmp;//返回处理后的图像
    }

tips:表面上看每个像素点的alpha分量并没有用到,但是处理png图像时就能看到效果了。因为png图像的背景是透明的,我们在合成新像素值时利用了原像素点的alph值,也就是新图像的背景也是透明的。如果不用alpha分量,那么处理后的图像背景就不透明了(可能为纯黑纯白或其他颜色)。如果你不处理png图形则在合成颜色信息时可以用下面这个方法。

newPx[i] = Color.rgb(gray,gray,gray);

效果

            

非0即1法只有被处理图像中的纯黑部分(也就是r,g,b分量都为0)才会保留下来,其他部分都将变成白色。因此在使用范围上有一定的局限性。

二、固定阈值法

思路:

 

  1. 传入需要处理的图像
  2. 获取用户输入的阈值T
  3. 遍历整个图像取出图像中每个点的像素值存到一个数组中(oldPix)
  4. 在循环中获取每个像素点的颜色值,并抽取每个像素中的r,g,b,a分量准备处理
  5. 利用灰度公式计算出每个点的灰度值(范围0-255)
  6. 如果某点的灰度值小于给定阈值则将此点灰度值置为0(黑色)
  7. 如果某点的灰度值大于或等于给定阈值,则将该点灰度值置为255(白色)
  8. 将处理后的灰度值合成像素点的颜色值,存到一个新数组中(newPix)
  9. 创建一个高度、宽度和原图完全一样的新图
  10. 将存新数组中的颜色值赋给新图
  11. 将得到的新图传给ImageView

用于处理图像的函数如下:

    private void singleThreshold(final Bitmap bm) {

        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());//创建AlertDialog对话框
        builder.setTitle("固定阈值法");//对话框标题
        builder.setMessage("请输入阈值");//对话框内容
        View view1 = LayoutInflater.from(getContext()).inflate(R.layout.threshold,null);//载入自定义布局
        final EditText mSingleThresholdEt = view1.findViewById(R.id.digit_dialog);//自定义布局中的EditText,用于接收用户输入
        builder.setView(view1);//将布局设置到对话框中


        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {//对话框的确定按钮点击事件
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

                int width = bm.getWidth();//原图像宽度
                int height = bm.getHeight();//原图高度
                int color;//用来存储某个像素点的颜色值
                int r, g, b, a;//红,绿,蓝,透明度
                int digit = 0;//用于存储用户在对话框中属于的阈值
                //创建空白图像,宽度等于原图宽度,高度等于原图高度,用ARGB_8888渲染,这个不用了解,这样写就行了
                Bitmap bmp = Bitmap.createBitmap(width, height
                        , Bitmap.Config.ARGB_8888);

                int[] oldPx = new int[width * height];//用来存储原图每个像素点的颜色信息
                int[] newPx = new int[width * height];//用来处理处理之后的每个像素点的颜色信息
                /**
                 * 第一个参数oldPix[]:用来接收(存储)bm这个图像中像素点颜色信息的数组
                 * 第二个参数offset:oldPix[]数组中第一个接收颜色信息的下标值
                 * 第三个参数width:在行之间跳过像素的条目数,必须大于等于图像每行的像素数
                 * 第四个参数x:从图像bm中读取的第一个像素的横坐标
                 * 第五个参数y:从图像bm中读取的第一个像素的纵坐标
                 * 第六个参数width:每行需要读取的像素个数
                 * 第七个参数height:需要读取的行总数
                 */
                bm.getPixels(oldPx, 0, width, 0, 0, width, height);//获取原图中的像素信息

                String str = mSingleThresholdEt.getText().toString();//获取用户输入的内容

                if("".equals(str)) {//如果用户输入的内容为空
                    digit = 0;//将阈值置为0
                } else {//否则
                    digit = Integer.valueOf(str);//将用户输入的阈值转换为整数
                }

                for (int j = 0; j < width * height; j++) {//循环处理图像中每个像素点的颜色值
                    color = oldPx[j];//取得某个点的像素值
                    r = Color.red(color);//取得此像素点的r(红色)分量
                    g = Color.green(color);//取得此像素点的g(绿色)分量
                    b = Color.blue(color);//取得此像素点的b(蓝色分量)
                    a = Color.alpha(color);//取得此像素点的a通道值

                    //此公式将r,g,b运算获得灰度值,经验公式不需要理解
                    int gray = (int)((float)r*0.3+(float)g*0.59+(float)b*0.11);
                    
                    if(gray < digit) {//如果某点像素灰度小于给定阈值
                        gray = 0;//将该点像素的灰度值置为0(黑色)
                    } else {//如果某点像素灰度大于或等于给定阈值
                        gray = 255;//将该点像素的灰度值置为1(白色)
                    }
                    newPx[j] = Color.argb(a,gray,gray,gray);//将处理后的透明度(没变),r,g,b分量重新合成颜色值并将其存储在数组中
                }
                /**
                 * 第一个参数newPix[]:需要赋给新图像的颜色数组//The colors to write the bitmap
                 * 第二个参数offset:newPix[]数组中第一个需要设置给图像颜色的下标值//The index of the first color to read from pixels[]
                 * 第三个参数width:在行之间跳过像素的条目数//The number of colors in pixels[] to skip between rows.
                 * Normally this value will be the same as the width of the bitmap,but it can be larger(or negative).
                 * 第四个参数x:从图像bm中读取的第一个像素的横坐标//The x coordinate of the first pixels to write to in the bitmap.
                 * 第五个参数y:从图像bm中读取的第一个像素的纵坐标//The y coordinate of the first pixels to write to in the bitmap.
                 * 第六个参数width:每行需要读取的像素个数The number of colors to copy from pixels[] per row.
                 * 第七个参数height:需要读取的行总数//The number of rows to write to the bitmap.
                 */
                bmp.setPixels(newPx, 0, width, 0, 0, width, height);//将处理后的像素信息赋给新图
                mImageView.setImageBitmap(bmp);//将处理后的新图赋给ImageView
            }
        });


        AlertDialog dialog = builder.create();
        dialog.show();
    }

下面是我们在接收用户输入时使用的对话框所引入的自定义布局threshold.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="阈值:"/>
    <EditText
        android:id="@+id/digit_dialog"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

效果

  

三、双固定阈值法

 

思路:

  1. 传入需要处理的图像
  2. 获取用户输入的阈值下限T1和阈值上限T2
  3. 遍历整个图像取出图像中每个点的像素值存到一个数组中(oldPix)
  4. 在循环中获取每个像素点的颜色值,并抽取每个像素中的r,g,b,a分量准备处理
  5. 利用灰度公式计算出每个点的灰度值(范围0-255)
  6. 如果某点的灰度值小于阈值下限T1或大于阈值上限T2,将其灰度值置为0
  7. 如果某点的灰度值大于等于阈值下限T1或小于等于阈值上限T2,将其灰度值置为255
  8. 将处理后的灰度值合成像素点的颜色值,存到一个新数组中(newPix)
  9. 创建一个高度、宽度和原图完全一样的新图
  10. 将存新数组中的颜色值赋给新图
  11. 将得到的新图传给ImageView

用于处理图像的函数如下

    private void doubleThreshold(final Bitmap bm) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        builder.setTitle("双固定阈值法(0-255-0)");
        builder.setMessage("请输入阈值");
        View view1 = LayoutInflater.from(getContext()).inflate(R.layout.double_threshold_layout,null);
        mLowThresholdEt = view1.findViewById(R.id.low_digit_dialog);
        mHighThresholdEt = view1.findViewById(R.id.heigh_digit_dialog);
        builder.setView(view1);


        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

                int width = bm.getWidth();//原图像宽度
                int height = bm.getHeight();//原图高度
                int color;//用来存储某个像素点的颜色值
                int r, g, b, a;//红,绿,蓝,透明度
                //创建空白图像,宽度等于原图宽度,高度等于原图高度,用ARGB_8888渲染,这个不用了解,这样写就行了
                Bitmap bmp = Bitmap.createBitmap(width, height
                        , Bitmap.Config.ARGB_8888);

                int[] oldPx = new int[width * height];//用来存储原图每个像素点的颜色信息
                int[] newPx = new int[width * height];//用来处理处理之后的每个像素点的颜色信息
                /**
                 * 第一个参数oldPix[]:用来接收(存储)bm这个图像中像素点颜色信息的数组
                 * 第二个参数offset:oldPix[]数组中第一个接收颜色信息的下标值
                 * 第三个参数width:在行之间跳过像素的条目数,必须大于等于图像每行的像素数
                 * 第四个参数x:从图像bm中读取的第一个像素的横坐标
                 * 第五个参数y:从图像bm中读取的第一个像素的纵坐标
                 * 第六个参数width:每行需要读取的像素个数
                 * 第七个参数height:需要读取的行总数
                 */
                bm.getPixels(oldPx, 0, width, 0, 0, width, height);

                String str1 = mLowThresholdEt.getText().toString();
                String str2 = mHighThresholdEt.getText().toString();
                if("".equals(str1)) {
                    lowDigit = 0;
                } else {
                    lowDigit = Integer.valueOf(str1);//用户输入的阈值下限
                }

                if("".equals(str2)) {
                    heighDigit = 255;
                } else {
                    heighDigit = Integer.valueOf(str2);//用户输入的阈值上限
                }

                for (int j = 0; j < width * height; j++) {//循环处理图像中每个像素点的颜色值
                    color = oldPx[j];//取得某个点的像素值
                    r = Color.red(color);//取得此像素点的r(红色)分量
                    g = Color.green(color);//取得此像素点的g(绿色)分量
                    b = Color.blue(color);//取得此像素点的b(蓝色分量)
                    a = Color.alpha(color);//取得此像素点的a通道值
                    //此公式将r,g,b运算获得灰度值,经验公式不需要理解
                    int gray = (int)((float)r*0.3+(float)g*0.59+(float)b*0.11);

                    if(gray < lowDigit || gray > heighDigit) {//如果某点像素的灰度值小于阈值下限或大于阈值上限
                        gray = 0;//将该点灰度值置为0(黑色)
                    } else {//如果某点像素的灰度值大于等于阈值下限或小于等于阈值上限
                        gray = 255;//将该点灰度值置为255(白色)
                    }
                    newPx[j] = Color.argb(a,gray,gray,gray);//将处理后的透明度(没变),r,g,b分量重新合成颜色值并将其存储在数组中
                }
                /**
                 * 第一个参数newPix[]:需要赋给新图像的颜色数组//The colors to write the bitmap
                 * 第二个参数offset:newPix[]数组中第一个需要设置给图像颜色的下标值//The index of the first color to read from pixels[]
                 * 第三个参数width:在行之间跳过像素的条目数//The number of colors in pixels[] to skip between rows.
                 * Normally this value will be the same as the width of the bitmap,but it can be larger(or negative).
                 * 第四个参数x:从图像bm中读取的第一个像素的横坐标//The x coordinate of the first pixels to write to in the bitmap.
                 * 第五个参数y:从图像bm中读取的第一个像素的纵坐标//The y coordinate of the first pixels to write to in the bitmap.
                 * 第六个参数width:每行需要读取的像素个数The number of colors to copy from pixels[] per row.
                 * 第七个参数height:需要读取的行总数//The number of rows to write to the bitmap.
                 */
                bmp.setPixels(newPx, 0, width, 0, 0, width, height);//将处理后的像素信息赋给新图
                mImageView.setImageBitmap(bmp);//将处理后的新图赋给ImageView
            }
        });


        AlertDialog dialog = builder.create();
        dialog.show();
    }

tips:此处我们用的模型为(0-255-0)即将小于下限或大于下限的灰度值置为0,将在下限和上限之间的灰度值置为255。读者可以仿照此例,做一个(255-0-255)的双阈值固定法

下面是我们在接收用户输入时使用的对话框所引入的自定义布局double_threshold_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="下限值:"/>
        <EditText
            android:id="@+id/low_digit_dialog"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="上限值:"/>
        <EditText
            android:id="@+id/heigh_digit_dialog"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</LinearLayout>

效果 

  

代码已上传到github,点击这里可以下载体验

 

 

 

 

 

 

2014-05-21 17:08:22 miaowei163 阅读数 0

Android图像处理

       相机的拍摄照片尺寸通常都很大,需要预先处理,然后才能在ImageView视图上显示。主流Android手机都带有800万像素的照相机组件。大尺寸的图片很容易耗尽应用的内存。因此,加载图片前,需要编写代码缩小图片。图片使用完毕,也需要编写代码清理删除它。

 

/**
 * 图像处理
 * @author mw
 *
 */
public class PictureUtils {

	/**
	 * 将图片缩放到设备默认的显示尺寸 onStart()调用
	 * @param a
	 * @param path
	 * @return
	 */
	public static BitmapDrawable getScaledDrawable(Activity a,String path){
		
		Display display = a.getWindowManager().getDefaultDisplay();
		
		float destWidth = display.getWidth();
		float destHeight = display.getHeight();
		
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path,options);
		
		float srcWidth = options.outWidth;
		float srcHeight = options.outHeight;
		
		int inSampleSize = 1;
		if (srcWidth > destWidth || srcHeight > destHeight) {
		
			if (srcWidth > srcHeight) {
				
				inSampleSize = Math.round(srcWidth/ destWidth);
				
			}else{
				
				inSampleSize = Math.round(srcHeight / destHeight);
			}
			
			
		}
		
		options = new BitmapFactory.Options();
		options.inSampleSize = inSampleSize;
		
		Bitmap bitmap = BitmapFactory.decodeFile(path,options);
		
		return new BitmapDrawable(a.getResources(),bitmap);
		
	}
	/**
	 * 缷载图片 onStop()调用
	 * @param imageView
	 */
	public static void cleanImageView(ImageView imageView){
		
		if ( !(imageView.getDrawable() instanceof BitmapDrawable)) {
			
			return;
		}
		
		BitmapDrawable b = (BitmapDrawable)imageView.getDrawable();
		//释放bitmap占用的原始存储空间,避免可能的内存耗尽问题
		b.getBitmap().recycle();
		imageView.setImageDrawable(null);
		
	}
}
 //以下示例:加载图片---压缩图片---缩放图片---处理圆角
/**
	 * 根据传入的宽和高,计算出合适的inSampleSize值
	 * @param options
	 * @param reqWidth
	 * @param reqHeight
	 * @return
	 */
	public static int calculateInSampleSize(BitmapFactory.Options options,
			int reqWidth, int reqHeight) {
		// 源图片的高度和宽度
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;
		if (height > reqHeight || width > reqWidth) {
			// 计算出实际宽高和目标宽高的比率
			if (width > height) {
				
				inSampleSize = Math.round((float) width / (float) reqWidth);
				
			}else {
				
				//round 返回最接近参数,意思也就是四舍五入math.round(-8.1)=-8 math.round(8.9)=9
				inSampleSize = Math.round((float) height / (float) reqHeight);
			}
			
			
			// 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
			// 一定都会大于等于目标的宽和高。
			//inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
		}
		return inSampleSize;
	}
	/**
	 * 压缩好的bitmap
	 * @param pathName
	 * @param reqWidth
	 * @param reqHeight
	 * @return
	 */
	public static Bitmap decodeSampledBitmapFromResource(String pathName, 
			int reqWidth, int reqHeight) { 
		// 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(pathName,options);
		// 调用上面定义的方法计算inSampleSize值
		options.inSampleSize = calculateInSampleSize(options, reqWidth,reqHeight);
		// 使用获取到的inSampleSize值再次解析图片
		options.inJustDecodeBounds = false;
		//options.inSampleSize = 5;
		return BitmapFactory.decodeFile(pathName,options);
	}
	/**
	 * 处理圆角的图标
	 * @param background
	 * @param src
	 * @param r 弧度
	 * @param x
	 * @param y
	 * @return
	 */
    public static Bitmap mergerIcon(Bitmap background,Bitmap src,int r,int x,int y){
    	Bitmap output = Bitmap.createBitmap(background.getWidth(), background.getHeight(), Config.ARGB_8888);  
        Canvas canvas = new Canvas(output);  
  
        final int color = 0xff000000;  
        final Paint paint = new Paint();  
        final Rect rect = new Rect(0, 0, background.getWidth(), background.getHeight());  
        final RectF rectF = new RectF(rect);  
        final float roundPx = r;  
  
        paint.setAntiAlias(true);  
        canvas.drawARGB(0, 0, 0, 0);  
        paint.setColor(color);  
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);  
  
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));  
        canvas.drawBitmap(background, rect, rect, paint);
//        canvas.drawBitmap(src, rect, rect, paint);
        canvas.drawBitmap(src, x, y, paint);
        canvas.save();
        
        return output;
    }
    
    /**缩放图片*/
    public static Bitmap resizeImage(Bitmap src, int destW, int destH){
    	if(src == null)return null;
        int srcW = src.getWidth();
        int srcH = src.getHeight();
        float scaleWidth = 1;
        float scaleHeight = 1;
        if(srcW == destW&&srcH == destH){
        	return src;
        }
        //计算出这次要缩小的比例
        scaleWidth=(float)destW/(float)srcW;
        scaleHeight=(float)destH/(float)srcH;
        //产生resize后的Bitmap对象
        Matrix matrix=new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        
        Bitmap resizeBmp=Bitmap.createBitmap(src, 0, 0, srcW, srcH, matrix, true);
        
        return resizeBmp;
    }
 //示例使用
        //获取图片路径
	File fileDir = new File(SdcardUtil.getSdcardCollInfo() + str + "/" + pathList.get(0));
	//处理图片
	Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromResource(fileDir.getPath(),200,700);
					
	Bitmap background = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.intdex_page_cll_point);
	//缩放图片
	Bitmap map = BitmapUtils.resizeImage(bitmap, background.getWidth(), background.getWidth());
	//处理圆角
	image_Bitemap.setImageBitmap(BitmapUtils.mergerIcon(background, map, 7,0,0));
 
 
 
2015-10-26 18:00:47 luzhenyuxfcy 阅读数 0

我们常用的处理方式基本都是在对像素矩阵按照一定的数学规律处理得到的,常用的如下;我们也可以通过一个开源的图片处理库(C++)的方式处理,opencv,官网:http://opencv.org/   下载对应平台的SDK,这个库很强大,里面基本包含了常用的处理操作,而且效率很高。对应的文字处理库是OCR(顺带提一下)。

以下是参考文献:

点击打开链接

点击打开链接

点击打开链接

这里有一个开源库很是不错:https://github.com/CyberAgent/android-gpuimage

以上是参考链接,已经很详细了,接下来我会出一个通用的demo在后期会更新上传到这篇博客上。

1、圆角图片

/**
     * 转换成圆角
     * 
     * @param bmp
     * @param roundPx
     * @return
     */
    public static Bitmap convertToRoundedCorner(Bitmap bmp, float roundPx) {
        Bitmap newBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(),
                Config.ARGB_8888);
        // 得到画布
        Canvas canvas = new Canvas(newBmp);
        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bmp.getWidth(), bmp.getHeight());
        final RectF rectF = new RectF(rect);
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        // 第二个和第三个参数一样则画的是正圆的一角,否则是椭圆的一角
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bmp, rect, rect, paint);
        return newBmp;
    }

2、图片灰度化

/**
	 * 图片灰度化处理
	 * 
	 * @param bmSrc
	 * */
	public Bitmap bitmap2Gray(Bitmap bmSrc) {
		// 得到图片的长和宽
		int width = bmSrc.getWidth();
		int height = bmSrc.getHeight();
		// 创建目标灰度图像
		Bitmap bmpGray = null;
		bmpGray = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
		// 创建画布
		Canvas c = new Canvas(bmpGray);
		Paint paint = new Paint();
		ColorMatrix cm = new ColorMatrix();
		cm.setSaturation(0);
		ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
		paint.setColorFilter(f);
		c.drawBitmap(bmSrc, 0, 0, paint);
		return bmpGray;
	}

3、线性灰度化

/**
	 * 图片线性灰度处理
	 * 
	 * @param image
	 * */
	public Bitmap lineGrey(Bitmap image) {
		// 得到图像的宽度和长度
		int width = image.getWidth();
		int height = image.getHeight();
		// 创建线性拉升灰度图像
		Bitmap linegray = null;
		linegray = image.copy(Config.ARGB_8888, true);
		// 依次循环对图像的像素进行处理
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				// 得到每点的像素值
				int col = image.getPixel(i, j);
				int alpha = col & 0xFF000000;
				int red = (col & 0x00FF0000) >> 16;
				int green = (col & 0x0000FF00) >> 8;
				int blue = (col & 0x000000FF);
				// 增加了图像的亮度
				red = (int) (1.1 * red + 30);
				green = (int) (1.1 * green + 30);
				blue = (int) (1.1 * blue + 30);
				// 对图像像素越界进行处理
				if (red >= 255) {
					red = 255;
				}

				if (green >= 255) {
					green = 255;
				}

				if (blue >= 255) {
					blue = 255;
				}
				// 新的ARGB
				int newColor = alpha | (red << 16) | (green << 8) | blue;
				// 设置新图像的RGB值
				linegray.setPixel(i, j, newColor);
			}
		}
		return linegray;
	}

4、图片二值化

/**
	 * 图像二值化处理
	 * 
	 * @param graymap
	 * */
	public Bitmap gray2Binary(Bitmap graymap) {
		// 得到图形的宽度和长度
		int width = graymap.getWidth();
		int height = graymap.getHeight();
		// 创建二值化图像
		Bitmap binarymap = null;
		binarymap = graymap.copy(Config.ARGB_8888, true);
		// 依次循环,对图像的像素进行处理
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				// 得到当前像素的值
				int col = binarymap.getPixel(i, j);
				// 得到alpha通道的值
				int alpha = col & 0xFF000000;
				// 得到图像的像素RGB的值
				int red = (col & 0x00FF0000) >> 16;
				int green = (col & 0x0000FF00) >> 8;
				int blue = (col & 0x000000FF);
				// 用公式X = 0.3×R+0.59×G+0.11×B计算出X代替原来的RGB
				int gray = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11);
				// 对图像进行二值化处理
				if (gray <= 95) {
					gray = 0;
				} else {
					gray = 255;
				}
				// 新的ARGB
				int newColor = alpha | (gray << 16) | (gray << 8) | gray;
				// 设置新图像的当前像素值
				binarymap.setPixel(i, j, newColor);
			}
		}
		return binarymap;
	}

5、高斯模糊

/**
     * 高斯模糊
     * 
     * @param bmp
     * @return
     */
    public static Bitmap convertToBlur(Bitmap bmp) {
        // 高斯矩阵
        int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };
        int width = bmp.getWidth();
        int height = bmp.getHeight();
        Bitmap newBmp = Bitmap.createBitmap(width, height,
                Bitmap.Config.RGB_565);
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int pixColor = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        int delta = 16; // 值越小图片会越亮,越大则越暗
        int idx = 0;
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 1, length = height - 1; i < length; i++) {
            for (int k = 1, len = width - 1; k < len; k++) {
                idx = 0;
                for (int m = -1; m <= 1; m++) {
                    for (int n = -1; n <= 1; n++) {
                        pixColor = pixels[(i + m) * width + k + n];
                        pixR = Color.red(pixColor);
                        pixG = Color.green(pixColor);
                        pixB = Color.blue(pixColor);
                        newR = newR + pixR * gauss[idx];
                        newG = newG + pixG * gauss[idx];
                        newB = newB + pixB * gauss[idx];
                        idx++;
                    }
                }
                newR /= delta;
                newG /= delta;
                newB /= delta;
                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));
                pixels[i * width + k] = Color.argb(255, newR, newG, newB);
                newR = 0;
                newG = 0;
                newB = 0;
            }
        }
        newBmp.setPixels(pixels, 0, width, 0, 0, width, height);
        return newBmp;
    }

6、素描效果

/**
     * 素描效果
     * 
     * @param bmp
     * @return
     */
    public static Bitmap convertToSketch(Bitmap bmp) {
        int pos, row, col, clr;
        int width = bmp.getWidth();
        int height = bmp.getHeight();
        int[] pixSrc = new int[width * height];
        int[] pixNvt = new int[width * height];
        // 先对图象的像素处理成灰度颜色后再取反
        bmp.getPixels(pixSrc, 0, width, 0, 0, width, height);
        for (row = 0; row < height; row++) {
            for (col = 0; col < width; col++) {
                pos = row * width + col;
                pixSrc[pos] = (Color.red(pixSrc[pos])
                        + Color.green(pixSrc[pos]) + Color.blue(pixSrc[pos])) / 3;
                pixNvt[pos] = 255 - pixSrc[pos];
            }
        }
        // 对取反的像素进行高斯模糊, 强度可以设置,暂定为5.0
        gaussGray(pixNvt, 5.0, 5.0, width, height);
        // 灰度颜色和模糊后像素进行差值运算
        for (row = 0; row < height; row++) {
            for (col = 0; col < width; col++) {
                pos = row * width + col;
                clr = pixSrc[pos] << 8;
                clr /= 256 - pixNvt[pos];
                clr = Math.min(clr, 255);
                pixSrc[pos] = Color.rgb(clr, clr, clr);
            }
        }
        bmp.setPixels(pixSrc, 0, width, 0, 0, width, height);
        return bmp;
    }
    private static int gaussGray(int[] psrc, double horz, double vert,
            int width, int height) {
        int[] dst, src;
        double[] n_p, n_m, d_p, d_m, bd_p, bd_m;
        double[] val_p, val_m;
        int i, j, t, k, row, col, terms;
        int[] initial_p, initial_m;
        double std_dev;
        int row_stride = width;
        int max_len = Math.max(width, height);
        int sp_p_idx, sp_m_idx, vp_idx, vm_idx;
        val_p = new double[max_len];
        val_m = new double[max_len];
        n_p = new double[5];
        n_m = new double[5];
        d_p = new double[5];
        d_m = new double[5];
        bd_p = new double[5];
        bd_m = new double[5];
        src = new int[max_len];
        dst = new int[max_len];
        initial_p = new int[4];
        initial_m = new int[4];
        // 垂直方向
        if (vert > 0.0) {
            vert = Math.abs(vert) + 1.0;
            std_dev = Math.sqrt(-(vert * vert) / (2 * Math.log(1.0 / 255.0)));
            // 初试化常量
            findConstants(n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
            for (col = 0; col < width; col++) {
                for (k = 0; k < max_len; k++) {
                    val_m[k] = val_p[k] = 0;
                }
                for (t = 0; t < height; t++) {
                    src[t] = psrc[t * row_stride + col];
                }
                sp_p_idx = 0;
                sp_m_idx = height - 1;
                vp_idx = 0;
                vm_idx = height - 1;
                initial_p[0] = src[0];
                initial_m[0] = src[height - 1];
                for (row = 0; row < height; row++) {
                    terms = (row < 4) ? row : 4;
                    for (i = 0; i <= terms; i++) {
                        val_p[vp_idx] += n_p[i] * src[sp_p_idx - i] - d_p[i]
                                * val_p[vp_idx - i];
                        val_m[vm_idx] += n_m[i] * src[sp_m_idx + i] - d_m[i]
                                * val_m[vm_idx + i];
                    }
                    for (j = i; j <= 4; j++) {
                        val_p[vp_idx] += (n_p[j] - bd_p[j]) * initial_p[0];
                        val_m[vm_idx] += (n_m[j] - bd_m[j]) * initial_m[0];
                    }
                    sp_p_idx++;
                    sp_m_idx--;
                    vp_idx++;
                    vm_idx--;
                }
                transferGaussPixels(val_p, val_m, dst, 1, height);
                for (t = 0; t < height; t++) {
                    psrc[t * row_stride + col] = dst[t];
                }
            }
        }
        // 水平方向
        if (horz > 0.0) {
            horz = Math.abs(horz) + 1.0;
            if (horz != vert) {
                std_dev = Math.sqrt(-(horz * horz)
                        / (2 * Math.log(1.0 / 255.0)));
                // 初试化常量
                findConstants(n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
            }
            for (row = 0; row < height; row++) {
                for (k = 0; k < max_len; k++) {
                    val_m[k] = val_p[k] = 0;
                }
                for (t = 0; t < width; t++) {
                    src[t] = psrc[row * row_stride + t];
                }
                sp_p_idx = 0;
                sp_m_idx = width - 1;
                vp_idx = 0;
                vm_idx = width - 1;
                initial_p[0] = src[0];
                initial_m[0] = src[width - 1];
                for (col = 0; col < width; col++) {
                    terms = (col < 4) ? col : 4;
                    for (i = 0; i <= terms; i++) {
                        val_p[vp_idx] += n_p[i] * src[sp_p_idx - i] - d_p[i]
                                * val_p[vp_idx - i];
                        val_m[vm_idx] += n_m[i] * src[sp_m_idx + i] - d_m[i]
                                * val_m[vm_idx + i];
                    }
                    for (j = i; j <= 4; j++) {
                        val_p[vp_idx] += (n_p[j] - bd_p[j]) * initial_p[0];
                        val_m[vm_idx] += (n_m[j] - bd_m[j]) * initial_m[0];
                    }
                    sp_p_idx++;
                    sp_m_idx--;
                    vp_idx++;
                    vm_idx--;
                }
                transferGaussPixels(val_p, val_m, dst, 1, width);
                for (t = 0; t < width; t++) {
                    psrc[row * row_stride + t] = dst[t];
                }
            }
        }
        return 0;
    }
    private static void transferGaussPixels(double[] src1, double[] src2,
            int[] dest, int bytes, int width) {
        int i, j, k, b;
        int bend = bytes * width;
        double sum;
        i = j = k = 0;
        for (b = 0; b < bend; b++) {
            sum = src1[i++] + src2[j++];
            if (sum > 255)
                sum = 255;
            else if (sum < 0)
                sum = 0;
            dest[k++] = (int) sum;
        }
    }
    private static void findConstants(double[] n_p, double[] n_m, double[] d_p,
            double[] d_m, double[] bd_p, double[] bd_m, double std_dev) {
        double div = Math.sqrt(2 * 3.141593) * std_dev;
        double x0 = -1.783 / std_dev;
        double x1 = -1.723 / std_dev;
        double x2 = 0.6318 / std_dev;
        double x3 = 1.997 / std_dev;
        double x4 = 1.6803 / div;
        double x5 = 3.735 / div;
        double x6 = -0.6803 / div;
        double x7 = -0.2598 / div;
        int i;
        n_p[0] = x4 + x6;
        n_p[1] = (Math.exp(x1)
                * (x7 * Math.sin(x3) - (x6 + 2 * x4) * Math.cos(x3)) + Math
                .exp(x0) * (x5 * Math.sin(x2) - (2 * x6 + x4) * Math.cos(x2)));
        n_p[2] = (2
                * Math.exp(x0 + x1)
                * ((x4 + x6) * Math.cos(x3) * Math.cos(x2) - x5 * Math.cos(x3)
                        * Math.sin(x2) - x7 * Math.cos(x2) * Math.sin(x3)) + x6
                * Math.exp(2 * x0) + x4 * Math.exp(2 * x1));
        n_p[3] = (Math.exp(x1 + 2 * x0)
                * (x7 * Math.sin(x3) - x6 * Math.cos(x3)) + Math.exp(x0 + 2
                * x1)
                * (x5 * Math.sin(x2) - x4 * Math.cos(x2)));
        n_p[4] = 0.0;
        d_p[0] = 0.0;
        d_p[1] = -2 * Math.exp(x1) * Math.cos(x3) - 2 * Math.exp(x0)
                * Math.cos(x2);
        d_p[2] = 4 * Math.cos(x3) * Math.cos(x2) * Math.exp(x0 + x1)
                + Math.exp(2 * x1) + Math.exp(2 * x0);
        d_p[3] = -2 * Math.cos(x2) * Math.exp(x0 + 2 * x1) - 2 * Math.cos(x3)
                * Math.exp(x1 + 2 * x0);
        d_p[4] = Math.exp(2 * x0 + 2 * x1);
        for (i = 0; i <= 4; i++) {
            d_m[i] = d_p[i];
        }
        n_m[0] = 0.0;
        for (i = 1; i <= 4; i++) {
            n_m[i] = n_p[i] - d_p[i] * n_p[0];
        }
        double sum_n_p, sum_n_m, sum_d;
        double a, b;
        sum_n_p = 0.0;
        sum_n_m = 0.0;
        sum_d = 0.0;
        for (i = 0; i <= 4; i++) {
            sum_n_p += n_p[i];
            sum_n_m += n_m[i];
            sum_d += d_p[i];
        }
        a = sum_n_p / (1.0 + sum_d);
        b = sum_n_m / (1.0 + sum_d);
        for (i = 0; i <= 4; i++) {
            bd_p[i] = d_p[i] * a;
            bd_m[i] = d_m[i] * b;
        }
    }

7、锐化

/**
     * 图片锐化(拉普拉斯变换)
     * 
     * @param bmp
     * @return
     */
    public static Bitmap sharpenImageAmeliorate(Bitmap bmp) {
        // 拉普拉斯矩阵
        int[] laplacian = new int[] { -1, -1, -1, -1, 9, -1, -1, -1, -1 };
        int width = bmp.getWidth();
        int height = bmp.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height,
                Bitmap.Config.RGB_565);
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int pixColor = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        int idx = 0;
        float alpha = 0.3F;
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 1, length = height - 1; i < length; i++) {
            for (int k = 1, len = width - 1; k < len; k++) {
                idx = 0;
                for (int m = -1; m <= 1; m++) {
                    for (int n = -1; n <= 1; n++) {
                        pixColor = pixels[(i + n) * width + k + m];
                        pixR = Color.red(pixColor);
                        pixG = Color.green(pixColor);
                        pixB = Color.blue(pixColor);
                        newR = newR + (int) (pixR * laplacian[idx] * alpha);
                        newG = newG + (int) (pixG * laplacian[idx] * alpha);
                        newB = newB + (int) (pixB * laplacian[idx] * alpha);
                        idx++;
                    }
                }
                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));
                pixels[i * width + k] = Color.argb(255, newR, newG, newB);
                newR = 0;
                newG = 0;
                newB = 0;
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

8、怀旧

private Bitmap OldRemeberImage(Bitmap bmp)
	{
	  /*
	   * 怀旧处理算法即设置新的RGB
	   * R=0.393r+0.769g+0.189b
	   * G=0.349r+0.686g+0.168b
	   * B=0.272r+0.534g+0.131b
	   */
	  int width = bmp.getWidth();
	  int height = bmp.getHeight();
	  Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
	  int pixColor = 0;
	  int pixR = 0;
	  int pixG = 0;
	  int pixB = 0;
	  int newR = 0;
	  int newG = 0;
	  int newB = 0;
	  int[] pixels = new int[width * height];
	  bmp.getPixels(pixels, 0, width, 0, 0, width, height);
	  for (int i = 0; i < height; i++)
	  {
	    for (int k = 0; k < width; k++)
	    {
	      pixColor = pixels[width * i + k];
	      pixR = Color.red(pixColor);
	      pixG = Color.green(pixColor);
	      pixB = Color.blue(pixColor);
	      newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
	      newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
	      newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);
	      int newColor = Color.argb(255, newR > 255 ? 255 : newR, newG > 255 ? 255 : newG, newB > 255 ? 255 : newB);
	      pixels[width * i + k] = newColor;
	    }
	  }
	  bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
	  return bitmap;
	}

9、浮雕

//图片浮雕处理
	//底片效果也非常简单:将当前像素点的RGB值分别与255之差后的值作为当前点的RGB
	//灰度图像:通常使用的方法是gray=0.3*pixR+0.59*pixG+0.11*pixB
	private Bitmap ReliefImage(Bitmap bmp)
	{
	  /*
	   * 算法原理:(前一个像素点RGB-当前像素点RGB+127)作为当前像素点RGB值
	   * 在ABC中计算B点浮雕效果(RGB值在0~255)
	   * B.r = C.r - B.r + 127
	   * B.g = C.g - B.g + 127
	   * B.b = C.b - B.b + 127
	   */
	  int width = bmp.getWidth();
	  int height = bmp.getHeight();
	  Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
	  int pixColor = 0;
	  int pixR = 0;
	  int pixG = 0;
	  int pixB = 0;
	  int newR = 0;
	  int newG = 0;
	  int newB = 0;
	  int[] pixels = new int[width * height];
	  bmp.getPixels(pixels, 0, width, 0, 0, width, height);
	  for (int i = 1; i < height-1; i++)
	  {
	    for (int k = 1; k < width-1; k++)
	    {
	      //获取前一个像素颜色
	      pixColor = pixels[width * i + k];   
	      pixR = Color.red(pixColor);
	      pixG = Color.green(pixColor);
	      pixB = Color.blue(pixColor);
	      //获取当前像素
	      pixColor = pixels[(width * i + k) + 1];
	      newR = Color.red(pixColor) - pixR +127;
	      newG = Color.green(pixColor) - pixG +127;
	      newB = Color.blue(pixColor) - pixB +127;
	      newR = Math.min(255, Math.max(0, newR));
	      newG = Math.min(255, Math.max(0, newG));
	      newB = Math.min(255, Math.max(0, newB));
	      pixels[width * i + k] = Color.argb(255, newR, newG, newB);
	    }
	  }
	  bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
	  return bitmap;
	}

10、光照效果

//图片光照效果
	private Bitmap SunshineImage(Bitmap bmp)
	{
	  /*
	   * 算法原理:(前一个像素点RGB-当前像素点RGB+127)作为当前像素点RGB值
	   * 在ABC中计算B点浮雕效果(RGB值在0~255)
	   * B.r = C.r - B.r + 127
	   * B.g = C.g - B.g + 127
	   * B.b = C.b - B.b + 127
	   * 光照中心取长宽较小值为半径,也可以自定义从左上角射过来
	   */		
	  int width = bmp.getWidth();
	  int height = bmp.getHeight();
	  Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
	  int pixColor = 0;
	  int pixR = 0;
	  int pixG = 0;
	  int pixB = 0;
	  int newR = 0;
	  int newG = 0;
	  int newB = 0;
	  //围绕圆形光照
	  int centerX = width / 2;
	  int centerY = height / 2;
	  int radius = Math.min(centerX, centerY);
	  float strength = 150F;  //光照强度100-150
	  int[] pixels = new int[width * height];
	  bmp.getPixels(pixels, 0, width, 0, 0, width, height);
	  for (int i = 1; i < height-1; i++)
	  {
	    for (int k = 1; k < width-1; k++)
	    {
	      //获取前一个像素颜色
	      pixColor = pixels[width * i + k];   
	      pixR = Color.red(pixColor);
	      pixG = Color.green(pixColor);
	      pixB = Color.blue(pixColor);
	      newR = pixR;
	      newG = pixG;
	      newB = pixB;
	      //计算当前点到光照中心的距离,平面坐标系中两点之间的距离
	      int distance = (int) (Math.pow((centerY-i), 2) + Math.pow((centerX-k), 2));
	      if(distance < radius*radius)
	      {
	        //按照距离大小计算增强的光照值
	        int result = (int)(strength*( 1.0-Math.sqrt(distance) / radius ));
	        newR = pixR + result;
	        newG = newG + result;
	        newB = pixB + result;
	      }
	      newR = Math.min(255, Math.max(0, newR));
	      newG = Math.min(255, Math.max(0, newG));
	      newB = Math.min(255, Math.max(0, newB));
	      pixels[width * i + k] = Color.argb(255, newR, newG, newB);
	    }
	  }
	  bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
	  return bitmap;
	}

11、冰冻效果

//图片冰冻效果
	private Bitmap IceImage(Bitmap bmp)
	{
	  int width = bmp.getWidth();
	  int height = bmp.getHeight();
	  Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
	  int pixColor = 0;
	  int pixR = 0;
	  int pixG = 0;
	  int pixB = 0;
	  int newColor = 0;
	  int newR = 0;
	  int newG = 0;
	  int newB =0;
	  int[] pixels = new int[width * height];
	  bmp.getPixels(pixels, 0, width, 0, 0, width, height);
	  for (int i = 0; i < height; i++)
	  {
	    for (int k = 0; k < width; k++)
	    {
	      //获取前一个像素颜色
	      pixColor = pixels[width * i + k];   
	      pixR = Color.red(pixColor);
	      pixG = Color.green(pixColor);
	      pixB = Color.blue(pixColor);
	      //红色
	      newColor = pixR - pixG - pixB;
	      newColor = newColor * 3 / 2;
	      if(newColor < 0) {
	        newColor = -newColor;
	      }
	      if(newColor >255) {
	        newColor = 255;
	      }
	      newR = newColor;
	      //绿色
	      newColor = pixG - pixB - pixR;
	      newColor = newColor * 3 / 2;
	      if(newColor < 0) {
	        newColor = -newColor;
	      }
	      if(newColor >255) {
	        newColor = 255;
	      }
	      newG = newColor;
	      //蓝色
	      newColor = pixB - pixG - pixR;
	      newColor = newColor * 3 / 2;
	      if(newColor < 0) {
	        newColor = -newColor;
	      }
	      if(newColor >255) {
	        newColor = 255;
	      }
	      newB = newColor;
	      pixels[width * i + k] = Color.argb(255, newR, newG, newB);
	    }
	  }
	  bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
	  return bitmap;
	}

12、直方图均值化

/*
	 *直方图均衡化
	 */
    public Bitmap histEqualize(Bitmap myBitmap){
        // Create new array
        int width = myBitmap.getWidth();
        int height = myBitmap.getHeight();
        int[] pix = new int[width * height];
        myBitmap.getPixels(pix, 0, width, 0, 0, width, height);
        Matrix dataR=getDataR(pix, width, height);
        Matrix dataG=getDataG(pix, width, height);
        Matrix dataB=getDataB(pix, width, height);
        //Matrix dataGray=getDataGray(pix, width, height);
        /////////////////////////////////////////////////////////
        dataR=eachEqualize(dataR,width,height);
        dataG=eachEqualize(dataG,width,height);
        dataB=eachEqualize(dataB,width,height);
        ///////////////////////////////////////////////////////////////
        // Change bitmap to use new array
        Bitmap bitmap=makeToBitmap(dataR, dataG, dataB, width, height);
        myBitmap = null;
        pix = null;
        return bitmap;
    }
    private Matrix eachEqualize(Matrix temp,int width,int height){
        // 灰度映射表
        int	bMap[]=new int[256];
        // 灰度映射表
        int lCount[]=new int[256];
        // 重置计数为0
        int i,j;
        for (i = 0; i < 256; i ++){
            // 清零
            lCount[i] = 0;
        }
        // 计算各个灰度值的计数 - 参考灰度直方图的绘制代码 (对话框类中)
        for (i = 0; i < height; i ++){
            for (j = 0; j < width; j ++){
                lCount[(int)temp.get(i, j)]++;  // 计数加1
            }
        }
        // 计算灰度映射表
        for (i = 0; i < 256; i++){
            // 初始为0
            int Temp = 0;
            for (j = 0; j <= i ; j++){
                Temp += lCount[j];
            }
            // 计算对应的新灰度值
            bMap[i] = (int) (Temp * 255 / height / width);
        }
        // 每行
        for (i = 0; i < height; i++){
            // 每列
            for (j = 0; j < width; j++){
                temp.set(i, j, bMap[(int)temp.get(i,j)]);
            }
        }
        return temp;
    }

特效处理代码源码:

package com.lzy.imageprolib.kits;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.media.ThumbnailUtils;
import android.os.Environment;
import android.text.TextUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

/**
 * Created by luzhenyu on 2016/5/11.
 */
public class ImageProcessHelper {

    ////////////////////////////////////////////////////////////////////

    private ImageProcessHelper() {

    }

    private static class HelperTemp {
        private static ImageProcessHelper helper = new ImageProcessHelper();
    }

    /**
     * 获取处理实例
     * Get ImageProcessHelper instance by single
     *
     * @return ImageProcessHelper
     */
    public static ImageProcessHelper getInstance() {
        return HelperTemp.helper;
    }
    ///////////////////////////////////////////////////////////////////

    //////////////////////////////图片位置//////////////////////////////
    /**
     * 位置 上下左右中 左上角 左下角 右上角 右下角 中间
     * */
    public enum Position {
        LEFT,
        RIGHT,
        TOP,
        BOTTOM,
        CENTRE,
        LEFT_UP,
        LEFT_DOWN,
        RIGHT_UP,
        RIGHT_DOWN,
        CENTER;
    }

    /**
     * 图片格式
     * */
    public enum Format {
        JPEG,
        PNG,
        WEBP;
    }

    /**
     * Bitmap图片转换成圆角
     *
     * @param mBitmapSrc 图片源
     * @param roundPx    float
     * @return Bitmap
     */
    public Bitmap convert2RoundedCorner(Bitmap mBitmapSrc, float roundPx) {
        Bitmap newBitmap = Bitmap.createBitmap(mBitmapSrc.getWidth(), mBitmapSrc.getHeight(),
                Bitmap.Config.ARGB_8888);
        // 得到画布
        Canvas canvas = new Canvas(newBitmap);
        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, mBitmapSrc.getWidth(), mBitmapSrc.getHeight());
        final RectF rectF = new RectF(rect);
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        // 第二个和第三个参数一样则画的是正圆的一角,否则是椭圆的一角
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(mBitmapSrc, rect, rect, paint);
        return newBitmap;
    }

    /**
     * Bitmap图片灰度化处理
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap bitmap2Gray(Bitmap mBitmapSrc) {
        // 得到图片的长和宽
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        // 创建目标灰度图像
        Bitmap bmpGray = null;
        bmpGray = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        // 创建画布
        Canvas c = new Canvas(bmpGray);
        Paint paint = new Paint();
        ColorMatrix cm = new ColorMatrix();
        cm.setSaturation(0);
        ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
        paint.setColorFilter(f);
        c.drawBitmap(mBitmapSrc, 0, 0, paint);
        return bmpGray;
    }

    /**
     * 图片线性灰度处理
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap bitmap2LineGrey(Bitmap mBitmapSrc) {
        // 得到图像的宽度和长度
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        // 创建线性拉升灰度图像
        Bitmap bitmap = mBitmapSrc.copy(Bitmap.Config.ARGB_8888, true);
        // 依次循环对图像的像素进行处理
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                // 得到每点的像素值
                int col = mBitmapSrc.getPixel(i, j);
                int alpha = col & 0xFF000000;
                int red = (col & 0x00FF0000) >> 16;
                int green = (col & 0x0000FF00) >> 8;
                int blue = (col & 0x000000FF);
                // 增加了图像的亮度
                red = (int) (1.1 * red + 30);
                green = (int) (1.1 * green + 30);
                blue = (int) (1.1 * blue + 30);
                // 对图像像素越界进行处理
                if (red >= 255) {
                    red = 255;
                }

                if (green >= 255) {
                    green = 255;
                }

                if (blue >= 255) {
                    blue = 255;
                }
                // 新的ARGB
                int newColor = alpha | (red << 16) | (green << 8) | blue;
                // 设置新图像的RGB值
                bitmap.setPixel(i, j, newColor);
            }
        }
        return bitmap;
    }

    /**
     * 图像二值化处理
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap gray2Binary(Bitmap mBitmapSrc) {
        // 得到图形的宽度和长度
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        // 创建二值化图像
        Bitmap binarybm = null;
        binarybm = mBitmapSrc.copy(Bitmap.Config.ARGB_8888, true);
        // 依次循环,对图像的像素进行处理
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                // 得到当前像素的值
                int col = binarybm.getPixel(i, j);
                // 得到alpha通道的值
                int alpha = col & 0xFF000000;
                // 得到图像的像素RGB的值
                int red = (col & 0x00FF0000) >> 16;
                int green = (col & 0x0000FF00) >> 8;
                int blue = (col & 0x000000FF);
                // 用公式X = 0.3×R+0.59×G+0.11×B计算出X代替原来的RGB
                int gray = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11);
                // 对图像进行二值化处理
                if (gray <= 95) {
                    gray = 0;
                } else {
                    gray = 255;
                }
                // 新的ARGB
                int newColor = alpha | (gray << 16) | (gray << 8) | gray;
                // 设置新图像的当前像素值
                binarybm.setPixel(i, j, newColor);
            }
        }
        return binarybm;
    }

    /**
     * 高斯模糊
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap convertToBlur(Bitmap mBitmapSrc) {
        // 高斯矩阵
        int[] gauss = new int[]{1, 2, 1, 2, 4, 2, 1, 2, 1};
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        Bitmap newBmp = Bitmap.createBitmap(width, height,
                Bitmap.Config.RGB_565);
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int pixColor = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        int delta = 16; // 值越小图片会越亮,越大则越暗
        int idx = 0;
        int[] pixels = new int[width * height];
        mBitmapSrc.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 1, length = height - 1; i < length; i++) {
            for (int k = 1, len = width - 1; k < len; k++) {
                idx = 0;
                for (int m = -1; m <= 1; m++) {
                    for (int n = -1; n <= 1; n++) {
                        pixColor = pixels[(i + m) * width + k + n];
                        pixR = Color.red(pixColor);
                        pixG = Color.green(pixColor);
                        pixB = Color.blue(pixColor);
                        newR = newR + pixR * gauss[idx];
                        newG = newG + pixG * gauss[idx];
                        newB = newB + pixB * gauss[idx];
                        idx++;
                    }
                }
                newR /= delta;
                newG /= delta;
                newB /= delta;
                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));
                pixels[i * width + k] = Color.argb(255, newR, newG, newB);
                newR = 0;
                newG = 0;
                newB = 0;
            }
        }
        newBmp.setPixels(pixels, 0, width, 0, 0, width, height);
        return newBmp;
    }

    /**
     * 素描效果
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap convertToSketch(Bitmap mBitmapSrc) {
        int pos, row, col, clr;
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        int[] pixSrc = new int[width * height];
        int[] pixNvt = new int[width * height];
        // 先对图象的像素处理成灰度颜色后再取反
        mBitmapSrc.getPixels(pixSrc, 0, width, 0, 0, width, height);
        for (row = 0; row < height; row++) {
            for (col = 0; col < width; col++) {
                pos = row * width + col;
                pixSrc[pos] = (Color.red(pixSrc[pos])
                        + Color.green(pixSrc[pos]) + Color.blue(pixSrc[pos])) / 3;
                pixNvt[pos] = 255 - pixSrc[pos];
            }
        }
        // 对取反的像素进行高斯模糊, 强度可以设置,暂定为5.0
        gaussGray(pixNvt, 5.0, 5.0, width, height);
        // 灰度颜色和模糊后像素进行差值运算
        for (row = 0; row < height; row++) {
            for (col = 0; col < width; col++) {
                pos = row * width + col;
                clr = pixSrc[pos] << 8;
                clr /= 256 - pixNvt[pos];
                clr = Math.min(clr, 255);
                pixSrc[pos] = Color.rgb(clr, clr, clr);
            }
        }
        mBitmapSrc.setPixels(pixSrc, 0, width, 0, 0, width, height);
        return mBitmapSrc;
    }

    private int gaussGray(int[] psrc, double horz, double vert,
                          int width, int height) {
        int[] dst, src;
        double[] n_p, n_m, d_p, d_m, bd_p, bd_m;
        double[] val_p, val_m;
        int i, j, t, k, row, col, terms;
        int[] initial_p, initial_m;
        double std_dev;
        int row_stride = width;
        int max_len = Math.max(width, height);
        int sp_p_idx, sp_m_idx, vp_idx, vm_idx;
        val_p = new double[max_len];
        val_m = new double[max_len];
        n_p = new double[5];
        n_m = new double[5];
        d_p = new double[5];
        d_m = new double[5];
        bd_p = new double[5];
        bd_m = new double[5];
        src = new int[max_len];
        dst = new int[max_len];
        initial_p = new int[4];
        initial_m = new int[4];
        // 垂直方向
        if (vert > 0.0) {
            vert = Math.abs(vert) + 1.0;
            std_dev = Math.sqrt(-(vert * vert) / (2 * Math.log(1.0 / 255.0)));
            // 初试化常量
            findConstants(n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
            for (col = 0; col < width; col++) {
                for (k = 0; k < max_len; k++) {
                    val_m[k] = val_p[k] = 0;
                }
                for (t = 0; t < height; t++) {
                    src[t] = psrc[t * row_stride + col];
                }
                sp_p_idx = 0;
                sp_m_idx = height - 1;
                vp_idx = 0;
                vm_idx = height - 1;
                initial_p[0] = src[0];
                initial_m[0] = src[height - 1];
                for (row = 0; row < height; row++) {
                    terms = (row < 4) ? row : 4;
                    for (i = 0; i <= terms; i++) {
                        val_p[vp_idx] += n_p[i] * src[sp_p_idx - i] - d_p[i]
                                * val_p[vp_idx - i];
                        val_m[vm_idx] += n_m[i] * src[sp_m_idx + i] - d_m[i]
                                * val_m[vm_idx + i];
                    }
                    for (j = i; j <= 4; j++) {
                        val_p[vp_idx] += (n_p[j] - bd_p[j]) * initial_p[0];
                        val_m[vm_idx] += (n_m[j] - bd_m[j]) * initial_m[0];
                    }
                    sp_p_idx++;
                    sp_m_idx--;
                    vp_idx++;
                    vm_idx--;
                }
                int i1, j1, k1, b;
                int bend = 1 * height;
                double sum;
                i1 = j1 = k1 = 0;
                for (b = 0; b < bend; b++) {
                    sum = val_p[i1++] + val_m[j1++];
                    if (sum > 255)
                        sum = 255;
                    else if (sum < 0)
                        sum = 0;
                    dst[k1++] = (int) sum;
                }
                for (t = 0; t < height; t++) {
                    psrc[t * row_stride + col] = dst[t];
                }
            }
        }
        // 水平方向
        if (horz > 0.0) {
            horz = Math.abs(horz) + 1.0;
            if (horz != vert) {
                std_dev = Math.sqrt(-(horz * horz)
                        / (2 * Math.log(1.0 / 255.0)));
                // 初试化常量
                findConstants(n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
            }
            for (row = 0; row < height; row++) {
                for (k = 0; k < max_len; k++) {
                    val_m[k] = val_p[k] = 0;
                }
                for (t = 0; t < width; t++) {
                    src[t] = psrc[row * row_stride + t];
                }
                sp_p_idx = 0;
                sp_m_idx = width - 1;
                vp_idx = 0;
                vm_idx = width - 1;
                initial_p[0] = src[0];
                initial_m[0] = src[width - 1];
                for (col = 0; col < width; col++) {
                    terms = (col < 4) ? col : 4;
                    for (i = 0; i <= terms; i++) {
                        val_p[vp_idx] += n_p[i] * src[sp_p_idx - i] - d_p[i]
                                * val_p[vp_idx - i];
                        val_m[vm_idx] += n_m[i] * src[sp_m_idx + i] - d_m[i]
                                * val_m[vm_idx + i];
                    }
                    for (j = i; j <= 4; j++) {
                        val_p[vp_idx] += (n_p[j] - bd_p[j]) * initial_p[0];
                        val_m[vm_idx] += (n_m[j] - bd_m[j]) * initial_m[0];
                    }
                    sp_p_idx++;
                    sp_m_idx--;
                    vp_idx++;
                    vm_idx--;
                }
                int i1, j1, k1, b;
                int bend = 1 * width;
                double sum;
                i1 = j1 = k1 = 0;
                for (b = 0; b < bend; b++) {
                    sum = val_p[i1++] + val_m[j1++];
                    if (sum > 255)
                        sum = 255;
                    else if (sum < 0)
                        sum = 0;
                    dst[k1++] = (int) sum;
                }
                for (t = 0; t < width; t++) {
                    psrc[row * row_stride + t] = dst[t];
                }
            }
        }
        return 0;
    }

    private void findConstants(double[] n_p, double[] n_m, double[] d_p,
                               double[] d_m, double[] bd_p, double[] bd_m, double std_dev) {
        double div = Math.sqrt(2 * 3.141593) * std_dev;
        double x0 = -1.783 / std_dev;
        double x1 = -1.723 / std_dev;
        double x2 = 0.6318 / std_dev;
        double x3 = 1.997 / std_dev;
        double x4 = 1.6803 / div;
        double x5 = 3.735 / div;
        double x6 = -0.6803 / div;
        double x7 = -0.2598 / div;
        int i;
        n_p[0] = x4 + x6;
        n_p[1] = (Math.exp(x1)
                * (x7 * Math.sin(x3) - (x6 + 2 * x4) * Math.cos(x3)) + Math
                .exp(x0) * (x5 * Math.sin(x2) - (2 * x6 + x4) * Math.cos(x2)));
        n_p[2] = (2
                * Math.exp(x0 + x1)
                * ((x4 + x6) * Math.cos(x3) * Math.cos(x2) - x5 * Math.cos(x3)
                * Math.sin(x2) - x7 * Math.cos(x2) * Math.sin(x3)) + x6
                * Math.exp(2 * x0) + x4 * Math.exp(2 * x1));
        n_p[3] = (Math.exp(x1 + 2 * x0)
                * (x7 * Math.sin(x3) - x6 * Math.cos(x3)) + Math.exp(x0 + 2
                * x1)
                * (x5 * Math.sin(x2) - x4 * Math.cos(x2)));
        n_p[4] = 0.0;
        d_p[0] = 0.0;
        d_p[1] = -2 * Math.exp(x1) * Math.cos(x3) - 2 * Math.exp(x0)
                * Math.cos(x2);
        d_p[2] = 4 * Math.cos(x3) * Math.cos(x2) * Math.exp(x0 + x1)
                + Math.exp(2 * x1) + Math.exp(2 * x0);
        d_p[3] = -2 * Math.cos(x2) * Math.exp(x0 + 2 * x1) - 2 * Math.cos(x3)
                * Math.exp(x1 + 2 * x0);
        d_p[4] = Math.exp(2 * x0 + 2 * x1);
        for (i = 0; i <= 4; i++) {
            d_m[i] = d_p[i];
        }
        n_m[0] = 0.0;
        for (i = 1; i <= 4; i++) {
            n_m[i] = n_p[i] - d_p[i] * n_p[0];
        }
        double sum_n_p, sum_n_m, sum_d;
        double a, b;
        sum_n_p = 0.0;
        sum_n_m = 0.0;
        sum_d = 0.0;
        for (i = 0; i <= 4; i++) {
            sum_n_p += n_p[i];
            sum_n_m += n_m[i];
            sum_d += d_p[i];
        }
        a = sum_n_p / (1.0 + sum_d);
        b = sum_n_m / (1.0 + sum_d);
        for (i = 0; i <= 4; i++) {
            bd_p[i] = d_p[i] * a;
            bd_m[i] = d_m[i] * b;
        }
    }

    /**
     * 图片锐化(拉普拉斯变换)
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap sharpenImageAmeliorate(Bitmap mBitmapSrc) {
        // 拉普拉斯矩阵
        int[] laplacian = new int[]{-1, -1, -1, -1, 9, -1, -1, -1, -1};
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height,
                Bitmap.Config.RGB_565);
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int pixColor = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        int idx = 0;
        float alpha = 0.3F;
        int[] pixels = new int[width * height];
        mBitmapSrc.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 1, length = height - 1; i < length; i++) {
            for (int k = 1, len = width - 1; k < len; k++) {
                idx = 0;
                for (int m = -1; m <= 1; m++) {
                    for (int n = -1; n <= 1; n++) {
                        pixColor = pixels[(i + n) * width + k + m];
                        pixR = Color.red(pixColor);
                        pixG = Color.green(pixColor);
                        pixB = Color.blue(pixColor);
                        newR = newR + (int) (pixR * laplacian[idx] * alpha);
                        newG = newG + (int) (pixG * laplacian[idx] * alpha);
                        newB = newB + (int) (pixB * laplacian[idx] * alpha);
                        idx++;
                    }
                }
                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));
                pixels[i * width + k] = Color.argb(255, newR, newG, newB);
                newR = 0;
                newG = 0;
                newB = 0;
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 图片复古
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap oldRemeberImage(Bitmap mBitmapSrc) {
      /*
       * 怀旧处理算法即设置新的RGB
	   * R=0.393r+0.769g+0.189b
	   * G=0.349r+0.686g+0.168b
	   * B=0.272r+0.534g+0.131b
	   */
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        int pixColor = 0;
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        int[] pixels = new int[width * height];
        mBitmapSrc.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 0; i < height; i++) {
            for (int k = 0; k < width; k++) {
                pixColor = pixels[width * i + k];
                pixR = Color.red(pixColor);
                pixG = Color.green(pixColor);
                pixB = Color.blue(pixColor);
                newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
                newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
                newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);
                int newColor = Color.argb(255, newR > 255 ? 255 : newR, newG > 255 ? 255 : newG, newB > 255 ? 255 : newB);
                pixels[width * i + k] = newColor;
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 图片浮雕
     * 将当前像素点的RGB值分别与255之差后的值作为当前点的RGB
     * 灰度图像:通常使用的方法是gray=0.3*pixR+0.59*pixG+0.11*pixB
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap reliefImage(Bitmap mBitmapSrc) {
      /*
       * 算法原理:(前一个像素点RGB-当前像素点RGB+127)作为当前像素点RGB值
	   * 在ABC中计算B点浮雕效果(RGB值在0~255)
	   * B.r = C.r - B.r + 127
	   * B.g = C.g - B.g + 127
	   * B.b = C.b - B.b + 127
	   */
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        int pixColor = 0;
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        int[] pixels = new int[width * height];
        mBitmapSrc.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 1; i < height - 1; i++) {
            for (int k = 1; k < width - 1; k++) {
                //获取前一个像素颜色
                pixColor = pixels[width * i + k];
                pixR = Color.red(pixColor);
                pixG = Color.green(pixColor);
                pixB = Color.blue(pixColor);
                //获取当前像素
                pixColor = pixels[(width * i + k) + 1];
                newR = Color.red(pixColor) - pixR + 127;
                newG = Color.green(pixColor) - pixG + 127;
                newB = Color.blue(pixColor) - pixB + 127;
                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));
                pixels[width * i + k] = Color.argb(255, newR, newG, newB);
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 图片光照效果
     *
     * @param mBitmapSrc  图片源
     * @param position 光照位置 默认居中
     * @param strength    光照强度 100-150
     * @return Bitmap
     */
    public Bitmap sunshineImage(Bitmap mBitmapSrc, Position position, float strength) {
      /*
       * 算法原理:(前一个像素点RGB-当前像素点RGB+127)作为当前像素点RGB值
	   * 在ABC中计算B点浮雕效果(RGB值在0~255)
	   * B.r = C.r - B.r + 127
	   * B.g = C.g - B.g + 127
	   * B.b = C.b - B.b + 127
	   * 光照中心取长宽较小值为半径,也可以自定义从左上角射过来
	   */
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        int pixColor = 0;
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        //光照
        int centerX;
        int centerY;
        if (position == Position.LEFT_DOWN){centerX = width * (1/4); centerY = height * (3/4);}
        else if (position == Position.LEFT_UP){centerX = width * (1/4); centerY = height * (1/4);}
        else if (position == Position.RIGHT_DOWN){centerX = width * (3/4); centerY = height * (3/4);}
        else if (position == Position.RIGHT_UP){centerX = width * (3/4); centerY = height * (1/4);}
        else {centerX = width / 2; centerY = height / 2;}//默认居中

        int radius = Math.min(centerX, centerY);
        int[] pixels = new int[width * height];
        mBitmapSrc.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 1; i < height - 1; i++) {
            for (int k = 1; k < width - 1; k++) {
                //获取前一个像素颜色
                pixColor = pixels[width * i + k];
                pixR = Color.red(pixColor);
                pixG = Color.green(pixColor);
                pixB = Color.blue(pixColor);
                newR = pixR;
                newG = pixG;
                newB = pixB;
                //计算当前点到光照中心的距离,平面坐标系中两点之间的距离
                int distance = (int) (Math.pow((centerY - i), 2) + Math.pow((centerX - k), 2));
                if (distance < radius * radius) {
                    //按照距离大小计算增强的光照值
                    int result = (int) (strength * (1.0 - Math.sqrt(distance) / radius));
                    newR = pixR + result;
                    newG = newG + result;
                    newB = pixB + result;
                }
                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));
                pixels[width * i + k] = Color.argb(255, newR, newG, newB);
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 图片冰冻效果
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap iceImage(Bitmap mBitmapSrc) {
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        int pixColor = 0;
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int newColor = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        int[] pixels = new int[width * height];
        mBitmapSrc.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 0; i < height; i++) {
            for (int k = 0; k < width; k++) {
                //获取前一个像素颜色
                pixColor = pixels[width * i + k];
                pixR = Color.red(pixColor);
                pixG = Color.green(pixColor);
                pixB = Color.blue(pixColor);
                //红色
                newColor = pixR - pixG - pixB;
                newColor = newColor * 3 / 2;
                if (newColor < 0) {
                    newColor = -newColor;
                }
                if (newColor > 255) {
                    newColor = 255;
                }
                newR = newColor;
                //绿色
                newColor = pixG - pixB - pixR;
                newColor = newColor * 3 / 2;
                if (newColor < 0) {
                    newColor = -newColor;
                }
                if (newColor > 255) {
                    newColor = 255;
                }
                newG = newColor;
                //蓝色
                newColor = pixB - pixG - pixR;
                newColor = newColor * 3 / 2;
                if (newColor < 0) {
                    newColor = -newColor;
                }
                if (newColor > 255) {
                    newColor = 255;
                }
                newB = newColor;
                pixels[width * i + k] = Color.argb(255, newR, newG, newB);
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 放大缩小图片
     *
     * @param mBitmapSrc 图片源
     * @param w          压缩后的宽度 负数时为反向
     * @param h          压缩后的高度 负数为反向
     * @return Bitmap
     */
    public Bitmap zoomBitmap(Bitmap mBitmapSrc, int w, int h) {
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        Matrix matrix = new Matrix();
        float scaleWidth = ((float) w / width);
        float scaleHeight = ((float) h / height);
        matrix.postScale(scaleWidth, scaleHeight);
        return Bitmap.createBitmap(mBitmapSrc, 0, 0, width, height, matrix, true);
    }

    /**
     * 按比例放大缩小图片
     *
     * @param mBitmapSrc  图片源
     * @param widthScale  宽缩放比
     * @param heightScale 高缩放比
     * @return Bitmap
     */
    public Bitmap zoomBitmap(Bitmap mBitmapSrc, float widthScale, float heightScale) {
        Matrix matrix = new Matrix();
        matrix.postScale(widthScale, heightScale);
        return Bitmap.createBitmap(mBitmapSrc, 0, 0, mBitmapSrc.getWidth(), mBitmapSrc.getHeight(), matrix, true);
    }

    /**
     * 将Drawable转化为Bitmap
     *
     * @param mDrawableSrc 要转化的源drawable
     * @return Bitmap
     */
    public Bitmap drawableToBitmap(Drawable mDrawableSrc) {
        int width = mDrawableSrc.getIntrinsicWidth();
        int height = mDrawableSrc.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height,
                mDrawableSrc.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
                        : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        mDrawableSrc.setBounds(0, 0, width, height);
        mDrawableSrc.draw(canvas);
        return bitmap;

    }

    /**
     * 倒影图片
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap toReflectedImage(Bitmap mBitmapSrc) {
        final int reflectionGap = 4;
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        Matrix matrix = new Matrix();
        matrix.preScale(1, -1);
        Bitmap reflectionImage = Bitmap.createBitmap(mBitmapSrc, 0,
                height / 2, width, height / 2, matrix, false);
        Bitmap bitmap = Bitmap.createBitmap(width,
                (height + height / 2), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawBitmap(mBitmapSrc, 0, 0, null);
        Paint defaultPaint = new Paint();
        canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
        canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
        Paint paint = new Paint();
        LinearGradient shader = new LinearGradient(0,
                mBitmapSrc.getHeight(), 0, bitmap.getHeight()
                + reflectionGap, 0x70FFFFFF, 0x00FFFFFF,
                Shader.TileMode.MIRROR);
        paint.setShader(shader);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        canvas.drawRect(0, height, width, bitmap.getHeight()
                + reflectionGap, paint);
        return bitmap;
    }

    /**
     * 水印特效
     *
     * @param mBitmapSrc   图片源
     * @param waterMarkSrc Bitmap
     * @return Bitmap
     */
    public Bitmap createBitmapWithWatermark(Bitmap mBitmapSrc, Bitmap waterMarkSrc, Position position) {
        if (mBitmapSrc == null) {
            return null;
        }
        int w = mBitmapSrc.getWidth();
        int h = mBitmapSrc.getHeight();
        int ww = waterMarkSrc.getWidth();
        int wh = waterMarkSrc.getHeight();

        Bitmap newBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
        Canvas cv = new Canvas(newBitmap);

        cv.drawBitmap(mBitmapSrc, 0, 0, null);// 在 0,0坐标开始画入src

        if (position == Position.RIGHT_DOWN)
            cv.drawBitmap(waterMarkSrc, w - ww + 5, h - wh + 5, null);// 在src的右下角画入水印
        else if (position == Position.RIGHT_UP)
            cv.drawBitmap(waterMarkSrc, w - ww + 5, 5, null);// 在src的右上角画入水印
        else if (position == Position.LEFT_DOWN)
            cv.drawBitmap(waterMarkSrc, 5, h - wh + 5, null);// 在src的左下角画入水印
        else if (position == Position.LEFT_UP)
            cv.drawBitmap(waterMarkSrc, 5, 5, null);// 在src的左上角画入水印
        else
            cv.drawBitmap(waterMarkSrc, w/2 - ww/2, h/2 - wh, null);// 在src的中间画入水印

        cv.save(Canvas.ALL_SAVE_FLAG);// 保存
        cv.restore();// 存储
        return newBitmap;
    }

    /**
     * 获取缩略图
     * 默认获取的宽高为 100
     *
     * @param mBitmapSrc 图片源
     * @param width      int
     * @param height     int
     * @return Bitmap
     */
    public Bitmap getThumbBitmap(Bitmap mBitmapSrc, int width, int height) {
        if (width == 0) width = 100;
        if (height == 0) height = 100;
        Bitmap thumbBitmap;
        thumbBitmap = ThumbnailUtils.extractThumbnail(mBitmapSrc, width, height);
        return thumbBitmap;
    }

    /**
     * 黑白照片
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap toBlackAndWhite(Bitmap mBitmapSrc) {
        int mBitmapWidth;
        int mBitmapHeight;

        mBitmapWidth = mBitmapSrc.getWidth();
        mBitmapHeight = mBitmapSrc.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight,
                Bitmap.Config.ARGB_8888);
        int iPixel;
        for (int i = 0; i < mBitmapWidth; i++) {
            for (int j = 0; j < mBitmapHeight; j++) {
                int curr_color = mBitmapSrc.getPixel(i, j);

                int avg = (Color.red(curr_color) + Color.green(curr_color) + Color
                        .blue(curr_color)) / 3;
                if (avg >= 100) {
                    iPixel = 255;
                } else {
                    iPixel = 0;
                }
                int modify_color = Color.argb(255, iPixel, iPixel, iPixel);

                bitmap.setPixel(i, j, modify_color);
            }
        }
        return bitmap;
    }

    /**
     * 底片效果
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    private Bitmap negativeFilm(Bitmap mBitmapSrc) {
        // RGBA的最大值
        final int MAX_VALUE = 255;
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

        int pixR;
        int pixG;
        int pixB;

        int pixColor;

        int newR;
        int newG;
        int newB;

        int[] pixels = new int[width * height];
        mBitmapSrc.getPixels(pixels, 0, width, 0, 0, width, height);
        int pos = 0;
        for (int i = 1, length = height - 1; i < length; i++) {
            for (int k = 1, len = width - 1; k < len; k++) {
                pos = i * width + k;
                pixColor = pixels[pos];

                pixR = Color.red(pixColor);
                pixG = Color.green(pixColor);
                pixB = Color.blue(pixColor);

                newR = MAX_VALUE - pixR;
                newG = MAX_VALUE - pixG;
                newB = MAX_VALUE - pixB;

                newR = Math.min(MAX_VALUE, Math.max(0, newR));
                newG = Math.min(MAX_VALUE, Math.max(0, newG));
                newB = Math.min(MAX_VALUE, Math.max(0, newB));

                pixels[pos] = Color.argb(MAX_VALUE, newR, newG, newB);
            }
        }

        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 油画效果
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */
    public Bitmap oilPainting(Bitmap mBitmapSrc) {
        Bitmap bmpReturn = Bitmap.createBitmap(mBitmapSrc.getWidth(),
                mBitmapSrc.getHeight(), Bitmap.Config.RGB_565);
        int color = 0;
        int Radio = 0;
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();

        Random rnd = new Random();
        int iModel = 10;
        int i = width - iModel;
        while (i > 1) {
            int j = height - iModel;
            while (j > 1) {
                int iPos = rnd.nextInt(100000) % iModel;
                color = mBitmapSrc.getPixel(i + iPos, j + iPos);
                bmpReturn.setPixel(i, j, color);
                j = j - 1;
            }
            i = i - 1;
        }
        return bmpReturn;
    }

    /**
     * 图片合成
     *
     * @param position   组合位置: -1 :左   1 :右   2 :上   -2 :下
     * @param mBitmapSrcs 图片源
     * @return Bitmap
     */
    public Bitmap photoMix(Position position, Bitmap... mBitmapSrcs) {
        if (mBitmapSrcs.length <= 0) {
            return null;
        }
        if (mBitmapSrcs.length == 1) {
            return mBitmapSrcs[0];
        }
        Bitmap newBitmap = mBitmapSrcs[0];

        for (int i = 1; i < mBitmapSrcs.length; i++) {
            newBitmap = createBitmapForPhotoMix(newBitmap, mBitmapSrcs[i], position);
        }
        return newBitmap;
    }

    private Bitmap createBitmapForPhotoMix(Bitmap first, Bitmap second, Position position) {
        if (first == null) {
            return null;
        }
        if (second == null) {
            return first;
        }
        int fw = first.getWidth();
        int fh = first.getHeight();
        int sw = second.getWidth();
        int sh = second.getHeight();
        Bitmap newBitmap = null;
        if (position == Position.LEFT) {
            newBitmap = Bitmap.createBitmap(fw + sw, fh > sh ? fh : sh, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(newBitmap);
            canvas.drawBitmap(first, sw, 0, null);
            canvas.drawBitmap(second, 0, 0, null);
        } else if (position == Position.RIGHT) {
            newBitmap = Bitmap.createBitmap(fw + sw, fh > sh ? fh : sh, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(newBitmap);
            canvas.drawBitmap(first, 0, 0, null);
            canvas.drawBitmap(second, fw, 0, null);
        } else if (position == Position.TOP) {
            newBitmap = Bitmap.createBitmap(sw > fw ? sw : fw, fh + sh, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(newBitmap);
            canvas.drawBitmap(first, 0, sh, null);
            canvas.drawBitmap(second, 0, 0, null);
        } else if (position ==  Position.BOTTOM) {
            newBitmap = Bitmap.createBitmap(sw > fw ? sw : fw, fh + sh, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(newBitmap);
            canvas.drawBitmap(first, 0, 0, null);
            canvas.drawBitmap(second, 0, fh, null);
        } else if (position ==  Position.CENTRE) {
            newBitmap = Bitmap.createBitmap(Math.max(fw, sw), Math.max(fw, sw), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(newBitmap);
            canvas.drawBitmap(first, 0, 0, null);
            canvas.drawBitmap(second, fw / 2, fh / 2, null);
        }
        return newBitmap;
    }

    /**
     * bitmap 位图保存成文件
     *
     * @param mBitmapSrc 图片源
     * @param fileName   文件名
     * @param filePath   保存的文件路径(默认为空时在内存根目录)
     * @param format     保存的图片格式(默认 JPEG)
     */
    public void saveBitmap2File(Bitmap mBitmapSrc, String fileName, String filePath, Format format) {
        String suffix = "jpg";
        if (TextUtils.isEmpty(filePath))
            filePath = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
        Bitmap.CompressFormat compressFormat = Bitmap.CompressFormat.JPEG;
        if (format == Format.JPEG){
            compressFormat = Bitmap.CompressFormat.JPEG;
            suffix = ".jpeg";
        }
        else if (format == Format.PNG){
            compressFormat = Bitmap.CompressFormat.PNG;
            suffix = ".png";
        }
        else if (format == Format.WEBP){
            compressFormat = Bitmap.CompressFormat.WEBP;
            suffix = ".webp";
        }

        File file = new File(filePath + File.separator, fileName + suffix);
        try {
            file.createNewFile();
            OutputStream os = new FileOutputStream(file);
            mBitmapSrc.compress(compressFormat, 100, os);
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 图片平滑处理
     * 3*3掩模处理(平均处理),降低噪声
     *
     * @param mBitmapSrc 图片源
     * @return Bitmap
     */

    public Bitmap smoothImage(Bitmap mBitmapSrc) {
        int w = mBitmapSrc.getWidth();
        int h = mBitmapSrc.getHeight();
        int[] data = new int[w * h];
        mBitmapSrc.getPixels(data, 0, w, 0, 0, w, h);
        int[] resultData = new int[w * h];
        try {
            resultData = filter(data, w, h);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Bitmap newBitmap = Bitmap.createBitmap(resultData, w, h, Bitmap.Config.ARGB_8888);
        return newBitmap;
    }

    private int[] filter(int[] data, int width, int height) throws Exception {
        int filterData[] = new int[data.length];
        int min = 10000;
        int max = -10000;
        if (data.length != width * height) return filterData;
        try {
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    if (i == 0 || i == 1 || i == height - 1 || i == height - 2 || j == 0 || j == 1 || j == width - 1 || j == width - 2) {
                        filterData[i * width + j] = data[i * width + j];
                    } else {
                        double average;             //中心的九个像素点
                        average = (data[i * width + j] + data[i * width + j - 1] + data[i * width + j + 1]
                                + data[(i - 1) * width + j] + data[(i - 1) * width + j - 1] + data[(i - 1) * width + j + 1]
                                + data[(i + 1) * width + j] + data[(i + 1) * width + j - 1] + data[(i + 1) * width + j + 1]) / 9;
                        filterData[i * width + j] = (int) (average);
                    }
                    if (filterData[i * width + j] < min)
                        min = filterData[i * width + j];
                    if (filterData[i * width + j] > max)
                        max = filterData[i * width + j];
                }
            }
            for (int i = 0; i < width * height; i++) {
                filterData[i] = (filterData[i] - min) * 255 / (max - min);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e);
        }
        return filterData;
    }

    /**
     * 图片增亮
     *
     * @param mBitmapSrc     图片源
     * @param brightenOffset 增加的亮度值
     * @return Bitmap
     */
    public Bitmap brightenBitmap(Bitmap mBitmapSrc, int brightenOffset) {
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        int[] pix = new int[width * height];
        mBitmapSrc.getPixels(pix, 0, width, 0, 0, width, height);

        // Apply pixel-by-pixel change
        int index = 0;
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int r = (pix[index] >> 16) & 0xff;
                int g = (pix[index] >> 8) & 0xff;
                int b = pix[index] & 0xff;
                r = Math.max(0, Math.min(255, r + brightenOffset));
                g = Math.max(0, Math.min(255, g + brightenOffset));
                b = Math.max(0, Math.min(255, b + brightenOffset));
                pix[index] = 0xff000000 | (r << 16) | (g << 8) | b;
                index++;
            } // x
        } // y

        // Change bitmap to use new array
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        bitmap.setPixels(pix, 0, width, 0, 0, width, height);
        mBitmapSrc = null;
        pix = null;
        return bitmap;
    }

    /**
     * 均值滤波
     *
     * @param mBitmapSrc   图片源
     * @param filterWidth  滤波宽度值
     * @param filterHeight 滤波高度值
     */
    public Bitmap averageFilter(Bitmap mBitmapSrc, int filterWidth, int filterHeight) {
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        int[] pixNew = new int[width * height];
        int[] pixOld = new int[width * height];
        mBitmapSrc.getPixels(pixNew, 0, width, 0, 0, width, height);
        mBitmapSrc.getPixels(pixOld, 0, width, 0, 0, width, height);

        // Apply pixel-by-pixel change
        int filterHalfWidth = filterWidth / 2;
        int filterHalfHeight = filterHeight / 2;
        int filterArea = filterWidth * filterHeight;
        for (int y = filterHalfHeight; y < height - filterHalfHeight; y++) {
            for (int x = filterHalfWidth; x < width - filterHalfWidth; x++) {
                // Accumulate values in neighborhood
                int accumR = 0, accumG = 0, accumB = 0;
                for (int dy = -filterHalfHeight; dy <= filterHalfHeight; dy++) {
                    for (int dx = -filterHalfWidth; dx <= filterHalfWidth; dx++) {
                        int index = (y + dy) * width + (x + dx);
                        accumR += (pixOld[index] >> 16) & 0xff;
                        accumG += (pixOld[index] >> 8) & 0xff;
                        accumB += pixOld[index] & 0xff;
                    } // dx
                } // dy

                // Normalize
                accumR /= filterArea;
                accumG /= filterArea;
                accumB /= filterArea;
                int index = y * width + x;
                pixNew[index] = 0xff000000 | (accumR << 16) | (accumG << 8) | accumB;
            } // x
        } // y

        // Change bitmap to use new array
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        bitmap.setPixels(pixNew, 0, width, 0, 0, width, height);
        mBitmapSrc = null;
        pixOld = null;
        pixNew = null;
        return bitmap;
    }

    /**
     * 中值滤波
     *
     * @param mBitmapSrc   图片源
     * @param filterWidth  滤波宽度值
     * @param filterHeight 滤波高度值
     */
    public Bitmap medianFilter(Bitmap mBitmapSrc, int filterWidth, int filterHeight) {
        int width = mBitmapSrc.getWidth();
        int height = mBitmapSrc.getHeight();
        int[] pixNew = new int[width * height];
        int[] pixOld = new int[width * height];
        mBitmapSrc.getPixels(pixNew, 0, width, 0, 0, width, height);
        mBitmapSrc.getPixels(pixOld, 0, width, 0, 0, width, height);

        // Apply pixel-by-pixel change
        int filterHalfWidth = filterWidth / 2;
        int filterHalfHeight = filterHeight / 2;
        int filterArea = filterWidth * filterHeight;
        for (int y = filterHalfHeight; y < height - filterHalfHeight; y++) {
            for (int x = filterHalfWidth; x < width - filterHalfWidth; x++) {
                // Accumulate values in neighborhood
                int accumR = 0, accumG = 0, accumB = 0;
                for (int dy = -filterHalfHeight; dy <= filterHalfHeight; dy++) {
                    for (int dx = -filterHalfWidth; dx <= filterHalfWidth; dx++) {
                        int index = (y + dy) * width + (x + dx);
                        accumR += (pixOld[index] >> 16) & 0xff;
                        accumG += (pixOld[index] >> 8) & 0xff;
                        accumB += pixOld[index] & 0xff;
                    } // dx
                } // dy

                // Normalize
                accumR /= filterArea;
                accumG /= filterArea;
                accumB /= filterArea;
                int index = y * width + x;
                pixNew[index] = 0xff000000 | (accumR << 16) | (accumG << 8) | accumB;
            } // x
        } // y

        // Change bitmap to use new array
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        bitmap.setPixels(pixNew, 0, width, 0, 0, width, height);
        mBitmapSrc = null;
        pixOld = null;
        pixNew = null;
        return bitmap;
    }
}

DEMO下载地址:Download

—— lovey hy.

【欢迎上码】

【微信公众号搜索 h2o2s2】