ImageView的子类无法加载图片

在图片预览时,偶现图片无法现实,在查看程序的时候发现Bitmap是实际存在的,但是在ImageView中缺绘制不出来,这个问题困然了我很久,查看代码也查不出原因,再加上是偶现的,查原因时费了不少时间。

先来看看异常:

10-14 09:53:34.902   9003-10023/? W/OpenGLRenderer﹕ Bitmap too large to be uploaded into a texture (1024x9297, max=8192x8192)
10-14 09:53:34.902   9003-10023/? W/OpenGLRenderer﹕ Shape too large to be rendered into a texture (940x8510, max=8192x8192)
10-14 09:53:34.917   9003-10023/? W/OpenGLRenderer﹕ Bitmap too large to be uploaded into a texture (1024x9297, max=8192x8192)
10-14 09:53:34.919   9003-10023/? W/OpenGLRenderer﹕ Bitmap too large to be uploaded into a texture (1024x9297, max=8192x8192)
10-14 09:53:34.919   9003-10023/? W/OpenGLRenderer﹕ Bitmap too large to be uploaded into a texture (1024x9297, max=8192x8192)

 

其实是因为图片过长的原因,图片可以绘制的最大高度为8192,而我的图片高度为9297,在Canvas绘制时,OpenGL无法绘制出来,所以导致在预览长图时无法显示出来。

修改方式:

1.在异步加载图片时,判断图片的宽高,如果高度超出了底层OpenGL绘制的高度,那就把图片缩小。代码如下:

 1 public void loadImage(final MediaItem mediaItem) {
 2         if (mBitmap == null && !mDestoryDecodeThread && !mDestory) {
 3             mHardWareDecodeFuture = ThreadPool.getInstance().submit(new ThreadPool.Job<Bitmap>() {
 4                 @Override
 5                 public Bitmap run(ThreadPool.JobContext jc) {
 6                     boolean rotated = ((mediaItem.getRotation() / 90) & 1) == 1;
 7                     int photoWidth = rotated ? mediaItem.getHeight() : mediaItem.getWidth();
 8                     int photoHeight = rotated ? mediaItem.getWidth() : mediaItem.getHeight();
 9                     final BitmapFactory.Options options = new BitmapFactory.Options();
10                     jc.setCancelListener(new ThreadPool.CancelListener() {
11                         @Override
12                         public void onCancel() {
13                             options.requestCancelDecode();
14                         }
15                     });
16                     InputStream is = null;
17                     try {
18                         Bitmap bitmap = null;
19                         Uri uri = mediaItem.getContentUri();
20                         int sampleSize = 1;
21                         if (photoHeight > mHeight || photoWidth > mWidth) {
22                             final int heightRatio = (int) Math.floor((float) photoHeight / (float) mHeight);
23                             final int widthRatio = (int) Math.floor((float) photoWidth / (float) mWidth);
24                             sampleSize = heightRatio > widthRatio ? heightRatio : widthRatio;
25                         }
26                         options.inSampleSize = sampleSize;
27                         if (bitmap != null) {
28                             options.inBitmap = bitmap;
29                         }
30 
31                         if (uri.toString().startsWith("file://")) {
32                             bitmap = BitmapFactory.decodeFile(uri.toString().substring("file://".length(), uri.toString().length()), options);
33                         } else {
34                             is = getContext().getContentResolver().openInputStream(uri);
35                             bitmap = BitmapFactory.decodeStream(is, null, options);
36                         }
37 
38                         /*重点缩小图片大小的代码*/
39                         int maxHeight = EglUtil.getMaxTextureSize(getContext());
40                         if (bitmap.getHeight() > maxHeight) {
41                             int w = bitmap.getWidth();
42                             int h = bitmap.getHeight();
43                             while (h > maxHeight) {
44                                 w = w / 2;
45                                 h = h / 2;
46                             }
47                             Bitmap b = Bitmap.createScaledBitmap(bitmap, w, h, true);
48                             bitmap.recycle();
49                             bitmap = b;
50                         }
51                         /**/
52 
53                         if (jc.isCancelled() || mDestory || mDestoryDecodeThread) {
54                             WeakReference<Bitmap> ref = new WeakReference<Bitmap>(bitmap);
55                             return null;
56                         }
57                         return bitmap;
58                     } catch (Exception ex) {
59                     } finally {
60                         MediaItem.closeSilently(is);
61                     }
62                     return null;
63                 }
64             }, new FutureListener<Bitmap>() {
65                 @Override
66                 public void onFutureDone(final Future<Bitmap> future) {
67                     if (future != null && future.get() != null) {
68                         post(new Runnable() {
69                             @Override
70                             public void run() {
71                                 mBitmap = future.get();
72                                 if (!mStopDrawBigBmp && !mDestoryDecodeThread && !mDestory) {
73                                     mScreenNailLoaded = true;
74                                     initBitmapRect();
75                                     invalidate();
76                                 } else {
77                                     if (mBitmap != null && !mBitmap.isRecycled()) {
78                                         mBitmap.recycle();
79                                     }
80                                 }
81 
82 
83                             }
84                         });
85                     }
86                 }
87             });
88         }
89     }

