"位图太大而无法上传到纹理中"

Oll*_*e C 149 android android-image android-imageview android-bitmap

我正在将一个位图加载到ImageView中,并看到此错误.我收集此限制与OpenGL硬件纹理(2048x2048)的大小限制有关.我需要加载的图像是大约4,000像素高的捏缩图像.

我试过关闭清单中的硬件加速,但没有快乐.

    <application
        android:hardwareAccelerated="false"
        ....
        >
Run Code Online (Sandbox Code Playgroud)

是否可以将大于2048像素的图像加载到ImageView中?

Pil*_*_51 401

这不是问题的直接答案(加载图像> 2048),而是遇到错误的任何人的可能解决方案.

在我的情况下,图像在两个维度上都小于2048(准确地说是1280x727),而且问题是在Galaxy Nexus上经历的.图像位于drawable文件夹中,没有任何限定文件夹.Android假定没有密度限定符的drawable是mdpi,并将其缩放或缩小以获得其他密度,在这种情况下,xhdpi的扩展为2x.移动罪魁祸首图像以drawable-nodpi防止缩放解决了问题.

  • 这是正确的答案,应该这样标记. (16认同)
  • 到底是怎么回事!我认为99%的Android程序员认为"可绘制"意味着"不要扩展这个". (9认同)
  • 我在尝试加载drawable时遇到内存问题.花了2个小时试图理解为什么会这样.谢谢你的间接答​​复. (3认同)
  • 现在大约三个半月我在Android上编程几乎是全职,我刚才意识到这一点.看起来很愚蠢,使`drawable`本质上是一个隐藏的'drawable-mdpi`文件夹.这也解释了为什么我的自定义地图标记看起来很糟糕(它们被放大,然后缩小尺寸). (3认同)
  • 这是我在任何地方见过的最有用的答案。我只能说是要发送赏金!谢谢。 (2认同)

小智 104

我用这种方式缩小了图像:

ImageView iv  = (ImageView)waypointListView.findViewById(R.id.waypoint_picker_photo);
Bitmap d = new BitmapDrawable(ctx.getResources() , w.photo.getAbsolutePath()).getBitmap();
int nh = (int) ( d.getHeight() * (512.0 / d.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(d, 512, nh, true);
iv.setImageBitmap(scaled);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,createScaledBitmap有助于我显示一个太大的位图 (2认同)

jpt*_*ung 46

所有渲染都基于OpenGL,因此不能超过此限制(GL_MAX_TEXTURE_SIZE取决于设备,但最小值为2048x2048,因此任何低于2048x2048的图像都适合).

有了这么大的图像,如果你想放大,在移动设备中,你应该设置一个类似于你在谷歌地图中看到的系统.随着图像分成几个部分,和几个定义.

或者您可以在显示之前缩小图像(请参阅user1352407对此问题的回答).

此外,请注意将图像放入哪个文件夹,Android可以自动放大图像.请看下面关于这个问题的Pilot_51的答案.

  • 这真的没有任何意义.我现在遇到了同样的问题 - 图像为1286x835像素.AND:仅在Galaxy Nexus上我收到此错误消息而没有图像!顶级智能手机无法显示如此小的图像,这似乎很荒谬!我的HTC Hero能够显示出来!我能做什么? (24认同)
  • 如果是这种情况,Gallery应用程序如何允许显示和操作使用相机拍摄的图像?2048x2048只是一张400万像素,许多Android手机拍摄的照片比这大得多,而Gallery应用程序似乎也没有问题. (23认同)
  • 因为GL_MAX_TEXTURE_SIZE取决于设备. (3认同)
  • @OllieC我也想知道画廊应用程序是如何做到的.因此,如果有人知道,或者有一个显示大图像的例子,这将是伟大的. (3认同)

Phi*_*o99 35

而不是花费数小时尝试手动编写/调试所有这些下采样代码,为什么不使用Picasso?它是为处理bitmaps所有类型和/或尺寸而制作的.

我用这一行代码删除了我的"位图太大......"问题:

Picasso.load(resourceId).fit().centerCrop().into(imageView);
Run Code Online (Sandbox Code Playgroud)

  • 快速,简单,简单的解决方案.不确定它是否是最好的,但我得到了我想要的东西.非常感谢你 (2认同)

小智 16

将图像文件drawable-nodpidrawable文件夹更改为文件夹对我有用.


小智 15

在(AndroidManifest.xml)中添加以下2个属性对我有用:

android:largeHeap="true"
android:hardwareAccelerated="false"
Run Code Online (Sandbox Code Playgroud)


She*_*rry 9

我使用了毕加索并遇到了同样的问题.图像太大,至少在尺寸,宽度或高度上都是如此.最后我在这里找到了解决方案.您可以根据显示尺寸缩小大图像并保持纵横比:

    public Point getDisplaySize(Display display) {
    Point size = new Point();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
        display.getSize(size);
    } else {
        int width = display.getWidth();
        int height = display.getHeight();
        size = new Point(width, height);
    }

    return size;
}
Run Code Online (Sandbox Code Playgroud)

并使用此方法通过Picasso加载图像:

    final Point displySize = getDisplaySize(getWindowManager().getDefaultDisplay());
        final int size = (int) Math.ceil(Math.sqrt(displySize.x * displySize.y));
        Picasso.with(this)
                .load(urlSource)
                .resize(size, size)
                .centerInside()
                .into(imageViewd);
Run Code Online (Sandbox Code Playgroud)

为了获得更好的性能,您可以根据显示屏的宽度和高度下载图像,而不是整个图像:

    public String reviseImageUrl(final Integer displayWidth,     final Integer displayHeight,
        final String originalImageUrl) {
    final String revisedImageUrl;

    if (displayWidth == null && displayHeight == null) {
        revisedImageUrl = originalImageUrl;
    } else {
        final Uri.Builder uriBuilder = Uri.parse(originalImageUrl).buildUpon();

        if (displayWidth != null && displayWidth > 0) {
            uriBuilder.appendQueryParameter(QUERY_KEY_DISPLAY_WIDTH, String.valueOf(displayWidth));
        }

        if (displayHeight != null && displayHeight > 0) {
            uriBuilder.appendQueryParameter(QUERY_KEY_DISPLAY_HEIGHT, String.valueOf(displayHeight));
        }

        revisedImageUrl = uriBuilder.toString();
    }

    return revisedImageUrl;
}

    final String newImageUlr = reviseImageUrl(displySize.x, displySize.y, urlSource);
Run Code Online (Sandbox Code Playgroud)

然后:

    Picasso.with(this)
                .load(newImageUlr)
                .resize(size, size)
                .centerInside()
                .into(imageViewd);
Run Code Online (Sandbox Code Playgroud)

编辑:getDisplaySize()

display.getWidth()/getHeight()已弃用.而不是Display使用DisplayMetrics.

public Point getDisplaySize(DisplayMetrics displayMetrics) {
        int width = displayMetrics.widthPixels;
        int height = displayMetrics.heightPixels;
        return new Point(width, height);
}
Run Code Online (Sandbox Code Playgroud)


Lar*_*cho 6

BitmapRegionDecoder 诀窍.

您可以覆盖onDraw(Canvas canvas),启动新线程并解码用户可见的区域.


die*_*ima 5

正如Larcho所指出的,从API级别10开始,您可以使用BitmapRegionDecoder从图像加载特定区域,通过这种方式,您可以通过在内存中分配所需的区域来完成以高分辨率显示大图像.我最近开发了一个lib,它通过触摸手势处理提供大图像的可视化.源代码和示例可在此处获得.