最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android中超大圖片無(wú)法顯示的問(wèn)題解決

 更新時(shí)間:2017年01月18日 11:58:19   作者:viclee108  
最近在工作中發(fā)現(xiàn)一個(gè)問(wèn)題,在做圖片瀏覽的時(shí)候發(fā)現(xiàn)超大圖圖片無(wú)法顯示,無(wú)奈只能上網(wǎng)找解決方法,后來(lái)通過(guò)測(cè)試找到了解決的方法,下面這篇文章就主要介紹了Android中超大圖無(wú)法顯示的問(wèn)題解決方法,需要的朋友可以參考借鑒。

發(fā)現(xiàn)問(wèn)題

最近在做圖片瀏覽功能時(shí)遇到了一個(gè)很蛋疼的問(wèn)題,在開(kāi)啟硬件加速情況下,超大圖無(wú)法正常顯示(圖的長(zhǎng)寬有一個(gè)大于9000),而且程序不會(huì)crash,只是圖片加載不出來(lái),View顯示為黑色。通過(guò)查看日志,發(fā)現(xiàn)系統(tǒng)打印出了下面的內(nèi)容:

W OpenGLRenderer( 4014): Bitmap too large to be uploaded into a texture (600x9518, max=8192x8192) 

從日志內(nèi)容可以看出,這是由OpenGL打印出來(lái)的日志,是由于圖片的尺寸太大導(dǎo)致的。而且我們可以發(fā)現(xiàn),由于這個(gè)問(wèn)題系統(tǒng)日志是以Warning級(jí)別打印出來(lái)的,并沒(méi)有拋出異常,程序并不會(huì)報(bào)錯(cuò),只是圖片顯示不出來(lái),很難發(fā)現(xiàn)問(wèn)題。當(dāng)我們把頁(yè)面的硬件加速關(guān)掉后,圖片就可以顯示出來(lái)了。

問(wèn)題分析

從日志最后的內(nèi)容可以看出,OpenGL對(duì)圖片尺寸的限制是8192,這個(gè)尺寸是怎么得到的呢?是否所有的設(shè)備都是這個(gè)值呢?

要解釋這個(gè)問(wèn)題,需要先來(lái)看一下GLES10中的一個(gè)常量GL_MAX_TEXTURE_SIZE,從字面上看,它表示Texture的最大值。 查看文檔:

https://www.khronos.org/opengles/sdk/1.1/docs/man/glGet.xml

這里給出的解釋是: The value gives a rough estimate of the largest texture that the GL can handle。也就是OpenGL可以處理的最大尺寸的粗略估計(jì)值。既然是粗略估計(jì)值,那肯定是有一個(gè)準(zhǔn)確值的。

網(wǎng)上搜索了一下,基本上都是說(shuō)通過(guò)執(zhí)行下面的代碼,可以得到這個(gè)準(zhǔn)確值。

int[] maxTextureSize = new int[1]; 
GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0); 

然而,這段代碼在我的設(shè)備上運(yùn)行的結(jié)果始終是0。這是由于在A(yíng)ndroid 5.0之后,在進(jìn)行OpenGL方法的調(diào)用時(shí),需要手動(dòng)創(chuàng)建OpenGL的Context。而這個(gè)工作在5.0之前是由framework來(lái)完成的。我們這里就是因?yàn)闆](méi)有創(chuàng)建這個(gè)Context導(dǎo)致調(diào)用結(jié)果為0。

那么有效的代碼就是下面這樣子的:

private void getGLESTextureLimitBelowLollipop() { 
 int[] maxSize = new int[1]; 
 GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0); 
 Toast.makeText(this," " + maxSize[0],Toast.LENGTH_LONG).show(); 
} 
 
private void getGLESTextureLimitEqualAboveLollipop() { 
 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); 
 
 Toast.makeText(this," " + maxSize[0],Toast.LENGTH_LONG).show(); 
} 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
 getGLESTextureLimitEqualAboveLollipop(); 
} else { 
 getGLESTextureLimitBelowLollipop(); 
} 

在我的5.0的手機(jī)上,執(zhí)行上面的代碼,得到這個(gè)最大值maxSize是16384,也就是說(shuō),當(dāng)圖片的長(zhǎng)和寬有一個(gè)超過(guò)這個(gè)值得時(shí)候,在開(kāi)啟硬件加速的情況下,圖片就顯示不出來(lái)了。在不同的手機(jī)上運(yùn)行上述代碼,運(yùn)行結(jié)果不盡相同,說(shuō)明這個(gè)值是設(shè)備相關(guān)的。

問(wèn)題解決

既然知道了問(wèn)題所在,下面就是想辦法來(lái)解決這個(gè)問(wèn)題了。

首先,前面既然提到了是硬件加速導(dǎo)致的這個(gè)問(wèn)題,最簡(jiǎn)單的方法當(dāng)然是關(guān)閉硬件加速,可以在A(yíng)ctivity級(jí)別,也可以在View級(jí)別關(guān)閉硬件加速。這種是屬于簡(jiǎn)單粗暴型的。
Activity級(jí)別:

android:hardwareAccelerated="false"

View級(jí)別:

view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

另外一種方法是通過(guò)縮小Bitmap的方式,保證圖片的尺寸不會(huì)超過(guò)OpenGL的限制,但是,對(duì)于查看高清圖的情況,不允許對(duì)圖片進(jìn)行縮放,這個(gè)方法是無(wú)效的。

最后也是最合理的方式,就是通過(guò)Android提供的BitmapRegionDecoder類(lèi)來(lái)處理大圖加載。它的原理是每次只根據(jù)需要加載圖片的一部分,然后根據(jù)當(dāng)前用戶(hù)的操作去截取圖片不同部分進(jìn)行更新。具體的用法可以參考官方文檔。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)各位Android開(kāi)發(fā)者們能有一定的幫助,如果有疑問(wèn)大家可以留言交流。

相關(guān)文章

最新評(píng)論

额敏县| 黔东| 克山县| 凤台县| 嘉义县| 平度市| 田东县| 天全县| 镇安县| 崇信县| 宣武区| 灌阳县| 开平市| 喜德县| 油尖旺区| 永嘉县| 闸北区| 故城县| 玉屏| 扶风县| 长子县| 永城市| 于都县| 包头市| 杭锦后旗| 来安县| 澳门| 错那县| 眉山市| 黑水县| 南和县| 汶川县| 通州区| 商丘市| 尼玛县| 福州市| 宾阳县| 富裕县| 应城市| 宁城县| 霞浦县|