最近在搞一個app 的上傳圖片評價功能,分別從相機相冊中獲取圖片,然後要上傳到服務器,但是如果上傳的話那麼圖片就不能太大,不然太費流量了,所以要壓縮下。
網上搜索了下壓縮的方法,發現大部分的人都是用將文件轉換爲Bitmap壓縮,然後再上傳,我也試了試,發現如果用Bitmap 壓縮的話壓縮的太厲害圖片的清晰度就不清晰了。
又搗鼓搗鼓,發現如果用btye 壓縮的話就沒這個問題,我用byte壓縮把2M的圖片壓縮到小於50k竟然還是很清晰所以果斷換byte的壓縮方法。
方法如下:
首先通過相機和相冊獲取到uri ,這裏就省略了,不多講解了。
content 就是uri轉換的byte,
ImageUtil.CompressBytes 是Byte壓縮函數壓縮後返回壓縮後的byte。
saveMybyte(content) 函數是將壓縮後的byte轉換成新的文件。並返回新文件路徑。
最後根據file_URL文件路徑我們把這個臨時的圖片文件上傳服務器,上傳成功後可以調用ImageUtil.deleteTempFile(file_URL); 刪除臨時的壓縮文件。以下是流程的大概代碼:
byte[] content = null;
uri = Uri.fromFile(picture); /picture圖片文件
try {
content = ImageUtil.readStream(getContentResolver().openInputStream(
Uri.parse(uri.toString())));
Log.e("cui", "壓縮前文件大小 :" + content.length);
content =ImageUtil.CompressBytes(content,50000); //小於50k
Log.e("cui", "壓縮後文件大小 :" + content.length);
file_URL=saveMybyte(content); //儲存臨時文件地址,上傳成功後刪除臨時文件
} catch (Exception e) {
e.printStackTrace();
}
上面的代碼涉及到的函數如下:
ImageUtil.CompressBytes
public static byte[] CompressBytes(byte[] content, int max_size) {
HashMap<String, Object> resultMap = new HashMap<String, Object>();
Bitmap bm;
byte[] compressBytes = null;
int rate = 100;
int scale = (int) Math.floor(content.length / max_size);
BitmapFactory.Options option = new BitmapFactory.Options();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
option.inJustDecodeBounds = false;
option.inSampleSize = 1;
if (scale < 2) {
option.inSampleSize = 1;
} else if (scale >= 2 && scale < 8) {
option.inSampleSize = 2;
} else if (scale >= 8 && scale < 32) {
option.inSampleSize = 4;
} else if (scale >= 32 && scale < 128) {
option.inSampleSize = 8;
} else {
option.inSampleSize = 16;
}
try {
bm = BitmapFactory.decodeByteArray(content, 0, content.length,
option);
} catch (OutOfMemoryError e) {
option.inSampleSize *= 2;
bm = BitmapFactory.decodeByteArray(content, 0, content.length,
option);
}
do {
if (compressBytes == null) {
bm.compress(Bitmap.CompressFormat.JPEG, rate, baos);
compressBytes = baos.toByteArray();
} else {
rate = rate - 3;
baos.reset();
compressBytes = null;
System.gc();
bm.compress(Bitmap.CompressFormat.JPEG, rate, baos);
compressBytes = baos.toByteArray();
}
} while (compressBytes.length > max_size);
bm = null;
System.gc();
return compressBytes;
}
saveMybyte
private String saveMybyte(byte[] content){
String absPath = null;
//給文件取名字 以時間命名 防止重複 被覆蓋
String picturename = DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg";
ImageUtil.byte2File(content,SessionManager.getInstance().getAppFileDirPath(),picturename);
absPath = SessionManager.getInstance().getAppFileDirPath() + picturename; //存放在軟件安裝的地址
return absPath;
}
ImageUtil.byte2File
/**
* byte 轉file
* @param buf
* @param filePath
* @param fileName
*/
public static void byte2File(byte[] buf, String filePath, String fileName)
{
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try
{
File dir = new File(filePath);
if (!dir.exists() && dir.isDirectory())
{
dir.mkdirs();
}
file = new File(filePath + File.separator + fileName);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(buf);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (bos != null)
{
try
{
bos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if (fos != null)
{
try
{
fos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
deleteTempFile
/**
* 根據路徑刪除圖片
*
* @param path
*/
public static void deleteTempFile(String path) {
File file = new File(path);
if (file.exists()) {
file.delete();
}
}