====== Android Animation ====== ===== Animation ===== - Android API Animation:http://developer.android.com/reference/android/view/animation/Animation.html - Android Animation Guide:http://developer.android.com/guide/topics/graphics/animation.html ===== Camera ===== - Android API Camera:http://developer.android.com/reference/android/graphics/Camera.html ===== Matrix ===== - Android画图之Matrix(一):http://chroya.iteye.com/blog/712078 - Android画图之Matrix(二):http://chroya.iteye.com/blog/713869 - Android API Matrix:http://developer.android.com/reference/android/graphics/Matrix.html - pre/post/set Translate:http://stackoverflow.com/questions/8197656/looking-for-an-explanation-of-post-pre-set-translate-in-matrix-object-and-how ===== Image Util ===== package me.pjq.imageutil; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.Log; import java.io.ByteArrayOutputStream; /** * 图片处理
* Reference:http://blog.csdn.net/maylian7700/article/category/799453 * * @author pengjianqing@gmail.com */ public class ImageUtil { /** * 图片旋转 * * @param bmp 要旋转的图片 * @param degree 图片旋转的角度,负值为逆时针旋转,正值为顺时针旋转 * @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); } /** * 图片缩放 * * @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); } /** * 图片缩放 * * @param bm * @param w 缩小或放大成的宽 * @param h 缩小或放大成的高 * @return */ public static Bitmap resizeBitmap(Bitmap bm, int w, int h) { Bitmap BitmapOrg = bm; int width = BitmapOrg.getWidth(); int height = BitmapOrg.getHeight(); float scaleWidth = ((float) w) / width; float scaleHeight = ((float) h) / height; Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); return Bitmap.createBitmap(BitmapOrg, 0, 0, width, height, matrix, true); } /** * 图片反转 * * @param bm * @param flag 0为水平反转,1为垂直反转 * @return */ public static Bitmap reverseBitmap(Bitmap bmp, int flag) { float[] floats = null; switch (flag) { case 0: // 水平反转 floats = new float[] { -1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f }; break; case 1: // 垂直反转 floats = new float[] { 1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f }; break; } if (floats != null) { Matrix matrix = new Matrix(); matrix.setValues(floats); return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true); } return bmp; } /** * 图片效果叠加 * * @param bmp 限制了尺寸大小的Bitmap * @return */ public static Bitmap overlay(Bitmap bmp, Bitmap overlay) { long start = System.currentTimeMillis(); 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.rainbow_overlay); int w = overlay.getWidth(); int h = overlay.getHeight(); float scaleX = width * 1F / w; float scaleY = height * 1F / h; Matrix matrix = new Matrix(); matrix.postScale(scaleX, scaleY); Bitmap overlayCopy = Bitmap.createBitmap(overlay, 0, 0, w, h, matrix, true); int pixColor = 0; int layColor = 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; final float alpha = 0.5F; int[] srcPixels = new int[width * height]; int[] layPixels = new int[width * height]; bmp.getPixels(srcPixels, 0, width, 0, 0, width, height); overlayCopy.getPixels(layPixels, 0, width, 0, 0, width, height); int pos = 0; for (int i = 0; i < height; i++) { for (int k = 0; k < width; k++) { pos = i * width + k; 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); newR = (int) (pixR * alpha + layR * (1 - alpha)); newG = (int) (pixG * alpha + layG * (1 - alpha)); newB = (int) (pixB * alpha + layB * (1 - alpha)); layA = (int) (pixA * alpha + layA * (1 - alpha)); 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)); return bitmap; } /** * 浮雕效果 * * @param bmp * @return */ public static 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[] 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 + k; 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); return bitmap; } /** * 叠加边框图片有用部分 * * @param bmp * @return */ public static Bitmap alphaLayer(Bitmap bmp, Bitmap overlay) { 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 / w; float scaleY = height * 1F / h; Matrix matrix = new Matrix(); matrix.postScale(scaleX, scaleY); Bitmap overlayCopy = Bitmap.createBitmap(overlay, 0, 0, w, h, matrix, 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; for (int i = 0; i < width; i++) { for (int k = 0; k < height; k++) { pixColor = bmp.getPixel(i, k); layColor = overlayCopy.getPixel(i, k); // 获取原图片的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 = alpha; alphaG = alpha; alphaB = alpha; // 两种颜色叠加 newR = (int) (pixR * alphaR + layR * (1 - alphaR)); newG = (int) (pixG * alphaG + layG * (1 - alphaG)); newB = (int) (pixB * alphaB + layB * (1 - alphaB)); layA = (int) (pixA * alpha + layA * (1 - alpha)); // 值在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); } } return bitmap; } /** * Bitmap转换成byte数组 * * @param bmp * @return */ public static byte[] bitmap2Byte(Bitmap bmp) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.PNG, 100, baos); return baos.toByteArray(); } /** * 数组转换成Bitmap * * @param buffer * @return */ public static Bitmap byte2Bitmap(byte[] buffer) { return BitmapFactory.decodeByteArray(buffer, 0, buffer.length); } /** * 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(); } /** * 怀旧效果(相对之前做了优化快一倍) * * @param bmp * @return */ public static Bitmap oldRemeber(Bitmap bmp) { // 速度测试 long start = System.currentTimeMillis(); 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); long end = System.currentTimeMillis(); Log.d("may", "used time=" + (end - start)); return bitmap; } /** * 模糊效果 * * @param bmp * @return */ public static 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[][] colors = new int[9][3]; for (int i = 1, length = width - 1; i < length; i++) { for (int k = 1, len = height - 1; k < len; k++) { for (int m = 0; m < 9; m++) { int s = 0; int p = 0; switch (m) { case 0: s = i - 1; p = k - 1; break; case 1: s = i; p = k - 1; break; case 2: s = i + 1; p = k - 1; break; case 3: s = i + 1; p = k; break; case 4: s = i + 1; p = k + 1; break; case 5: s = i; p = k + 1; break; case 6: s = i - 1; p = k + 1; break; case 7: s = i - 1; p = k; break; case 8: s = i; p = k; } pixColor = bmp.getPixel(s, p); colors[m][0] = Color.red(pixColor); colors[m][1] = Color.green(pixColor); colors[m][2] = Color.blue(pixColor); } for (int m = 0; m < 9; m++) { newR += colors[m][0]; newG += colors[m][1]; newB += colors[m][2]; } newR = (int) (newR / 9F); newG = (int) (newG / 9F); newB = (int) (newB / 9F); 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; } } return bitmap; } /** * 柔化效果(高斯模糊)(优化后比上面快三倍) * * @param bmp * @return */ public static Bitmap blurImageAmeliorate(Bitmap bmp) { long start = System.currentTimeMillis(); // 高斯矩阵 int[] gauss = new 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 = 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 + (int) (pixR * gauss[idx]); newG = newG + (int) (pixG * gauss[idx]); newB = newB + (int) (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; } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); long end = System.currentTimeMillis(); Log.d("may", "used time=" + (end - start)); return bitmap; } /** 图片的上半部分标识 */ 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; public static Bitmap cropBitmap(Bitmap bmp) { // 将图片切成左右两块 Bitmap 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 = null; right = null; // 创建新图片,中间留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); // 放在左上角 canvas.drawBitmap(leftBottom, leftPos, 0, null); // 放在右上角 canvas.drawBitmap(rightTop, 0, topPos, null); // 放在左下角 canvas.drawBitmap(leftTop, leftPos, topPos, null); // 放在右下角 // 图片回收 leftTop.recycle(); leftBottom.recycle(); rightTop.recycle(); rightBottom.recycle(); rightTop = null; leftTop = null; leftBottom = null; rightBottom = null; return bitmap; } /** * 水平切割图片,也就是将图片分成左右两块 * * @param bmp 图片 * @param flag 是保留左边还是右边的标识 * @return */ public static Bitmap cropBitmapLandscape(Bitmap bmp, int flag) { 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); // 创建新的图片,宽度只有原来的一半 switch (flag) { case FLAG_LEFT: break; case FLAG_RIGHT: startWidth = endWidth; endWidth = width; break; } 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); // 切割图片 return bitmap; } /** * 垂直切割图片,也就是说将图片切成上下两块 * * @param bmp * @param flag 图片是保留上面还是下面 * @return */ public static Bitmap cropBitmapPortrait(Bitmap bmp, int flag) { 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); // 创建新图片,高度只有原来的一半 switch (flag) { case FLAG_TOP: break; case FLAG_BOTTOM: startHeight = endHeight; endHeight = height; break; } 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); // 切割图片 return bitmap; } }