draw drawBitmap 如何设置ps调整图片角度度

android图片处理总结_甜梦文库|文库百度|百度文库下载|百度文档|新浪文库|豆丁文库|冰点文库|文库宝|免费下载百度文库
甜梦文库_文库百度,百度文库下载,下载百度文库的文档,新浪文库,豆丁文库,冰点文库,文库宝,免费下载百度文库
当前位置: >>
>> android图片处理总结
1. android 图像处理系列之一--Bitmap、Drawable 和 byte[]之间的相互转换..................................................2 2. android 图像处理系列之二--图片旋转、缩放、反转........................................................................................ 3 3. android 图像处理系列之三--图片色调饱和度、色相、亮度处理.....................................................................6 4. android 图像处理系列之四--给图片添加边框(上)...................................................................................... 15 5. android 图像处理系列之五--给图片添加边框(中)...................................................................................... 19 6. android 图像处理系列之六--给图片添加边框(下)-图片叠加...................................................................21 7. android 图像处理系列之七--图片涂鸦,水印-图片叠加.............................................................................. 25 8. android 图像处理系列之八--图片特效处理之一-怀旧效果.......................................................................... 26 9. android 图像处理系列之九--图片特效处理之二-模糊效果.......................................................................... 28 10. android 图像处理系列之十--图片特效处理之三-锐化效果........................................................................ 33 11. android 图像处理系列之十一--图片特效处理之四-浮雕效果.....................................................................36 12. android 图像处理系列之十二--图片特效处理之五-底片效果.....................................................................38 13. android 图像处理系列之十三--图片特效处理之六-光照效果.....................................................................40 14. android 图像处理系列之十四--图片特效处理之七-图片叠加.....................................................................43 15. android 图像处理系列之十五--图片特效处理之八-光晕效果.....................................................................45 16. android 图像处理系列之十六--图片特效处理之九-条纹效果.....................................................................48 17. android 图像处理系列之十七--图片特效处理之十-国际象棋棋盘的绘制.................................................50 18. android 图像处理系列之十八--图片特效处理之十一-图片乾坤大挪移之图片裁剪组合.........................51 19. android 图像处理系列之十九--图片特效处理之十二-图片自由裁剪、人脸识别.....................................54 20. android 图像处理系列之二十--图片处理总结................................................................................................ 57-1作者:jacpy. 1.android 图像处理系列之一--Bitmap、Drawable 和 byte[]之间的相互转换到年底了,却被公司劝退,很悲催!正好有时间把自己之前在 android 中对图片的处理资料整理一下,打算出一 个图片处理系列。 先来最简单的: android Bitmap、Drawable 和 byte[]之间的相互转换 package com.jacp.image. import java.io.ByteArrayOutputS import android.graphics.B import android.graphics.BitmapF import android.graphics.drawable.BitmapD import android.graphics.drawable.D /** * Bitmap Drawable byte[] 数组之间转换 * @author
* */ public class ImageSwitch { /** * Bitmap 转换成 byte 数组 * @param bmp * @return */ public static byte[] bitmap2Byte(Bitmap bmp) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); pressFormat.PNG, 100, baos); return baos.toByteArray(); } /** * 数组转换成 Bitmap * @param buffer * @return */ public static Bitmap byte2Bitmap(byte[] buffer) { return BitmapFactory.decodeByteArray(buffer, 0, buffer.length); } /**-2作者:jacpy. * Bitmap 转换成 Drawable * @param bmp * @return */ public static Drawable bitmap2Drawable(Bitmap bmp) { return new BitmapDrawable(bmp); } /** * BitmapDrawable 转换成 Bitmap * @param drawable * @return */ public static Bitmap drawable2Bitmap(BitmapDrawable drawable) { return drawable.getBitmap(); } }2.android 图像处理系列之二--图片旋转、缩放、反转注意是反转,不是翻转。贴图: 原图:处理后:-3作者:jacpy. 下面看代码:1 2 3 4 5 6 7 8 9 10 11 /** * 图片处理 * * @author
* */ import android.graphics.B import android.graphics.M package com.jacp.image.12 public class ImageHandler { 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 /** * 图片缩放 -4作者:jacpy. } /** * 图片旋转 * * @param bmp * * * @return */ public static Bitmap rotateBitmap(Bitmap bmp, float degree) { Matrix matrix = new Matrix(); matrix.postRotate(degree); return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true true); 要旋转的图片 图片旋转的角度,负值为逆时针旋转,正值为顺时针旋转 * @param degree 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75* * @param bm * @param scale * * @return */ public static Bitmap resizeBitmap(Bitmap bm, float scale) { Matrix matrix = new Matrix(); matrix.postScale(scale, scale); return Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true true); } /** * 图片缩放 * * @param bm * @param w * * @param h * * @return */ public static Bitmap resizeBitmap(Bitmap bm, int w, int h) { Bitmap BitmapOrg = int width = BitmapOrg.getWidth(); int height = BitmapOrg.getHeight(); float float scaleWidth = ((float w) / float) float float scaleHeight = ((float h) / float) Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); return Bitmap.createBitmap(BitmapOrg, 0, 0, width, height, matrix, true true); } /** * 图片反转 * * @param bm * @param flag * * @return */ public static Bitmap reverseBitmap(Bitmap bmp, int flag) { -5作者:jacpy. 0为水平反转,1为垂直反转 缩小或放大成的高 缩小或放大成的宽 值小于则为缩小,否则为放大 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 } }float float[] floats = switch (flag) { case 0: // 水平反转 floats = new float float[] { -1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f }; case 1: // 垂直反转 floats = new float float[] { 1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f }; } if (floats != null { null) Matrix matrix = new Matrix(); matrix.setValues(floats); return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true true); }3.android 图像处理系列之三--图片色调饱和度、色相、亮度处理原图:处理后:-6作者:jacpy. 下面贴代码: 一、图片处理层:1 2 3 4 5 6 7 8 9 import android.content.C import android.graphics.B import android.graphics.C import android.graphics.ColorM import android.graphics.ColorMatrixColorF import java.util.ArrayL package com.jacp.tone.10 import android.graphics.P 11 import android.view.G 12 import android.view.V 13 import android.widget.LinearL 14 import android.widget.SeekB 15 import android.widget.SeekBar.OnSeekBarChangeL 16 import android.widget.TextV 17 18 import com.jacp.tone.R; 19 20 /** 21 * 图片调色处理 -7作者:jacpy. 22 23 24* @author
* */25 public class ToneLayer { 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 private ColorMatrix mLightnessM private ColorMatrix mSaturationM -8作者:jacpy. private LinearLayout mP private float mD private static final int TEXT_WIDTH = 50; /** * 亮度 */ private TextView mL private SeekBar mLumB /** * 色相 */ private TextView mH private SeekBar mHueB /** * 饱和度 */ private TextView mS private SeekBar mSaturationB /** * 色相标识 */ public static final int FLAG_HUE = 0x2; /** * 亮度标识 */ public static final int FLAG_LUM = 0x1; /** * 饱和度标识 */ public static final int FLAG_SATURATION = 0x0; 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111private ColorMatrix mHueM private ColorMatrix mAllM /** * 亮度 */ private float mLumValue = 1F; /** * 饱和度 */ private float mSaturationValue = 0F; /** * 色相 */ private float mHueValue = 0F; /** * SeekBar 的中间值 */ private static final int MIDDLE_VALUE = 127; /** * SeekBar 的最大值 */ private static final int MAX_VALUE = 255; private ArrayList&SeekBar& mSeekBars = new ArrayList&SeekBar&(); public ToneLayer(Context context) { init(context); } private void init(Context context) { mDensity = context.getResources().getDisplayMetrics(). mSaturation = new TextView(context); mSaturation.setText(R.string.saturation); mHue = new TextView(context); mHue.setText(R.string.contrast); mLum = new TextView(context); mLum.setText(R.string.lightness); mSaturationBar = new SeekBar(context); -9作者:jacpy. 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128mHueBar = new SeekBar(context); mLumBar = new SeekBar(context); mSeekBars.add(mSaturationBar); mSeekBars.add(mHueBar); mSeekBars.add(mLumBar); int for (int i = 0, size = mSeekBars.size(); i & i++) { SeekBar seekBar = mSeekBars.get(i); seekBar.setMax(MAX_VALUE); seekBar.setProgress(MIDDLE_VALUE); seekBar.setTag(i); } LinearLayout saturation = new LinearLayout(context); saturation.setOrientation(LinearLayout.HORIZONTAL); new saturation.setLayoutParams(newLinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); 129 130 int LinearLayout.LayoutParams txtLayoutparams = new LinearLayout.LayoutParams((int (TEXT_WIDTH int) mSaturation.setGravity(Gravity.CENTER); saturation.addView(mSaturation, txtLayoutparams); LinearLayout.LayoutParams seekLayoutparams = new * mDensity), LinearLayout.LayoutParams.MATCH_PARENT); 131 132 133 134 LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); 135 136 137 138 139 LinearLayout hue = new LinearLayout(context); hue.setOrientation(LinearLayout.HORIZONTAL); new hue.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, saturation.addView(mSaturationBar, seekLayoutparams);LinearLayout.LayoutParams.WRAP_CONTENT)); 140 141 142 143 144 145 146 147 LinearLayout lum = new LinearLayout(context); lum.setOrientation(LinearLayout.HORIZONTAL); new lum.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, mHue.setGravity(Gravity.CENTER); hue.addView(mHue, txtLayoutparams); hue.addView(mHueBar, seekLayoutparams);LinearLayout.LayoutParams.WRAP_CONTENT)); 148 149 mLum.setGravity(Gravity.CENTER); - 10 作者:jacpy. 150 151 152 153 154 155lum.addView(mLum, txtLayoutparams); lum.addView(mLumBar, seekLayoutparams); mParent = new LinearLayout(context); mParent.setOrientation(LinearLayout.VERTICAL); new mParent.setLayoutParams(newLinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 - 11 作者:jacpy. } public ArrayList&SeekBar& getSeekBars() { return mSeekB } /** * 设置亮度值 * @param lum */ int public void setLum(int lum) { mLumValue = (lum - MIDDLE_VALUE) * 1.0F / MIDDLE_VALUE * 180; } /** * 设置色相值 * @param hue */ int public void setHue(int hue) { mHueValue = hue * 1.0F / MIDDLE_VALUE; } /** * 设置饱和度值 * @param saturation */ int public void setSaturation(int saturation) { mSaturationValue = saturation * 1.0F / MIDDLE_VALUE; } public View getParentView() { return mP } mParent.addView(saturation); mParent.addView(hue); mParent.addView(lum); 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211/** * * @param flag * */ public Bitmap handleImage(Bitmap bm, int flag) { Bitmap bmp = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Bitmap.Config.ARGB_8888); // 创建一个相同尺寸的可变的位图区,用于绘制调色后的图片 Canvas canvas = new Canvas(bmp); // 得到画笔对象 Paint paint = new Paint(); // 新建 paint true paint.setAntiAlias(true true); // 设置抗锯齿,也即是边缘做平滑处理 null if (null == mAllMatrix) { mAllMatrix = new ColorMatrix(); } null if (null == mLightnessMatrix) { mLightnessMatrix = new ColorMatrix(); // 用于颜色变换的矩阵,android 位图颜色变化处理主要 } null if (null == mSaturationMatrix) { mSaturationMatrix = new ColorMatrix(); } if (null == mHueMatrix) { null mHueMatrix = new ColorMatrix(); } switch (flag) { case FLAG_HUE: // 需要改变色相 mHueMatrix.reset(); mHueMatrix.setScale(mHueValue, mHueValue, mHueValue, 1); // 红、绿、蓝三分量按相同的比例, // // android // case FLAG_SATURATION: // 需要改变饱和度 // saturation 饱和度值,最小可设为0,此时对应的是灰度图(也就是俗话的“黑白图”), // 为1表示饱和度不变,设置大于1,就显示过饱和 mSaturationMatrix.reset(); mSaturationMatrix.setSaturation(mSaturationValue); case FLAG_LUM: // 亮度 // hueColor 就是色轮旋转的角度,正值表示顺时针旋转,负值表示逆时针旋转 - 12 作者:jacpy. 比特位0 表示是否改变色相,比位1表示是否改变饱和度,比特位2表示是否改变明亮度是靠该对象完成 212 213 214 215 216 217 218 219 220 221 222 223 224 225最后一个参数1表示透明度不做变化,此函数详细说明参考 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 } } }mLightnessMatrix.reset(); // 设为默认值 mLightnessMatrix.setRotate(0, mLumValue); // 控制让红色区在色轮上旋转的角度 mLightnessMatrix.setRotate(1, mLumValue); // 控制让绿红色区在色轮上旋转的角度 mLightnessMatrix.setRotate(2, mLumValue); // 控制让蓝色区在色轮上旋转的角度 // 这里相当于改变的是全图的色相 mAllMatrix.reset(); mAllMatrix.postConcat(mHueMatrix); mAllMatrix.postConcat(mSaturationMatrix); // 效果叠加 mAllMatrix.postConcat(mLightnessMatrix); // 效果叠加 new paint.setColorFilter(new ColorMatrixColorFilter(mAllMatrix));// 设置颜色变换效果 canvas.drawBitmap(bm, 0, 0, paint); // 将颜色变化后的图片输出到新创建的位图区 // 返回新的位图,也即调色处理后的图片二、主界面:256 package com.jacp. 257 258 import java.util.ArrayL 259 260 import android.app.A 261 import android.graphics.B 262 import android.graphics.BitmapF 263 import android.os.B 264 import android.widget.ImageV 265 import android.widget.LinearL 266 import android.widget.SeekB 267 import android.widget.SeekBar.OnSeekBarChangeL 268 269 import com.jacp.tone.view.ToneL 270 271 /** 272 273 274 275 * 启动的主界面 * @author
* */ private ToneLayer mToneL private ImageView mImageV - 13 作者:jacpy.276 public class ImageToneActivity extends Activity implements OnSeekBarChangeListener { 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324private Bitmap mB @Override public void onCreate(Bundle savedInstanceState) { super super.onCreate(savedInstanceState); setContentView(R.layout.main); init(); } private void init() { this mToneLayer = new ToneLayer(this this); mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test); mImageView = (ImageView) findViewById(R.id.img_view); mImageView.setImageBitmap(mBitmap); ((LinearLayout) findViewById(R.id.tone_view)).addView(mToneLayer.getParentView()); ArrayList&SeekBar& seekBars = mToneLayer.getSeekBars(); int for (int i = 0, size = seekBars.size(); i & i++) { this seekBars.get(i).setOnSeekBarChangeListener(this this); } } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { int flag = (Integer) seekBar.getTag(); switch (flag) { case ToneLayer.FLAG_SATURATION: mToneLayer.setSaturation(progress); case ToneLayer.FLAG_LUM: mToneLayer.setLum(progress); case ToneLayer.FLAG_HUE: mToneLayer.setHue(progress); } mImageView.setImageBitmap(mToneLayer.handleImage(mBitmap, flag)); } - 14 作者:jacpy. 325 326 327 328 329 330 331 332 333 334 }@Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { }三、布局文件:335 &?xml version=&1.0& encoding=&utf-8&?& 336 &ScrollView xmlns:android=&/apk/res/android& 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 &ImageView android:layout_width=&wrap_content& android:layout_height=&wrap_content& android:layout_weight=&1& android:id=&@+id/img_view& android:layout_gravity=&center& /& &LinearLayout android:layout_width=&match_parent& android:layout_height=&wrap_content& android:id=&@+id/tone_view& /& &/LinearLayout& &LinearLayout android:layout_width=&match_parent& android:layout_height=&match_parent& android:orientation=&vertical& & android:layout_width=&match_parent& android:layout_height=&match_parent& &359 &/ScrollView&4.android 图像处理系列之四--给图片添加边框(上)图片处理时,有时需要为图片加一些边框,下面介绍一种为图片添加简单边框的方法。 基本思路是:将边框图片裁剪成八张小图片(图片大小最好一致,不然后面处理会很麻烦) ,分别对应左上角, 左边,左下角,下边,右下角,右边,右上角,上边,其中左右上下只需要一个有效长度,就像重写水平进度条 一样,只需要一个有效的长度,然后平铺,就达到了最后想要的效果,不错,左右上下边采用的也是这样的思路。 也可以将八张图片组合在一起,然后读取整张图片,用代码裁剪,下面会给出相应的代码。下面的代码主要是给 出第一种方法,后一种给出代码,有兴趣的可以自己试试。注意图片不要放到 drawable 目录下面,因为屏幕分- 15 作者:jacpy. 辨率会影响图片的大小,所以最好是放在 assets 目录里面。下面代码为了简便所以没有那样做。后面一篇还会 讲到另一种添加边框图片的方法。 下面贴图片: 原图片:处理后:代码(res 参数为上面所说的八个边框组合图片资源):1 2 3 4 5 6 7/** jacpy. * 图片与边框组合 * @param bm 原图片 * @param res 边框资源 * @return */ private Bitmap combinateFrame(Bitmap bm, int int[] res) - 16 作者:jacpy. 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38{ Bitmap bmp = decodeBitmap(res[0]); // 边框的宽高 final int smallW = bmp.getWidth(); final int smallH = bmp.getHeight(); // 原图片的宽高 final int bigW = bm.getWidth(); final int bigH = bm.getHeight(); int int wCount = (int Math.ceil(bigW * 1.0 / smallW); int) int int hCount = (int Math.ceil(bigH int) // 组合后图片的宽高 int newW = (wCount + 2) * smallW; int newH = (hCount + 2) * smallH; // 重新定义大小 Bitmap newBitmap = Bitmap.createBitmap(newW, newH, Config.ARGB_8888); Canvas canvas = new Canvas(newBitmap); Paint p = new Paint(); p.setColor(Color.TRANSPARENT); new canvas.drawRect(new Rect(0, 0, newW, newH), p); Rect rect = new Rect(smallW, smallH, newW - smallW, newH - smallH); Paint paint = new Paint(); paint.setColor(Color.WHITE); canvas.drawRect(rect, paint); // 绘原图 canvas.drawBitmap(bm, (newW - bigW - 2 * smallW) / 2 + smallW, (newH - bigH - 2 * smallH) // 绘边框 // 绘四个角 int startW = newW - smallW; int startH = newH - smallH; Bitmap leftTopBm = decodeBitmap(res[0]); // 左上角 Bitmap leftBottomBm = decodeBitmap(res[2]); // 左下角 Bitmap rightBottomBm = decodeBitmap(res[4]); // 右下角 Bitmap rightTopBm = decodeBitmap(res[6]); // 右上角 canvas.drawBitmap(leftTopBm, 0, 0, null null); canvas.drawBitmap(leftBottomBm, 0, startH, null null); canvas.drawBitmap(rightBottomBm, startW, startH, null null); canvas.drawBitmap(rightTopBm, startW, 0, null null); - 17 作者:jacpy. * 1.0 / smallH);/ 2 + smallH, null null); 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 }leftTopBm.recycle(); leftTopBm = leftBottomBm.recycle(); leftBottomBm = rightBottomBm.recycle(); rightBottomBm = rightTopBm.recycle(); rightTopBm = // 绘左右边框 Bitmap leftBm = decodeBitmap(res[1]); Bitmap rightBm = decodeBitmap(res[5]); int for (int i = 0, length = hC i & i++) { int h = smallH * (i + 1); canvas.drawBitmap(leftBm, 0, h, null null); canvas.drawBitmap(rightBm, startW, h, null null); } leftBm.recycle(); leftBm = rightBm.recycle(); rightBm = // 绘上下边框 Bitmap bottomBm = decodeBitmap(res[3]); Bitmap topBm = decodeBitmap(res[7]); int for (int i = 0, length = wC i & i++) { int w = smallW * (i + 1); canvas.drawBitmap(bottomBm, w, startH, null null); canvas.drawBitmap(topBm, w, 0, null null); } bottomBm.recycle(); bottomBm = topBm.recycle(); topBm = canvas.save(Canvas.ALL_SAVE_FLAG); canvas.restore(); return newB- 18 作者:jacpy. 如果边框是在一张图片里面,下面给出从一张图片取中间200X200的区域。如何类似边框过多,可以将裁剪的 信息写入到指定的文件,裁剪时可先将边框图片信息读取出来,然后再裁剪出边框。如果处理的原图片太大, 可能会出内存溢出。可先将图片缩小到一定尺寸再处理,具体缩小方法,参见 android 图像处理系列之二-- 图片旋转、缩放、反转的图片缩放。[java] view plaincopy97 /** jacpy. 98 99 100 101 * 截取图片的中间的200X200的区域 * @param bm * @return */102 private Bitmap cropCenter(Bitmap bm) 103 { 104 105 106 107 108 109 110 } 111 112 /** 113 114 115 116 117 * 剪切图片 * @param bmp 被剪切的图片 * @param src 剪切的位置 * @return 剪切后的图片 */ int dstWidth = 200; int dstHeight = 200; int startWidth = (bm.getWidth() - dstWidth)/2; int startHeight = ((bm.getHeight() - dstHeight) / 2); Rect src = new Rect(startWidth, startHeight, startWidth + dstWidth, startHeight + dstHeight); return dividePart(bm, src);118 private Bitmap dividePart(Bitmap bmp, Rect src) 119 { 120 121 122 123 124 125 126 127 } int width = src.width(); int height = src.height(); Rect des = new Rect(0, 0, width, height); Bitmap croppedImage = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); Canvas canvas = new Canvas(croppedImage); canvas.drawBitmap(bmp, src, des, null null); return croppedI处理后图片(原图片还是上面的图片) :- 19 作者:jacpy. 5.android 图像处理系列之五--给图片添加边框(中)前面一篇讲到给图片加边框的方式,只能给图片加一些有规则的边框,如果想加一些比较精美的效果,就有点麻 烦了。下面就给出解决这个问题的思路。 思路是:一些比较精美的花边图片我们是很难用代码控制,就目前本人水平是达不到,不排除牛人,再说了 PS 那些效果都是程序员做出来,肯定有实现的方法,这可能就要涉及很复杂的图形学。扯远了,接来说怎么用那些 精美的花边做为图片的边框。简单的方式是用两张图片叠加。最简单的一种是本文介绍的,用透明的 PNG 格式 图片。因为 android 是支持 PNG 图片处理的,而且 PNG 图片有透明度值,所以,添加那些花边边框可以先把 图片做成全透明的(美工做图片的时候可以先创建一张全透明图片,再往图片上添加花边。,然后再叠加上去就 ) OK 了。要注意的是,边框有大小,最好是大一点,如果要处理的图片比较大,可以先将缩放到一定比例,再添 加边框;如果边框比图片大,先要对边框进行缩放,具体缩放见前面的 android 图像处理系列之二--图片旋 转、缩放、反转,这里面就不贴代码了。 废话少说,下面看效果图: (截图的时候图片大小不一样,比较丑)+1 2 3 4 5 6 7 8 9 10 11 12 13 /** jacpy. * 添加边框 * @param bm 原图片 * @param res 边框资源 * @return */ private Bitmap addBigFrame(Bitmap bm, int res) { Bitmap bitmap = decodeBitmap(res); Drawable[] array = new Drawable[2]; array[0] = new BitmapDrawable(bm);=代码: 这里的 res 是边框图片,还是一样,不建议放到 drawable 下面,最后是放到 assets 目录,原因就不用说了吧。Bitmap b = resize(bitmap, bm.getWidth(), bm.getHeight()); array[1] = new BitmapDrawable(b); - 20 作者:jacpy. 14 15 16 } 17LayerDrawable layer = new LayerDrawable(array); return drawableToBitmap(layer);18 /** jacpy. 19 20 21 22 * 将 Drawable 转换成 Bitmap * @param drawable * @return */23 private Bitmap drawableToBitmap(Drawable drawable) 24 { 25 Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); 26 27 28 29 30 31 } 32 33 /** jacpy. 34 35 36 37 * 将 R.drawable.*转换成 Bitmap * @param res * @return */ Canvas canvas = new Canvas(bitmap); // canvas.setBitmap(bitmap); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); drawable.draw(canvas);int 38 private Bitmap decodeBitmap(int res) 39 { 40 41 } return BitmapFactory.decodeResource(mContext.getResources(), res);下面一篇将继续讲讨论另外一种添加图片边框的处理方式,敬请期待!6.android 图像处理系列之六--给图片添加边框(下)-图片叠加前面介绍了一种用透明图片叠加的方式添加花边边框,下面将介绍另外一种图片叠加添加花边边框的方式。前面 方法有一个缺点,就是做成 PNG 图片,图片体积会很大,不是一般的大,比同样的 JPG 大三倍多,如果项目 可以忽略包的大小,那么可以用前种处理方式,本文讲到的虽然可以减小图片的体积,但处理较复杂,而且本人 研究的还不是很成熟。本文就是针对 JPG 边框处理,但缺点是还不够成熟,仅提供思路。 思路:可以将边框做成 JPG 图片,没有边框的地方,一般都是中间区域调成特殊颜色,比如黑色。在两张图片 叠加的时候,对边框图片做特殊处理,比如是黑色的点过滤掉,改变边框图片像素点的透明度,即可完成前面 PNG 图片的效果。 下面看效果:- 21 作者:jacpy. +=目前代码处理的还不是很好,非黑色点与黑色点的交界处没有做模糊处理,具体方法后面的文章会讲到。一样的 边框图片建议放在 assets 目录。 下面贴代码:12 3 4 5 6 7/** jacpy. * 叠加边框图片有用部分 * @param bmp * @return */ private Bitmap alphaLayer(Bitmap bmp) - 22 作者:jacpy. 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53{ int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); // 边框图片 Bitmap overlay = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.black); int w = overlay.getWidth(); int h = overlay.getHeight(); float scaleX = width * 1F / float scaleY = height * 1F / Matrix matrix = new Matrix(); matrix.postScale(scaleX, scaleY); Bitmap overlayCopy = Bitmap.createBitmap(overlay, 0, 0, w, h, matrix, true true); int pixColor = 0; int layColor = 0; int newColor = 0; int pixR = 0; int pixG = 0; int pixB = 0; int pixA = 0; int newR = 0; int newG = 0; int newB = 0; int newA = 0; int layR = 0; int layG = 0; int layB = 0; int layA = 0; float alpha = 0.3F; float alphaR = 0F; float alphaG = 0F; float alphaB = 0F; int for (int i = 0; i & i++) { int for (int k = 0; k & k++) { pixColor = bmp.getPixel(i, k); layColor = overlayCopy.getPixel(i, k); - 23 作者:jacpy. 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 } }// 获取原图片的 RGBA 值 pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); pixA = Color.alpha(pixColor); // 获取边框图片的 RGBA 值 layR = Color.red(layColor); layG = Color.green(layColor); layB = Color.blue(layColor); layA = Color.alpha(layColor); // 颜色与纯黑色相近的点 if (layR & 20 && layG & 20 && layB & 20) { alpha = 1F; } else { alpha = 0.3F; } alphaR = alphaG = alphaB = // 两种颜色叠加 int newR = (int (pixR * alphaR + layR * (1 - alphaR)); int) int newG = (int (pixG * alphaG + layG * (1 - alphaG)); int) int newB = (int (pixB * alphaB + layB * (1 - alphaB)); int) int layA = (int (pixA * alpha + layA * (1 - alpha)); int) // 值在0~255之间 newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); newA = Math.min(255, Math.max(0, layA)); newColor = Color.argb(newA, newR, newG, newB); bitmap.setPixel(i, k, newColor); - 24 作者:jacpy. 99}这种方式图片处理比较慢,因为像素点要一个个 getPixel(),组成新图片的时候要一个个 setPixel()。另外可 以用 getPixels(),和 setPixels()方法,这种处理要快一点,本人对其它类似效果的处理测试了一下,后面处 理方式要比前面快 3 多倍。因为这种图片叠加是对像素点处理,是后面的特效处理系列,因为涉及到图片叠 加,所以放到前面来。具体怎么使用,后面也会很快讨论到,读者也可以自己研究。优化的代码会在后面贴 出来,敬请期待。7.android 图像处理系列之七--图片涂鸦,水印-图片叠加图片涂鸦和水印其实是一个功能,实现的方式是一样的,就是一张大图片和一张小点图片叠加即可。前面在 android 图像处理系列之六--给图片添加边框(下)-图片叠加中也讲到了图片叠加,里面实现的原理是直接 操作像素点。下面给出别外一种方式让图片叠加--用 Canvas 处理图片,canvas 已经封装好了,直接调用就 行。 下面看效果:+代码:1 2 3 4 5 6 7 8 9 10 /** jacpy. * 组合涂鸦图片和源图片 * @param src 源图片 * @param watermark 涂鸦图片 * @return */=public Bitmap doodle(Bitmap src, Bitmap watermark) { // 另外创建一张图片 Bitmap newb = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Config.ARGB_8888);// 创 Canvas canvas = new Canvas(newb); canvas.drawBitmap(src, 0, 0, null null);// 在 0,0坐标开始画入原图片 src - 25 作者:jacpy.建一个新的和 SRC 长度宽度一样的位图 11 12 13canvas.drawBitmap(watermark, (src.getWidth() - watermark.getWidth()) / 2, (src.getHeight() canvas.save(Canvas.ALL_SAVE_FLAG); canvas.restore(); watermark.recycle(); watermark = }- watermark.getHeight()) / 2, null null); // 涂鸦图片画到原图片中间位置 14 15 16 17 18 19 20 21跟前面一样,要注意图片最好放在 assets 目录,另外注意图片回收,不然图片过到会造成内存紧张。这种叠加 方式一般选用 PNG 格式的图片做为涂鸦图片或者水印,当然也可以用 JPG,那就需要按照前面所说的 android 图像处理系列之六--给图片添加边框(下)-图片叠加进行像素点过滤,这样会影响处理速度,所以不建议用 JPG 图片,如果能写更高效的算法,也可以。 另外在做涂鸦的时候,需求可能会是用户可以按住涂鸦图片,然后进行拖动效果。这样的话,我给个思路,重写 ImageView 里面的 onTouchEvent 方法,MotionEvent.getAction()里面有三种状态, MotionEvent.ACTION_DOWN、MotionEvent.ACTION_UP 和 MotionEvent.ACTION_MOVE,根据这三种状态 来判断用户的行为,决定是否移动图片,另外要注意判断涂鸦图片是否移动到原图片的边缘。由于这部分代码是 跟裁剪放在一样的,不好贴出来,所以给大家一个思路,后面会把裁剪的代码贴出来。 OK,这篇就写到这里,后面还有一种图片叠加的方式,敬请期待!8.android 图像处理系列之八--图片特效处理之一-怀旧效果图片特效处理系列将介绍图片的像素点的特效处理,这些物资注重的是原理。也就是说只要你知道这些算法不管 是 C++,VB,C#,JAVA 都可以做出相同的特效。下面将介绍图片怀旧效果的算法。算法如下:上面公式的意思是说将每个像素点的 RGB 值先分离出来,然后再按照上面的三个算式分别重新计算出 RGB 值 然后做为当前点的 RGB 值。 下面看效果图片: 原图片:- 26 作者:jacpy. 处理后:代码:1 2 3 4 5 6 7 8 9 10 11/** jacpy. * 怀旧效果(相对之前做了优化快一倍) * @param bmp * @return */ private Bitmap oldRemeber(Bitmap bmp) { // 速度测试 long start = System.currentTimeMillis(); int width = bmp.getWidth(); int height = bmp.getHeight(); - 27 作者:jacpy. 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33Bitmap 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 int[] pixels = new int int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); int for (int i = 0; i & i++) { int for (int k = 0; k & k++) { pixColor = pixels[width * i + k]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); int newR = (int (0.393 * pixR + 0.769 * pixG + 0.189 * pixB); int) int newG = (int (0.349 * pixR + 0.686 * pixG + 0.168 * pixB); int) int newB = (int (0.272 * pixR + 0.534 * pixG + 0.131 * pixB); int) int newColor = Color.argb(255, newR & 255 ? 255 : newR, newG & 255 ? 255 : newG, newB pixels[width * i + k] = newC } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); long end = System.currentTimeMillis(); Log.d(&may&, &used time=&+(end - start)); }& 255 ? 255 : newB); 34 35 36 37 38 39 40 41 42上面的代码是优化了的,也就是用到了这篇 android 图像处理系列之六--给图片添加边框(下)-图片 叠加里面所说的 getPixels()和 setPixels()。自己简单的测试了一下,速度比原来 getPixel()和 setPixel()速度快 了一倍。9.android 图像处理系列之九--图片特效处理之二-模糊效果这篇将讲到图片特效处理的模糊效果。跟前面一样是对像素点进行处理,算法是通用的,但耗时会更长,至于为 什么,看了下面的代码你就会明白。 算法: 一、简单算法:将像素点周围八个点包括自身一共九个点的 RGB 值分别相加后平均,作为当前像素点的 RGB 值,即可实现效果。 举例:- 28 作者:jacpy. ABC DEF GHI 假如当前点是 E,那么会有:1E.r = (A.r + B.r + C.r + D.r + E.r + F.r + G.r + H.r + I.r) / 9// r 表示的是 E 像素点 RGB 值的 R 值E 像素点的 GB 值类似。 二、采用高斯模糊: 高斯矩阵:2int int[] gauss = new int int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };算法是:将九个点的 RGB 值分别与高斯矩阵中的对应项相乘的和,然后再除以一个相应的值作为当前像素点的 RGB 值。举例: (还是上面的九个点) 假如当前点是 E,那么会有:3 4int delta = 16; E.r =( A.r * gauss[0] + B.r * gauss[1] + C.r * gauss[2] + D.r * gauss[3] + E.r * gauss[4] + F.r *gauss[5] + G.r * gauss[6] + H.r * gauss[7] + I.r * gauss[8]) / deltaE 像素点的 GB 值类似,delta 的取值貌似没有规定值,可以自己设置任意值,但要想达到效果,能设的值很少, 下面图片是值为16的效果。 处理效果:原图片:处理后:- 29 作者:jacpy. 两种处理方式的代码:5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33/** jacpy. * 模糊效果 * @param bmp * @return */ private Bitmap blurImage(Bitmap bmp) { int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixColor = 0; int newR = 0; int newG = 0; int newB = 0; int newColor = 0; int int[][] colors = new int int[9][3]; int for (int i = 1, length = width - 1; i & i++) { int for (int k = 1, len = height - 1; k & k++) { int for (int m = 0; m & 9; m++) { int s = 0; int p = 0; switch switch(m) - 30 作者:jacpy. 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 }{ case 0: s = i - 1; p = k - 1; case 1: s = p = k - 1; case 2: s = i + 1; p = k - 1; case 3: s = i + 1; p = case 4: s = i + 1; p = k + 1; case 5: s = p = k + 1; case 6: s = i - 1; p = k + 1; case 7: s = i - 1; p = case 8: s = p = } pixColor = bmp.getPixel(s, p); colors[m][0] = Color.red(pixColor); colors[m][1] = Color.green(pixColor); colors[m][2] = Color.blue(pixColor);int for (int m = 0; m & 9; m++) { - 31 作者:jacpy. 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 } } } }newR += colors[m][0]; newG += colors[m][1]; newB += colors[m][2];int newR = (int (newR / 9F); int) int newG = (int (newG / 9F); int) int newB = (int (newB / 9F); int) newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); newColor = Color.argb(255, newR, newG, newB); bitmap.setPixel(i, k, newColor); newR = 0; newG = 0; newB = 0;/** jacpy. * 柔化效果(高斯模糊)(优化后比上面快三倍) * @param bmp * @return */ private Bitmap blurImageAmeliorate(Bitmap bmp) { long start = System.currentTimeMillis(); // 高斯矩阵 int int[] gauss = new int int[] { 1, 2, 1, 2, 4, 2, 1, 2, 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; - 32 作者:jacpy. 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170int newR = 0; int newG = 0; int newB = 0; int delta = 16; // 值越小图片会越亮,越大则越暗 int idx = 0; int int[] pixels = new int int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); int for (int i = 1, length = height - 1; i & i++) { int for (int k = 1, len = width - 1; k & k++) { idx = 0; int for (int m = -1; m &= 1; m++) { int 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); int newR = newR + (int (pixR * gauss[idx]); int) int newG = newG + (int (pixG * gauss[idx]); int) int newB = newB + (int (pixB * gauss[idx]); int) idx++; } } newR /= newG /= newB /= 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; } } - 33 作者:jacpy. 171 172 173 174 175 }bitmap.setPixels(pixels, 0, width, 0, 0, width, height); long end = System.currentTimeMillis(); Log.d(&may&, &used time=&+(end - start));在优化后的代码中要注意了,pixels 数组不能超过规定的大小,也就是说图片的尺寸不能太大,否则会栈内存 溢出。10.android 图像处理系列之十--图片特效处理之三-锐化效果这篇将讲到图片特效处理的锐化效果。跟前面一样是对像素点进行处理,算法是通用的。 算法原理: 一、简单算法:分别获取当前像素点和八个周围像素点的 RGB 值,先求出当前像素点的 RGB 值与八个像素点 RGB 值的和的平均数,再乘以相应的系数,然后在与当前像素点之和。 例: ABC DEF GHI 对 E 点进行锐化:1 2float delta = 0.3; E.r = (E.r - (A.r + B.r + C.r + D.r + F.r + G.r + H.r + I.r) / 8) * delta + E.r;E.g,E.b 类似,delta 建议取0.3,具体多少无所谓,试一下就知道了。但按照上面原理,没有达到预期的效果, 改变 delta 的值也不行,所以后面代码就不贴出来了,感兴趣的可以研究一下。二、拉普拉斯变换:将拉普拉斯矩阵中的项与相应点的 RGB 值之积再乘以相应的系数的和作为当前点的 RGB 值。 例:用上面的例子,还是对 E 点进行锐化。3 4 5 6// 拉普拉斯矩阵 int int[] laplacian = new int int[] { -1, -1, -1, -1, 9, -1, -1, -1, -1 }; float delta = 0.3; E.r = A.r * laplacian[0] * delta + B.r * laplacian[1] * delta + C.r * laplacian[2] * delta + D.r* laplacian[3] * delta + E.r * laplacian[4] * delta + F.r * laplacian[5] * delta + G.r * laplacian[6] * delta + H.r * laplacian[7] * delta + I.r * laplacian[8] * 7 // E.g 和 E.b 值类似下面看效果图:- 34 作者:jacpy. 原图:处理后:貌似处理有点问题, 中间会看到很多的竖线, 很明显, 可能是没有优化好, 因为采用了 getPiexels() 和 setPixels() 方法,所以一维数组的对应图片的宽高有点麻烦。 下面贴代码,仅供参数,同样注意图片的大小,数组大小不能超过虚拟机规定值。8 9 10 11 12 13 14 15 16/** jacpy. * 图片锐化(拉普拉斯变换) * @param bmp * @return */ private Bitmap sharpenImageAmeliorate(Bitmap bmp) { long start = System.currentTimeMillis(); // 拉普拉斯矩阵 - 35 作者:jacpy. 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61int int[] laplacian = new int 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 int[] pixels = new int int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); int for (int i = 1, length = height - 1; i & i++) { int for (int k = 1, len = width - 1; k & k++) { idx = 0; for (int m = -1; m &= 1; m++) int { int 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); int newR = newR + (int (pixR * laplacian[idx] * alpha); int) int newG = newG + (int (pixG * laplacian[idx] * alpha); int) int newB = newB + (int (pixB * laplacian[idx] * alpha); int) 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));- 36 作者:jacpy. 62 63 64 65 66 67 68 69 70 71 72 73 } } }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); long end = System.currentTimeMillis(); Log.d(&may&, &used time=&+(end - start));11.android 图像处理系列之十一--图片特效处理之四-浮雕效果这篇将讲到图片特效处理的浮雕效果。跟前面一样是对像素点进行处理,算法是通用的。 算法原理:用前一个像素点的 RGB 值分别减去当前像素点的 RGB 值并加上127作为当前像素点的 RGB 值。 例: ABC 求 B 点的浮雕效果如下: B.r = C.r - B.r + 127; B.g = C.g - B.g + 127; B.b = C.b - B.b + 127; 注意 RGB 值在0~255之间。 下面贴效果图: 原图:处理后:- 37 作者:jacpy. 代码:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28/** jacpy. * 浮雕效果 * @param bmp * @return */ private Bitmap emboss(Bitmap bmp) { 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 int[] pixels = new int int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); int pos = 0; int for (int i = 1, length = height - 1; i & i++) { int for (int k = 1, len = width - 1; k & k++) { - 38 作者:jacpy. 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 } } }pos = i * width + pixColor = pixels[pos]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); pixColor = pixels[pos + 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[pos] = Color.argb(255, newR, newG, newB);bitmap.setPixels(pixels, 0, width, 0, 0, width, height);12.android 图像处理系列之十二--图片特效处理之五-底片效果这篇将讲到图片特效处理的底片效果。跟前面一样是对像素点进行处理,算法是通用的。 算法原理:将当前像素点的 RGB 值分别与255之差后的值作为当前点的 RGB 值。 例: ABC 求 B 点的底片效果: B.r = 255 - B.r; B.g = 255 - B.g; B.b = 255 - B.b; 效果图: 原图:- 39 作者:jacpy. 处理后:代码:1 2 3 4 5 6 7 8 9 10 11 12 13/** jacpy. * 底片效果 * @param bmp * @return */ private Bitmap film(Bitmap bmp) { // RGBA 的最大值 final int MAX_VALUE = 255; int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);- 40 作者:jacpy. 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 }int pixR = 0; int pixG = 0; int pixB = 0; int pixColor = 0; int newR = 0; int newG = 0; int newB = 0; int int[] pixels = new int int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); int pos = 0; int for (int i = 1, length = height - 1; i & i++) { for (int k = 1, len = width - 1; k & k++) int { pos = i * width + 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);13.android 图像处理系列之十三--图片特效处理之六-光照效果这篇将讲到图片特效处理的光照效果。跟前面一样是对像素点进行处理,算法是通用的。 算法原理:图片上面的像素点按照给定圆心,按照圆半径的变化,像素点的 RGB 值分别加上相应的值作为当前 点的 RGB 值。 例: ABCDE- 41 作者:jacpy. FGHIJ KLMNO 如果指定 H 点为光照效果的中心,半径为两个像素点,那么 G 点 RGB 值分别加上的值会比 F 点的要大,因为 RGB 值越大,就越接近白色,所以 G 点看起来比 F 点要白,也就是距光照中心越近,看效果图: 原图:处理后:代码: 光照强度值 strength 可以按照想要的效果试着改。1 2 3 4 5 6 7/** jacpy. * 光照效果 * @param bmp * @return */ public Bitmap sunshine(Bitmap bmp) { - 42 作者:jacpy. 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52final int width = bmp.getWidth(); final 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 centerX = width / 2; int centerY = height / 2; int radius = Math.min(centerX, centerY); final float strength = 150F; // 光照强度 100~150 int[] pixels = new int[width * height]; bmp.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 + pixColor = pixels[pos]; 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 + newG = pixG + - 43 作者:jacpy. 53 54 55 56 57 58 59 60 61 62 63 64 65 66 } } } }newB = pixB +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[pos] = Color.argb(255, newR, newG, newB);bitmap.setPixels(pixels, 0, width, 0, 0, width, height);14.android 图像处理系列之十四--图片特效处理之七-图片叠加这篇将讲到图片特效处理的图片叠加效果。跟前面一样是对像素点进行处理,可参照前面的 android 图像处理 系列之七--图片涂鸦,水印-图片叠加和 android 图像处理系列之六--给图片添加边框(下)-图片叠加 两篇文章,此篇所讲的与之前有一点区别。叠加原理是两张图片的像素点按透明度叠加,不会进行颜色过滤。 叠 加图片可以是 JPG 格式,跟前在一样,最好是放大 assets 目录。下面看效果图:+代码:1 2 3 4 5 6 7 8 9 /** jacpy. * 图片效果叠加 * @param bmp 限制了尺寸大小的 Bitmap * @return */ private Bitmap overlay(Bitmap bmp) { long start = System.currentTimeMillis(); int width = bmp.getWidth(); - 44 作者:jacpy.= 10 11 12 13 14int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); // 对边框图片进行缩放 Bitmap overlay = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.rainbow_overlay); 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 int pos = 0; int for (int i = 0; i & i++) { int for (int k = 0; k & k++) { - 45 作者:jacpy. int int[] srcPixels = new int int[width * height]; int int[] layPixels = new int int[width * height]; bmp.getPixels(srcPixels, 0, width, 0, 0, width, height); overlayCopy.getPixels(layPixels, 0, width, 0, 0, width, height); final float alpha = 0.5F; int layR = 0; int layG = 0; int layB = 0; int layA = 0; int newR = 0; int newG = 0; int newB = 0; int newA = 0; int pixR = 0; int pixG = 0; int pixB = 0; int pixA = 0; int pixColor = 0; int layColor = 0; Bitmap overlayCopy = Bitmap.createBitmap(overlay, 0, 0, w, h, matrix, true true); int w = overlay.getWidth(); int h = overlay.getHeight(); float scaleX = width * 1F / float scaleY = height * 1F / Matrix matrix = new Matrix(); matrix.postScale(scaleX, scaleY); 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 } } }pos = i * width + pixColor = srcPixels[pos]; layColor = layPixels[pos]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); pixA = Color.alpha(pixColor); layR = Color.red(layColor); layG = Color.green(layColor); layB = Color.blue(layColor); layA = Color.alpha(layColor); int newR = (int (pixR * alpha + layR * (1 - alpha)); int) int newG = (int (pixG * alpha + layG * (1 - alpha)); int) int newB = (int (pixB * alpha + layB * (1 - alpha)); int) int layA = (int (pixA * alpha + layA * (1 - alpha)); int) newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); newA = Math.min(255, Math.max(0, layA)); srcPixels[pos] = Color.argb(newA, newR, newG, newB);bitmap.setPixels(srcPixels, 0, width, 0, 0, width, height); long end = System.currentTimeMillis(); Log.d(&may&, &overlayAmeliorate used time=&+(end - start));叠加的边框图片还是大点比较好,也要控制被叠加图片大小。alpha 变量值可以根据需求修改,建议还是大 于 0.5 比较好,不然原图会看不清楚。15.android 图像处理系列之十五--图片特效处理之八-光晕效果这篇将讲到图片特效处理的图片光晕效果。跟前面一样是对像素点进行处理,本篇实现的思路可参见 android 图像处理系列之九--图片特效处理之二-模糊效果和 android 图像处理系列之十三--图片特效处理之六- 光照效果。实现的效果是圆圈之内图片像素点不变,圆圈之外的点做模糊处理。所以用到了模糊效果和光照效果 里面的是否是在圆圈内的算法,可以说是上面提到的两篇的效果的组合。 下面看效果图: 原图:- 46 作者:jacpy. 效果图:光晕效果看得不是很明显,模糊强度不够,但是还能明显看到图片中有一个圆圈,圈内区域要比圈外区域看得清 楚一点(MM 的左右脸就可以看到效果) 。处理效果不是很理想,在此只能抛砖引玉。下面贴代码:1 2 3 4 5 6 7 8 9 10 11 12/** jacpy. * 光晕效果 * @param bmp * @param x 光晕中心点在 bmp 中的 x 坐标 * @param y 光晕中心点在 bmp 中的 y 坐标 * @param r 光晕的半径 * @return */ public Bitmap halo(Bitmap bmp, int x, int y, float r) { long start = System.currentTimeMillis(); // 高斯矩阵 - 47 作者:jacpy. 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58int int[] gauss = new int int[] { 1, 2, 1, 2, 4, 2, 1, 2, 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 delta = 18; // 值越小图片会越亮,越大则越暗 int idx = 0; int int[] pixels = new int int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); int for (int i = 1, length = height - 1; i & i++) { int for (int k = 1, len = width - 1; k & k++) { idx = 0; int int distance = (int (Math.pow(k - x, 2) + Math.pow(i - y, 2)); int) // 不是中心区域的点做模糊处理 if (distance & r * r) { int for (int m = -1; m &= 1; m++) { int 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); int newR = newR + (int (pixR * gauss[idx]); int) int newG = newG + (int (pixG * gauss[idx]); int) int newB = newB + (int (pixB * gauss[idx]); int) idx++; } } - 48 作者:jacpy. 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 } } } }newR /= newG /= newB /= 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); long end = System.currentTimeMillis(); Log.d(&may&, &used time=&+(end - start));16.android 图像处理系列之十六--图片特效处理之九-条纹效果这篇将讲到图片特效处理的图片条纹效果。跟前面一样是对像素点进行处理,也没什么特别之处,跟前面的都是 一个类型的,只是注释写的清楚一点,前面有人评论说看不懂,所以此篇的主要目的是介绍用法,做一个简单的 效果以供参考。下面看效果: 原图:处理后:- 49 作者:jacpy. 下面的示例是在高度方向,以40个像素为单位,前10个像素所在的行的像素点会全部被处理成黑色。下面贴代 码:1 2 3 4 5 6 7 8 9 10 11 12/** jacpy. * 黑色条纹效果 * @param bmp * @return */ public Bitmap stria(Bitmap bmp) { long start = System.currentTimeMillis(); int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); // 创建一个相同大小的图片 13 14 15 16 17 18 19 20 int int[] pixels = new int int[width * height]; // 保存图片的像素点信息 bmp.getPixels(pixels, 0, width, 0, 0, width, height); // 将整个图片保存到一维数组中,每 width 个 // 保存像素点的 RGB 值 int newR = 0; int newG = 0; int newB = 0;长度为一行 21 22 23 24 25 - 50 作者:jacpy. final int delta = 40; // 每40个像素的高度作为一个单位 final int blackHeight = 10; // 黑色区域高度 final int BLACK = 0; 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 }int for (int i = 0; i & i++) { // 对图片的进行纵向处理 // 每隔30个像素的高度就会产生一个高度为10个像素的黑色宽带 // 每40个像素为一个单位,前面的10像素就会被处理成黑色 if (i % delta &= blackHeight) { int for (int k = 0; k & k++) { // 对当前像素点赋新的 RGB 值 newR = BLACK; newG = BLACK; newB = BLACK; // Color.argb(),是将四个0~255的值组成一个像素点,也就是 RGBA 值,A 是 alpha,即透明度 pixels[i * width + k] = Color.argb(255, newR, newG, newB); // 修改像素点 } } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); // 向创建的相同大小的新图片绘像素点值 long end = System.currentTimeMillis(); Log.d(&may&, &used time=&+(end - start));17.android 图像处理系列之十七--图片特效处理之十-国际象棋棋盘的绘制此篇将会讲到绘制国际棋盘的方法,可以在游戏里面会用得到,下面讲一下自己的思路,以供参考。 国际象棋棋盘是8X8黑白相间的一张图片,首先第一步是计算出64块中一块的宽高的大小,宽度和高度是大小是 一致的,因为是正方形;然后先画出纵向黑白相间的图(也可以先画出横向的黑白相间的图,后面也要跟着变。), 也就是说最后看到的效果会是黑白相间的行,而且行有一定的高度,也就是第一步计算出来的高度;最后保证在 纵向黑白相间的基础上,横向是黑白相间的列就 OK 了,列的宽高是第一步计算出来的,也就完成整个棋盘的绘 制。下面看效果图:下面贴代码:- 51 作者:jacpy. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ///** jacpy. * 绘制国际象棋棋盘 * @param width 棋盘的宽高 * @return */ private Bitmap chessbord(int width) int { long start = System.currentTimeMillis(); Bitmap bitmap = Bitmap.createBitmap(width, width, Bitmap.Config.RGB_565); int int[] pixels = new int int[width * width]; final int delta = width / 8; // 将整个图片分成8 X 8个区域,delta 表示每个区域的宽度或高度 final int blackPix = Color.BLACK; // 黑色点 final int whitePix = Color.WHITE; // 白色点 int pixColor = whiteP boolean isWhite = false // 白色的标识 int for (int i = 0; i & i++) // 纵向 { isWhite = !(i / delta % 2 == 0); // 第一块区域开始为黑色,纵向的奇数块位置是白色 int for (int k = 0; k & k++) // 横向 { if (k / delta % 2 != 0) // 横向上的黑白相间,偶数块区域是黑色 { pixColor = isWhite ? blackPix : whiteP // 如果前面的是白色则要变成黑色 } else { pixColor = isWhite ? whitePix : blackP // 在纵向上是黑白相间 } pixColor = k / delta % 2 != 0 ? (isWhite ? blackPix : whitePix) : (isWhite ? whitePix : pixels[i * width + k] = pixC } } bitmap.setPixels(pixels, 0, width, 0, 0, width, width); long end = System.currentTimeMillis(); Log.d(&may&, &used time=&+(end - start)); }blackPix); 33 34 35 36 37 38 39 40 41 4218.android 图像处理系列之十八--图片特效处理之十一-图片乾坤大挪移之图片裁剪组合这篇将讲到图片特效处理的图片组合。也就是先将整张图片按规律裁剪,再组合成新的图片。下面看效果图:- 52 作者:jacpy. 原图:处理后:可怜的 MM 图片,被俺整成这样,唉! 代码:1 2 3 4 5 6 7 8 9/** 图片的上半部分标识 */ public static final int FLAG_TOP = 0x1; /** 图片的下半部分标识 */ public static final int FLAG_BOTTOM = FLAG_TOP && 1; /** 图片的左半部分标识 */ public static final int FLAG_LEFT = FLAG_TOP && 2; /** 图片的右半部分标识 */ public static final int FLAG_RIGHT = FLAG_TOP && 3; // jacpy.10 public Bitmap cropBitmap(Bitmap bmp) 11 { 12 // 将图片切成左右两块 - 53 作者:jacpy. 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 } 55Bitmap left = cropBitmapLandscape(bmp, FLAG_LEFT); Bitmap right = cropBitmapLandscape(bmp, FLAG_RIGHT); // 再将左右两块图片切成四块 Bitmap leftTop = cropBitmapPortrait(left, FLAG_TOP); Bitmap leftBottom = cropBitmapPortrait(left, FLAG_BOTTOM); Bitmap rightTop = cropBitmapPortrait(right, FLAG_TOP); Bitmap rightBottom = cropBitmapPortrait(right, FLAG_BOTTOM); // 原左右两块图片回收 left.recycle(); right.recycle(); left = right = // 创建新图片,中间留10个像素的间距 final int width = bmp.getWidth() + 10; final int height = bmp.getHeight() + 10; Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); // 组合图片 final int leftPos = width - leftBottom.getWidth(); final int topPos = height - leftBottom.getHeight(); Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(rightBottom, 0, 0, null null); // 放在左上角 canvas.drawBitmap(leftBottom, leftPos, 0, null null); // 放在右上角 canvas.drawBitmap(rightTop, 0, topPos, null null); // 放在左下角 canvas.drawBitmap(leftTop, leftPos, topPos, null null); // 放在右下角 // 图片回收 leftTop.recycle(); leftBottom.recycle(); rightTop.recycle(); rightBottom.recycle(); rightTop = leftTop = leftBottom = rightBottom =56 /** jacpy. 57 * 水平切割图片,也就是将图片分成左右两块 - 54 作者:jacpy. 58 59 60 61* @param bmp 图片 * @param flag 是保留左边还是右边的标识 * @return */62 private Bitmap cropBitmapLandscape(Bitmap bmp, int flag) 63 { 64 65 66 67 68 final int width = bmp.getWidth(); final int height = bmp.getHeight(); int startWidth = 0; // 起始宽度位置 int endWidth = width / 2; // 结束宽度位置 Bitmap bitmap = Bitmap.createBitmap(endWidth, height, Bitmap.Config.RGB_565); // 创建新的图片,宽度只有原来的一半 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 } 86 87 /** jacpy. 88 89 90 91 92 * 垂直切割图片,也就是说将图片切成上下两块 * @param bmp * @param flag 图片是保留上面还是下面 * @return */ Rect r = new Rect(startWidth, 0, endWidth, height); // 图片要切的范围 Rect rect = new Rect(0, 0, width / 2, height); // 新图片的大小 Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(bmp, r, rect, null null); // 切割图片 } switch (flag) { case FLAG_LEFT: case FLAG_RIGHT: startWidth = endW endWidth =93 private Bitmap cropBitmapPortrait(Bitmap bmp, int flag) 94 { 95 96 97 98 99 final int width = bmp.getWidth(); final int height = bmp.getHeight(); int startHeight = 0; // 高度的起始位置 int endHeight = height / 2; // 高度的结束位置 Bitmap bitmap = Bitmap.createBitmap(width, height / 2, Bitmap.Config.RGB_565); // 创建新图片,高度只有原来的一半 100 - 55 作者:jacpy. 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 }switch (flag) { case FLAG_TOP: case FLAG_BOTTOM: startHeight = endH endHeight = } Rect r = new Rect(0, startHeight, width, endHeight); // 图片要切的范围 Rect rect = new Rect(0, 0, width, height / 2); // 新图片的大小 Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(bmp, r, rect, null null); // 切割图片19.android 图像处理系列之十九--图片特效处理之十二-图片自由裁剪、人脸识别这篇将讲到图片裁剪,会讲到两种方案。 先看效果图:一、系统默认的裁剪方案:系统默认会有一个 Gallery,里面提供裁剪功能,跳转到系统裁剪界面有很多种方法, 下面是其中的一种。 代码:1 2 3 4final Intent intent = new Intent (&com.android.camera.action.CROP&); intent.setClassName(&com.android.camera&, &com.android.camera.CropImage&); intent.setData( photoUri); startActivityForResult(intent, REQUEST_CROP_IMAGE);photoUri 是怎么来的呢?有几种方式,第一种是指定图片,也就是说通过 Uri.fromFile(file// 图片文件)获取图 片文件路径的 Uri;第二种方式就是就是通过下面的代码:[java] view plaincopy- 56 作者:jacpy. 5 6 7 8 9Intent intent = new Intent(); intent.setAction(Intent.ACTION_PICK); intent.setType(&image/*&); startActivityForResult(intent, FLAG_CHOOSE);10 // ... 11 12 @Override int 13 protected void onActivityResult(int requestCode, int resultCode, Intent data) 14 { 15 16 17 18 19 20 21 if (resultCode == RESULT_OK && null != data) { switch (requestCode) { case FLAG_CHOOSE: Uri uri = data.getData(); // ...来获取 uri,也就是从系统选择图片界面返回的 uri。上面代码意思是跳转到系统选择图片界面,选择完成后,返 回选择的图片的 uri,调用 startActivityForResult()方法后,从上一个界面返回就会调用 onActivityResult()方法, 因此重写即可获得返回的数据。二、从 Gallery3D 中提取的裁剪方案:android2.3.3系统中的 Gallery3D 裁剪功 能提供了人脸识别功能,准确的来说应用是人眼识别(你会看到黑框是在人眼部位) ,具体用法参见 Gallery3D 中 CropImage 类中的 mRunFaceDetection 成员变量中的 run(),下面是部分代码:22 FaceDetector.Face[] mFaces = new FaceDetector.Face[3]; // 最多能识别三张人脸 23 public void run() { 24 25 26 27 28 29 mScale = 1.0F / mS if (faceBitmap != null { null) FaceDetector detector = new FaceDetector(faceBitmap.getWidth(), faceBitmap.getHeight(), mNumFaces = detector.findFaces(faceBitmap, mFaces); // 返回总供识别的脸数 } if (faceBitmap != null && faceBitmap != mBitmap) { faceBitmap.recycle(); } new mHandler.post(new Runnable() { public void run() { mWaitingToPick = mNumFaces & 1; - 57 作者:jacpy. mImageMatrix = mImageView.getImageMatrix(); Bitmap faceBitmap = prepareBitmap();mFaces.length); 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56if (mNumFaces & 0) { // 识别到人脸,则会找到对应人脸的位置,显示多个黑色的框 int for (int i = 0; i & mNumF i++) { handleFace(mFaces[i]); // 计算出人脸的位置,显示黑色的框 } } else { // 没有识别到人脸,则进行默认裁剪处理 makeDefault(); } mImageView.invalidate(); if (mImageView.mHighlightViews.size() == 1) { mCrop = mImageView.mHighlightViews.get(0); true mCrop.setFocus(true true); } if (mNumFaces & 1) { // 识别超过一张,则提示选择其中的一张进行选择处理 // CR: no need for the variable t. just do // Toast.makeText(...).show(). Toast t = Toast.makeText(mContext, R.string.multiface_crop_help, t.show(); } } });Toast.LENGTH_SHORT); 57 58 59 60 61 }文章最后会给出 Demo 的下载地址。在发现人脸识别的功能中间有一个小插曲,自己跟之前公司的一位同事合 拍一张图片,发现都可以识别出来,和另外一个同事拍的,死活识别不了,不知道是机子问题,还是人品问题。 今天在测试的时候又有一个小插曲,之前老是拿那个 MM 图片做测试,几天照例,发现了一个奇怪的现象。看下图:相信你也看出问题出来了,看来谷歌提供的 API 很牛 X,竟然这么智能,还有这爱好,俺没话说了。如果看到图 片中出现一个黑色的框,那么那个就是人脸识别功能起作用了,如果有“轻点一张脸开始裁剪”那么就是识别了多 张脸。OK,就介绍到这里,下面给 Demo。- 58 作者:jacpy. 下载地址:http://download.csdn.net/detail/maylian 里面的部分代码是从 Gallery3D 里面提取出来的,因为之前在 HW 做云相册的时候对 Gallery3D 源代码比较熟, 所以整理出来了,以供参考。20.android 图像处理系列之二十--图片处理总结android 图片一些简单的处理就写到这里了。 做图片处理的时候建议要注意以下几个问题: 一、图片回收,也就是调用 Bitmap.recycle()方法。特别是在处理大图片的时候,如果处理不好程序就会因为资 源被耗尽而崩溃;有时候由于逻辑处理的需要,图片不能回收,比如说要保存原图片,那么在处理完后,原图片 就不能回收了,但到最后记得一定要在适当的地方回收,图片很占内存;还有些时候回收的时候会出错,如果出 现 java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@40541cf8 错误,那么就是图片回收位置不对,再选一个比较合适的地方回收。 二、处理效率,如果要求处理的速度要快,建议还是交给底层去做,用 C/C++代码编写,那样会更快;特别是 在处理大图片,非常耗时。如果没有这方面的要求,那么就是进行得法优化,比如说,刚开始都是用 setPixel() 和 getPixel(),处理速度很慢,最后用 setPixels()和 getPixels(),速度确实快了很多。如果用 JAVA 写,还有优 化的地方就是 for 循环里面的逻辑处理,也就是算法。 三、如果是做边框处理,边框建议放在 assets 目录,因为放在那个文件下面的东西不会做参与编译,也就是说 图片大小不会改变,如果说边框图片过多,那么可以将边框图片的信息按照指定的格式写入到文件中,同样保存 在 assets 目录中,处理的时候只需要对文件进行解析即可获取边框信息,这样可以节省很多的代码。 暂时想的问题也就这么多,当然图片的处理方式有很多,前面讲到的都是一些简单图片的处理,我只是把个人的 一些思路写出来,供大家参考,也没必要局限于这几种处理方式。只要图片处理的一些基本方法掌握了,可以做 出很多的效果,就像 android 图像处理系列之十七--图片特效处理之十-国际象棋棋盘的绘制这篇里面提到 的棋盘绘制,刚开始并没有打算想写这一篇,只是在写了 android 图像处理系列之十六--图片特效处理之九 -条纹效果这篇之后,突然来的想法。横向纵向都加条纹的话就变成了棋盘了,我也没有做过游戏,国际象棋也 没玩过,刚开始也没想到是棋盘,只是想到在模拟器里面跑 APIDEMOS 里面的模拟相机的时候,背景图好像是 这个样子的,最后才想到好像是棋盘。然后花了一上午时间把算法给写出来了。所以只要有想法,就可以实现。 那些图片处理和效果是自己在以前公司老大交给的任务,就是研究 android 图片处理,自己到网上也找了,关于 此方面的资料很少,也到了一些其它语言方面的资料,比如网上就有 JAVA,C++,VB,C#等语言的图片处理, 自己有些是借鉴别人的,然后在 android 里面做相应的效果,前面提到的很多算法都是通用的,没有语言限制。 自己在以前公司也看到一本关于图片处理的书,用 C++写的,书名不记得了,好像是 Visual C++图像处理,反 正就那几个字,翻了一下,里面效果很多,很复杂,有很多的专业术语都看不懂,我不是计算机专业的,很多都 不懂,只是看着上面的效果,空羡慕而已。有兴趣的可以去研究一下。 谢谢亲们的关注!http://download.csdn.net/detail/maylian 这个里面是图片处理系列的一 个集合 demo,网上的代码都是从里面 copy 出来的,里面包含了图片处理系列的所有 代码,写的比较乱,没有整理。- 59 作者:jacpy.
广而告之:
相关文档:
下载文档:
搜索更多:
All rights reserved Powered by
copyright &copyright 。甜梦文库内容来自网络,如有侵犯请联系客服。|

我要回帖

更多关于 ps调整图片角度 的文章

 

随机推荐