“비트 맵이 너무 커서 텍스처에 업로드 할 수 없습니다”


154

비트 맵을 ImageView에로드하고 있는데이 오류가 나타납니다. 이 제한은 OpenGL 하드웨어 텍스처 (2048x2048)의 크기 제한과 관련이 있습니다. 로드해야하는 이미지는 높이가 약 4,000 픽셀 인 핀치 확대 이미지입니다.

매니페스트에서 하드웨어 가속을 해제하려고 시도했지만 기쁨은 없습니다.

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

2048 픽셀보다 큰 이미지를 ImageView에로드 할 수 있습니까?


1
여기를 보는 사람이라면 스크롤 가능하게하려면 이미지를 스크롤보기에 두는 것을 잊지 마십시오. 오류가 제거됩니다. 나는 그것이 내 문제라는 것을 깨닫기 전에 시간을 낭비했다.
Jason Ridge

여전히 화질을 유지하면서 큰 이미지를 표시하려는 사람은 아래 @stoefln answer의 라이브러리를 참조하십시오. 나는 그것을 사용했고 시도해 볼 가치가있다. inSampleSize접근 방식 보다 확실히 좋습니다 .
Mahendra Liya 2012

1
@Joe Blow 현재 답변이 귀하의 경우에 효과가 없었습니까? 그렇다면이 질문과 관련하여 직면 한 문제에 대해 자세히 설명해주십시오.
Pravin Divraniya

1
안녕 @ VC.One-내 남자에 대해 일을하는 것은 이상한 일이다. "기존 답변 보상"을 클릭해야합니다. 어리석기 때문에 SO 팝업에서 "최고"버튼을 엄청나게 누르는 사람은 아무도 없습니다.) 현상금을 클릭하면 모두 해결됩니다. 건배!!
Fattie

1
나는 항상 바운티를 지불하려고합니다 (포인트를 모으는 것을 좋아하지 않습니다). 내 프로필을 클릭 한 다음 바운티, @VC를 클릭하면 몇 년 동안 많은 훌륭한 QA를 볼 수 있습니다. !!!!!!!!!!!!!!!
Fattie

답변:


48

모든 렌더링은 OpenGL을 기반으로하므로이 제한을 초과 할 수 없습니다 ( GL_MAX_TEXTURE_SIZE장치에 따라 다르지만 최소값은 2048x2048이므로 2048x2048보다 낮은 이미지는 적합 함).

이러한 큰 이미지를 사용하여 확대하거나 모바일로 보려면 예를 들어 Google지도에 표시되는 것과 유사한 시스템을 설정해야합니다. 이미지가 여러 조각으로 분할되고 여러 정의가 있습니다.

또는 이미지를 표시하기 전에 이미지를 축소 할 수 있습니다 ( 이 질문에 대한 user1352407의 답변 참조 ).

또한 이미지를 넣은 폴더에주의를 기울이면 Android에서 이미지를 자동으로 확대 할 수 있습니다. 이 질문에 대한 아래 의 Pilot_51의 답변을 살펴보십시오 .


23
이 경우 갤러리 앱을 사용하여 카메라로 촬영 한 이미지를 표시하고 조작 할 수 있습니까? 2048x2048은 4MP 이미지 일 뿐이며 많은 Android 휴대 전화에서 이보다 훨씬 큰 사진을 찍으며 갤러리 앱에는 문제가없는 것 같습니다.
Ollie C

3
GL_MAX_TEXTURE_SIZE는 장치에 따라 다릅니다.
jptsetung

24
이것은 실제로 의미가 없습니다. 1286x835 픽셀의 이미지로 동일한 문제가 발생했습니다. 그리고 : Galaxy Nexus에서만이 오류 메시지가 표시되고 이미지가 표시되지 않습니다! 최첨단 스마트 폰이 그런 작은 이미지를 표시 할 수 없다는 것은 우스운 것 같습니다! 내 HTC 영웅은 그것을 표시 할 수 있습니다! 어떡해?
Zordid

1
Romain의 답변은 여기를 참조하십시오 : stackoverflow.com/questions/7428996/…
Ben Lee

