Table of Contents

Android Animation

Animation

Camera

Matrix

  1. Android画图之Matrix(一):http://chroya.iteye.com/blog/712078
  2. Android画图之Matrix(二):http://chroya.iteye.com/blog/713869

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;

/**
 * 图片处理 <br>
 * 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;
    }

}