项目需求:有一个xml文件,记录了一张图片每个元素的位置,大小,样式信息。
通过XmlResourceParser解析xml文件,得到每个元素的属性。
然后使用Paint绘制元素到Canvas上,得到一张Bitmap位图
将位图模糊处理,处理算法的原理(取图片上每个像素点周围的8个点平均值)
模糊算法:
- package com.metek.blur;
- import android.content.Context;
- import android.graphics.Bitmap;
- public class BlurUtils {
- /**
- * Android api 17实现的虚化
- * 某些机型上可能会Crash
- *
- * @param context
- * @param sentBitmap
- * @param radius 大于1小于等于25
- * @return
- */
- public static Bitmap fastblur(Context context,Bitmap sentBitmap,int radius) {
- if (sentBitmap == null) {
- return null;
- }
- // if (Build.VERSION.SDK_INT > 16) {
- // Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(),true);
- //
- // final RenderScript rs = RenderScript.create(context);
- // final Allocation input = Allocation.createFromBitmap(rs,// sentBitmap,Allocation.MipmapControl.MIPMAP_NONE,// Allocation.USAGE_SCRIPT);
- // final Allocation output = Allocation.createTyped(rs,// input.getType());
- // final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs,// Element.U8_4(rs));
- // script.setRadius(radius /* e.g. 3.f */);
- // script.setInput(input);
- // script.forEach(output);
- // output.copyTo(bitmap);
- // return bitmap;
- // }
- return stackblur(sentBitmap,radius);
- }
- /**
- * 纯Java实现的虚化,适用老版本api,外部只需调fastblur,会自动判断
- *
- * @param sentBitmap
- * @param radius
- * @return
- */
- private static Bitmap stackblur(Bitmap sentBitmap,int radius) {
- Bitmap bitmap = null;
- try {
- bitmap = sentBitmap.copy(sentBitmap.getConfig(),true);
- } catch (OutOfMemoryError e) {
- e.printStackTrace();
- return sentBitmap;
- }
- if (radius < 1) {
- return (null);
- }
- int w = bitmap.getWidth();
- int h = bitmap.getHeight();
- int[] pix = new int[w * h];
- bitmap.getPixels(pix,w,h);
- int wm = w - 1;
- int hm = h - 1;
- int wh = w * h;
- int div = radius + radius + 1;
- int r[] = new int[wh];
- int g[] = new int[wh];
- int b[] = new int[wh];
- int rsum,gsum,bsum,x,y,i,p,yp,yi,yw;
- int vmin[] = new int[Math.max(w,h)];
- int divsum = (div + 1) >> 1;
- divsum *= divsum;
- int dv[] = new int[256 * divsum];
- for (i = 0; i < 256 * divsum; i++) {
- dv[i] = (i / divsum);
- }
- yw = yi = 0;
- int[][] stack = new int[div][3];
- int stackpointer;
- int stackstart;
- int[] sir;
- int rbs;
- int r1 = radius + 1;
- int routsum,goutsum,boutsum;
- int rinsum,ginsum,binsum;
- for (y = 0; y < h; y++) {
- rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
- for (i = -radius; i <= radius; i++) {
- p = pix[yi + Math.min(wm,Math.max(i,0))];
- sir = stack[i + radius];
- sir[0] = (p & 0xff0000) >> 16;
- sir[1] = (p & 0x00ff00) >> 8;
- sir[2] = (p & 0x0000ff);
- rbs = r1 - Math.abs(i);
- rsum += sir[0] * rbs;
- gsum += sir[1] * rbs;
- bsum += sir[2] * rbs;
- if (i > 0) {
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- } else {
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- }
- }
- stackpointer = radius;
- for (x = 0; x < w; x++) {
- r[yi] = dv[rsum];
- g[yi] = dv[gsum];
- b[yi] = dv[bsum];
- rsum -= routsum;
- gsum -= goutsum;
- bsum -= boutsum;
- stackstart = stackpointer - radius + div;
- sir = stack[stackstart % div];
- routsum -= sir[0];
- goutsum -= sir[1];
- boutsum -= sir[2];
- if (y == 0) {
- vmin[x] = Math.min(x + radius + 1,wm);
- }
- p = pix[yw + vmin[x]];
- sir[0] = (p & 0xff0000) >> 16;
- sir[1] = (p & 0x00ff00) >> 8;
- sir[2] = (p & 0x0000ff);
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- rsum += rinsum;
- gsum += ginsum;
- bsum += binsum;
- stackpointer = (stackpointer + 1) % div;
- sir = stack[(stackpointer) % div];
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- rinsum -= sir[0];
- ginsum -= sir[1];
- binsum -= sir[2];
- yi++;
- }
- yw += w;
- }
- for (x = 0; x < w; x++) {
- rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
- yp = -radius * w;
- for (i = -radius; i <= radius; i++) {
- yi = Math.max(0,yp) + x;
- sir = stack[i + radius];
- sir[0] = r[yi];
- sir[1] = g[yi];
- sir[2] = b[yi];
- rbs = r1 - Math.abs(i);
- rsum += r[yi] * rbs;
- gsum += g[yi] * rbs;
- bsum += b[yi] * rbs;
- if (i > 0) {
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- } else {
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- }
- if (i < hm) {
- yp += w;
- }
- }
- yi = x;
- stackpointer = radius;
- for (y = 0; y < h; y++) {
- // Preserve alpha channel: ( 0xff000000 & pix[yi] )
- pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16)
- | (dv[gsum] << 8) | dv[bsum];
- rsum -= routsum;
- gsum -= goutsum;
- bsum -= boutsum;
- stackstart = stackpointer - radius + div;
- sir = stack[stackstart % div];
- routsum -= sir[0];
- goutsum -= sir[1];
- boutsum -= sir[2];
- if (x == 0) {
- vmin[y] = Math.min(y + r1,hm) * w;
- }
- p = x + vmin[y];
- sir[0] = r[p];
- sir[1] = g[p];
- sir[2] = b[p];
- rinsum += sir[0];
- ginsum += sir[1];
- binsum += sir[2];
- rsum += rinsum;
- gsum += ginsum;
- bsum += binsum;
- stackpointer = (stackpointer + 1) % div;
- sir = stack[stackpointer];
- routsum += sir[0];
- goutsum += sir[1];
- boutsum += sir[2];
- rinsum -= sir[0];
- ginsum -= sir[1];
- binsum -= sir[2];
- yi += w;
- }
- }
- bitmap.setPixels(pix,h);
- return (bitmap);
- }
- }
- package com.metek.blur;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import android.content.Context;
- import android.content.res.XmlResourceParser;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Paint;
- import android.os.AsyncTask;
- import android.os.SystemClock;
- import android.util.DisplayMetrics;
- /**
- * 生成天气模糊背景图
- *
- */
- public class BlurWeatherImage {
- private static final String TAG = "BlurWeatherImage";
- private Bitmap bitmap = null;
- private Paint paint;
- private Canvas canvas;
- private FileOutputStream out = null;
- private float wRate;
- private float hRate;
- private int width;
- private int height;
- private Context context;
- private static final String IMAGENAME="ani_cloudy_night.png";
- public BlurWeatherImage(Context context) {
- super();
- this.context = context;
- DisplayMetrics dm = context.getResources().getDisplayMetrics();
- width = dm.widthPixels;
- height = dm.heightPixels;
- bitmap = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
- paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- canvas = new Canvas(bitmap);
- wRate = width / 720f;
- hRate = height / 1280f;
- }
- /** 模糊图片 */
- public void blurImage() {
- BulurAsyncTask bat = new BulurAsyncTask();
- bat.execute();
- }
- class BulurAsyncTask extends AsyncTask<Void,Void,Void> {
- protected Void doInBackground(Void... params) {
- analysisXml();
- return null;
- }
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- listener.drawEnd();
- }
- }
- public void analysisXml() {
- canvas.drawColor(0xff102d37);
- XmlResourceParser parser = context.getResources().getXml(R.xml.ani_cloudy_night);
- try {
- int event = parser.getEventType();
- while (event != XmlResourceParser.END_DOCUMENT) {
- String tagName = parser.getName();
- if (event == XmlResourceParser.START_TAG) {
- if (tagName.equals("view")) {
- int x = Integer.parseInt(parser.getAttributeValue(null,"x"));
- int y = Integer.parseInt(parser.getAttributeValue(null,"y"));
- int w = Integer.parseInt(parser.getAttributeValue(null,"w"));
- int h = Integer.parseInt(parser.getAttributeValue(null,"h"));
- String residname = parser.getAttributeValue(null,"resid");
- int resid = context.getResources().getIdentifier(residname.replace("@drawable/",""),"drawable",context.getPackageName());
- picture(bitmap,h,resid);
- SystemClock.sleep(100);
- }
- }
- event = parser.next();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- out = context.openFileOutput(IMAGENAME,Context.MODE_PRIVATE);
- bitmap.compress(Bitmap.CompressFormat.PNG,100,out);
- out = context.openFileOutput("blur_"+IMAGENAME,Context.MODE_PRIVATE);
- Bitmap blurBitmap = BlurUtils.fastblur(context,bitmap,80);
- blurBitmap.compress(Bitmap.CompressFormat.PNG,out);
- android.util.Log.i(TAG,IMAGENAME + "writer success");
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- }
- /**
- * @param x
- * 元素x坐标
- * @param y
- * 元素y坐标
- * @param w
- * 元素宽度
- * @param h
- * 元素高度
- * @param resId
- * 资源id
- */
- public void picture(Bitmap bitmap,int x,int y,int w,int h,int resId) {
- Bitmap element = BitmapFactory.decodeResource(context.getResources(),resId);
- int scaleW = (int) (w * wRate);
- int scaleH = (int) (h * hRate);
- Bitmap scaled = Bitmap.createScaledBitmap(element,scaleW,scaleH,false);
- canvas.drawBitmap(scaled,x * wRate,y * hRate,paint);
- }
- private OnDrawListener listener;
- public interface OnDrawListener {
- /** 绘图结束 */
- public void drawEnd();
- }
- public void setOnDrawListener(OnDrawListener listener) {
- this.listener = listener;
- }
- }