【问题标题】:Android - loading large bitmaps into TouchImageViewAndroid - 将大位图加载到 TouchImageView
【发布时间】:2016-06-06 05:55:33
【问题描述】:

我是 Android 新手,但做过一些 iOS 工作。从三星 S4 (4.4.4) 上的相机图像加载位图时出现错误:

bmp = BitmapFactory.decodeFile(photoFilePath, options);

imgView.setImageBitmap(bmp);

这里的imgView是一个TouchImageView。 (我尝试使用 ImageViewZoom,但无法将其导入 AndroidStudio。)

我收到此错误:

W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (4128x3096, max=4096x4096)

来自 iOS 我很惊讶 Android 无法从手机自带的摄像头加载图像!我希望有一个不太难的方法。这一定是可能的,因为画廊似乎能够做到这一点。 我在网上看到的示例(建议您对图像进行二次采样)似乎没有抓住重点。使用平移和缩放(应该内置在 ImageView 中),图像视图只是一个更大的图像的小窗口。您不必使位图适合视图的像素大小。我担心这个愚蠢的建议(下采样)反映了 Android 的严重缺陷。

【问题讨论】:

    标签: android image bitmap imageview


    【解决方案1】:

    我认为错误消息与 OpenGL 而非 Android 有关。 GPU 可能会限制最大纹理分辨率。对于您的情况,即 4096x4096 像素。建议开发者将缩小版本加载到 UI 中,因为在手机等有限屏幕显示中查看大图像是不合理的。有关这方面的更多信息,请访问here

    如果您需要查看实际尺寸的大图像,则可以只绘制图像的可见部分。

    【讨论】:

    • iPhone是手机,没有这个限制。
    • Android 因为 Honeycomb 使用 GPU 硬件加速来显示屏幕上显示的所有内容。所以View 基本上只是附有纹理的 3D 多边形。它是由 Android 完成的,对开发人员来说大多是透明的,而在 iOS 中,AFAIK 并非如此。
    【解决方案2】:

    我认为答案是“不容易”。我怀疑这一点,但必须检查以确保。我确实发现在清单中设置android:hardwareAccelerated = "false" 允许加载大型位图,但随后应用程序很快就会因内存不足而崩溃。有趣的是,缺乏硬件加速似乎对性能没有太大影响。

    【讨论】:

      【解决方案3】:

      我的库旨在解决这个问题,它最初对图像进行二次采样,然后在您放大时加载更高分辨率的图块。如果您仔细观察,您会发现大多数 Android 图库应用程序都在做同样的事情。

      https://github.com/davemorrissey/subsampling-scale-image-view

      【讨论】:

      • 这看起来像一个不错的库。不幸的是,除了只显示我的应用程序还需要访问整个位图以进行图像处理。
      【解决方案4】:

      如果任何尺寸更大,您可以做的是获得最大纹理尺寸和缩放图像。

      不幸的是,我不记得我从哪里得到这个 sn-p(它不是我的)。 很长一段时间以来,它在生产中都可以正常工作。

      public int provideMaxTextureSize() {
              EGL10 egl = (EGL10) EGLContext.getEGL();
      
              EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
              int[] vers = new int[2];
              egl.eglInitialize(dpy, vers);
      
              int[] configAttr = {
                      EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RGB_BUFFER,
                      EGL10.EGL_LEVEL, 0,
                      EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
                      EGL10.EGL_NONE
              };
              EGLConfig[] configs = new EGLConfig[1];
              int[] numConfig = new int[1];
              egl.eglChooseConfig(dpy, configAttr, configs, 1, numConfig);
              if (numConfig[0] == 0) {
                  // TROUBLE! No config found.
              }
              EGLConfig config = configs[0];
      
              int[] surfAttr = {
                      EGL10.EGL_WIDTH, 64,
                      EGL10.EGL_HEIGHT, 64,
                      EGL10.EGL_NONE
              };
              EGLSurface surf = egl.eglCreatePbufferSurface(dpy, config, surfAttr);
              final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;  // missing in EGL10
              int[] ctxAttrib = {
                      EGL_CONTEXT_CLIENT_VERSION, 1,
                      EGL10.EGL_NONE
              };
              EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, ctxAttrib);
              egl.eglMakeCurrent(dpy, surf, surf, ctx);
              int[] maxSize = new int[1];
              GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
              egl.eglMakeCurrent(dpy, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
                      EGL10.EGL_NO_CONTEXT);
              egl.eglDestroySurface(dpy, surf);
              egl.eglDestroyContext(dpy, ctx);
              egl.eglTerminate(dpy);
      
              return maxSize[0];
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-29
        • 2012-02-18
        • 1970-01-01
        相关资源
        最近更新 更多