3
@OllieC 갤러리 앱이 어떻게 작동하는지 알고 싶습니다. 따라서 큰 이미지를 아는 사람이나 알고있는 사람이 있다면 좋을 것입니다.
Innova

408

이 질문에 대한 직접적인 대답은 아니지만 (이미지 2048 이상로드) 오류가 발생하는 모든 사람에게 가능한 해결책입니다.

필자의 경우 이미지는 두 크기 모두에서 2048보다 작았으며 (정확히 1280x727)이 문제는 Galaxy Nexus에서 구체적으로 발생했습니다. 이미지가 drawable폴더에 있고 정규 폴더가 없습니다. Android는 밀도 한정자가없는 드로어 블이 mdpi 인 것으로 가정하고 다른 밀도에 대해 확대 또는 축소합니다 (이 경우 xhdpi의 경우 2 배 확대). drawable-nodpi조정을 방지하기 위해 범인 이미지를 이동하면 문제가 해결되었습니다.


3
드로어 블을로드하려는 메모리 문제가있었습니다. 왜 이런 일이 일어나고 있는지 이해하려고 2 시간을 보냈습니다. 간접 답변 주셔서 감사합니다.
TrueCoke

16
정답이며 이와 같이 표시해야합니다.
wblaschko

3
약 3 개월 반 정도 인 지금 저는 거의 풀 타임으로 안드로이드에서 프로그래밍을 해왔고 이제 막 깨달았습니다. drawable본질적으로 숨겨진 drawable-mdpi폴더 를 만들려면 바보 처럼 보입니다 . 이것은 또한 내 맞춤지도 표시가 끔찍해 보이는 이유를 설명했습니다 (그들은 업 스케일 된 후 다운 스케일되었습니다).
theblang

10
그래 도대체! 안드로이드 프로그래머의 99 %가 "드로어 블"이 "스케일하지 않음"을 의미한다고 생각합니다.
Matt Logan

3
이것은 내가 본 것 중 가장 유용한 답변입니다. 내가 말할 수있는 것은 현상금을 보내는 것입니다! 감사.
Fattie

105

이 방법으로 이미지를 축소했습니다.

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

2
고마워, createScaledBitmap은 너무 큰 비트 맵을 보여줄 수있게 도와주었습니다
Boy

내 문제를 해결했습니다. 감사합니다. 실제로 나는 카메라에서 이미지를
가져와

죄송하지만 "w"가 무엇인지 감지 할 수 없습니다
Bobbelinio

1
미안,이게 무슨 ctx뜻이야?
Ameer Sabith

1
@AmeerSabith는 ctx가 Context 객체 인 것처럼 보입니다 (예 : 실행중인 활동)
Matt

34

이 다운 샘플링 코드를 모두 수동으로 작성 / 디버깅하는 데 몇 시간을 소비하는 대신 왜 사용하지 Picasso않습니까? bitmaps모든 유형 및 / 또는 크기 를 처리하기 위해 만들어졌습니다 .

이 "한 줄의 코드를 사용하여 "비트 맵이 너무 큽니다 ... " 문제 를 제거했습니다 .

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

resize ()를 호출하지 않고 centerCrop ()을 사용하면 IllegalStateException이 발생합니다. 가운데 자르기가 사용될 때 라이브러리에서 크기 조정을 호출합니다.
Zsolt Boldizsár

자르기는 이미지의 크기를 조정한다는 의미이므로 완벽하게 이해됩니다.
Phileo99

2
빠르고 쉽고 간단한 솔루션. 그것이 최고인지 확실하지 않지만, 내가 원하는 것을 얻었습니다. 대단히 감사합니다
Nabin

