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

ImageView无法显示大尺寸图片求助(4128x3096)

解决大图片无法显示(白屏)的问题

看了你的代码和LogCat日志,核心问题已经很明确了:

Bitmap too large to be uploaded into a texture (3096x4128, max=4096x4096)

你的图片旋转后尺寸是3096×4128,刚好超过了OpenGL Renderer支持的最大纹理尺寸(4096×4096),导致无法将图片上传到GPU纹理,最终显示白屏。而1080×720的图片远小于这个限制,所以能正常加载。

下面是具体的解决方案,兼顾图片缩放适配纹理限制和填充显示到ImageView的需求:

步骤1:动态获取设备支持的最大纹理尺寸

不同设备的最大纹理尺寸可能存在差异,不要硬编码4096,我们可以通过代码动态获取:

private fun getMaxTextureSize(): Int {
    val display = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)
    val version = IntArray(2)
    EGL14.eglInitialize(display, version, 0, version, 1)
    
    val configAttrs = intArrayOf(
        EGL14.EGL_RED_SIZE, 8,
        EGL14.EGL_GREEN_SIZE, 8,
        EGL14.EGL_BLUE_SIZE, 8,
        EGL14.EGL_ALPHA_SIZE, 8,
        EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
        EGL14.EGL_NONE
    )
    val configs = arrayOfNulls<EGLConfig>(1)
    val configCount = IntArray(1)
    EGL14.eglChooseConfig(display, configAttrs, 0, configs, 0, configs.size, configCount, 0)
    
    val contextAttrs = intArrayOf(
        EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL14.EGL_NONE
    )
    val context = EGL14.eglCreateContext(display, configs[0], EGL14.EGL_NO_CONTEXT, contextAttrs, 0)
    EGL14.eglMakeCurrent(display, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, context)
    
    val maxTextureSize = IntArray(1)
    GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0)
    
    EGL14.eglDestroyContext(display, context)
    EGL14.eglTerminate(display)
    return maxTextureSize[0]
}

步骤2:计算合适的图片缩放比例

我们需要计算一个采样比例,让缩放后的图片宽高都不超过最大纹理尺寸,同时保留原有的宽高比:

fun calculateInSampleSize(options: BitmapFactory.Options, maxWidth: Int, maxHeight: Int): Int {
    val originalHeight = options.outHeight
    val originalWidth = options.outWidth
    var inSampleSize = 1

    if (originalHeight > maxHeight || originalWidth > maxWidth) {
        val halfHeight = originalHeight / 2
        val halfWidth = originalWidth / 2

        // 找到最大的采样比例,确保缩放后尺寸不超过限制
        while ((halfHeight / inSampleSize) >= maxHeight && (halfWidth / inSampleSize) >= maxWidth) {
            inSampleSize *= 2
        }
    }
    return inSampleSize
}

步骤3:整合缩放、旋转与ImageView填充显示

把上面的方法整合到你的加载逻辑里,先高效加载缩放后的图片,再处理旋转,最后设置填充显示:

val patchFile = "你的图片路径"
val maxTextureSize = getMaxTextureSize()

// 第一步:获取图片原始尺寸,不加载到内存
val options = BitmapFactory.Options().apply {
    inJustDecodeBounds = true
}
BitmapFactory.decodeFile(patchFile, options)

// 第二步:计算采样比例,加载缩放后的图片
options.apply {
    inJustDecodeBounds = false
    inSampleSize = calculateInSampleSize(options, maxTextureSize, maxTextureSize)
    inPreferredConfig = Bitmap.Config.RGB_565 // 降低内存占用,可选
}
val bitmap = BitmapFactory.decodeFile(patchFile, options)

// 第三步:处理图片旋转
val matrix = Matrix()
matrix.postRotate(90F)
val rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)

// 第四步:设置ImageView为填充显示模式
imageView.scaleType = ImageView.ScaleType.CENTER_CROP // 按比例填充,裁剪超出部分
// 如果你不需要裁剪,也可以用FIT_XY:拉伸填充整个ImageView
// imageView.scaleType = ImageView.ScaleType.FIT_XY
imageView.setImageBitmap(rotatedBitmap)

// 回收原始Bitmap,避免内存泄漏
bitmap.recycle()

额外处理:Toast线程警告问题

LogCat里还有一个关于Handler的警告:

Handler (android.widget.Toast$TN$2) {a8d7afe} sending message to a Handler on a dead thread

这是因为你在子线程中显示Toast后,线程提前销毁导致Toast的回调无法执行。解决方法是确保Toast在主线程显示,比如用runOnUiThread包裹:

runOnUiThread {
    Toast.makeText(this, "你的提示内容", Toast.LENGTH_SHORT).show()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:49:26