package com.csq.thesceneryalong.utils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.util.List;
import com.csq.thesceneryalong.R;
import com.csq.thesceneryalong.app.App;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
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.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.Log;
public class BitmapUtil {
// ***************************** 计算图片缩小倍数 *******************************
private static int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels, int orientation) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels, orientation);
int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}
return roundedSize;
}
private static int computeInitialSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels, int orientation) {
double w, h;
if (orientation == 0 || orientation == 180) {
w = options.outWidth;
h = options.outHeight;
} else {
w = options.outHeight;
h = options.outWidth;
}
int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
Math.floor(w / minSideLength), Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
return lowerBound;
}
if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}
// ***************************** 加载图片 *******************************
/**
* 从uri加载图片 Try to load a {@link Bitmap} from the passed {@link Uri} ( a
* file, a content or an url )
*
* @param uri
* the image source
* @param minSideLength
* @param maxNumOfPixels
* @return null if load was unsuccesful
*/
public static Bitmap decodeBitmapFromUri(Context context, Uri uri, int minSideLength,
int maxNumOfPixels) {
InputStream stream = openInputStream(context,
uri);
if (null == stream) {
return null;
}
int orientation = ExifUtils.getExifOrientation(
context, uri);
Bitmap bitmap = null;
final BitmapFactory.Options decoded = decodeImageBounds(stream);
IOUtils.closeSilently(stream);
if (decoded != null) {
int sampleSize;
if (minSideLength < 0 || maxNumOfPixels < 0) {
sampleSize = 1;
} else {
sampleSize = computeSampleSize(decoded, minSideLength,
maxNumOfPixels, orientation);
}
BitmapFactory.Options options = getDefaultOptions();
options.inSampleSize = sampleSize;
bitmap = decodeBitmapFromUri(context, uri, options, minSideLength,
maxNumOfPixels, orientation, 0);
}
return bitmap;
}
private static Bitmap decodeBitmapFromUri(Context context, Uri uri,
BitmapFactory.Options options, int minSideLength,
int maxNumOfPixels, int orientation, int loadTimes) {
Bitmap bitmap = null;
Bitmap newBitmap = null;
if (loadTimes > 16) {
return null;
}
InputStream stream = openInputStream(context,
uri);
if (null == stream)
return null;
try {
// decode the bitmap via android BitmapFactory
bitmap = BitmapFactory.decodeStream(stream, null, options);
IOUtils.closeSilently(stream);
if (bitmap != null) {
if (minSideLength > 0 && maxNumOfPixels > 0) {
newBitmap = rotateBitmap(bitmap, orientation);
if (bitmap != newBitmap) {
bitmap.recycle();
}
bitmap = newBitmap;
}
}
} catch (OutOfMemoryError error) {
IOUtils.closeSilently(stream);
if (null != bitmap) {
bitmap.recycle();
}
options.inSampleSize += 1;
bitmap = decodeBitmapFromUri(context, uri, options, minSideLength,
maxNumOfPixels, orientation, loadTimes + 1);
}
return bitmap;
}
/**
* 从文件路径加载图片
*
* @param imageFile 图片文件路径
* @param minSideLength 最小边长
* @param maxNumOfPixels 最多像素点数
*/
public static Bitmap decodeBitmapFromFile(Context context, String imageFile,
int minSideLength, int maxNumOfPixels) {
return decodeBitmapFromUri(context, Uri.fromFile(new File(imageFile)),
minSideLength, maxNumOfPixels);
}
/**
* 通过资源路径加载图片
*
* @param context
* @param imageResId
* @param minSideLength
* @param maxNumOfPixels
* @return
*/
public static Bitmap decodeResource(Context context, int imageResId,
int minSideLength, int maxNumOfPixels) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(context.getResources(), imageResId, opts);
opts.inSampleSize = computeSampleSize(opts, minSideLength,
maxNumOfPixels, 0);
// 这里一定要将其设置回false,因为之前我们将其设置成了true
opts.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(context.getResources(), imageResId,
opts);
}
// ***************************** 图片处理 *******************************
/**
* 获得圆角图片
*
* @param bitmap
* @param roundPx
* @return
*/
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 Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
/**
* 旋转图片
*
* @param bmp
* @param rotation 旋转角度
* @return
*/
public static Bitmap rotateBitmap(Bitmap bmp, float rotation) {
if (rotation == 0) {
return bmp;
}
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
return Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(),
matrix, true);
}
/**
* 将图片变为灰度图
*
* @param old
* @return
*/
public static Bitmap getGreyImage(Bitmap old)
{
int width, height;
height = old.getHeight();
width = old.getWidth();
Bitmap n = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(old.copy(Bitmap.Config.ARGB_8888, true));
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(n, 0, 0, paint);
return n;
}
/**
* 缩放图片大小
*
* @param bitmap
* @param width
* @param height
* @return
*/
public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height)
{
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
matrix.postScale((float) width / w, (float) height / h);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
}
/**
* 获得带倒影的图片
*
* @param bitmap
* @return
*/
public static Bitmap getReflectionImageWithOrigin(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 defaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);
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);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
return bitmapWithReflection;
}
/**
* 适配缩放图片大小
*
* @param bitmap
* @param width
* @param height
* @return
*/
public static Bitmap zoomAdjustBitmap(Bitmap bitmap, int width, int height)
{
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int sw = w > width ? width : w;
int sh = h > height ? height : h;
if (w * h > width * height)
{
sw = width;
sh = height;
}
Matrix matrix = new Matrix();
matrix.postScale((float) sw / w, (float) sh / h);
return Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
}
/**
* 压缩图片
* @param fromFile
* @param toFile
* @param width
* @param height
* @param quality
* @return
*/
public static boolean transImage(String fromFile,String toFile,int width,int height,int quality){
Bitmap bitmap = null;
Bitmap resizeBitmap = null;
FileOutputStream out = null;
try
{
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fromFile, opts);
if(opts.outWidth * opts.outHeight < width * height)
{
// 指定太大无法压缩,原图返回
return false;
}
bitmap = BitmapFactory.decodeFile(fromFile);
resizeBitmap = zoomAdjustBitmap(bitmap,width,height);
//saveFile
File mycaptureFile = new File(toFile);
out = new FileOutputStream(mycaptureFile);
if (resizeBitmap.compress(Bitmap.CompressFormat.JPEG, quality, out))
{
out.flush();
}
return true;
}catch (Exception e)
{
e.printStackTrace();
}finally
{
if (bitmap != null && !bitmap.isRecycled())
{
// 记得释放资源,否则会内存溢出
bitmap.recycle();
bitmap = null;
}
if (resizeBitmap != null && !resizeBitmap.isRecycled())
{
resizeBitmap.recycle();
resizeBitmap = null;
}
if(out != null)
{
try
{
out.close();
out = null;
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return false;
}
/**
* 上下拼接2个图片 bitmaps 要拼接的图片
*/
public static Bitmap spliceBitmapVertical(List<Bitmap> bitmaps,
int backgroundColor) {
if (bitmaps == null || bitmaps.isEmpty()) {
return null;
}
int newWidth = 0;
int newHeight = 0;
for (Bitmap b : bitmaps) {
if (b != null) {
if (newWidth < b.getWidth()) {
newWidth = b.getWidth();
}
newHeight += b.getHeight();
}
}
if (newWidth == 0 || newHeight == 0) {
return null;
}
Bitmap result = Bitmap.createBitmap(newWidth, newHeight,
Config.ARGB_8888);
Canvas canvas = new Canvas(result);
canvas.drawColor(backgroundColor);
int y = 0;
for (Bitmap b : bitmaps) {
if (b != null) {
canvas.drawBitmap(b, 0, y, null);
y += b.getHeight();
}
}
return result;
}
private static Bitmap bMark;
/**
* @description: 给图片添加视频水印
* @author: chenshiqiang E-mail:csqwyyx@163.com
* @param bitmap
*/
public static Bitmap addVideoWatermark(Bitmap bitmap){
if(bitmap != null){
Bitmap dest = bitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas c = new Canvas(dest);
int markSize = (int) (0.4f * Math.min(bitmap.getWidth(), bitmap.getHeight()));
if(markSize > 150){
markSize = 150;
}
if(bMark == null){
bMark = BitmapFactory.decodeResource(App.getResources(),
R.drawable.ic_scenery_type_video);
}
c.drawBitmap(bMark,
new Rect(0, 0, bMark.getWidth(), bMark.getHeight()),
new Rect((bitmap.getWidth() - markSize)/2,
(bitmap.getHeight() - markSize)/2,
(bitmap.getWidth() + markSize)/2,
(bitmap.getHeight() + markSize)/2),
new Paint());
return dest;
}
return null;
}
// ***************************** 图片保存 *******************************
/**
* 保存图片
*
* @param bm
* @param savePath
* @param format
* @param quality
* @return
*/
public static final boolean saveBitmap(Bitmap bm, String savePath,
CompressFormat format, int quality) {
BufferedOutputStream bos = null;
try {
File cf = new File(savePath);
bos = new BufferedOutputStream(new FileOutputStream(cf));
bm.compress(format, quality, bos);
bos.flush();
return true;
} catch (Exception e) {
// TODO: handle exception
Log.e("", "saveBitmap ===== " + e.toString());
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return false;
}
// ***************************** 获取图片信息 *******************************
/**
* 获取图片长宽等信息
*
* @param stream
* @return
*/
public static BitmapFactory.Options decodeImageBounds(
final InputStream stream) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(stream, null, options);
if (options.outHeight > 0 && options.outWidth > 0) {
return options;
}
return null;
}
static BitmapFactory.Options getDefaultOptions() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inDither = false;
options.inJustDecodeBounds = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
return options;
}
// ***************************** 文件流 *******************************
/**
* Return an {@link InputStream} from the given uri. ( can be a local
* content, a file path or an http url )
*
* @param context
* @param uri
* @return the {@link InputStream} from the given uri, null if uri cannot be
* opened
*/
public static InputStream openInputStream(Context context, Uri uri) {
if (null == uri)
return null;
final String scheme = uri.getScheme();
InputStream stream = null;
if (scheme == null || ContentResolver.SCHEME_FILE.equals(scheme)) {
// from file
stream = openFileInputStream(uri.getPath());
} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
// from content
stream = openContentInputStream(context, uri);
} else if ("http".equals(scheme) || "https".equals(scheme)) {
// from remote uri
stream = openRemoteInputStream(uri);
}
return stream;
}
/**
* Return a {@link FileInputStream} from the given path or null if file not
* found
*
* @param path
* the file path
* @return the {@link FileInputStream} of the given path, null if
* {@link FileNotFoundException} is thrown
*/
static InputStream openFileInputStream(String path) {
try {
return new FileInputStream(path);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* Return a {@link BufferedInputStream} from the given uri or null if an
* exception is thrown
*
* @param context
* @param uri
* @return the {@link InputStream} of the given path. null if file is not
* found
*/
static InputStream openContentInputStream(Context context, Uri uri) {
try {
return context.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* Return an {@link InputStream} from the given url or null if failed to
* retrieve the content
*
* @param uri
* @return
*/
public static InputStream openRemoteInputStream(Uri uri) {
java.net.URL finalUrl;
try {
finalUrl = new java.net.URL(uri.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
HttpURLConnection connection;
try {
connection = (HttpURLConnection) finalUrl.openConnection();
} catch (IOException e) {
e.printStackTrace();
return null;
}
connection.setInstanceFollowRedirects(false);
int code;
try {
code = connection.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
return null;
}
// permanent redirection
if (code == HttpURLConnection.HTTP_MOVED_PERM
|| code == HttpURLConnection.HTTP_MOVED_TEMP
|| code == HttpURLConnection.HTTP_SEE_OTHER) {
String newLocation = connection.getHeaderField("Location");
return openRemoteInputStream(Uri.parse(newLocation));
}
try {
return (InputStream) finalUrl.getContent();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// ***************************** 转换 *******************************
public static final Bitmap getFromDrawable(Drawable d) {
if (d instanceof BitmapDrawable) {
return ((BitmapDrawable) d).getBitmap();
}
return null;
}
/**
* 将Drawable转化为Bitmap
*
* @param drawable
* @return
*/
public static Bitmap drawableToBitmap(Drawable drawable)
{
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, drawable
.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);
return bitmap;
}
public static final Drawable toDrawable(Context context, Bitmap b) {
BitmapDrawable bitmapDrawable = new BitmapDrawable(
context.getResources(), b);
return (Drawable) bitmapDrawable;
}
}