gpt4 book ai didi

java - 解码为 Bitmap 和压缩期间内存泄漏

转载 作者:行者123 更新时间:2023-11-29 07:56:20 25 4
gpt4 key购买 nike

我一直在研究以下代码,它在 android 平板电脑上打开存储的图像,将其解码为位图,然后将其转换为 base64 字符串,以便可以将其存储在 SQLite 数据库中。

据我所知,多达 2MB 的数据从该事务中泄漏,对该函数的多次调用占用越来越多的内存,而这些内存未被正确地垃圾收集。

填充 origin_photo 后,它大约占用 49kb,一旦转换为 base64,它大约占用 65kb。

photo.insert 函数是一个简单的 SQLite base64 插入以及一些小信息。我不认为这是问题的一部分。

此功能完成后,我还在日志 cat 中收到一条消息“跳过 57 帧!应用程序可能在其主线程上做了太多工作”(没有任何断点会减慢代码速度)

我可能弄错了,这是导致泄漏的代码附近运行的不同部分,但这似乎是最有可能的候选者。非常感谢任何帮助。

更新:base64.encodeBytes 函数取自

http://iharder.net/base64

public void savePhoto() 
{
try
{
String[] projection = { MediaStore.Images.Media.DATA };
//Get last captured image in db
String capturedImageFilePath = null;
try
{
//NOTE: The warning on activity.managedQuert states you must NOT close the cursor it creates yourself
Cursor cursor = activity.managedQuery(mCapturedImageURI, projection, null, null, null);
int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
//Get file path from last stored photo
capturedImageFilePath = new String(cursor.getString(column_index_data));
//cursor.close();
}
catch(IllegalArgumentException e)
{
ErrorCodes.CreateError(ErrorCodes.DCDF_SAVE_PHOTO_GET_IMAGE_FILE_PATH, this.getActivity());
}
catch(NullPointerException e)
{
ErrorCodes.CreateError(ErrorCodes.DCDF_SAVE_PHOTO_GET_IMAGE_FILE_PATH, this.getActivity());
}
catch(Exception e)
{
ErrorCodes.CreateError(ErrorCodes.DCDF_SAVE_PHOTO_GET_IMAGE_FILE_PATH, this.getActivity());
}

int orientation = -1;
//Get Exif data from current image and store orientation
//Note exif data will be stripped when this filepath is turned
//into a bitmap
try
{
ExifInterface e = new ExifInterface(capturedImageFilePath);
orientation = e.getAttributeInt("Orientation", -1);
}
catch (IOException ioe)
{
ioe.printStackTrace();
ErrorCodes.CreateError(ErrorCodes.DCDF_SAVE_PHOTO_EXIF_DATA_IO, this.getActivity());
}
catch(Exception e) { ErrorCodes.CreateError(ErrorCodes.DCDF_SAVE_PHOTO_EXIF_DATA_GENERAL, this.getActivity()); }

//Decode current photo into a Bitmap
Bitmap b = BitmapFactory.decodeFile(capturedImageFilePath);

if(b == null)
{
Log.d("activitycrossellcalls", "error open " + capturedImageFilePath);
ErrorCodes.CreateError(ErrorCodes.DCDF_SAVE_PHOTO_NULL_BITMAP, this.getActivity());
}
else
{
int width = -1;
int height = -1;

width = b.getWidth();
height = b.getHeight();
Log.d("activitycrossellcalls", "w: "+width+", h:"+height);
//Scale down if too big
int max = (width > height)?width:height;
float ratio = 1;
if(max > MAX_IMAGE_SIZE)
ratio = (float)max/(float)MAX_IMAGE_SIZE;
width /= ratio;
height /= ratio;

b = Photos.getResizedBitmap(b, height, width);

Log.i("activitycrossellcalls", "new w: " + width + ", h: " + height);

// Encode
ByteArrayOutputStream baos = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG, 70, baos);
b.recycle();


byte[] origin_photo = null;

origin_photo = baos.toByteArray();

// Insert
Photo photo = null;
try
{
photo = new Photo();
photo.base64 = Base64.encodeBytes(origin_photo);
photo.call = DailyCallsDetailsActivity.call.id;
photo.tag_id = TaggingActivity.currentTag.id;
photo.orientation = orientation;
}
catch(Exception e) { ErrorCodes.CreateError(ErrorCodes.DCDF_SAVE_PHOTO_INIT, this.getActivity()); }

photo.insert();
}
}
catch(Exception e) { ErrorCodes.CreateError(ErrorCodes.DCDF_SAVE_PHOTO, this.getActivity()); }
}

.

public static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) 
{
try
{
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
bm.recycle();
return resizedBitmap;
}
catch(Exception e) { ErrorCodes.ReportError(ErrorCodes.PHOTS_GET_RESIZED_BITMAP); return null; }
}

最佳答案

我想我找到了

Bitmap b = BitmapFactory.decodeFile(capturedImageFilePath);
...
b = Photos.getResizedBitmap(b, height, width);

你不是在回收原来的 b。这不应该是永久性泄漏,但肯定会导致 GC 崩溃。

您可能还想考虑使用 LRUCache 来自动循环进出位图。

关于java - 解码为 Bitmap 和压缩期间内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17446199/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com