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绘制的高度,那就把图片缩小。代码如下:
public void loadImage(final MediaItem mediaItem) {
if (mBitmap == null && !mDestoryDecodeThread && !mDestory) {
mHardWareDecodeFuture = ThreadPool.getInstance().submit(new ThreadPool.Job<Bitmap>() {
@Override
public Bitmap run(ThreadPool.JobContext jc) {
boolean rotated = ((mediaItem.getRotation() / 90) & 1) == 1;
int photoWidth = rotated ? mediaItem.getHeight() : mediaItem.getWidth();
int photoHeight = rotated ? mediaItem.getWidth() : mediaItem.getHeight();
final BitmapFactory.Options options = new BitmapFactory.Options();
jc.setCancelListener(new ThreadPool.CancelListener() {
@Override
public void onCancel() {
options.requestCancelDecode();
}
});
InputStream is = null;
try {
Bitmap bitmap = null;
Uri uri = mediaItem.getContentUri();
int sampleSize = 1;
if (photoHeight > mHeight || photoWidth > mWidth) {
final int heightRatio = (int) Math.floor((float) photoHeight / (float) mHeight);
final int widthRatio = (int) Math.floor((float) photoWidth / (float) mWidth);
sampleSize = heightRatio > widthRatio ? heightRatio : widthRatio;
}
options.inSampleSize = sampleSize;
if (bitmap != null) {
options.inBitmap = bitmap;
}
if (uri.toString().startsWith("file://")) {
bitmap = BitmapFactory.decodeFile(uri.toString().substring("file://".length(), uri.toString().length()), options);
} else {
is = getContext().getContentResolver().openInputStream(uri);
bitmap = BitmapFactory.decodeStream(is, null, options);
}
/*重点缩小图片大小的代码*/
int maxHeight = EglUtil.getMaxTextureSize(getContext());
if (bitmap.getHeight() > maxHeight) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
while (h > maxHeight) {
w = w / 2;
h = h / 2;
}
Bitmap b = Bitmap.createScaledBitmap(bitmap, w, h, true);
bitmap.recycle();
bitmap = b;
}
/**/
if (jc.isCancelled() || mDestory || mDestoryDecodeThread) {
WeakReference<Bitmap> ref = new WeakReference<Bitmap>(bitmap);
return null;
}
return bitmap;
} catch (Exception ex) {
} finally {
MediaItem.closeSilently(is);
}
return null;
}
}, new FutureListener<Bitmap>() {
@Override
public void onFutureDone(final Future<Bitmap> future) {
if (future != null && future.get() != null) {
post(new Runnable() {
@Override
public void run() {
mBitmap = future.get();
if (!mStopDrawBigBmp && !mDestoryDecodeThread && !mDestory) {
mScreenNailLoaded = true;
initBitmapRect();
invalidate();
} else {
if (mBitmap != null && !mBitmap.isRecycled()) {
mBitmap.recycle();
}
}
}
});
}
}
});
}
}
2.判断图片是否超过绘制的最高高度。没一台手机,可绘制的最大高度是有可能不一样的,在Android5.0以上的版本中可以获取绘制的最大高度值,代码如下:
public static int getMaxTextureSize(Context context){
if(maxTextureSize != -1){
return maxTextureSize;
}
maxTextureSize = 0;
int[] maxSize = new int[1];
try {
ConfigurationInfo configurationInfo = ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getDeviceConfigurationInfo();
int glesVersion = configurationInfo.reqGlEsVersion;
if(Build.VERSION.SDK_INT >= 21) {
//configureEGLContext
EGLDisplay mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
throw new IllegalStateException("No EGL14 display");
}
int[] version = new int[2];
if (!EGL14.eglInitialize(mEGLDisplay, version, /*offset*/ 0, version, /*offset*/ 1)) {
throw new IllegalStateException("Cannot initialize EGL14");
}
int[] attribList = {
EGL14.EGL_RED_SIZE, 8,
EGL14.EGL_GREEN_SIZE, 8,
EGL14.EGL_BLUE_SIZE, 8,
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
//EGL_RECORDABLE_ANDROID, 1,
EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT | EGL14.EGL_WINDOW_BIT,
EGL14.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] numConfigs = new int[1];
EGL14.eglChooseConfig(mEGLDisplay, attribList, /*offset*/ 0, configs, /*offset*/ 0,
configs.length, numConfigs, /*offset*/ 0);
if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
throw new IllegalStateException("eglCreateContext RGB888+recordable ES2" + ": EGL error: 0x" + Integer.toHexString(EGL14.eglGetError()));
}
int[] attrib_list = {
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
EGL14.EGL_NONE
};
EGLContext mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
attrib_list, /*offset*/ 0);
if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
throw new IllegalStateException("eglCreateContext" + ": EGL error: 0x" + Integer.toHexString(EGL14.eglGetError()));
}
if (mEGLContext == EGL14.EGL_NO_CONTEXT) {
throw new IllegalStateException("No EGLContext could be made");
}
int[] surfaceAttribs = {
EGL14.EGL_WIDTH, 64,
EGL14.EGL_HEIGHT, 64,
EGL14.EGL_NONE
};
EGLSurface surface = EGL14.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs, 0);
EGL14.eglMakeCurrent(mEGLDisplay, surface, surface, mEGLContext);
//getMaxTextureSize
if(glesVersion >= 0x20000) {
GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxSize, 0);
}else if(glesVersion >= 0x10000) {
GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
}
//releaseEGLContext
EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
EGL14.eglReleaseThread();
EGL14.eglTerminate(mEGLDisplay);
}else {
if(glesVersion >= 0x20000) {
GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxSize, 0);
}else if(glesVersion >= 0x10000) {
GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
}
}
} catch (IllegalStateException e) {
e.printStackTrace();
}
maxTextureSize = maxSize[0] > 0 ? maxSize[0] : DEFAULT_MAX_BITMAP_DIMENSION;
return maxTextureSize;
}
注意:以上获取最大高度值是在android5.0以上的版本才行。android5.0以下的版本使用:
private static final int DEFAULT_MAX_BITMAP_DIMENSION = 8196;
这样就能保证不管图片有多长,都能显示出来了。
ImageView的子类无法加载图片的更多相关文章
- Android Studio [ImageView/使用第三方库加载图片]
ImageViewActivity.class package com.xdw.a122; import android.support.v7.app.AppCompatActivity; impor ...
- [Android]异步加载图片,内存缓存,文件缓存,imageview显示图片时增加淡入淡出动画
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3574131.html 这个可以实现ImageView异步加载 ...
- android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存
经常会用到 网络文件 比如查看大图片数据 资源优化的问题,当然用开源的项目 Android-Universal-Image-Loader 或者 ignition 都是个很好的选择. 在这里把原来 ...
- ImageLoader加载图片
先导universal-image-loader-1.9.3包 在application配置 android:name=".MyApplication" intent权限 1 pa ...
- Glide 加载图片
//通过model获取到图片的url,将Url转换成bitmap对象: //设置不保存内存和硬盘缓存, 1 Glide.with(mContext).load(model.getVideoUrl()) ...
- 实例演示Android异步加载图片
本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...
- 实例演示Android异步加载图片(转)
本文给大家演示异步加载图片的分析过程.让大家了解异步加载图片的好处,以及如何更新UI.首先给出main.xml布局文件:简单来说就是 LinearLayout 布局,其下放了2个TextView和5个 ...
- android listview 异步加载图片并防止错位
网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertVie ...
- ListView异步加载图片,完美实现图文混排
昨天参加一个面试,面试官让当场写一个类似于新闻列表的页面,文本数据和图片都从网络上获取,想起我还没写过ListView异步加载图片并实现图文混排效果的文章,so,今天就来写一下,介绍一下经验. Lis ...
随机推荐
- JavaScript数学函数的操作
<script> var a=3.14; var a1=Math.ceil(a);//大于当前小数的最小整数; alert(a1); var a2=Math.floor(a);//小于当前 ...
- 教程:使用 MongoDB、WCF、OData 和 PowerBI 构建 Azure 上的商业智能解决方案
发布于 2014-05-20 作者 陈 忠岳 目录 概述 前提条件 创建 Windows Server 2012 Datacenter 虚拟机 通过 WCF(Windows Communicat ...
- 【Android 复习】:Android之ViewFlipper(一)
屏幕切换指的是在同一个Activity内屏幕见的切换,最长见的情况就是在一个FrameLayout内有多个页面,比如一个系统设置页面:一个个性化设置页面. 通过查看Android API文档可以发现, ...
- git diff old mode 100755 new mode 100644
755 vs 644 在linux下载了Qt的软件仓库,拷贝了一份到windows下.在 msysgit 下,发现所有的文件都被修改了. 用 git diff 查看,发现是: $ git diff u ...
- Windows不能在本地计算机启动OracleDBConsoleorcl .错误代码2
Windows 不能在 本地计算机 启动 OracleDBConsoleorcl.有关更多信息,查阅系统事件日志.如果这是非 Microsoft 服务,请与服务厂商联系,并参考特定服务错误代码 2. ...
- Spark-Java版本WordCount示例
首先创建Spark的Maven工程,我这里使用的是Eclipse. 1.编写WordCountApp代码 package com.mengyao.spark.java.core; import jav ...
- oc学习之路-----搞死指针之内存存储int类型
关于每个数据类型个字节在内存中的存储地址(以int为例) 先上图 如题,为什么说好的*p = &c是1啊,为什么是513呢,一开始,我也觉得挺惊讶的,后面听老师分析了一下才知道怎么回事,但是还 ...
- tomcat部署web项目的方式 转
JavaWeb开发Tomcat中三种部署项目的方法,开始Java web开发必不可少的步骤,经过查找,觉得有篇文章介绍的不错 1.在conf目录中新建Catalina\localhost目录,在该目录 ...
- 20169210《Linux内核原理与分析》第九周作业
第一部分:实验 首先还是网易云课堂的学习,这次的课程是可执行程序的装载. 预处理.编译和链接: 可执行程序是怎么来的 以c语言代码为例的话,经过预处理,编译成汇编代码,再汇编成目标码再链接可执行文件. ...
- WinForm TextBox自定义扩展方法数据验证
本文转载:http://www.cnblogs.com/gis-crazy/archive/2013/03/17/2964132.html 查看公司项目代码时,存在这样一个问题:winform界面上有 ...