/**
* Copyright (c) 2012-2013, Michael Yang 杨福海 (www.yangfuhai.com).
*
* 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 org.aisen.android.component.bitmaploader.core;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.text.TextUtils;
import org.aisen.android.common.utils.BitmapUtil;
import org.aisen.android.common.utils.BitmapUtil.BitmapType;
import org.aisen.android.common.utils.KeyGenerator;
import org.aisen.android.common.utils.Logger;
import org.aisen.android.component.bitmaploader.BitmapLoader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
public class BitmapProcess {
private static final String TAG = "BitmapCache";
private FileDisk compFielDisk;// 保存压缩或者缩放后的图片
private FileDisk origFileDisk;// 保存原始下载
public BitmapProcess(String imageCache) {
compFielDisk = new FileDisk(imageCache + File.separator + "compression");
origFileDisk = new FileDisk(imageCache + File.separator + "originate");
}
private byte[] getBitmapFromDiskCache(String url, String key, FileDisk fileDisk, ImageConfig config) throws Exception {
InputStream inputStream = fileDisk.getInputStream(url, key);
if (inputStream == null)
return null;
if (config.getProgress() != null)
config.getProgress().sendLength(inputStream.available());
byte[] buffer = new byte[8 * 1024];
int readLen = -1;
int readBytes = 0;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
while ((readLen = inputStream.read(buffer)) != -1) {
readBytes += readLen;
if (config.getProgress() != null)
config.getProgress().sendProgress(readBytes);
outputStream.write(buffer, 0, readLen);
}
return outputStream.toByteArray();
}
public File getOirgFile(String url) {
String key = KeyGenerator.generateMD5(BitmapLoader.getKeyByConfig(url, null));
return origFileDisk.getFile(url, key);
}
public File getCompressFile(String url, String imageId) {
ImageConfig config = null;
if (!TextUtils.isEmpty(imageId)) {
config = new ImageConfig();
config.setId(imageId);
}
String key = KeyGenerator.generateMD5(BitmapLoader.getKeyByConfig(url, config));
return compFielDisk.getFile(url, key);
}
public void deleteFile(String url, ImageConfig config) {
String key = KeyGenerator.generateMD5(BitmapLoader.getKeyByConfig(url, config));
compFielDisk.deleteFile(url, key);
origFileDisk.deleteFile(url, key);
}
/**
* 将数据写入原始缓存
*
* @param bs
*/
public void writeBytesToOrigDisk(byte[] bs, String url) throws Exception {
String key = KeyGenerator.generateMD5(BitmapLoader.getKeyByConfig(url, null));
OutputStream out = origFileDisk.getOutputStream(url, key);
ByteArrayInputStream in = new ByteArrayInputStream(bs);
byte[] buffer = new byte[8 * 1024];
int len = -1;
while ((len = in.read(buffer)) != -1)
out.write(buffer, 0, len);
out.flush();
in.close();
out.close();
origFileDisk.renameFile(url, key);
}
public void writeBytesToCompressDisk(String url, String key, byte[] bytes) throws Exception {
OutputStream out = compFielDisk.getOutputStream(url, key);
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
byte[] buffer = new byte[8 * 1024];
int len = -1;
while ((len = in.read(buffer)) != -1)
out.write(buffer, 0, len);
out.flush();
in.close();
out.close();
compFielDisk.renameFile(url, key);
}
/**
* 从二级缓存获取位图数据
*
* @param url
* @param config
* @return
* @throws Exception
*/
public byte[] getBitmapFromCompDiskCache(String url, ImageConfig config) throws Exception {
String key = KeyGenerator.generateMD5(BitmapLoader.getKeyByConfig(url, config));
return getBitmapFromDiskCache(url, key, compFielDisk, config);
}
/**
* 从原始缓存获取位图数据
*
* @param url
* @param config
* @return
* @throws Exception
*/
public byte[] getBitmapFromOrigDiskCache(String url, ImageConfig config) throws Exception {
String key = KeyGenerator.generateMD5(BitmapLoader.getKeyByConfig(url, null));
return getBitmapFromDiskCache(url, key, origFileDisk, config);
}
/**
* 图片做二级缓存处理
*
* @param bitmapBytes
* @param url
* @param config
* @return
* @throws Exception
*/
public MyBitmap compressBitmap(Context context, byte[] bitmapBytes, String url, int flag, ImageConfig config) throws Exception {
boolean writeToComp = config.getCorner() > 0;
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length, options);
BitmapType bitmapType = BitmapUtil.getType(bitmapBytes);
MyBitmap myBitmap = null;
// 如果图片取自压缩目录,则不再对图片做压缩或者其他处理,直接返回
if ((flag & 0x01) != 0) {
myBitmap = new MyBitmap(BitmapDecoder.decodeSampledBitmapFromByte(context, bitmapBytes), url);
return myBitmap;
}
// 判断是否需要压缩图片
IBitmapCompress bitmapCompress = config.getBitmapCompress().newInstance();
myBitmap = bitmapCompress.compress(bitmapBytes, getOirgFile(url), url, config, options.outWidth, options.outHeight);
Bitmap bitmap = myBitmap.getBitmap();
if (bitmap == null) {
// 如果没压缩,就原始解析图片
bitmap = BitmapDecoder.decodeSampledBitmapFromByte(context, bitmapBytes);
} else {
// 如果图片做了压缩处理,则需要写入二级缓存
writeToComp = true;
}
// 对图片做圆角处理
if (bitmapType != BitmapType.gif && config.getCorner() > 0) {
bitmap = BitmapUtil.setImageCorner(bitmap, config.getCorner());
bitmapType = BitmapType.png;
}
// GIF图片,进行压缩
if (bitmapType == BitmapType.gif)
writeToComp = true;
// 当图片做了圆角、压缩处理后,将图片放置二级缓存
if (writeToComp && config.isCompressCacheEnable()) {
String key = KeyGenerator.generateMD5(BitmapLoader.getKeyByConfig(url, config));
// PNG以外其他格式,都压缩成JPG格式
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(BitmapType.png == bitmapType ? CompressFormat.PNG : CompressFormat.JPEG, 100, out);
byte[] bytes = out.toByteArray();
writeBytesToCompressDisk(url, key, bytes);
// 如果是GIF图片,无论如何,返回压缩格式图片
if (bitmapType == BitmapType.gif) {
Logger.v(TAG, String.format("parse gif image[url=%s,key=%s]", url, key));
bitmap.recycle();
bitmap = BitmapDecoder.decodeSampledBitmapFromByte(context, bytes);
}
}
myBitmap.setBitmap(bitmap);
return myBitmap;
}
}