Android “位图太大无法上传到纹理中”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10271020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Bitmap too large to be uploaded into a texture"
提问by Ollie C
I'm loading a bitmap into an ImageView, and seeing this error. I gather this limit relates to a size limit for OpenGL hardware textures (2048x2048). The image I need to load is a pinch-zoom image of about 4,000 pixels high.
我正在将位图加载到 ImageView 中,并看到此错误。我认为此限制与 OpenGL 硬件纹理 (2048x2048) 的大小限制有关。我需要加载的图像是大约 4,000 像素高的缩放图像。
I've tried turning off hardware acceleration in the manifest, but no joy.
我试过在清单中关闭硬件加速,但没有任何乐趣。
<application
android:hardwareAccelerated="false"
....
>
Is it possible to load an image larger than 2048 pixels into an ImageView?
是否可以将大于 2048 像素的图像加载到 ImageView 中?
采纳答案by jptsetung
All rendering is based on OpenGL, so no you can't go over this limit (GL_MAX_TEXTURE_SIZE
depends on the device, but the minimum is 2048x2048, so any image lower than 2048x2048 will fit).
所有渲染均基于 OpenGL,因此您不能超过此限制(GL_MAX_TEXTURE_SIZE
取决于设备,但最小值为 2048x2048,因此任何低于 2048x2048 的图像都适合)。
With such big images, if you want to zoom in out, and in a mobile, you should setup a system similar to what you see in google maps for example. With the image split in several pieces, and several definitions.
对于如此大的图像,如果你想放大,在手机中,你应该设置一个类似于你在谷歌地图中看到的系统。将图像分成几部分和几个定义。
Or you could scale down the image before displaying it (see user1352407's answeron this question).
或者您可以在显示之前缩小图像(请参阅user1352407对此问题的回答)。
And also, be careful to which folder you put the image into, Android can automatically scale up images. Have a look at Pilot_51's answerbelow on this question.
而且,请注意您将图像放入哪个文件夹,Android 可以自动放大图像。看看下面关于这个问题的Pilot_51 的回答。
回答by Pilot_51
This isn't a direct answer to the question (loading images >2048), but a possible solution for anyone experiencing the error.
这不是问题的直接答案(加载图像 > 2048),而是任何遇到错误的人的可能解决方案。
In my case, the image was smaller than 2048 in both dimensions (1280x727 to be exact) and the issue was specifically experienced on a Galaxy Nexus. The image was in the drawable
folder and none of the qualified folders. Android assumes drawables without a density qualifier are mdpi and scales them up or down for other densities, in this case scaled up 2x for xhdpi. Moving the culprit image to drawable-nodpi
to prevent scaling solved the problem.
就我而言,图像在两个维度上都小于 2048(准确地说是 1280x727),并且这个问题是在 Galaxy Nexus 上特别出现的。图像在drawable
文件夹中,没有任何合格的文件夹。Android 假定没有密度限定符的可绘制对象是 mdpi,并根据其他密度将它们放大或缩小,在这种情况下,xhdpi 放大 2 倍。移动罪魁祸首图像以drawable-nodpi
防止缩放解决了问题。
回答by user1352407
I have scaled down the image in this way:
我以这种方式缩小了图像:
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);
回答by Phileo99
Instead of spending hours upon hours trying to write/debug all this downsampling code manually, why not use Picasso
? It was made for dealing with bitmaps
of all types and/or sizes.
与其花费数小时的时间尝试手动编写/调试所有这些下采样代码,为什么不使用Picasso
?它是为处理bitmaps
所有类型和/或大小而设计的。
I have used this single line of code to remove my "bitmap too large...."problem:
我已经使用这一行代码来删除我的“位图太大....”问题:
Picasso.load(resourceId).fit().centerCrop().into(imageView);
回答by Sachin Lala
Addition of the following 2 attributes in (AndroidManifest.xml
) worked for me:
在 ( AndroidManifest.xml
) 中添加以下 2 个属性对我有用:
android:largeHeap="true"
android:hardwareAccelerated="false"
回答by Asha Antony
Changing the image file to drawable-nodpi
folder from drawable
folder worked for me.
将图像文件drawable-nodpi
从drawable
文件夹更改为文件夹对我有用。
回答by Sherry
I used Picasso and had the same problem. image was too large at least in on size, width or height. finally I found the solution here. you can scale the large image down according to display size and also keep the aspect ratio:
我使用了毕加索并遇到了同样的问题。图像太大,至少在尺寸、宽度或高度上。最后我在这里找到了解决方案。您可以根据显示尺寸缩小大图像并保持纵横比:
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;
}
and use this method for loading image by 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);
also for better performance you can download the image according to width and height of the display screen, not whole the image:
同样为了更好的性能,您可以根据显示屏的宽度和高度下载图像,而不是整个图像:
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);
and then:
进而:
Picasso.with(this)
.load(newImageUlr)
.resize(size, size)
.centerInside()
.into(imageViewd);
EDIT: getDisplaySize()
编辑:getDisplaySize()
display.getWidth()/getHeight()
is deprecated. Instead of Display
use DisplayMetrics
.
display.getWidth()/getHeight()
已弃用。而不是Display
使用DisplayMetrics
.
public Point getDisplaySize(DisplayMetrics displayMetrics) {
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
return new Point(width, height);
}
回答by Larcho
BitmapRegionDecoder
does the trick.
BitmapRegionDecoder
诀窍。
You can override onDraw(Canvas canvas)
, start a new Thread and decode the area visible to the user.
您可以覆盖onDraw(Canvas canvas)
,启动一个新线程并解码用户可见的区域。
回答by diegocarloslima
As pointed by Larcho, starting from API level 10, you can use BitmapRegionDecoder
to load specific regions from an image and with that, you can accomplish to show a large image in high resolution by allocating in memory just the needed regions. I've recently developed a lib that provides the visualisation of large images with touch gesture handling. The source code and samples are available here.
正如 Larcho 所指出的,从 API 级别 10 开始,您可以使用BitmapRegionDecoder
从图像加载特定区域,然后通过在内存中仅分配所需区域来完成以高分辨率显示大图像。我最近开发了一个库,它通过触摸手势处理提供大图像的可视化。源代码和示例可在此处获得。
回答by Abhijit Gujar
I ran through same problem, here is my solution. set the width of image same as android screen width and then scales the height
我遇到了同样的问题,这是我的解决方案。将图像的宽度设置为与 android 屏幕宽度相同,然后缩放高度
Bitmap myBitmap = BitmapFactory.decodeFile(image.getAbsolutePath());
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Log.e("Screen width ", " "+width);
Log.e("Screen height ", " "+height);
Log.e("img width ", " "+myBitmap.getWidth());
Log.e("img height ", " "+myBitmap.getHeight());
float scaleHt =(float) width/myBitmap.getWidth();
Log.e("Scaled percent ", " "+scaleHt);
Bitmap scaled = Bitmap.createScaledBitmap(myBitmap, width, (int)(myBitmap.getWidth()*scaleHt), true);
myImage.setImageBitmap(scaled);
This is better for any size android screen. let me know if it works for you.
这对于任何尺寸的安卓屏幕都更好。请让我知道这对你有没有用。