位图太大,无法上传到纹理。

159

我正在将一张位图加载到ImageView中,但遇到了这个错误。我了解到这个限制与OpenGL硬件纹理的大小限制有关(2048x2048)。我需要加载的图片是一个大约有4000个像素高度的缩放图片。

我尝试在清单文件中关闭硬件加速,但没有成功。

    <application
        android:hardwareAccelerated="false"
        ....
        >

是否可以将大小超过2048像素的图像加载到ImageView中?


1
对于任何在这里寻找答案的人,请不要忘记将您的图像放入滚动视图中,如果您想要它可以滚动的话。这样就可以消除错误了。我之前浪费了一些时间才意识到这是我的问题所在。 - Jason Ridge
对于任何想要显示大图像并仍保持图像质量的人,请参考下面@stoefln答案中的库。我使用过它,值得一试。绝对比“inSampleSize”方法更好。 - Mahendra Liya
1
@Joe Blow,当前的答案对您没有起作用吗?如果不是,那么请详细说明您在此问题的情况下遇到的问题。 - Pravin Divraniya
1
嘿 @VC.One - 关于我的那件事情让你感到不爽,确实有些奇怪。我应该点“Reward existing answer”按钮的。对于那个SO弹出窗口上的“最佳”按钮,因为它很愚蠢,所以没有人会费心地去单击。现在问题已经解决了,因为我点击了悬赏按钮。谢谢! - Fattie
1
我尽量总是支付赏金(我不喜欢积攒积分)。我猜,如果你点击我的个人资料,然后选择赏金,@VC.One,你会看到多年来来自SO的许多非常棒的问答!!!!!!! - Fattie
显示剩余5条评论
18个回答

3

我曾经遇到同样的问题,这是我的解决方案。将图像的宽度设置为与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);

这对于任何尺寸的安卓屏幕都更好。如果它适用于您,请告诉我。

2
使用Glide库代替直接加载图像到imageview
Glide:https://github.com/bumptech/glide
Glide.with(this).load(Uri.parse(filelocation))).into(img_selectPassportPic);

2
使用Glide代替Picasso很有帮助。看起来Glide默认处理这样的问题。 - Johnny Five

2

缩小图像:

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的幂值。


如何知道reqHeight和reqWidth?我的意思是,我们需要将其固定为静态值吗?还是可以根据设备更改这些值? - Prashanth Debbadwar

1

我尝试了上面所有的解决方案,一个接一个地尝试了好几个小时,但似乎都不起作用!最后,我决定寻找一些关于使用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);
}

0

使用正确的drawable子文件夹解决了我的问题。我的解决方案是将全分辨率图像(1920x1200)放入drawable-xhdpi文件夹中,而不是drawable文件夹。

我还将缩小的图像(1280x800)放入drawable-hdpi文件夹中。

这两个分辨率与我正在编程的2013年和2012年Nexus 7平板电脑相匹配。我还在其他平板电脑上测试了解决方案。


0

想要添加小尺寸图片的注意事项:

Pilot_51的解决方案(将您的图像移动到drawable-nodpi文件夹中)可以解决问题,但还有另一个问题:除非将图像调整为非常大的分辨率(如2000 x 3800)以适应屏幕,否则它会使图像在屏幕上过于小——然后会使您的应用程序更重。

解决方案:将您的图像文件放在drawable-hdpi中——这对我来说起作用了。


1
你只是掩盖了图像密度问题。在低密度硬件上,你的图像会看起来更大。 - rupps
我也认为Pilot_51的解决方案没有任何问题,你应该根据自己的需求使用适当的图像尺寸。 - Nilabja

0
@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);

    }
}

这段代码是可行的


0
将以下代码添加到清单文件中
<activity
        android:name="com.yalantis.ucrop.UCropActivity"
        android:screenOrientation="portrait"
        android:hardwareAccelerated="false"
        android:theme="@style/Theme.AppCompat.Light.NoActionBar" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接