我正在将一张位图加载到ImageView中,但遇到了这个错误。我了解到这个限制与OpenGL硬件纹理的大小限制有关(2048x2048)。我需要加载的图片是一个大约有4000个像素高度的缩放图片。
我尝试在清单文件中关闭硬件加速,但没有成功。
<application
android:hardwareAccelerated="false"
....
>
是否可以将大小超过2048像素的图像加载到ImageView中?
我正在将一张位图加载到ImageView中,但遇到了这个错误。我了解到这个限制与OpenGL硬件纹理的大小限制有关(2048x2048)。我需要加载的图片是一个大约有4000个像素高度的缩放图片。
我尝试在清单文件中关闭硬件加速,但没有成功。
<application
android:hardwareAccelerated="false"
....
>
是否可以将大小超过2048像素的图像加载到ImageView中?
这并不是直接回答问题(加载大于2048的图像)的方式,而是为那些遇到这个错误的人提供一个可能的解决方案。
在我的情况下,图像在两个维度上都小于2048(确切地说是1280x727),并且问题特别出现在Galaxy Nexus上。该图像位于 drawable 文件夹中,没有任何合格的文件夹。 Android假定没有密度限定符的drawable是mdpi,并将它们缩放到其他密度,例如在这种情况下将xhdpi缩放2倍。将有问题的图片移动到
drawable-nodpi 中以防止缩放可以解决问题。
setImageBitmap
来设置图像。在这种情况下该怎么办? - Tushar Gognadrawable
文件夹中。我将它移动到了drawable-hdpi
文件夹中,现在它可以正常工作了。谢谢! - user2230662我是这样缩小图像的:
ImageView iv = (ImageView)waypointListView.findViewById(R.id.waypoint_picker_photo);
Bitmap d = new BitmapDrawable(ctx.getResources() , w.photo.getAbsolutePath()).getBitmap();
int nh = (int) ( d.getHeight() * (512.0 / d.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(d, 512, nh, true);
iv.setImageBitmap(scaled);
ctx
是什么意思? - sabith.ak所有渲染都基于OpenGL,因此您不能超过此限制(GL_MAX_TEXTURE_SIZE
取决于设备,但最小值为2048x2048,因此任何尺寸小于2048x2048的图像都适合)。
对于如此大的图像,如果您想在移动设备上进行缩放,应该设置类似于Google地图的系统。将图像分成几个部分,并定义多个分辨率。
或者,在显示图像之前可以将其缩小(请参见此问题上user1352407的答案 )。
另外,要注意将图像放入哪个文件夹中,Android可能会自动缩放图像。请参阅此问题下面Pilot_51的答案。
为什么要花费大量时间手动编写/调试所有这些降采样代码,不如使用Picasso
?它是专门用来处理各种类型和/或大小的位图
的。
我只用了这一行代码就解决了我的"位图太大..."问题:
Picasso.load(resourceId).fit().centerCrop().into(imageView);
在 AndroidManifest.xml
中添加以下 2 个属性对我有用:
android:largeHeap="true"
android:hardwareAccelerated="false"
drawable
文件夹更改为drawable-nodpi
文件夹对我有用。drawable
文件夹中的任何内容。 - Chris Cirefice我使用了Picasso,但遇到了同样的问题。在宽度或高度中至少有一个图片太大了。最终我在这里找到了解决办法。您可以根据显示大小将大图缩小,并保持宽高比:
public Point getDisplaySize(Display display) {
Point size = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
display.getSize(size);
} else {
int width = display.getWidth();
int height = display.getHeight();
size = new Point(width, height);
}
return size;
}
并使用Picasso加载图片的方法:
final Point displySize = getDisplaySize(getWindowManager().getDefaultDisplay());
final int size = (int) Math.ceil(Math.sqrt(displySize.x * displySize.y));
Picasso.with(this)
.load(urlSource)
.resize(size, size)
.centerInside()
.into(imageViewd);
public String reviseImageUrl(final Integer displayWidth, final Integer displayHeight,
final String originalImageUrl) {
final String revisedImageUrl;
if (displayWidth == null && displayHeight == null) {
revisedImageUrl = originalImageUrl;
} else {
final Uri.Builder uriBuilder = Uri.parse(originalImageUrl).buildUpon();
if (displayWidth != null && displayWidth > 0) {
uriBuilder.appendQueryParameter(QUERY_KEY_DISPLAY_WIDTH, String.valueOf(displayWidth));
}
if (displayHeight != null && displayHeight > 0) {
uriBuilder.appendQueryParameter(QUERY_KEY_DISPLAY_HEIGHT, String.valueOf(displayHeight));
}
revisedImageUrl = uriBuilder.toString();
}
return revisedImageUrl;
}
final String newImageUlr = reviseImageUrl(displySize.x, displySize.y, urlSource);
然后:
Picasso.with(this)
.load(newImageUlr)
.resize(size, size)
.centerInside()
.into(imageViewd);
编辑:getDisplaySize()
display.getWidth()/getHeight()
已经过时。请使用DisplayMetrics
而不是Display
。
public Point getDisplaySize(DisplayMetrics displayMetrics) {
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
return new Point(width, height);
}
BitmapRegionDecoder
可以解决这个问题。
您可以重写 onDraw(Canvas canvas)
方法,启动新线程并解码用户可见的区域。
BitmapRegionDecoder
从图像中加载特定区域,并通过仅在内存中分配所需区域来实现以高分辨率显示大型图像。我最近开发了一个库,提供了触摸手势处理的大型图像可视化。源代码和示例在此处可用。视图级别
您可以使用以下代码在运行时禁用单个视图的硬件加速:
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);