“位图太大,无法上传到纹理”“位图太大,无法上传到纹理”(“Bitmap too large to

2019-05-13 14:54发布

我加载一个位图到一个ImageView的,看到这个错误。 我收集此限制涉及一个大小限制OpenGL硬件纹理(2048×2048)。 我需要加载的图像是约4000像素高捏缩放图像。

我试着在清单关闭硬件加速,但没有喜悦。

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

是否有可能装载2048个像素为​​ImageView的放大图像?

Answer 1:

所有的渲染是基于OpenGL,因此没有你不能超过这个限度去( GL_MAX_TEXTURE_SIZE取决于设备,但最低为2048×2048,所以比低2048×2048的任何图像将适合)。

有了这样大的图像,如果你想放大出来,在移动,您应该设置类似于您在谷歌地图,例如看到的系统。 随着几件图像分割,和几个定义。

或者你可以显示它(参见之前缩小图像user1352407的回答这个问题)。

而且,要小心哪个文件夹把图像分成,机器人可以自动扩展的图像。 看看Pilot_51的回答下面关于这个问题的。



Answer 2:

这不是一个直接的答案的问题(加载图像> 2048),但对任何人遇到的错误可能的解决方案。

在我的情况下,图像是在两个维度上小于2048(1280x727要准确)和问题是在Galaxy Nexus的特别经历。 该图像是在drawable文件夹,并没有一个合格的文件夹。 Android的假设没有一个密度预选赛绘项目是MDPI和规模向上或向下为其他密度,在这种情况下扩大了2倍xhdpi。 罪魁祸首图像移动到drawable-nodpi防止结垢解决了这个问题。



Answer 3:

我已缩减这样的形象:

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


Answer 4:

除了手动花费在小时小时想写/调试所有这些采样代码,为什么不使用Picasso ? 它被用于处理由bitmaps所有类型的和/或大小。

我已经使用了这一行代码删除我的“位图太大......”的问题:

Picasso.load(resourceId).fit().centerCrop().into(imageView);


Answer 5:

更改图像文件drawable-nodpi文件夹从drawable的文件夹为我工作。



Answer 6:

我用毕加索和有同样的问题。 图像太大至少在大小,宽度或高度。 最后我在这里找到了解决办法。 可以根据显示尺寸缩放大图像下来,也保持纵横比

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

也有更好的表现,你可以根据显示屏,而不是整个图像的宽度和高度下载图片:

    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);
}


Answer 7:

下列(2个属性加成AndroidManifest.xml )为我工作:

android:largeHeap="true"
android:hardwareAccelerated="false"


Answer 8:

BitmapRegionDecoder的伎俩。

您可以重写onDraw(Canvas canvas) ,开始一个新的线程和解码区域对用户可见。



Answer 9:

正如指出的Larcho,从API 10级开始,你可以使用BitmapRegionDecoder从图像和与加载特定区域,可以完成在内存中分配只是需要的地区,以显示高分辨率的大图像。 我最近开发了一个lib,提供大量图像的可视化触摸手势操作。 源代码和样品,可浏览这里 。



Answer 10:

我经历同样的问题跑了,这里是我的解决方案。 设置的图像相同的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更好。 请让我知道这对你有没有用。



Answer 11:

查看水平

您可以在下面的代码运行时的个人观点禁用硬件加速:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE,NULL);



Answer 12:

缩小图像:

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个值的功率。



Answer 13:

我尝试了所有的解决方案上面,一后的,其他的,相当多小时,似乎没有工作! 最后,我决定到处寻找关于捕获图像与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);
}


Answer 14:

注:对于那些希望把小尺寸的图像:

Pilot_51的解决方案(移动图像进行drawable-nodpi文件夹)的作品,但有一个问题:它使图像太小屏幕上,除非将图像调整到一个非常大的(如2000×3800)分辨率,以适应屏幕-那么它使您的应用程序更重。

解决方案 :把图像文件drawable-hdpi -它的工作对我来说就像魅力。



Answer 15:

使用正确绘制子解决了这个问题对我来说。 我的解决办法是把我的全分辨率图像(1920×1200)到绘制-xhdpi文件夹,而不是绘制文件夹。

我也把一个按比例缩小的图像(1280×800)到绘制,华电国际的文件夹。

这两种解决方案符合2013年和2012年的Nexus 7平板电脑,我的编程。 我还测试了一些其他平板电脑解决方案。



Answer 16:

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

    }
}

此代码是工作



Answer 17:

使用滑翔库,而不是直接加载到ImageView的

滑翔: https://github.com/bumptech/glide

Glide.with(this).load(Uri.parse(filelocation))).into(img_selectPassportPic);


文章来源: “Bitmap too large to be uploaded into a texture”