“位图太大,无法上传到纹理”
我正在加载一个ImageView到一个ImageView,并看到这个错误。 我收集这个限制与OpenGL硬件纹理的大小限制(2048×2048)有关。 我需要加载的图像是一个大约4000像素的捏缩放图像。
我已经尝试closures清单中的硬件加速,但没有喜悦。
<application android:hardwareAccelerated="false" .... >
是否有可能将大于2048像素的图像加载到ImageView中?
所有渲染都基于OpenGL,所以不能超过这个限制( GL_MAX_TEXTURE_SIZE
取决于设备,但最小值是2048×2048,因此低于2048×2048的图像将适合)。
有了这么大的图片,如果你想放大,在手机上,你应该设置一个类似于你在谷歌地图中看到的系统。 随着图像分成几个部分,以及几个定义。
或者,您可以在显示图像之前缩小图像(请参阅user1352407对此问题的回答 )。
而且,要注意将图片放入哪个文件夹,Android可以自动放大图像。 在这个问题上看看Pilot_51的答案 。
这不是对问题的直接回答(加载图像> 2048),而是任何人遇到错误的可能解决scheme。
在我的情况下,这个图像在两个维度上都小于2048(准确的说是1280×727),这个问题在Galaxy Nexus上特别经历过。 该图像是在drawable
文件夹中,没有合格的文件夹。 Android假定没有密度限定符的drawable是mdpi,并将其缩放为其他密度,在这种情况下,为xhdpi放大2倍。 将罪魁祸首的图像移动到drawable-nodpi
以防止缩放解决了这个问题。
我用这种方式缩小了图像:
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);
试图手动编写/debugging所有这些下采样代码,而不是花费数小时,为什么不使用毕加索? 它是用来处理所有types和/或大小的位图。
我用这一行代码来删除我的“位图太大….”的问题:
Picasso.with(context).load(resourceId).fit().centerCrop().into(imageView);
将图像文件从drawable
文件夹更改为drawable-nodpi
文件夹。
我用毕加索,也有同样的问题。 至less在大小,宽度或高度上的图像太大了。 最后我在这里find了解决办法。 您可以根据显示器尺寸缩小大图像,并保持宽高比:
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; }
并使用这种方法来加载毕加索的图像:
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);
也为了更好的performance,您可以根据显示屏幕的宽度和高度来下载图像,而不是整个图像:
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()
已弃用。 而不是Display
使用DisplayMetrics
。
public Point getDisplaySize(DisplayMetrics displayMetrics) { int width = displayMetrics.widthPixels; int height = displayMetrics.heightPixels; return new Point(width, height); }
BitmapRegionDecoder的诀窍。
您可以重写onDraw(Canvascanvas),启动一个新的线程并解码对用户可见。
正如Larcho所指出的,从API级别10开始,您可以使用BitmapRegionDecoder
从图像加载特定区域,通过在内存中分配所需的区域,可以实现以高分辨率显示大图像。 我最近开发了一个lib,提供了触摸手势处理的大图像的可视化。 源代码和示例可在这里find 。
(AndroidManifest.xml)中添加以下两个属性为我工作:
- 机器人:largeHeap = “真”
- 机器人:硬件加速=“假”
我遇到了同样的问题,这里是我的解决scheme。 设置图像的宽度与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);
这对于任何尺寸的android屏幕都更好。 让我知道,如果它适合你。
缩小图像:
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // Set height and width in options, does not return an image and no resource taken BitmapFactory.decodeStream(imagefile, null, options); int pow = 0; while (options.outHeight >> pow > reqHeight || options.outWidth >> pow > reqWidth) pow += 1; options.inSampleSize = 1 << pow; options.inJustDecodeBounds = false; image = BitmapFactory.decodeStream(imagefile, null, options);
图像将以reqHeight和reqWidth的大小缩小。 据我所知在样本大小只采取2值的权力。
感谢这里的所有贡献者,但是我尝试了所有上述的解决scheme,一个接一个地完成了很多个小时,而且没有任何一个能够工作! 最后,我决定寻找一个关于用Android相机拍摄图像并显示它们的官方示例。 官方的例子( 这里 )终于给了我唯一的工作方法。 下面我介绍了在该示例应用程序中find的解决scheme:
public void setThumbnailImageAndSave(final ImageView imgView, File imgFile) { /* There isn't enough memory to open up more than a couple camera photos */ /* So pre-scale the target bitmap into which the file is decoded */ /* Get the size of the ImageView */ int targetW = imgView.getWidth(); int targetH = imgView.getHeight(); /* Get the size of the image */ BitmapFactory.Options bmOptions = new BitmapFactory.Options(); bmOptions.inJustDecodeBounds = true; BitmapFactory.decodeFile(imgFile.getAbsolutePath(), bmOptions); int photoW = bmOptions.outWidth; int photoH = bmOptions.outHeight; /* Figure out which way needs to be reduced less */ int scaleFactor = 1; if ((targetW > 0) || (targetH > 0)) { scaleFactor = Math.min(photoW/targetW, photoH/targetH); } /* Set bitmap options to scale the image decode target */ bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = scaleFactor; bmOptions.inPurgeable = true; /* Decode the JPEG file into a Bitmap */ Bitmap bitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath(), bmOptions); /* Associate the Bitmap to the ImageView */ imgView.setImageBitmap(bitmap); imgView.setVisibility(View.VISIBLE); }
我希望早些时候知道这一点……所有这些时间:D
查看级别
您可以使用以下代码在运行时禁用单个视图的硬件加速:
myView.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
对那些希望放置小尺寸图像的人的提示:
Pilot_51的解决scheme(将图像移动到drawable-nodpi
文件夹)有效,但还有一个问题:除非将图像调整为非常大(如2000 x 3800)分辨率以适应屏幕,否则会使图像太小你的应用程序更重。
解决scheme :把你的图像文件放在drawable-hdpi
– 它对我来说就像一个魅力。
使用正确的可绘制的子文件夹解决了我。 我的解决scheme是将我的全分辨率图像(1920×1200)放入drawable-xhdpi文件夹,而不是可绘制的文件夹。
我也把缩小的图像(1280×800)放到drawable-hdpi文件夹中。
这两个解决scheme与我正在编程的2013和2012 Nexus 7平板电脑相匹配。 我还testing了其他一些平板电脑上的解决scheme。
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); ///* if (requestCode == PICK_FROM_FILE && resultCode == RESULT_OK && null != data){ uri = data.getData(); String[] prjection ={MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(uri,prjection,null,null,null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(prjection[0]); ImagePath = cursor.getString(columnIndex); cursor.close(); FixBitmap = BitmapFactory.decodeFile(ImagePath); ShowSelectedImage = (ImageView)findViewById(R.id.imageView); // FixBitmap = new BitmapDrawable(ImagePath); int nh = (int) ( FixBitmap.getHeight() * (512.0 / FixBitmap.getWidth()) ); FixBitmap = Bitmap.createScaledBitmap(FixBitmap, 512, nh, true); // ShowSelectedImage.setImageBitmap(BitmapFactory.decodeFile(ImagePath)); ShowSelectedImage.setImageBitmap(FixBitmap); } }
这个代码是工作的
我使用webview的分辨率太大。
1-)创build如下的响应html文件。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> html, body, img { margin: 0; padding: 0; height: 100%; display: block; } </style> </head> <body> <img src="img/program_first.png"> </body> </html>
2-)我在水平非常大的“img”文件夹中使用了5708×1634图像。 3-)添加“webview”你的布局和像这样设置负载。 “program1”是WebViewvariables的名称。
program1.loadUrl("file:///android_asset/program/content.html");