最近在做李宁的一个项目,要求特别高,所以今天记录一下自己遇到的难点,希望对初学者有用!本来想着用android系统图库的原来实现的,但是图片加密解密麻烦,图片也不让放本地。
流转换Bitmap的方法
public Bitmap doBitmapFile(InputStream in, boolean isFlag) {// isFlag是一个标志 true表示是大图 false小图
Bitmap bitmap = null;//
BitmapFactory.Options options = null;
ByteArrayOutputStream outStream = null;
final int BUFFER_SIZE = 2048;
if (in == null) {
return null;
}
try {
outStream = new ByteArrayOutputStream();
byte[] bytes = new byte[BUFFER_SIZE];
int len = -1;
while ((len = in.read(bytes)) != -1) {
outStream.write(bytes, 0, len);
outStream.flush();
}
byte[] data = new byte[outStream.toByteArray().length];
data = outStream.toByteArray();
options = new BitmapFactory.Options();
// 这里设置true的时候,decode时候Bitmap返回的为空, 将图片宽高读取放在Options里.
options.inJustDecodeBounds = true;
options.inTempStorage = new byte[16 * 1024];
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inInputShareable = true;
options.inPurgeable = true;
options.inDither = false;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
if (isFlag) {// 计算浏览单张图片的缩放比例值
int totalSize = 0;
int width = options.outWidth;
int height = options.outHeight;
totalSize = width * height * 4;//计算图片内存占用大小
if (totalSize < 13631488) {
options.inSampleSize = 1;
} else {
int maxNumOfPixels = 1280 * 1280 * 2;
options.inSampleSize = computeSampleSize(options, -1, maxNumOfPixels);
}
} else {// 计算浏览列表显示图片的缩放比例值
int maxNumOfPixels = MAX_RESOLUTION_A * MAX_RESOLUTION_B * 2;
options.inSampleSize = computeSampleSize(options, -1, maxNumOfPixels);
options.outWidth = options.outWidth / options.inSampleSize;
options.outHeight = options.outHeight / options.inSampleSize;
}
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
return watermarkBitmap(recycleBitmap(bitmap), "水印文字内容", Context, options);
} catch (OutOfMemoryError e) {
bitmap = null;
System.gc();
Log.e("Eeron", e.getMessage().toString());
e.printStackTrace();
return null;
} catch (Exception e) {
bitmap = null;
System.gc();
Log.e("Eeron", e.getMessage().toString());
return null;
} finally {
closeStream(in);
closeStream(outStream);
}
}
/**
* @Description: 关闭流
* @param stream
* @return: void
*/
private static void closeStream(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
Log.e("LiNing", "Could not close stream", e);
}
}
}
水印添加方法:
/**
* @Description: 添加水印
* @param bitmap
* @param title
* @param context
* @return
* @return: Bitmap
*/
public static Bitmap watermarkBitmap(Bitmap bitmap, String title, Context context, Options options) {
if (bitmap == null) {
return null;
}
Bitmap watermark = BitmapFactory.decodeResource(context.getResources(), R.drawable.add_water_mark, options);
int w = bitmap.getWidth();
int h = bitmap.getHeight();
// 需要处理图片太大造成的内存超过的问题,这里我的图片很小所以不写相应代码了
Bitmap newb = Bitmap.createBitmap(w, h, Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
Canvas cv = new Canvas(newb);
cv.drawBitmap(bitmap, 0, 0, null);// 在 0,0坐标开始画入src
// 加入图片
if (watermark != null) {
int ww = watermark.getWidth();
int wh = watermark.getHeight();
Rect src = new Rect();// 图片
Rect dst = new Rect();// 屏幕位置及尺寸
src.left = 0; // 0,0
src.top = 0;
src.right = w;// 是桌面图的宽度,
src.bottom = h;// 是桌面图的高度
// 下面的 dst 是表示 绘画这个图片的位置
dst.left = 0; // 绘图的起点X位置
dst.top = 0; // 相当于 桌面图片绘画起点的Y坐标
dst.right = ww + w - 60; // 表示需绘画的图片的右上角
dst.bottom = wh + h - 60; // 表示需绘画的图片的右下角
cv.drawBitmap(watermark, src, dst, null);// 在src的右下角画入水印
src = null;
dst = null;
}
// 加入文字
if (title != null) {
String familyName = "宋体";
Typeface font = Typeface.create(familyName, Typeface.BOLD);
TextPaint textPaint = new TextPaint();
textPaint.setColor(Color.RED);
textPaint.setTypeface(font);
textPaint.setTextSize(22);
textPaint.setAlpha(50);
cv.drawText(title, 40, h - 30, textPaint);
}
cv.save(Canvas.ALL_SAVE_FLAG);// 保存
cv.restore();// 存储
watermark.recycle();
bitmap.recycle();
return recycleBitmap(newb);
}
Bitmap内存释放方法:
public static Bitmap recycleBitmap(Bitmap bitmap) {
if (bitmap == null || bitmap.getConfig() != null) {
return bitmap;
}
Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false);
bitmap.recycle();
return newBitmap;
}
/**
* @Description:
* @param options
* @param minSideLength
* @param maxNumOfPixels
* @return 动态计算出图片的inSampleSize
* @return: int
*/
public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);
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) {
double w = options.outWidth;
double h = options.outHeight;
// Math.ceil(Math.sqrt(w * h / maxNumOfPixels)) :w * h /
// maxNumOfPixels平方结果的小数部分一律向整数部分进位
int lowerBound = (maxNumOfPixels == UNCONSTRAINED) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
// Math.floor(w / minSideLength) 将w / minSideLength结果值一律舍去小数,仅保留整数
int upperBound = (minSideLength == UNCONSTRAINED) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
return lowerBound;
}
if ((maxNumOfPixels == UNCONSTRAINED) && (minSideLength == UNCONSTRAINED)) {
return 1;
} else if (minSideLength == UNCONSTRAINED) {
return lowerBound;
} else {
return upperBound;
}
}