Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 连接大图像时发生OutOfMemory错误_Android_Bitmap_Out Of Memory - Fatal编程技术网

Android 连接大图像时发生OutOfMemory错误

Android 连接大图像时发生OutOfMemory错误,android,bitmap,out-of-memory,Android,Bitmap,Out Of Memory,我正在使用下面的代码连接两个图像,但是它抛出了一个OutOfMemory错误。我的图像每个大约1MB private Bitmap overlayMark(String first, String second) { Bitmap bmp1, bmp2; bmp1 = BitmapFactory.decodeFile(first); bmp2 = BitmapFactory.decodeFile(second); if (bmp1 == null || bmp2

我正在使用下面的代码连接两个图像,但是它抛出了一个
OutOfMemory
错误。我的图像每个大约1MB

private Bitmap overlayMark(String first, String second)
{
    Bitmap bmp1, bmp2;
    bmp1 = BitmapFactory.decodeFile(first);
    bmp2 = BitmapFactory.decodeFile(second);
    if (bmp1 == null || bmp2 == null)
        return bmp1;

    int height = bmp1.getHeight();
    if (height < bmp2.getHeight())
        height = bmp2.getHeight();

    Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth() + bmp2.getWidth(), height,
            Bitmap.Config.ARGB_8888);// Out of memory
    Canvas canvas = new Canvas(bmOverlay);
    canvas.drawBitmap(bmp1, 0, 0, null);
    canvas.drawBitmap(bmp2, bmp1.getWidth(), 0, null);
    bmp1.recycle();
    bmp2.recycle();
    return bmOverlay;
}
私有位图覆盖标记(字符串第一,字符串第二)
{
位图bmp1、bmp2;
bmp1=BitmapFactory.decodeFile(第一个);
bmp2=BitmapFactory.decodeFile(秒);
如果(bmp1==null | | bmp2==null)
返回bmp1;
int height=bmp1.getHeight();
if(高度
更新:我尝试了以下两个答案,但仍然无法创建如此大的位图。问题是生成的位图在2400x3200左右太大,因此内存不足


如何连接大型图像而不耗尽内存?

位图的内存表示所占用的空间不必与文件大小密切对应。所以,即使jvm有3mb的可用内存,也可能会出现OutOfMemoryException


您的代码正在同时创建三个内存映像。如果可以在不读取完整文件的情况下找到两个图像的大小,则可以修改代码,使其一次只在内存中包含一个源图像。如果这还不够的话,你可能需要某种流媒体方式来读取图像

无需将图像加载到内存中,您可以使用inJustDecodeBounds获取图像的大小。位图返回null,但所有参数都已设置。您可以相应地缩小图像的比例

如果您的JPEG图像每个有1个MiB,那么转换为BMP确实会占用大量内存。您可以通过图像的尺寸轻松计算其BMP等效值。如此大的图像转换预计确实会崩溃。Android将其应用程序限制为仅16 MiB虚拟机

也可以使用RGB_565而不是ARGB_8888

因此,您唯一的解决方案是: (a) 使用BitmapFactory.Options.inSampleSize缩小图像的步骤 或
(b) 在没有16 MiB限制的地方使用Android NDK。

您可能会从中得到一些想法

您是想显示这个超大图像还是只是想保存它

  • 如果您试图显示它。将图像切割成瓷砖。然后仅显示正在查看的平铺。如果用户缩小,则需要在显示整个内容之前减小位图的大小

  • 如果您试图保存它,请尝试将图像分割成多个部分保存到同一文件中


  • 在内存中加载210万个文件,然后创建一个200万个文件,仅图像的内存就有400万个。动态加载和卸载内存解决了这个问题,类似于谷歌地图上的分幅或其他面向地图的解决方案中的动态缩放

    如果您需要返回2400x3200的巨大位图作为结果,则无法实际实现此目标。原因是2400*3200*4字节~30MB!当您甚至无法将返回值放入有限的堆空间(即16Mb)中时,您如何希望实现此方法


    即使您使用16位颜色,它仍然会失败,因为您最终将使用大约15MB,这将不会为语言运行时留下足够的空间。

    我认为类似Sumon建议的解决方案可能会奏效

    • 计算出最终结果的大小 图像基于将在屏幕上显示的内容 屏幕
    • 使用获取第一个图像的大小 不公正的技术。 算出第一个的大小 最终图像中的图像。算计 调整参数大小
    • 调整图像大小,加载到内存中
    • 将调整大小的映像写回磁盘。 回收位图。(这会有帮助 调整第二个图像的大小时)
    • 对第二个图像重复此操作,仅对您执行此操作 可以跳过写入磁盘部分
    • 加载第一个图像

    如果您只需要显示,那么就这样做。如果没有,则此时可以合并为单个位图并写入磁盘。如果是这种情况,可能会很困难,因为内存中的屏幕大小实际上是2倍。在这种情况下,我建议调整尺寸更小。如果你不能走小一点,那么你就必须走NDK路线,我不确定。这是一个关于NDK和JNI的例子。最后,我强烈建议使用运行Android2.3+的手机来开发它,因为它使用堆分配位图将使调试更加容易。更多信息。

    我使用这个简单的经验法则: 繁重的工作(内存/CPU)在服务器上完成

    因此,编写一些servlet获取图像,将其大小调整到指定的维度(可能也会减少像素深度)并返回结果

    小菜一碟,它可以在你需要的任何移动设备上运行


    祝你好运

    其中“内存不足”来自-BitmapFactory.decodeFile()?在这一行,Bitmap bmOverlay=Bitmap.createBitmap(bmp1.getWidth()+bmp2.getWidth(),height,Bitmap.Config.ARGB_8888);在创建新位图之前,为什么不压缩这两个位图并重试呢。这将大大减少内存better@Andro_Selva我不能这样做,因为图像要缩放,这样做会降低质量。你能试着将bmp转换成png吗?然后,它可以压缩到更小的尺寸,但仍然不会失去任何质量。然后,如果Java API在这方面很聪明,并且允许您仍然访问每个像素的RGB颜色值,而不实际将其扩展为BMP数组,那么您可以手动构建BMP文件并将其流式输出到文件中。通过这种方式,您可以一次在内存中存储所需的所有数据,并且可以缓冲和存储数据