一任岸、插值法放大
參考【圖像縮放】雙立方(三次)卷積插值(Android版改寫)
思想是
1.拿到原始圖的所有像素點的哺哼,每個點的ARGB具體數值放到數組里沪铭。
2.按照比例關系算出目標尺寸圖對應點的對應像素點然后取原始圖的像素點數據串稀。
但是原方案粥庄,需要大量內存岖瑰,來回倒騰叛买,小圖還可以,
大圖4k
內存占用 = bitmap width * bitmap height * 4;
384021604/1024/1024=31.640625MB,
反復申請蹋订,折騰三下不得內存擠爆了率挣。
1.優(yōu)化:直接計算偏移量就好,
public static boolean imgScaleNear2(byte[] srcbuffer, byte[] desBuffer, int srcW, int srcH, int destW, int destH) {
float rowRatio = ((float) srcH) / ((float) destH);
float colRatio = ((float) srcW) / ((float) destW);
for (int row = 0; row < destH; row++) {
int srcRow = Math.round(((float) row) * rowRatio);
if (srcRow >= srcH) {
srcRow = srcH - 1;
}
for (int col = 0; col < destW; col++) {
int srcCol = Math.round(((float) col) * colRatio);
if (srcCol >= srcW) {
srcCol = srcW - 1;
}
int inpos = (srcRow*srcW +srcCol)*4;
int outpos = (row *destW+ col)*4;
//填充部分
desBuffer[outpos] = srcbuffer[inpos];
desBuffer[outpos + 1] = srcbuffer[inpos + 1];
desBuffer[outpos + 2] = srcbuffer[inpos + 2];
desBuffer[outpos + 3] = srcbuffer[inpos + 3];
//Log.e("tai","col=="+col+"=="+"row=="+row+"==");
}
}
return false;
}
2.使用
int bytes = bitmap.getByteCount(); //返回可用于儲存此位圖像素的最小字節(jié)數
ByteBuffer buffer = ByteBuffer.allocate(bytes); // 使用allocate()靜態(tài)方法創(chuàng)建字節(jié)緩沖區(qū)
bitmap.copyPixelsToBuffer(buffer); // 將位圖的像素復制到指定的緩沖區(qū)
bitmap.recycle();
ByteBuffer desBuffer = ByteBuffer.allocate(dWidth * dHeight * 4);
buffer.position(0);
desBuffer.position(0);
BitmapUtils.imgScaleNear2(buffer.array(), desBuffer.array(), sWidth, sHeight, dWidth, dHeight);
buffer.clear();
desBuffer.position(0);
Bitmap outbitmap = Bitmap.createBitmap(dWidth, dHeight, Bitmap.Config.ARGB_8888);
outbitmap.copyPixelsFromBuffer(desBuffer);
desBuffer.clear();
savePicture(outbitmap);
outbitmap.recycle();
3. buffer.position(0)作用露戒。
RuntimeException: Buffer not large enough for pixels
buffer.position(0);//將buffer的下一讀寫位置置為0椒功。
4.配置清單申請更大的Heap
android:largeHeap="true"
8k的圖片一張占
768043204/1024/1024=126.5625Mb
不申請是完全不夠的捶箱,大部分手機設備系統(tǒng)正常分配的內存最多為192M;當設置largeHeap時动漾,最多可申請512M丁屎。
打印測試工具
private void printCurrentMemory(String tag) {
final Runtime runtime = Runtime.getRuntime();
final long usedMemInMB = (runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB = runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;
Log.e(TAG, tag + ",usedMemInMB=" + usedMemInMB + ",maxHeapSizeInMB=" + maxHeapSizeInMB + ",availHeapSizeInMB=" + availHeapSizeInMB);
}
二、照片添加坐標信息
直接寫進入是不行的要轉換成度分秒格式
/**
* 浮點型經緯度值轉成度分秒格式
*
* @param coord
* @return
*/
public static String decimalToDMS(double coord) {
String output, degrees, minutes, seconds;
double mod = coord % 1;
int intPart = (int) coord;
degrees = String.valueOf(intPart);
coord = mod * 60;
mod = coord % 1;
intPart = (int) coord;
if (intPart < 0) {
intPart *= -1;
}
minutes = String.valueOf(intPart);
coord = mod * 60;
intPart = (int) coord;
if (intPart < 0) {
intPart *= -1;
}
seconds = String.valueOf(intPart);
output = degrees + "/1," + minutes + "/1," + seconds + "/1";
return output;
}
/**
* 將經緯度信息寫入JPEG圖片文件里
*
* @param picPath JPEG圖片文件路徑
* @param dLat 緯度
* @param dLon 經度
*/
public static void writeLatLonIntoJpeg(String picPath, double dLat, double dLon) {
File file = new File(picPath);
if (file.exists()) {
try {
ExifInterface exif = new ExifInterface(picPath);
String tagLat = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
String tagLon = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
if (tagLat == null && tagLon == null) {
// 無經緯度信息
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, decimalToDMS(dLat));
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, dLat > 0 ? "N" : "S"); // 區(qū)分南北半球
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, decimalToDMS(dLon));
exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, dLon > 0 ? "E" : "W"); // 區(qū)分東經西經
exif.saveAttributes();
}
exif.setAttribute(ExifInterface.TAG_MODEL, Build.MODEL);
} catch (Exception e) {
Log.e("exif", e.getMessage());
}
}
}