我正在将位图加载到ImageView中,并看到此错误。我收集到此限制与OpenGL硬件纹理(2048x2048)的大小限制有关。我需要加载的图像是约4000像素高的捏缩放图像。
我尝试关闭清单中的硬件加速,但没有任何乐趣。
<application
android:hardwareAccelerated="false"
....
>
是否可以将大于2048像素的图像加载到ImageView中?
inSampleSize方法更好。
我正在将位图加载到ImageView中,并看到此错误。我收集到此限制与OpenGL硬件纹理(2048x2048)的大小限制有关。我需要加载的图像是约4000像素高的捏缩放图像。
我尝试关闭清单中的硬件加速,但没有任何乐趣。
<application
android:hardwareAccelerated="false"
....
>
是否可以将大于2048像素的图像加载到ImageView中?
inSampleSize方法更好。
Answers:
所有渲染均基于OpenGL,因此,您不能超过此限制(GL_MAX_TEXTURE_SIZE取决于设备,但最小值为2048x2048,因此任何低于2048x2048的图像都可以容纳)。
有了如此大的图像,如果您想在移动设备上进行放大,则应设置一个类似于在Google地图中看到的系统。图像分为几个部分和几个定义。
或者您可以在显示图像之前按比例缩小图像(请参阅user1352407的答案关于此问题)。
另外,请注意将图片放入哪个文件夹,Android会自动放大图片。看看下面关于这个问题的Pilot_51的答案。
这不是问题的直接答案(加载大于2048的图像),但是对于任何遇到此错误的人来说,这都是可能的解决方案。
就我而言,图像的两个尺寸均小于2048(准确地说是1280x727),并且该问题在Galaxy Nexus上特别明显。该图像在该drawable文件夹中,没有合格的文件夹。Android假定不具有密度限定符的可绘制对象为mdpi,并针对其他密度将其放大或缩小,在本例中,对于xhdpi,其放大两倍。移动罪魁祸首图像以drawable-nodpi防止缩放可解决此问题。
drawable实际上使它成为一个隐藏drawable-mdpi文件夹。这也解释了为什么我的自定义地图标记看起来很糟糕(先放大,然后缩小)。
我以这种方式缩小了图像:
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意思?
为何不花大量时间尝试手动编写/调试所有这些下采样代码,为什么不使用Picasso?它是为处理bitmaps所有类型和/或大小而设计的。
我已经使用这一行代码来消除“位图太大...”的问题:
Picasso.load(resourceId).fit().centerCrop().into(imageView);
(AndroidManifest.xml)中添加了以下2个属性对我有用:
android:largeHeap="true"
android:hardwareAccelerated="false"
将图像文件drawable-nodpi从drawable文件夹更改为文件夹对我有用。
drawable文件夹中的任何内容。
我使用了毕加索,也遇到了同样的问题。图片太大,至少在大小,宽度或高度上太大。终于我在这里找到了解决方案。您可以根据显示尺寸缩小大图像,并保持宽高比:
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()不推荐使用。代替Display使用DisplayMetrics。
public Point getDisplaySize(DisplayMetrics displayMetrics) {
int width = displayMetrics.widthPixels;
int height = displayMetrics.heightPixels;
return new Point(width, height);
}
正如Larcho所指出的那样,从API级别10开始,您可以用来BitmapRegionDecoder从图像中加载特定区域,并且可以通过仅在内存中分配所需区域来完成以高分辨率显示大图像的操作。我最近开发了一个可通过触摸手势处理提供大图像可视化的库。源代码和示例可在此处获得。
我遇到了同样的问题,这是我的解决方案。设置图像的宽度与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的尺寸缩小。据我了解,inSampleSize仅接受2值的幂。
使用Glide库,而不是直接加载到imageview中
滑行:https : //github.com/bumptech/glide
Glide.with(this).load(Uri.parse(filelocation))).into(img_selectPassportPic);
我尝试了上述所有解决方案,一个接一个,花了很多小时,而且似乎都没有用!最后,我决定环顾四周,以获取有关使用Android相机捕获图像并进行显示的官方示例。官方示例(在此)最终给了我唯一可行的方法。下面,我介绍在该示例应用程序中找到的解决方案:
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);
}
@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);
}
}
此代码是有效的