处理Android的纹理大小限制

时间:2013-03-27 09:42:27

标签: android android-layout opengl-es android-gui

我要求在Android应用上显示一些大图像。 现在我正在使用带有源位图的ImageView。 据我所知,openGL有一定的设备无关限制 图像尺寸有多大,以便处理它。

是否有 ANY 方式显示这些图像(固定宽度,无需裁剪),无论此限制如何, 除了将图像分成多个ImageView元素?

谢谢。

2013年4月1日更新 到目前为止仍然没有运气所有建议都是为了降低图像质量。有人建议可以通过使用CPU进行处理而不是使用GPU来绕过此限制(尽管可能需要更多时间来处理)。 我不明白,是否真的无法在不降低图像质量的情况下显示固定宽度的长图像?我敢打赌,如果有人至少指出我正确的方向,我会喜欢它。

谢谢大家。

4 个答案:

答案 0 :(得分:10)

您可以使用BitmapRegionDecoder拆分更大的位图(需要API级别10)。我写了一个方法,它将利用这个类并返回一个可以放在Drawable内的ImageView

private static final int MAX_SIZE = 1024;

private Drawable createLargeDrawable(int resId) throws IOException {

    InputStream is = getResources().openRawResource(resId);
    BitmapRegionDecoder brd = BitmapRegionDecoder.newInstance(is, true);

    try {
        if (brd.getWidth() <= MAX_SIZE && brd.getHeight() <= MAX_SIZE) {
            return new BitmapDrawable(getResources(), is);
        }

        int rowCount = (int) Math.ceil((float) brd.getHeight() / (float) MAX_SIZE);
        int colCount = (int) Math.ceil((float) brd.getWidth() / (float) MAX_SIZE);

        BitmapDrawable[] drawables = new BitmapDrawable[rowCount * colCount];

        for (int i = 0; i < rowCount; i++) {

            int top = MAX_SIZE * i;
            int bottom = i == rowCount - 1 ? brd.getHeight() : top + MAX_SIZE;

            for (int j = 0; j < colCount; j++) {

                int left = MAX_SIZE * j;
                int right = j == colCount - 1 ? brd.getWidth() : left + MAX_SIZE;

                Bitmap b = brd.decodeRegion(new Rect(left, top, right, bottom), null);
                BitmapDrawable bd = new BitmapDrawable(getResources(), b);
                bd.setGravity(Gravity.TOP | Gravity.LEFT);
                drawables[i * colCount + j] = bd;
            }
        }

        LayerDrawable ld = new LayerDrawable(drawables);
        for (int i = 0; i < rowCount; i++) {
            for (int j = 0; j < colCount; j++) {
                ld.setLayerInset(i * colCount + j, MAX_SIZE * j, MAX_SIZE * i, 0, 0);
            }
        }

        return ld;
    }
    finally {
        brd.recycle();
    }
}

该方法将检查两个轴中的可绘制资源是否小于MAX_SIZE(1024)。如果是,它只返回drawable。如果不是,它会将图像分开并解码图像的块并将它们放在LayerDrawable中。

我选择了1024,因为我相信大多数可用的手机都支持至少那么大的图像。如果你想找到手机的实际纹理大小限制,你必须通过OpenGL做一些时髦的东西,而这不是我想要深入研究的。

我不确定您是如何访问图像的,所以我认为它们位于您的可绘制文件夹中。如果情况并非如此,那么重构该方法以获取您需要的任何参数应该相当容易。

答案 1 :(得分:3)

你可以使用BitmapFactoryOptions来减少图片的大小。你可以使用这样的东西:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 3; //reduce size 3 times

答案 2 :(得分:2)

你看过你的地图是如何工作的吗?我曾经为地图做了一个渲染器。您可以使用相同的技巧来显示图像。

将图像划分为方形图块(例如128x128像素)。创建自定义imageView支持从图块渲染。您的imageView知道它现在应该显示的位图的哪个部分,并且只显示从SD卡加载它们所需的图块。使用这样的瓷砖地图,您可以显示无尽的图像。

答案 3 :(得分:0)

如果您向我们提供了位图的尺寸,这将有所帮助。

请理解OpenGL符合自然数学限制。

例如,有一个很好的理由,OpenGL中的纹理必须是x的幂。这实际上是任何降尺度的数学运算都可以干净利落而没有任何余数的唯一方法。

因此,如果您向我们提供给您带来麻烦的最小位图的确切尺寸,我们中的一些人可能会告诉您正在运行的实际限制类型。