더 큰 크기의 이미지를 위해 Picasso와 함께 대상을 사용할 때 여전히 같은 오류가 발생합니다. (
Narendra Singh

버전 2.5.3-SNAPSHOT을 사용해보십시오. 이제 큰 이미지에서 제대로 작동하는 것 같습니다
Anton Malmygin

20

( AndroidManifest.xml) 에 다음 2 가지 속성을 추가하면 나를 위해 일했습니다.

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

이것은 삼성 장치에서 내 문제를 해결했습니다. 감사합니다
Hitesh Bisht

16

drawable-nodpi폴더에서 이미지 파일을 폴더로 변경하면 drawable나에게 도움이되었습니다.


이렇게하면 Android가 기기의 크기와 화면 밀도에 따라 이미지의 크기를 자동으로 조정하지 못하게됩니다. 이것이이 솔루션이 작동하는 이유입니다. Android는 drawable폴더의 모든 항목을 자동 크기 조정하려고 시도 합니다.
Chris Cirefice 2016 년

10

나는 Picasso를 사용했고 같은 문제가있었습니다. 이미지의 크기, 너비 또는 높이가 너무 큽니다. 마침내 나는 여기서 해결책을 찾았습니다. 디스플레이 크기에 따라 큰 이미지를 축소하고 가로 세로 비율을 유지할 수 있습니다.

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

6

BitmapRegionDecoder 트릭을 수행합니다.

를 재정의 onDraw(Canvas canvas)하고 새 스레드를 시작한 다음 사용자에게 표시되는 영역을 디코딩 할 수 있습니다.


5

API 레벨 10부터 Larcho가 지적한 것처럼 BitmapRegionDecoder이미지에서 특정 영역을로드 하는 데 사용할 수 있으며 필요한 영역 만 메모리에 할당하여 고해상도로 큰 이미지를 표시 할 수 있습니다. 최근에는 터치 제스처 처리로 큰 이미지를 시각화하는 lib를 개발했습니다. 소스 코드와 샘플은 여기에 있습니다 .


3

뷰 레벨

다음 코드를 사용하여 런타임시 개별보기에 대한 하드웨어 가속을 비활성화 할 수 있습니다.

myView.setLayerType (View.LAYER_TYPE_SOFTWARE, null);


3

나는 같은 문제를 겪었다. 여기 내 해결책이있다. 이미지의 너비를 안드로이드 화면 너비와 동일하게 설정 한 다음 높이를 조정합니다

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

이미지 축소 :

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를 아는 방법? 정적 값으로 수정해야합니까? 또는 우리는 그 WRT 장치를 변경할 수 있습니까?
Prashanth Debbadwar

2

이미지 뷰에 직접로드하는 대신 글라이드 라이브러리 사용

글라이드 : https://github.com/bumptech/glide

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

2
Picasso 대신 Glide를 사용하면 도움이됩니다. 글라이드처럼 보인다는 기본적으로 이러한 문제를 처리
조니 다섯

1

나는 위의 모든 솔루션을 차례로 여러 시간 동안 시도했지만 아무도 효과가 없었습니다! 마지막으로 Android 카메라로 이미지를 캡처하고 표시하는 것과 관련된 공식적인 예를 살펴보기로 결정했습니다. 공식 예제 ( here )는 마침내 나에게 유일한 방법을 주었다. 아래에는 해당 예제 앱에서 찾은 솔루션이 나와 있습니다.

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

작은 크기의 이미지를 넣고 싶은 사람을위한 참고 사항 :

Pilot_51의 솔루션 (이미지를 drawable-nodpi폴더로 이동 )은 작동하지만 다른 문제가 있습니다. 이미지가 화면에 맞게 매우 큰 (2000 x 3800과 같은) 해상도로 크기를 조정하지 않으면 이미지가 너무 작아 화면에 표시됩니다. .

해결책 : 이미지 파일을 넣으십시오 drawable-hdpi-그것은 매력적이었습니다.


1
이미지 밀도 문제를 숨기고 있습니다. 밀도가 낮은 하드웨어에서는 이미지가 더 커 보입니다.
rupps

또한 Pilot_51의 솔루션에 문제가 있다고 생각하지 않으므로 필요에 따라 적절한 이미지 크기를 사용해야합니다.
Nilabja

0

올바른 드로어 블 하위 폴더를 사용하면 문제가 해결되었습니다. 내 해결책은 내 해상도 이미지 (1920x1200)를 drawable 폴더 대신 drawable-xhdpi 폴더에 넣는 것입니다 .

또한 축소 이미지 (1280x800)를 drawable-hdpi 폴더에 넣습니다 .

이 두 가지 해상도는 프로그래밍중인 2013 및 2012 Nexus 7 태블릿과 일치합니다. 또한 다른 태블릿에서 솔루션을 테스트했습니다.


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

    }
}

이 코드는 작동합니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.