Bitmap 工具类主要包括获取 Bitmap 和对Bitmap的操作,此工具类不是网上大家用烂的那一份,是博主亲自编写,亲自测试,代码简洁清晰,可满足日常开发。
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PixelFormat;
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.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.util.Log;
import android.view.View;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
* Created on 2021/4/6 9:32
* Bitmap 工具类主要包括获取 Bitmap 和对Bitmap的操作
* @author Gong Youqiang
*/
public class BitmapUtil {
private static final boolean DEBUG = false;
private static final String TAG = BitmapUtil.class.getSimpleName();
/**
* Don't let anyone instantiate this class.
*/
private BitmapUtil() {
throw new Error("Do not need instantiate!");
}
/**
* 图片压缩处理(使用Options的方法)
* <p/>
* <br>
* <b>说明</b> 使用方法:
* 首先你要将Options的inJustDecodeBounds属性设置为true,BitmapFactory.decode一次图片 。
* 然后将Options连同期望的宽度和高度一起传递到到本方法中。
* 之后再使用本方法的返回值做参数调用BitmapFactory.decode创建图片。
* <p/>
* <br>
* <b>说明</b> BitmapFactory创建bitmap会尝试为已经构建的bitmap分配内存
* ,这时就会很容易导致OOM出现。为此每一种创建方法都提供了一个可选的Options参数
* ,将这个参数的inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存
* ,返回值也不再是一个Bitmap对象, 而是null。虽然Bitmap是null了,但是Options的outWidth、
* outHeight和outMimeType属性都会被赋值。
*
* @param reqWidth 目标宽度,这里的宽高只是阀值,实际显示的图片将小于等于这个值
* @param reqHeight 目标高度,这里的宽高只是阀值,实际显示的图片将小于等于这个值
*/
public static BitmapFactory.Options calculateInSampleSize(
final BitmapFactory.Options options, final int reqWidth,
final int reqHeight) {
// 源图片的高度和宽度
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > 400 || width > 450) {
if (height > reqHeight || width > reqWidth) {
// 计算出实际宽高和目标宽高的比率
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width
/ (float) reqWidth);
// 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
// 一定都会大于等于目标的宽和高。
inSampleSize = heightRatio < widthRatio ? heightRatio
: widthRatio;
}
}
// 设置压缩比例
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
return options;
}
/**
* 获取一个指定大小的bitmap
*
* @param res Resources
* @param resId 图片ID
* @param reqWidth 目标宽度
* @param reqHeight 目标高度
*/
public static Bitmap getBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// BitmapFactory.Options options = new BitmapFactory.Options();
// options.inJustDecodeBounds = true;
// BitmapFactory.decodeResource(res, resId, options);
// options = BitmapHelper.calculateInSampleSize(options, reqWidth,
// reqHeight);
// return BitmapFactory.decodeResource(res, resId, options);
// 通过JNI的形式读取本地图片达到节省内存的目的
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Config.RGB_565;
options.inPurgeable = true;
options.inInputShareable = true;
InputStream is = res.openRawResource(resId);
return getBitmapFromStream(is, null, reqWidth, reqHeight);
}
/**
* 获取一个指定大小的bitmap
*
* @param reqWidth 目标宽度
* @param reqHeight 目标高度
*/
public static Bitmap getBitmapFromFile(String pathName, int reqWidth,
int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
options = calculateInSampleSize(options, reqWidth, reqHeight);
return BitmapFactory.decodeFile(pathName, options);
}
/**
* 获取一个指定大小的bitmap
*
* @param data Bitmap的byte数组
* @param offset image从byte数组创建的起始位置
* @param length the number of bytes, 从offset处开始的长度
* @param reqWidth 目标宽度
* @param reqHeight 目标高度
*/
public static Bitmap getBitmapFromByteArray(byte[] data, int offset,
int length, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, offset, length, options);
options = calculateInSampleSize(options, reqWidth, reqHeight);
return BitmapFactory.decodeByteArray(data, offset, length, options);
}
/**
* 把bitmap转化为bytes
*
* @param bitmap 源Bitmap
* @return Byte数组
*/
public static byte[] getBytesFromBitmap(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
/**
* Stream转换成Byte
*
* @param inputStream InputStream
* @return Byte数组
*/
public static byte[] getBytesFromStream(InputStream inputStream) {
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int len;
try {
while ((len = inputStream.read(buffer)) >= 0) {
os.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
return os.toByteArray();
}
/**
* 获取一个指定大小的bitmap
*
* @param b Byte数组
* @return 需要的Bitmap
*/
public static Bitmap getBitmapFromBytes(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
/**
* 获取一个指定大小的bitmap
*
* @param is 从输入流中读取Bitmap
* @param outPadding If not null, return the padding rect for the bitmap if it
* exists, otherwise set padding to [-1,-1,-1,-1]. If no bitmap
* is returned (null) then padding is unchanged.
* @param reqWidth 目标宽度
* @param reqHeight 目标高度
*/
public static Bitmap getBitmapFromStream(InputStream is, Rect outPadding,
int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, outPadding, options);
options = calculateInSampleSize(options, reqWidth, reqHeight);
return BitmapFactory.decodeStream(is, outPadding, options);
}
/**
* 从View获取Bitmap
*
* @param view View
* @return Bitmap
*/
public static Bitmap getBitmapFromView(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.layout(view.getLeft(), view.getTop(), view.getRight(),
view.getBottom());
view.draw(canvas);
return bitmap;
}
/**
* 把一个View的对象转换成bitmap
*
* @param view View
* @return Bitmap
*/
public static Bitmap getBitmapFromView2(View view) {
view.clearFocus();
view.setPressed(false);
// 能画缓存就返回false
boolean willNotCache = view.willNotCacheDrawing();
view.setWillNotCacheDrawing(false);
int color = view.getDrawingCacheBackgroundColor();
view.setDrawingCacheBackgroundColor(0);
if (color != 0) {
view.destroyDrawingCache();
}
view.buildDrawingCache();
Bitmap cacheBitmap = view.getDrawingCache();
if (cacheBitmap == null) {
if (DEBUG) {
Log.e(TAG, "failed getViewBitmap(" + view + ")",
new RuntimeException());
}
return null;
}
Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
// Restore the view
view.destroyDrawingCache();
view.setWillNotCacheDrawing(willNotCache);
view.setDrawingCacheBackgroundColor(color);
return bitmap;
}
/**
* 将Drawable转化为Bitmap
*
* @param drawable Drawable
* @return Bitmap
*/
public static Bitmap getBitmapFromDrawable(Drawable drawable) {
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, drawable
.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
: Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);
return bitmap;
}
/**
* 合并Bitmap
* @param bgd 背景Bitmap
* @param fg 前景Bitmap
* @return 合成后的Bitmap
*/
public static Bitmap combineImages(Bitmap bgd, Bitmap fg) {
Bitmap bmp;
int width = bgd.getWidth() > fg.getWidth() ? bgd.getWidth() : fg
.getWidth();
int height = bgd.getHeight() > fg.getHeight() ? bgd.getHeight() : fg
.getHeight();
bmp = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));
Canvas canvas = new Canvas(bmp);
canvas.drawBitmap(bgd, 0, 0, null);
canvas.drawBitmap(fg, 0, 0, paint);
return bmp;
}
/**
* 合并
* @param bgd 后景Bitmap
* @param fg 前景Bitmap
* @return 合成后Bitmap
*/
public static Bitmap combineImagesToSameSize(Bitmap bgd, Bitmap fg) {
Bitmap bmp;
int width = bgd.getWidth() < fg.getWidth() ? bgd.getWidth() : fg
.getWidth();
int height = bgd.getHeight() < fg.getHeight() ? bgd.getHeight() : fg
.getHeight();
if (fg.getWidth() != width && fg.getHeight() != height) {
fg = zoom(fg, width, height);
}
if (bgd.getWidth() != width && bgd.getHeight() != height) {
bgd = zoom(bgd, width, height);
}
bmp = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));
Canvas canvas = new Canvas(bmp);
canvas.drawBitmap(bgd, 0, 0, null);
canvas.drawBitmap(fg, 0, 0, paint);
return bmp;
}
/**
* 放大缩小图片
*
* @param bitmap 源Bitmap
* @param w 宽
* @param h 高
* @return 目标Bitmap
*/
public static Bitmap zoom(Bitmap bitmap, int w, int h) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Matrix matrix = new Matrix();
float scaleWidht = ((float) w / width);
float scaleHeight = ((float) h / height);
matrix.postScale(scaleWidht, scaleHeight);
Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height,
matrix, true);
return newbmp;
}
/**
* 获得圆角图片的方法
*
* @param bitmap 源Bitmap
* @param roundPx 圆角大小
* @return 期望Bitmap
*/
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
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, rect, rect, paint);
return output;
}
/**
* 获得带倒影的图片方法
*
* @param bitmap 源Bitmap
* @return 带倒影的Bitmap
*/
public static Bitmap createReflectionBitmap(Bitmap bitmap) {
final int reflectionGap = 4;
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2,
width, height / 2, matrix, false);
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
(height + height / 2), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmapWithReflection);
canvas.drawBitmap(bitmap, 0, 0, null);
Paint deafalutPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, deafalutPaint);
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff,
0x00ffffff, TileMode.CLAMP);
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);
return bitmapWithReflection;
}
/**
* 压缩图片大小
*
* @param image 源Bitmap
* @return 压缩后的Bitmap
*/
public static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
options -= 10;// 每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
return bitmap;
}
/**
* 将彩色图转换为灰度图
*
* @param img 源Bitmap
* @return 返回转换好的位图
*/
public static Bitmap convertGreyImg(Bitmap img) {
int width = img.getWidth(); // 获取位图的宽
int height = img.getHeight(); // 获取位图的高
int[] pixels = new int[width * height]; // 通过位图的大小创建像素点数组
img.getPixels(pixels, 0, width, 0, 0, width, height);
int alpha = 0xFF << 24;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int grey = pixels[width * i + j];
int red = ((grey & 0x00FF0000) >> 16);
int green = ((grey & 0x0000FF00) >> 8);
int blue = (grey & 0x000000FF);
grey = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11);
grey = alpha | (grey << 16) | (grey << 8) | grey;
pixels[width * i + j] = grey;
}
}
Bitmap result = Bitmap.createBitmap(width, height, Config.RGB_565);
result.setPixels(pixels, 0, width, 0, 0, width, height);
return result;
}
/**
* 转换图片成圆形
*
* @param bitmap 传入Bitmap对象
* @return 圆形Bitmap
*/
public static Bitmap getRoundBitmap(Bitmap bitmap) {
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;
}
/**
* Returns a Bitmap representing the thumbnail of the specified Bitmap. The
* size of the thumbnail is defined by the dimension
* android.R.dimen.launcher_application_icon_size.
* <p/>
* This method is not thread-safe and should be invoked on the UI thread
* only.
*
* @param bitmap The bitmap to get a thumbnail of.
* @param context The application's context.
* @return A thumbnail for the specified bitmap or the bitmap itself if the
* thumbnail could not be created.
*/
public static Bitmap createThumbnailBitmap(Bitmap bitmap, Context context) {
int sIconWidth = -1;
int sIconHeight = -1;
final Resources resources = context.getResources();
sIconWidth = sIconHeight = (int) resources
.getDimension(android.R.dimen.app_icon_size);
final Paint sPaint = new Paint();
final Rect sBounds = new Rect();
final Rect sOldBounds = new Rect();
Canvas sCanvas = new Canvas();
int width = sIconWidth;
int height = sIconHeight;
sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
Paint.FILTER_BITMAP_FLAG));
final int bitmapWidth = bitmap.getWidth();
final int bitmapHeight = bitmap.getHeight();
if (width > 0 && height > 0) {
if (width < bitmapWidth || height < bitmapHeight) {
final float ratio = (float) bitmapWidth / bitmapHeight;
if (bitmapWidth > bitmapHeight) {
height = (int) (width / ratio);
} else if (bitmapHeight > bitmapWidth) {
width = (int) (height * ratio);
}
final Config c = (width == sIconWidth && height == sIconHeight) ? bitmap
.getConfig() : Config.ARGB_8888;
final Bitmap thumb = Bitmap.createBitmap(sIconWidth,
sIconHeight, c);
final Canvas canvas = sCanvas;
final Paint paint = sPaint;
canvas.setBitmap(thumb);
paint.setDither(false);
paint.setFilterBitmap(true);
sBounds.set((sIconWidth - width) / 2,
(sIconHeight - height) / 2, width, height);
sOldBounds.set(0, 0, bitmapWidth, bitmapHeight);
canvas.drawBitmap(bitmap, sOldBounds, sBounds, paint);
return thumb;
} else if (bitmapWidth < width || bitmapHeight < height) {
final Config c = Config.ARGB_8888;
final Bitmap thumb = Bitmap.createBitmap(sIconWidth,
sIconHeight, c);
final Canvas canvas = sCanvas;
final Paint paint = sPaint;
canvas.setBitmap(thumb);
paint.setDither(false);
paint.setFilterBitmap(true);
canvas.drawBitmap(bitmap, (sIconWidth - bitmapWidth) / 2,
(sIconHeight - bitmapHeight) / 2, paint);
return thumb;
}
}
return bitmap;
}
/**
* 生成水印图片 水印在右下角
*
* @param src the bitmap object you want proecss
* @param watermark the water mark above the src
* @return return a bitmap object ,if paramter's length is 0,return null
*/
public static Bitmap createWatermarkBitmap(Bitmap src, Bitmap watermark) {
if (src == null) {
return null;
}
int w = src.getWidth();
int h = src.getHeight();
int ww = watermark.getWidth();
int wh = watermark.getHeight();
// create the new blank bitmap
Bitmap newb = Bitmap.createBitmap(w, h, Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
Canvas cv = new Canvas(newb);
// draw src into
cv.drawBitmap(src, 0, 0, null);// 在 0,0坐标开始画入src
// draw watermark into
cv.drawBitmap(watermark, w - ww + 5, h - wh + 5, null);// 在src的右下角画入水印
// save all clip
cv.save();// 保存
// store
cv.restore();// 存储
return newb;
}
/**
* 重新编码Bitmap
*
* @param src 需要重新编码的Bitmap
* @param format 编码后的格式(目前只支持png和jpeg这两种格式)
* @param quality 重新生成后的bitmap的质量
* @return 返回重新生成后的bitmap
*/
public static Bitmap codec(Bitmap src, Bitmap.CompressFormat format,
int quality) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
src.compress(format, quality, os);
byte[] array = os.toByteArray();
return BitmapFactory.decodeByteArray(array, 0, array.length);
}
/**
* 图片压缩方法:(使用compress的方法)
* <p/>
* <br>
* <b>说明</b> 如果bitmap本身的大小小于maxSize,则不作处理
*
* @param bitmap 要压缩的图片
* @param maxSize 压缩后的大小,单位kb
*/
public static void compress(Bitmap bitmap, double maxSize) {
// 将bitmap放至数组中,意在获得bitmap的大小(与实际读取的原文件要大)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 格式、质量、输出流
bitmap.compress(Bitmap.CompressFormat.PNG, 70, baos);
byte[] b = baos.toByteArray();
// 将字节换成KB
double mid = b.length / 1024;
// 获取bitmap大小 是允许最大大小的多少倍
double i = mid / maxSize;
// 判断bitmap占用空间是否大于允许最大空间 如果大于则压缩 小于则不压缩
if (i > 1) {
// 缩放图片 此处用到平方根 将宽带和高度压缩掉对应的平方根倍
// (保持宽高不变,缩放后也达到了最大占用空间的大小)
bitmap = scale(bitmap, bitmap.getWidth() / Math.sqrt(i),
bitmap.getHeight() / Math.sqrt(i));
}
}
/**
* 图片的缩放方法
*
* @param src :源图片资源
* @param newWidth :缩放后宽度
* @param newHeight :缩放后高度
*/
public static Bitmap scale(Bitmap src, double newWidth, double newHeight) {
// 记录src的宽高
float width = src.getWidth();
float height = src.getHeight();
// 创建一个matrix容器
Matrix matrix = new Matrix();
// 计算缩放比例
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 开始缩放
matrix.postScale(scaleWidth, scaleHeight);
// 创建缩放后的图片
return Bitmap.createBitmap(src, 0, 0, (int) width, (int) height,
matrix, true);
}
/**
* 图片的缩放方法
*
* @param src :源图片资源
* @param scaleMatrix :缩放规则
*/
public static Bitmap scale(Bitmap src, Matrix scaleMatrix) {
return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(),
scaleMatrix, true);
}
/**
* 图片的缩放方法
*
* @param src :源图片资源
* @param scaleX :横向缩放比例
* @param scaleY :纵向缩放比例
*/
public static Bitmap scale(Bitmap src, float scaleX, float scaleY) {
Matrix matrix = new Matrix();
matrix.postScale(scaleX, scaleY);
return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(),
matrix, true);
}
/**
* 图片的缩放方法
*
* @param src :源图片资源
* @param scale :缩放比例
*/
public static Bitmap scale(Bitmap src, float scale) {
return scale(src, scale, scale);
}
/**
* 旋转图片
*
* @param angle 旋转角度
* @param bitmap 要旋转的图片
* @return 旋转后的图片
*/
public static Bitmap rotate(Bitmap bitmap, int angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
}
/**
* 水平翻转处理
*
* @param bitmap 原图
* @return 水平翻转后的图片
*/
public static Bitmap reverseByHorizontal(Bitmap bitmap) {
Matrix matrix = new Matrix();
matrix.preScale(-1, 1);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, false);
}
/**
* 垂直翻转处理
*
* @param bitmap 原图
* @return 垂直翻转后的图片
*/
public static Bitmap reverseByVertical(Bitmap bitmap) {
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, false);
}
/**
* 更改图片色系,变亮或变暗
*
* @param delta 图片的亮暗程度值,越小图片会越亮,取值范围(0,24)
* @return
*/
public static Bitmap adjustTone(Bitmap src, int delta) {
if (delta >= 24 || delta <= 0) {
return null;
}
// 设置高斯矩阵
int[] gauss = new int[]{1, 2, 1, 2, 4, 2, 1, 2, 1};
int width = src.getWidth();
int height = src.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height,
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;
int[] pixels = new int[width * height];
src.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 += (pixR * gauss[idx]);
newG += (pixG * gauss[idx]);
newB += (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);
return bitmap;
}
/**
* 将彩色图转换为黑白图
*
* @param bmp 位图
* @return 返回转换好的位图
*/
public static Bitmap convertToBlackWhite(Bitmap bmp) {
int width = bmp.getWidth();
int height = bmp.getHeight();
int[] pixels = new int[width * height];
bmp.getPixels(pixels, 0, width, 0, 0, width, height);
int alpha = 0xFF << 24; // 默认将bitmap当成24色图片
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int grey = pixels[width * i + j];
int red = ((grey & 0x00FF0000) >> 16);
int green = ((grey & 0x0000FF00) >> 8);
int blue = (grey & 0x000000FF);
grey = (int) (red * 0.3 + green * 0.59 + blue * 0.11);
grey = alpha | (grey << 16) | (grey << 8) | grey;
pixels[width * i + j] = grey;
}
}
Bitmap newBmp = Bitmap.createBitmap(width, height, Config.RGB_565);
newBmp.setPixels(pixels, 0, width, 0, 0, width, height);
return newBmp;
}
/**
* 读取图片属性:图片被旋转的角度
*
* @param path 图片绝对路径
* @return 旋转的角度
*/
public static int getImageDegree(String path) {
int degree = 0;
try {
ExifInterface exifInterface = new ExifInterface(path);
int orientation = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
/**
* Apply a blur to a Bitmap
*
* @param context Application context
* @param sentBitmap Bitmap to be converted
* @param radius Desired Radius, 0 < r < 25
* @return a copy of the image with a blur
*/
@SuppressLint("InlinedApi")
public static Bitmap blur(Context context, Bitmap sentBitmap, int radius) {
if (radius < 0) {
radius = 0;
if (DEBUG) {
}
} else if (radius > 25) {
radius = 25;
if (DEBUG) {
}
}
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;
}
// Stack Blur v1.0 from
// http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
//
// Java Author: Mario Klingemann <mario at quasimondo.com>
// http://incubator.quasimondo.com
// created Feburary 29, 2004
// Android port : Yahel Bouaziz <yahel at kayenko.com>
// http://www.kayenko.com
// ported april 5th, 2012
// This is a compromise between Gaussian Blur and Box blur
// It creates much better looking blurs than Box Blur, but is
// 7x faster than my Gaussian Blur implementation.
//
// I called it Stack Blur because this describes best how this
// filter works internally: it creates a kind of moving stack
// of colors whilst scanning through the image. Thereby it
// just has to add one new block of color to the right side
// of the stack and remove the leftmost color. The remaining
// colors on the topmost layer of the stack are either added on
// or reduced by one, depending on if they are on the right or
// on the left side of the stack.
//
// If you are using this algorithm in your code please add
// the following line:
//
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
if (radius < 1) {
return (null);
}
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int[] pix = new int[w * h];
Log.e("pix", w + " " + h + " " + pix.length);
bitmap.getPixels(pix, 0, w, 0, 0, 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;
}
}
Log.e("pix", w + " " + h + " " + pix.length);
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
return (bitmap);
}
/**
* 饱和度处理
*
* @param bitmap 原图
* @param saturationValue 新的饱和度值
* @return 改变了饱和度值之后的图片
*/
public static Bitmap saturation(Bitmap bitmap, int saturationValue) {
// 计算出符合要求的饱和度值
float newSaturationValue = saturationValue * 1.0F / 127;
// 创建一个颜色矩阵
ColorMatrix saturationColorMatrix = new ColorMatrix();
// 设置饱和度值
saturationColorMatrix.setSaturation(newSaturationValue);
// 创建一个画笔并设置其颜色过滤器
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(saturationColorMatrix));
// 创建一个新的图片并创建画布
Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
// 将原图使用给定的画笔画到画布上
canvas.drawBitmap(bitmap, 0, 0, paint);
return newBitmap;
}
/**
* 亮度处理
*
* @param bitmap 原图
* @param lumValue 新的亮度值
* @return 改变了亮度值之后的图片
*/
public static Bitmap lum(Bitmap bitmap, int lumValue) {
// 计算出符合要求的亮度值
float newlumValue = lumValue * 1.0F / 127;
// 创建一个颜色矩阵
ColorMatrix lumColorMatrix = new ColorMatrix();
// 设置亮度值
lumColorMatrix.setScale(newlumValue, newlumValue, newlumValue, 1);
// 创建一个画笔并设置其颜色过滤器
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(lumColorMatrix));
// 创建一个新的图片并创建画布
Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
// 将原图使用给定的画笔画到画布上
canvas.drawBitmap(bitmap, 0, 0, paint);
return newBitmap;
}
/**
* 色相处理
*
* @param bitmap 原图
* @param hueValue 新的色相值
* @return 改变了色相值之后的图片
*/
public static Bitmap hue(Bitmap bitmap, int hueValue) {
// 计算出符合要求的色相值
float newHueValue = (hueValue - 127) * 1.0F / 127 * 180;
// 创建一个颜色矩阵
ColorMatrix hueColorMatrix = new ColorMatrix();
// 控制让红色区在色轮上旋转的角度
hueColorMatrix.setRotate(0, newHueValue);
// 控制让绿红色区在色轮上旋转的角度
hueColorMatrix.setRotate(1, newHueValue);
// 控制让蓝色区在色轮上旋转的角度
hueColorMatrix.setRotate(2, newHueValue);
// 创建一个画笔并设置其颜色过滤器
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(hueColorMatrix));
// 创建一个新的图片并创建画布
Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
// 将原图使用给定的画笔画到画布上
canvas.drawBitmap(bitmap, 0, 0, paint);
return newBitmap;
}
/**
* 亮度、色相、饱和度处理
*
* @param bitmap 原图
* @param lumValue 亮度值
* @param hueValue 色相值
* @param saturationValue 饱和度值
* @return 亮度、色相、饱和度处理后的图片
*/
public static Bitmap lumAndHueAndSaturation(Bitmap bitmap, int lumValue,
int hueValue, int saturationValue) {
// 计算出符合要求的饱和度值
float newSaturationValue = saturationValue * 1.0F / 127;
// 计算出符合要求的亮度值
float newlumValue = lumValue * 1.0F / 127;
// 计算出符合要求的色相值
float newHueValue = (hueValue - 127) * 1.0F / 127 * 180;
// 创建一个颜色矩阵并设置其饱和度
ColorMatrix colorMatrix = new ColorMatrix();
// 设置饱和度值
colorMatrix.setSaturation(newSaturationValue);
// 设置亮度值
colorMatrix.setScale(newlumValue, newlumValue, newlumValue, 1);
// 控制让红色区在色轮上旋转的角度
colorMatrix.setRotate(0, newHueValue);
// 控制让绿红色区在色轮上旋转的角度
colorMatrix.setRotate(1, newHueValue);
// 控制让蓝色区在色轮上旋转的角度
colorMatrix.setRotate(2, newHueValue);
// 创建一个画笔并设置其颜色过滤器
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
// 创建一个新的图片并创建画布
Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
// 将原图使用给定的画笔画到画布上
canvas.drawBitmap(bitmap, 0, 0, paint);
return newBitmap;
}
/**
* 怀旧效果处理
*
* @param bitmap 原图
* @return 怀旧效果处理后的图片
*/
public static Bitmap nostalgic(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap newBitmap = Bitmap.createBitmap(width, height,
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];
bitmap.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;
}
}
newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return newBitmap;
}
/**
* 柔化效果处理
*
* @param bitmap 原图
* @return 柔化效果处理后的图片
*/
public static Bitmap soften(Bitmap bitmap) {
// 高斯矩阵
int[] gauss = new int[]{1, 2, 1, 2, 4, 2, 1, 2, 1};
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap newBitmap = Bitmap.createBitmap(width, height,
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];
bitmap.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;
}
}
newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return newBitmap;
}
/**
* 光照效果处理
*
* @param bitmap 原图
* @param centerX 光源在X轴的位置
* @param centerY 光源在Y轴的位置
* @return 光照效果处理后的图片
*/
public static Bitmap sunshine(Bitmap bitmap, int centerX, int centerY) {
final int width = bitmap.getWidth();
final int height = bitmap.getHeight();
Bitmap newBitmap = Bitmap.createBitmap(width, height,
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 radius = Math.min(centerX, centerY);
final float strength = 150F; // 光照强度 100~150
int[] pixels = new int[width * height];
bitmap.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);
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 + result;
newG = pixG + result;
newB = pixB + result;
}
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);
}
}
newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return newBitmap;
}
/**
* 底片效果处理
*
* @param bitmap 原图
* @return 底片效果处理后的图片
*/
public static Bitmap film(Bitmap bitmap) {
// RGBA的最大值
final int MAX_VALUE = 255;
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap newBitmap = Bitmap.createBitmap(width, height,
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];
bitmap.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);
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);
}
}
newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return newBitmap;
}
/**
* 锐化效果处理
*
* @param bitmap 原图
* @return 锐化效果处理后的图片
*/
public static Bitmap sharpen(Bitmap bitmap) {
// 拉普拉斯矩阵
int[] laplacian = new int[]{-1, -1, -1, -1, 9, -1, -1, -1, -1};
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap newBitmap = Bitmap.createBitmap(width, height,
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[] pixels = new int[width * height];
bitmap.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 + n) * width + k + m];
pixR = Color.red(pixColor);
pixG = Color.green(pixColor);
pixB = Color.blue(pixColor);
newR = newR + (int) (pixR * laplacian[idx] * alpha);
newG = newG + (int) (pixG * laplacian[idx] * alpha);
newB = newB + (int) (pixB * laplacian[idx] * alpha);
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));
pixels[i * width + k] = Color.argb(255, newR, newG, newB);
newR = 0;
newG = 0;
newB = 0;
}
}
newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return newBitmap;
}
/**
* 浮雕效果处理
*
* @param bitmap 原图
* @return 浮雕效果处理后的图片
*/
public static Bitmap emboss(Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
Bitmap newBitmap = Bitmap.createBitmap(width, height,
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];
bitmap.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);
}
}
newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return newBitmap;
}
/**
* 将YUV格式的图片的源数据从横屏模式转为竖屏模式,注意:将源图片的宽高互换一下就是新图片的宽高
*
* @param sourceData YUV格式的图片的源数据
* @param width 源图片的宽
* @param height 源图片的高
* @return
*/
public static final byte[] yuvLandscapeToPortrait(byte[] sourceData,
int width, int height) {
byte[] rotatedData = new byte[sourceData.length];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
rotatedData[x * height + height - y - 1] = sourceData[x + y
* width];
}
return rotatedData;
}
/**
* A safer decodeStream method
* rather than the one of {@link BitmapFactory}
* which will be easy to get OutOfMemory Exception
* while loading a big image file.
*
* @param uri 压缩相册返回的照片
* @return
* @throws FileNotFoundException
*/
public static Bitmap safeDecodeStream(Uri uri, int targetWidth, int targetHeight, Context mContext )
throws FileNotFoundException {
BitmapFactory.Options options = new BitmapFactory.Options();
android.content.ContentResolver resolver = mContext.getContentResolver();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(
new BufferedInputStream(resolver.openInputStream(uri), 16 * 1024), null, options);
// 得到图片的宽度、高度;
float imgWidth = options.outWidth;
float imgHeight = options.outHeight;
// 分别计算图片宽度、高度与目标宽度、高度的比例;取大于等于该比例的最小整数;
int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth);
int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight);
options.inSampleSize = 1;
if (widthRatio > 1 || widthRatio > 1) {
if (widthRatio > heightRatio) {
options.inSampleSize = widthRatio;
} else {
options.inSampleSize = heightRatio;
}
}
// 设置好缩放比例后,加载图片进内容;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeStream(new BufferedInputStream(resolver.openInputStream(uri), 16 * 1024), null, options);
}
}
网友评论