You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成超大PNG/JPEG文件以测试Android ImageDecoder的OOM场景

动态生成高体积编码图片触发ImageDecoder OOM的实用方案

针对你需要在Android Instrumentation测试中触发ImageDecoder的OutOfMemoryError、同时不想仓库存储大文件的需求,以下是几种不增大分辨率就能生成高体积编码图片的实用方案:


方法1:生成无规律像素数据+PNG无压缩存储

普通随机像素仍存在压缩空间,故意生成相邻像素完全无相似性的位图,让压缩算法无从下手,再配合PNG的无压缩级别,能生成接近原始位图大小的编码文件:

  • 核心逻辑:逐个像素生成与前一个像素完全互补的颜色,彻底消除重复模式
  • Kotlin代码示例:
val width = 4096
val height = 4096
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val pixels = IntArray(width * height)

for (i in pixels.indices) {
    // 翻转前一个像素的所有位,生成完全相反的颜色
    val prevPixel = if (i == 0) 0 else pixels[i - 1]
    pixels[i] = prevPixel xor 0xFFFFFFFF
}
bitmap.setPixels(pixels, 0, width, 0, 0, width, height)

// 用PNG压缩级别0(无压缩)保存
val outputStream = FileOutputStream(cacheDir.resolve("uncompressible.png"))
bitmap.compress(Bitmap.CompressFormat.PNG, 0, outputStream)
outputStream.close()

生成的文件大小接近原始位图(4096×4096×4≈64MB),足以触发OOM。


方法2:给编码文件追加冗余数据(最简高效)

不管原始压缩文件大小,直接在文件末尾填充大量无效但不影响解码的字节,瞬间放大体积,同时不改变图片实际像素数据:

  • 原理:PNG/JPG等格式的解码器只会处理开头的有效数据,末尾垃圾数据会被忽略
  • Kotlin代码示例:
val baseFile = cacheDir.resolve("base.png")
// 先保存任意一张4096×4096的位图(推荐用方法1的无规律图)
bitmap.compress(Bitmap.CompressFormat.PNG, 0, FileOutputStream(baseFile))

// 追加数据到目标大小(比如100MB)
val targetSize = 100 * 1024 * 1024L
val bytesToAdd = targetSize - baseFile.length()
val outputStream = FileOutputStream(baseFile, true) // 追加模式
val buffer = ByteArray(1024 * 1024) // 1MB缓冲区

var remainingBytes = bytesToAdd
while (remainingBytes > 0) {
    val writeSize = min(remainingBytes, buffer.size.toLong()).toInt()
    outputStream.write(buffer, 0, writeSize)
    remainingBytes -= writeSize
}
outputStream.close()

生成的文件大小精准可控,解码时仍会加载完整的4096×4096像素,触发OOM。


方法3:WebP无损压缩禁用优化

WebP的无损压缩支持更高的原始数据保留度,设置最高质量并禁用压缩优化,能生成接近原始位图大小的文件:

  • Kotlin代码示例(需Android 10+,测试环境通常满足):
val outputStream = FileOutputStream(cacheDir.resolve("uncompressible.webp"))
// WEBP_LOSSLESS模式+质量100,彻底禁用压缩优化
bitmap.compress(Bitmap.CompressFormat.WEBP_LOSSLESS, 100, outputStream)
outputStream.close()

测试辅助技巧

  • 若设备内存较大,可通过adb shell setprop dalvik.vm.heapsize 64m手动限制应用堆内存,更容易触发OOM
  • 测试sampleSize时,对比设置前后的内存占用(可通过Android Studio Profiler查看),确认是否有效避免内存溢出

内容的提问来源于stack exchange,提问作者fejd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 14:22:45