2.判断图片是否超过绘制的最高高度。没一台手机,可绘制的最大高度是有可能不一样的,在Android5.0以上的版本中可以获取绘制的最大高度值,代码如下:

 1 public static int getMaxTextureSize(Context context){
 2         if(maxTextureSize != -1){
 3             return maxTextureSize;
 4         }
 5         maxTextureSize = 0;
 6         int[] maxSize = new int[1];
 7         try {
 8             ConfigurationInfo configurationInfo = ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getDeviceConfigurationInfo();
 9             int glesVersion = configurationInfo.reqGlEsVersion;
10             if(Build.VERSION.SDK_INT >= 21) {
11                 //configureEGLContext
12                 EGLDisplay mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
13                 if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
14                     throw new IllegalStateException("No EGL14 display");
15                 }
16                 int[] version = new int[2];
17                 if (!EGL14.eglInitialize(mEGLDisplay, version, /*offset*/ 0, version, /*offset*/ 1)) {
18                     throw new IllegalStateException("Cannot initialize EGL14");
19                 }
20                 int[] attribList = {
21                         EGL14.EGL_RED_SIZE, 8,
22                         EGL14.EGL_GREEN_SIZE, 8,
23                         EGL14.EGL_BLUE_SIZE, 8,
24                         EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
25                         //EGL_RECORDABLE_ANDROID, 1,
26                         EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT | EGL14.EGL_WINDOW_BIT,
27                         EGL14.EGL_NONE
28                 };
29                 EGLConfig[] configs = new EGLConfig[1];
30                 int[] numConfigs = new int[1];
31                 EGL14.eglChooseConfig(mEGLDisplay, attribList, /*offset*/ 0, configs, /*offset*/ 0,
32                         configs.length, numConfigs, /*offset*/ 0);
33                 if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
34                     throw new IllegalStateException("eglCreateContext RGB888+recordable ES2" + ": EGL error: 0x" + Integer.toHexString(EGL14.eglGetError()));
35                 }
36                 int[] attrib_list = {
37                         EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
38                         EGL14.EGL_NONE
39                 };
40                 EGLContext mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
41                         attrib_list, /*offset*/ 0);
42                 if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
43                     throw new IllegalStateException("eglCreateContext" + ": EGL error: 0x" + Integer.toHexString(EGL14.eglGetError()));
44                 }
45                 if (mEGLContext == EGL14.EGL_NO_CONTEXT) {
46                     throw new IllegalStateException("No EGLContext could be made");
47                 }
48                 int[] surfaceAttribs = {
49                         EGL14.EGL_WIDTH, 64,
50                         EGL14.EGL_HEIGHT, 64,
51                         EGL14.EGL_NONE
52                 };
53                 EGLSurface surface = EGL14.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs, 0);
54                 EGL14.eglMakeCurrent(mEGLDisplay, surface, surface, mEGLContext);
55                 //getMaxTextureSize
56                 if(glesVersion >= 0x20000) {
57                     GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxSize, 0);
58                 }else if(glesVersion >= 0x10000) {
59                     GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
60                 }
61                 //releaseEGLContext
62                 EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
63                 EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
64                 EGL14.eglReleaseThread();
65                 EGL14.eglTerminate(mEGLDisplay);
66             }else {
67                 if(glesVersion >= 0x20000) {
68                     GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxSize, 0);
69                 }else if(glesVersion >= 0x10000) {
70                     GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
71                 }
72             }
73         } catch (IllegalStateException e) {
74             e.printStackTrace();
75         }
76         maxTextureSize = maxSize[0] > 0 ? maxSize[0] : DEFAULT_MAX_BITMAP_DIMENSION;
77         return maxTextureSize;
78     }

注意:以上获取最大高度值是在android5.0以上的版本才行。android5.0以下的版本使用:

private static final int DEFAULT_MAX_BITMAP_DIMENSION = 8196;

这样就能保证不管图片有多长,都能显示出来了。

posted @ 2015-10-29 16:21  年轮里的遐想  阅读(865)  评论(0编辑  收藏  举报