/*
* Copyright (C) 2012 www.amsoft.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ab.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ShortBuffer;
import java.text.SimpleDateFormat;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.YuvImage;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.MeasureSpec;
import android.widget.ImageView;
import com.ab.util.dct.FDCT;
// TODO: Auto-generated Javadoc
/**
* © 2012 amsoft.cn
* 名称:AbImageUtil.java
* 描述:图片处理类.
*
* @author 还如一梦中
* @version v1.0
* @date:2013-01-17 下午11:52:13
*/
public class AbImageUtil {
private final static String TAG = "AbImageUtil";
/** 图片处理:裁剪. */
public static final int CUTIMG = 0;
/** 图片处理:缩放. */
public static final int SCALEIMG = 1;
/** 图片处理:不处理. */
public static final int ORIGINALIMG = 2;
/** 图片最大宽度. */
public static final int MAX_WIDTH = 4096/2;
/** 图片最大高度. */
public static final int MAX_HEIGHT = 4096/2;
/**
* 从互联网上获取原始大小图片.
*
* @param url
* 要下载文件的网络地址
* @param desiredWidth
* 新图片的宽
* @param desiredHeight
* 新图片的高
* @return Bitmap 新图片
*/
public static Bitmap getBitmap(String url) {
Bitmap bitmap = null;
URLConnection con = null;
InputStream is = null;
try {
URL imageURL = new URL(url);
con = imageURL.openConnection();
con.setDoInput(true);
con.connect();
is = con.getInputStream();
// 获取资源图片
bitmap = BitmapFactory.decodeStream(is, null, null);
} catch (Exception e) {
AbLogUtil.d(AbImageUtil.class, "" + e.getMessage());
} finally {
try {
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmap;
}
/**
* 描述:获取原图.
*
* @param file
* File对象
* @return Bitmap 图片
*/
public static Bitmap getBitmap(File file) {
Bitmap resizeBmp = null;
try {
resizeBmp = BitmapFactory.decodeFile(file.getPath());
} catch (Exception e) {
e.printStackTrace();
}
return resizeBmp;
}
/**
* 从互联网上获取指定大小的图片.
*
* @param url
* 要下载文件的网络地址
* @param desiredWidth
* 新图片的宽
* @param desiredHeight
* 新图片的高
* @return Bitmap 新图片
*/
public static Bitmap getBitmap(String url,int desiredWidth, int desiredHeight) {
Bitmap bitmap = null;
URLConnection con = null;
InputStream is = null;
try {
URL imageURL = new URL(url);
con = imageURL.openConnection();
con.setDoInput(true);
con.connect();
is = con.getInputStream();
bitmap = getBitmap(is,desiredWidth,desiredHeight);
//超出的裁掉
if (bitmap.getWidth() > desiredWidth || bitmap.getHeight() > desiredHeight) {
bitmap = getCutBitmap(bitmap,desiredWidth,desiredHeight);
}
} catch (Exception e) {
e.printStackTrace();
AbLogUtil.d(AbImageUtil.class, "" + e.getMessage());
} finally {
try {
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmap;
}
/**
* 从流中获取指定大小的图片.
* @param inputStream
* @param desiredWidth
* @param desiredHeight
* @return
*/
public static Bitmap getBitmap(InputStream inputStream,int desiredWidth, int desiredHeight) {
Bitmap bitmap = null;
try {
byte [] data = AbStreamUtil.stream2bytes(inputStream);
bitmap = getBitmap(data,desiredWidth,desiredHeight);
} catch (Exception e) {
e.printStackTrace();
AbLogUtil.d(AbImageUtil.class, "" + e.getMessage());
}finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return bitmap;
}
/**
* 从流中获取指定大小的图片.
* @param data
* @param desiredWidth
* @param desiredHeight
* @return
*/
public static Bitmap getBitmap(byte [] data,int desiredWidth, int desiredHeight) {
Bitmap resizeBmp = null;
try {
BitmapFactory.Options opts = new BitmapFactory.Options();
// 设置为true,decodeFile先不创建内存 只获取一些解码边界信息即图片大小信息
opts.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, opts);
// 获取图片的原始宽度高度
int srcWidth = opts.outWidth;
int srcHeight = opts.outHeight;
int[] size = resizeToMaxSize(srcWidth, srcHeight, desiredWidth, desiredHeight);
desiredWidth = size[0];
desiredHeight = size[1];
// 默认为ARGB_8888.
opts.inPreferredConfig = Bitmap.Config.RGB_565;
// 以下两个字段需一起使用:
// 产生的位图将得到像素空间,如果系统gc,那么将被清空。当像素再次被访问,如果Bitmap已经decode,那么将被自动重新解码
opts.inPurgeable = true;
// 位图可以共享一个参考输入数据(inputstream、阵列等)
opts.inInputShareable = true;
// 缩放的比例,缩放是很难按准备的比例进行缩放的,通过inSampleSize来进行缩放,其值表明缩放的倍数,SDK中建议其值是2的指数值
int sampleSize = findBestSampleSize(srcWidth,srcHeight,desiredWidth,desiredHeight);
opts.inSampleSize = sampleSize;
// 创建内存
opts.inJustDecodeBounds = false;
// 使图片不抖动
opts.inDither = false;
resizeBmp = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
if (resizeBmp != null) {
resizeBmp = getCutBitmap(resizeBmp, desiredWidth, desiredHeight);
}
} catch (Exception e) {
e.printStackTrace();
AbLogUtil.d(AbImageUtil.class, "" + e.getMessage());
}
return resizeBmp;
}
/**
* 描述:缩放图片.
*
* @param file
* File对象
* @param desiredWidth
* 新图片的宽
* @param desiredHeight
* 新图片的高
* @return Bitmap 新图片
*/
public static Bitmap getScaleBitmap(File file, int desiredWidth, int desiredHeight) {
Bitmap resizeBmp = null;
BitmapFactory.Options opts = new BitmapFactory.Options();
// 设置为true,decodeFile先不创建内存 只获取一些解码边界信息即图片大小信息
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getPath(), opts);
// 获取图片的原始宽度高度
int srcWidth = opts.outWidth;
int srcHeight = opts.outHeight;
//需要的尺寸重置
int[] size = resizeToMaxSize(srcWidth, srcHeight, desiredWidth, desiredHeight);
desiredWidth = size[0];
desiredHeight = size[1];
// 默认为ARGB_8888.
opts.inPreferredConfig = Bitmap.Config.RGB_565;
// 以下两个字段需一起使用:
// 产生的位图将得到像素空间,如果系统gc,那么将被清空。当像素再次被访问,如果Bitmap已经decode,那么将被自动重新解码
opts.inPurgeable = true;
// 位图可以共享一个参考输入数据(inputstream、阵列等)
opts.inInputShareable = true;
// 缩放的比例,缩放是很难按准备的比例进行缩放的,通过inSampleSize来进行缩放,其值表明缩放的倍数,SDK中建议其值是2的指数值
int sampleSize = findBestSampleSize(srcWidth,srcHeight,desiredWidth,desiredHeight);
opts.inSampleSize = sampleSize;
// 创建内存
opts.inJustDecodeBounds = false;
// 使图片不抖动
opts.inDither = false;
resizeBmp = BitmapFactory.decodeFile(file.getPath(), opts);
// 缩放的比例
float scale = getMinScale(resizeBmp.getWidth(), resizeBmp.getHeight(), desiredWidth, desiredHeight);
if(scale < 1){
// 缩小
resizeBmp = scaleBitmap(resizeBmp, scale);
}
//超出的裁掉
if (resizeBmp.getWidth() > desiredWidth || resizeBmp.getHeight() > desiredHeight) {
resizeBmp = getCutBitmap(resizeBmp,desiredWidth,desiredHeight);
}
return resizeBmp;
}
/**
* 描述:缩放图片.
*
* @param bitmap
* the bitmap
* @param desiredWidth
* 新图片的宽
* @param desiredHeight
* 新图片的高
* @return Bitmap 新图片
*/
public static Bitmap getScaleBitmap(Bitmap bitmap, int desiredWidth, int desiredHeight) {
if (!checkBitmap(bitmap)) {
return null;
}
Bitmap resizeBmp = null;
// 获得图片的宽高
int srcWidth = bitmap.getWidth();
int srcHeight = bitmap.getHeight();
int[] size = resizeToMaxSize(srcWidth, srcHeight, desiredWidth, desiredHeight);
desiredWidth = size[0];
desiredHeight = size[1];
float scale = getMinScale(srcWidth, srcHeight, desiredWidth, desiredHeight);
resizeBmp = scaleBitmap(bitmap, scale);
//超出的裁掉
if (resizeBmp.getWidth() > desiredWidth || resizeBmp.getHeight() > desiredHeight) {
resizeBmp = getCutBitmap(resizeBmp,desiredWidth,desiredHeight);
}
return resizeBmp;
}
/**
* 描述:裁剪图片.
*
* @param file
* File对象
* @param desiredWidth
* 新图片的宽
* @param desiredHeight
* 新图片的高
* @return Bitmap 新图片
*/
public static Bitmap getCutBitmap(File file, int desiredWidth, int desiredHeight) {
Bitmap resizeBmp = null;
BitmapFactory.Options opts = new BitmapFactory.Options();
// 设置为true,decodeFile先不创建内存 只获取一些解码边界信息即图片大小信息
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getPath(), opts);
// 获取图片的原始宽度
int srcWidth = opts.outWidth;
// 获取图片原始高度
int srcHeight = opts.outHeight;
int[] size = resizeToMaxSize(srcWidth, srcHeight, desiredWidth, desiredHeight);
desiredWidth = size[0];
desiredHeight = size[1];
// 默认为ARGB_8888.
opts.inPreferredConfig = Bitmap.Config.RGB_565;
// 以下两个字段需一起使用:
// 产生的位图将得到像素空间,如果系统gc,那么将被清空。当像素再次被访问,如果Bitmap已经decode,那么将被自动重新解码
opts.inPurgeable = true;
// 位图可以共享一个参考输入数据(inputstream、阵列等)
opts.inInputShareable = true;
// 缩放的比例,缩放是很难按准备的比例进行缩放的,通过inSampleSize来进行缩放,其值表明缩放的倍数,SDK中建议其值是2的指数值
int sampleSize = findBestSampleSize(srcWidth,srcHeight,desiredWidth,desiredHeight);
opts.inSampleSize = sampleSize;
// 创建内存
opts.inJustDecodeBounds = false;
// 使图片不抖动
opts.inDither = false;
resizeBmp = BitmapFactory.decodeFile(file.getPath(), opts);
if (resizeBmp != null) {
resizeBmp = getCutBitmap(resizeBmp, desiredWidth, desiredHeight);
}
return resizeBmp;
}
/**
* 描述:裁剪图片.
*
* @param bitmap
* the bitmap
* @param desiredWidth
* 新图片的宽
* @param desiredHeight
* 新图片的高
* @return Bitmap 新图片
*/
public static Bitmap getCutBitmap(Bitmap bitmap, int desiredWidth, int desiredHeight) {
if (!checkBitmap(bitmap)) {
return null;
}
if (!checkSize(desiredWidth, desiredHeight)) {
return null;
}
Bitmap resizeBmp = null;
try {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int offsetX = 0;
int offsetY = 0;
if (width > desiredWidth) {
offsetX = (width - desiredWidth) / 2;
} else {
desiredWidth = width;
}
if (height > desiredHeight) {
offsetY = (height - desiredHeight) / 2;
} else {
desiredHeight = height;
}
resizeBmp = Bitmap.createBitmap(bitmap, offsetX, offsetY, desiredWidth,desiredHeight);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (resizeBmp != bitmap) {
bitmap.recycle();
}
}
return resizeBmp;
}
/**
* 描述:根据等比例缩放图片.
*
* @param bitmap
* the bitmap
* @param scale
* 比例
* @return Bitmap 新图片
*/
public static Bitmap scaleBitmap(Bitmap bitmap, float scale) {
if (!checkBitmap(bitmap)) {
return null;
}
if (scale == 1) {
return bitmap;
}
Bitmap resizeBmp = null;
try {
// 获取Bitmap资源的宽和高
int bmpW = bitmap.getWidth();
int bmpH = bitmap.getHeight();
// 注意这个Matirx是android.graphics底下的那个
Matrix matrix = new Matrix();
// 设置缩放系数,分别为原来的0.8和0.8
matrix.postScale(scale, scale);
resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bmpW, bmpH, matrix, true);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (resizeBmp != bitmap) {
bitmap.recycle();
}
}
return resizeBmp;
}
/**
* 描述:获取图片尺寸
*
* @param file File对象
* @return Bitmap 新图片
*/
public static float[] getBitmapSize(File file) {
float[] size = new float[2];
BitmapFactory.Options opts = new BitmapFactory.Options();
// 设置为true,decodeFile先不创建内存 只获取一些解码边界信息即图片大小信息
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getPath(), opts);
// 获取图片的原始宽度高度
size[0] = opts.outWidth;
size[1] = opts.outHeight;
return size;
}
/**
*
* 获取缩小的比例.
* @param srcWidth
* @param srcHeight
* @param desiredWidth
* @param desiredHeight
* @return
*/
private static float getMinScale(int srcWidth, int srcHeight, int desiredWidth,
int desiredHeight) {
// 缩放的比例
float scale = 0;
// 计算缩放比例,宽高的最小比例
float scaleWidth = (float) desiredWidth / srcWidth;
float scaleHeight = (float) desiredHeight / srcHeight;
if (scaleWidth > scaleHeight) {
scale = scaleWidth;
} else {
scale = scaleHeight;
}
return scale;
}
private static int[] resizeToMaxSize(int srcWidth, int srcHeight,
int desiredWidth, int desiredHeight) {
int[] size = new int[2];
if(desiredWidth <= 0){
desiredWidth = srcWidth;
}
if(desiredHeight <= 0){
desiredHeight = srcHeight;
}
if (desiredWidth > MAX_WIDTH) {
// 重新计算大小
desiredWidth = MAX_WIDTH;
float scaleWidth = (float) desiredWidth / srcWidth;
desiredHeight = (int) (desiredHeight * scaleWidth);
}
if (desiredHeight > MAX_HEIGHT) {
// 重新计算大小
desiredHeight = MAX_HEIGHT;
float scaleHeight = (float) desiredHeight / srcHeight;
desiredWidth = (int) (desiredWidth * scaleHeight);
}
size[0] = desiredWidth;
size[1] = desiredHeight;
return size;
}
private static boolean checkBitmap(Bitmap bitmap) {
if (bitmap == null) {
AbLogUtil.e(AbImageUtil.class, "原图Bitmap为空了");
return false;
}
if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
AbLogUtil.e(AbImageUtil.class, "原图Bitmap大小为0");
return false;
}
return true;
}
private static boolean checkSize(int desiredWidth, int desiredHeight) {
if (desiredWidth <= 0 || desiredHeight <= 0) {
AbLogUtil.e(AbImageUtil.class, "请求Bitmap的宽高参数必须大于0");
return false;
}
return true;
}
/**
* Drawable转Bitmap.
*
* @param drawable
* 要转化的Drawable
* @return Bitmap
*/
public static Bitmap drawableToBitmap(Drawable drawable) {
Bitmap bitmap = Bitmap
.createBitmap(
drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}
/**
* Bitmap对象转换Drawable对象.
*
* @param bitmap
* 要转化的Bitmap对象
* @return Drawable 转化完成的Drawable对象
*/
public static Drawable bitmapToDrawable(Bitmap bitmap) {
BitmapDrawable mBitmapDrawable = null;
try {
if (bitmap == null) {
return null;
}
mBitmapDrawable = new BitmapDrawable(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
return mBitmapDrawable;
}
/**
* Bitmap对象转换TransitionDrawable对象.
*
* @param bitmap
* 要转化的Bitmap对象 imageView.setImageDrawable(td);
* td.startTransition(200);
* @return Drawable 转化完成的Drawable对象
*/
public static TransitionDrawable bitmapToTransitionDrawable(Bitmap bitmap) {
TransitionDrawable mBitmapDrawable = null;
try {
if (bitmap == null) {
return null;
}
mBitmapDrawable = new TransitionDrawable(new Drawable[] {
new ColorDrawable(android.R.color.transparent),
new BitmapDrawable(bitmap) });
} catch (Exception e) {
e.printStackTrace();
}
return mBitmapDrawable;
}
/**
* Drawable对象转换TransitionDrawable对象.
*
* @param drawable
* 要转化的Drawable对象 imageView.setImageDrawable(td);
* td.startTransition(200);
* @return Drawable 转化完成的Drawable对象
*/
public static TransitionDrawable drawableToTransitionDrawable(
Drawable drawable) {
TransitionDrawable mBitmapDrawable = null;
try {
if (drawable == null) {
return null;
}
mBitmapDrawable = new TransitionDrawable(new Drawable[] {
new ColorDrawable(android.R.color.transparent), drawable });
} catch (Exception e) {
e.printStackTrace();
}
return mBitmapDrawable;
}
/**
* 将Bitmap转换为byte[].
*
* @param bitmap
* the bitmap
* @param mCompressFormat
* 图片格式 Bitmap.CompressFormat.JPEG,CompressFormat.PNG
* @param needRecycle
* 是否需要回收
* @return byte[] 图片的byte[]
*/
public static byte[] bitmap2Bytes(Bitmap bitmap,
Bitmap.CompressFormat mCompressFormat, final boolean needRecycle) {
byte[] result = null;
ByteArrayOutputStream output = null;
try {
output = new ByteArrayOutputStream();
bitmap.compress(mCompressFormat, 100, output);
result = output.toByteArray();
if (needRecycle) {
bitmap.recycle();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return result;
}
/**
* 获取Bitmap大小.
*
* @param bitmap
* the bitmap
* @param mCompressFormat
* 图片格式 Bitmap.CompressFormat.JPEG,CompressFormat.PNG
* @return 图片的大小
*/
public static int getByteCount(Bitmap bitmap,
Bitmap.CompressFormat mCompressFormat) {
int size = 0;
ByteArrayOutputStream output = null;
try {
output = new ByteArrayOutputStream();
bitmap.compress(mCompressFormat, 100, output);
byte[] result = output.toByteArray();
size = result.length;
result = null;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return size;
}
/**
* 描述:将byte[]转换为Bitmap.
*
* @param b
* 图片格式的byte[]数组
* @return bitmap 得到的Bitmap
*/
public static Bitmap bytes2Bimap(byte[] b) {
Bitmap bitmap = null;
try {
if (b.length != 0) {
bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
}
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
/**
* 将ImageView转换为Bitmap.
*
* @param view
* 要转换为bitmap的View
* @return byte[] 图片的byte[]
*/
public static Bitmap imageView2Bitmap(ImageView view) {
Bitmap bitmap = null;
try {
bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
/**
* 将View转换为Drawable.需要最上层布局为Linearlayout
*
* @param view
* 要转换为Drawable的View
* @return BitmapDrawable Drawable
*/
public static Drawable view2Drawable(View view) {
BitmapDrawable mBitmapDrawable = null;
try {
Bitmap newbmp = view2Bitmap(view);
if (newbmp != null) {
mBitmapDrawable = new BitmapDrawable(newbmp);
}
} catch (Exception e) {
e.printStackTrace();
}
return mBitmapDrawable;
}
/**
* 将View转换为Bitmap.需要最上层布局为Linearlayout
*
* @param view
* 要转换为bitmap的View
* @return byte[] 图片的byte[]
*/
public static Bitmap view2Bitmap(View view) {
Bitmap bitmap = null;
try {
if (view != null) {
view.setDrawingCacheEnabled(true);
view.measure(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
view.layout(0, 0, view.getMeasuredWidth(),
view.getMeasuredHeight());
view.buildDrawingCache();
bitmap = view.getDrawingCache();
}
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
/**
* 将View转换为byte[].
*
* @param view
* 要转换为byte[]的View
* @param compressFormat
* the compress format
* @return byte[] View图片的byte[]
*/
public static byte[] view2Bytes(View view,
Bitmap.CompressFormat compressFormat) {
byte[] b = null;
try {
Bitmap bitmap = AbImageUtil.view2Bitmap(view);
b = AbImageUtil.bitmap2Bytes(bitmap, compressFormat, true);
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
/**
* 描述:旋转Bitmap为一定的角度.
*
* @param bitmap
* the bitmap
* @param degrees
* the degrees
* @return the bitmap
*/
public static Bitmap rotateBitmap(Bitmap bitmap, float degrees) {
Bitmap mBitmap = null;
try {
Matrix m = new Matrix();
m.setRotate(degrees % 360);
mBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), m, false);
} catch (Exception e) {
e.printStackTrace();
}
return mBitmap;
}
/**
* 描述:旋转Bitmap为一定的角度并四周暗化处理.
*
* @param bitmap
* the bitmap
* @param degrees
* the degrees
* @return the bitmap
*/
public static Bitmap rotateBitmapTranslate(Bitmap bitmap, float degrees) {
Bitmap mBitmap = null;
int width;
int height;
try {
Matrix matrix = new Matrix();
if ((degrees / 90) % 2 != 0) {
width = bitmap.getWidth();
height = bitmap.getHeight();
} else {
width = bitmap.getHeight();
height = bitmap.getWidth();
}
int cx = width / 2;
int cy = height / 2;
matrix.preTranslate(-cx, -cy);
matrix.postRotate(degrees);
matrix.postTranslate(cx, cy);
} catch (Exception e) {
e.printStackTrace();
}
return mBitmap;
}
/**
* 转换图片转换成圆形.
*
* @param bitmap
* 传入Bitmap对象
* @return the bitmap
*/
public static Bitmap toRoundBitmap(Bitmap bitmap) {
if (bitmap == null) {
return null;
}
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float roundPx;
float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
if (width <= height) {
roundPx = width / 2;
top = 0;
bottom = width;
left = 0;
right = width;
height = width;
dst_left = 0;
dst_top = 0;
dst_right = width;
dst_bottom = width;
} else {
roundPx = height / 2;
float clip = (width - height) / 2;
left = clip;
right = width - clip;
top = 0;
bottom = height;
width = height;
dst_left = 0;
dst_top = 0;
dst_right = height;
dst_bottom = height;
}
Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect src = new Rect((int) left, (int) top, (int) right,
(int) bottom);
final Rect dst = new Rect((int) dst_left, (int) dst_top,
(int) dst_right, (int) dst_bottom);
final RectF rectF = new RectF(dst);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, src, dst, paint);
return output;
}
/**
* 转换图片转换成圆角.
*
* @param bitmap
* 传入Bitmap对象
* @return the bitmap
*/
public static Bitmap toRoundBitmap(Bitmap bitmap,int roundPx) {
if (bitmap == null) {
return null;
}
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
if (width <= height) {
top = 0;
bottom = width;
left = 0;
right = width;
height = width;
dst_left = 0;
dst_top = 0;
dst_right = width;
dst_bottom = width;
} else {
float clip = (width - height) / 2;
left = clip;
right = width - clip;
top = 0;
bottom = height;
width = height;
dst_left = 0;
dst_top = 0;
dst_right = height;
dst_bottom = height;
}
Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect src = new Rect((int) left, (int) top, (int) right,
(int) bottom);
final Rect dst = new Rect((int) dst_left, (int) dst_top,
(int) dst_right, (int) dst_bottom);
final RectF rectF = new RectF(dst);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, src, dst, paint);
return output;
}
/**
* 转换图片转换成镜面效果的图片.
*
* @param bitmap
* 传入Bitmap对象
* @return the bitmap
*/
public static Bitmap toReflectionBitmap(Bitmap bitmap) {
if (bitmap == null) {
return null;
}
try {
int reflectionGap = 1;
int width = bitmap.getWidth();
int height = bitmap.getHeight();
// This will not scale but will flip on the Y axis
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
// Create a Bitmap with the flip matrix applied to it.
// We only want the bottom half of the image
Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2,
width, height / 2, matrix, false);
// Create a new bitmap with same width but taller to fit
// reflection
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
(height + height / 2), Config.ARGB_8888);
// Create a new Canvas with the bitmap that's big enough for
// the image plus gap plus reflection
Canvas canvas = new Canvas(bitmapWithReflection);
// Draw in the original image
canvas.drawBitmap(bitmap, 0, 0, null);
// Draw in the gap
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap,
deafaultPaint);
// Draw in the reflection
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
// Create a shader that is a linear gradient that covers the
// reflection
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, bitmap.getHeight(),
0, bitmapWithReflection.getHeight() + reflectionGap,
0x70ffffff, 0x00ffffff, TileMode.CLAMP);
// Set the paint to use this shader (linear gradient)
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
bitmap = bitmapWithReflection;
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
/**
* 释放Bitmap对象.
*
* @param bitmap
* 要释放的Bitmap
*/
public static void releaseBitmap(Bitmap bitmap) {
if (bitmap != null) {
try {
if (!bitmap.isRecycled()) {
AbLogUtil.d(AbImageUtil.class,
"Bitmap释放" + bitmap.toString());
bitmap.recycle();
}
} catch (Exception e) {
}
bitmap = null;
}
}
/**
* 释放Bitmap数组.
*
* @param bitmaps
* 要释放的Bitmap数组
*/
public static void releaseBitmapArray(Bitmap[] bitmaps) {
if (bitmaps != null) {
try {
for (Bitmap bitmap : bitmaps) {
if (bitmap != null && !bitmap.isRecycled()) {
AbLogUtil.d(AbImageUtil.class,
"Bitmap释放" + bitmap.toString());
bitmap.recycle();
}
}
} catch (Exception e) {
}
}
}
/**
* 描述:简单的图像的特征值,用于缩略图找原图比较好.
*
* @param bitmap
* the bitmap
* @return the hash code
*/
public static String getHashCode(Bitmap bitmap) {
// 第一步,缩小尺寸。
// 将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,
// 只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。
Bitmap temp = Bitmap.createScaledBitmap(bitmap, 8, 8, false);
int width = temp.getWidth();
int height = temp.getHeight();
Log.i("th", "将图片缩小到8x8的尺寸:" + width + "*" + height);
// 第二步,第二步,简化色彩。
// 将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
int[] pixels = new int[width * height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
pixels[i * height + j] = rgbToGray(temp.getPixel(i, j));
}
}
releaseBitmap(temp);
// 第三步,计算平均值。
// 计算所有64个像素的灰度平均值。
int avgPixel = AbMathUtil.average(pixels);
// 第四步,比较像素的灰度。
// 将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
int[] comps = new int[width * height];
for (int i = 0; i < comps.length; i++) {
if (pixels[i] >= avgPixel) {
comps[i] = 1;
} else {
comps[i] = 0;
}
}
// 第五步,计算哈希值。
// 将上一步的比较结果,组合在一起,就构成了一个64位的整数,
// 这就是这张图片的指纹。
StringBuffer hashCode = new StringBuffer();
for (int i = 0; i < comps.length; i += 4) {
int result = comps[i] * (int) Math.pow(2, 3) + comps[i + 1]
* (int) Math.pow(2, 2) + comps[i + 2]
* (int) Math.pow(2, 1) + comps[i + 2];
hashCode.append(AbMathUtil.binaryToHex(result));
}
String sourceHashCode = hashCode.toString();
// 得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。
// 在理论上,这等同于计算"汉明距离"(Hamming distance)。
// 如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。
return sourceHashCode;
}
/**
* 描述:图像的特征值余弦相似度.
*
* @param bitmap
* the bitmap
* @return the DCT hash code
*/
public static String getDCTHashCode(Bitmap bitmap) {
// 将图片缩小到32x32的尺寸
Bitmap temp = Bitmap.createScaledBitmap(bitmap, 32, 32, false);
int width = temp.getWidth();
int height = temp.getHeight();
Log.i("th", "将图片缩小到32x32的尺寸:" + width + "*" + height);
// 简化色彩。
int[] pixels = new int[width * height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
pixels[i * height + j] = rgbToGray(temp.getPixel(i, j));
}
}
releaseBitmap(temp);
int[][] pxMatrix = AbMathUtil.arrayToMatrix(pixels, width, height);
double[][] doublePxMatrix = AbMathUtil.intToDoubleMatrix(pxMatrix);
// 计算DCT,已经变成8*8了
double[][] dtc = FDCT.fDctTransform(doublePxMatrix);
// 计算平均值。
double[] dctResult = AbMathUtil.matrixToArray(dtc);
int avgPixel = AbMathUtil.average(dctResult);
// 比较像素的灰度。
// 将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
int[] comps = new int[8 * 8];
for (int i = 0; i < comps.length; i++) {
if (dctResult[i] >= avgPixel) {
comps[i] = 1;
} else {
comps[i] = 0;
}
}
// 计算哈希值。
// 将上一步的比较结果,组合在一起,就构成了一个64位的整数,
// 这就是这张图片的指纹。
StringBuffer hashCode = new StringBuffer();
for (int i = 0; i < comps.length; i += 4) {
int result = comps[i] * (int) Math.pow(2, 3) + comps[i + 1]
* (int) Math.pow(2, 2) + comps[i + 2]
* (int) Math.pow(2, 1) + comps[i + 2];
hashCode.append(AbMathUtil.binaryToHex(result));
}
String sourceHashCode = hashCode.toString();
// 得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。
// 在理论上,这等同于计算"汉明距离"(Hamming distance)。
// 如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。
return sourceHashCode;
}
/**
* 描述:图像的特征值颜色分布 将颜色分4个区,0,1,2,3 区组合共64组,计算每个像素点属于哪个区.
*
* @param bitmap
* the bitmap
* @return the color histogram
*/
public static int[] getColorHistogram(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
// 区颜色分布
int[] areaColor = new int[64];
// 获取色彩数组。
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int pixels = bitmap.getPixel(i, j);
int alpha = (pixels >> 24) & 0xFF;
int red = (pixels >> 16) & 0xFF;
int green = (pixels >> 8) & 0xFF;
int blue = (pixels) & 0xFF;
int redArea = 0;
int greenArea = 0;
int blueArea = 0;
// 0-63 64-127 128-191 192-255
if (red >= 192) {
redArea = 3;
} else if (red >= 128) {
redArea = 2;
} else if (red >= 64) {
redArea = 1;
} else if (red >= 0) {
redArea = 0;
}
if (green >= 192) {
greenArea = 3;
} else if (green >= 128) {
greenArea = 2;
} else if (green >= 64) {
greenArea = 1;
} else if (green >= 0) {
greenArea = 0;
}
if (blue >= 192) {
blueArea = 3;
} else if (blue >= 128) {
blueArea = 2;
} else if (blue >= 64) {
blueArea = 1;
} else if (blue >= 0) {
blueArea = 0;
}
int index = redArea * 16 + greenArea * 4 + blueArea;
// 加入
areaColor[index] += 1;
}
}
return areaColor;
}
/**
* 计算"汉明距离"(Hamming distance)。
* 如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。.
*
* @param sourceHashCode
* 源hashCode
* @param hashCode
* 与之比较的hashCode
* @return the int
*/
public static int hammingDistance(String sourceHashCode, String hashCode) {
int difference = 0;
int len = sourceHashCode.length();
for (int i = 0; i < len; i++) {
if (sourceHashCode.charAt(i) != hashCode.charAt(i)) {
difference++;
}
}
return difference;
}
/**
* 灰度值计算.
*
* @param pixels
* 像素
* @return int 灰度值
*/
private static int rgbToGray(int pixels) {
// int _alpha = (pixels >> 24) & 0xFF;
int _red = (pixels >> 16) & 0xFF;
int _green = (pixels >> 8) & 0xFF;
int _blue = (pixels) & 0xFF;
return (int) (0.3 * _red + 0.59 * _green + 0.11 * _blue);
}
/**
* 找到最合适的SampleSize
* @param width
* @param height
* @param desiredWidth
* @param desiredHeight
* @return
*/
private static int findBestSampleSize(int width, int height, int desiredWidth, int desiredHeight) {
double wr = (double) width / desiredWidth;
double hr = (double) height / desiredHeight;
double ratio = Math.min(wr, hr);
float n = 1.0f;
while ((n * 2) <= ratio) {
n *= 2;
}
return (int) n;
}
/**
*
* 将yuv格式转换成灰度bitmap.
* @param yuvData
* @param width
* @param height
* @return
*/
public Bitmap yuv2GrayBitmap(byte[] yuvData, int width, int height) {
int[] pixels = new int[width * height];
byte[] yuv = yuvData;
int inputOffset = 0;
for (int y = 0; y < height; y++) {
int outputOffset = y * width;
for (int x = 0; x < width; x++) {
int grey = yuv[inputOffset + x] & 0xff;
pixels[outputOffset + x] = 0xFF000000 | (grey * 0x00010101);
}
inputOffset += width;
}
Bitmap bitmap = Bitmap.createBitmap(width, height,Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
/**
* 将yuv格式转换成bitmap
* ImageFormat.NV21 || format == ImageFormat.YUY2
* @param yuv
* @param width
* @param height
* @return RGB565 format bitmap
*/
public static Bitmap yuv2Bitmap(byte[] data, int width, int height) {
final YuvImage image = new YuvImage(data, ImageFormat.NV21, width, height, null);
ByteArrayOutputStream os = new ByteArrayOutputStream(data.length);
if(!image.compressToJpeg(new Rect(0, 0, width, height), 100, os)){
return null;
}
byte[] tmp = os.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(tmp, 0,tmp.length);
return bitmap;
}
/**
*
* TODO
* ImageFormat.NV21 || format == ImageFormat.YUY2.
* @param data
* @param width
* @param height
* @param rect
* @return
*/
public static Bitmap cropYuv2Bitmap(byte []data, int width, int height, Rect rect){
int w = rect.width();
int h = rect.height();
int frameSize = width*height;
int []pixels = new int [w*h];
byte []yuv = data;
int yOffset = rect.top*width + rect.left;
int uvOffset = (rect.top/2)*width + (rect.left/2)*2 + frameSize;
int y, u, v, k;
for(int i = 0; i < h; ++i){
int outputOffset = i*w;
for(int j = 0; j < w; ++j){
y = (0xff & yuv[yOffset+j])-16;
k = ((j>>1)<<1);
v = (0xff & yuv[uvOffset+k])-128;
u = (0xff & yuv[uvOffset+k+1])-128;
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0) r = 0; else if (r > 262143) r = 262143;
if (g < 0) g = 0; else if (g > 262143) g = 262143;
if (b < 0) b = 0; else if (b > 262143) b = 262143;
pixels[outputOffset+j] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
}
yOffset += width;
if(((rect.top+i) & 1) == 1){ uvOffset+= width; }
}
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
return bitmap;
}
/**
* 保存yuv为文件.
* @param data the data
* @param width the width
* @param height the height
* @return the string
*/
public static String savetoJPEG(byte[] data, int width, int height,String file) {
Rect frame = new Rect(0, 0, width, height);
YuvImage img = new YuvImage(data, ImageFormat.NV21, width, height, null);
OutputStream os = null;
File jpgfile = new File(file);
try {
os = new FileOutputStream(jpgfile);
img.compressToJpeg(frame, 100, os);
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
return jpgfile.getPath();
}
/**
* The main method.
*
* @param args
* the arguments
*/
public static void main(String[] args) {
// System.out.println(getHashCode(""));
}
}