“Bitmap dokuya yüklenemeyecek kadar büyük”


154

Bir ImageView içine bir bitmap yüklüyorum ve bu hatayı görüyorum. Bu sınırın OpenGL donanım dokuları (2048x2048) için bir boyut sınırı ile ilgili olduğunu düşünüyorum. Yüklemem gereken görüntü, yaklaşık 4.000 piksel yüksekliğinde bir sıkıştırılmış zum görüntüsüdür.

Manifestte donanım hızlandırmayı kapatmayı denedim, ama sevinç yok.

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

ImageView'e 2048 pikselden daha büyük bir resim yüklemek mümkün müdür?


1
Buraya bakan herkes için kaydırılabilir olmasını istiyorsanız görüntünüzü kaydırma görünümüne koymayı unutmayın. Bu hatadan kurtulacaktır. Bunun benim sorunum olduğunu fark etmeden önce biraz zaman harcadım.
Jason Ridge

Hala görüntü kalitesini koruyan büyük görüntüler görüntülemek isteyen herkes için aşağıdaki @stoefln yanıtındaki kütüphaneye bakın. Ben kullandım ve denemeye değer. Kesinlikle inSampleSizeyaklaşımdan daha iyi .
Mahendra Liya

1
@Joe Darbe akımı cevabı sizin durumunuzda işe yaramadı mı? Yanıtınız hayırsa, lütfen bu soru bağlamında karşılaştığınız sorunla ilgili ayrıntılı bilgi veriniz?
Pravin Divraniya

1
hey @ VC.One - adamım hakkında çalışılması garip bir şey. "Mevcut cevabı ödüllendir" i tıklamalıydım. Hiç kimse bu SO pop-up "en iyi" düğmesine basmak sıkıcı rahatsız ediyor, çünkü aptalca :) Ben şimdi lütuf tıkladı gibi şimdi çözüldü. Alkış !!
Fattie

1
Her zaman ödül ödemeye çalışırım (puan toplamayı sevmem). Sanırım, eğer profilime tıklarsanız, o zaman ödüller, @ VC.One yıllar boyunca SO'dan gerçekten harika QA göreceksiniz !!!!!!!!!!!!!!!
Fattie

Yanıtlar:


48

Tüm oluşturma işlemleri OpenGL'ye dayanmaktadır, bu nedenle bu sınırı aşamazsınız ( GL_MAX_TEXTURE_SIZEcihaza bağlıdır, ancak minimum değer 2048x2048'dir, bu nedenle 2048x2048'den düşük herhangi bir görüntü sığar).

Bu kadar büyük görüntülerle, yakınlaştırmak ve bir mobil cihazda, örneğin Google Haritalar'da gördüklerinize benzer bir sistem kurmalısınız. Görüntü birkaç parçaya bölünmüş ve birkaç tanım ile.

Veya görüntülemeden önce görüntüyü küçültebilirsiniz (bkz. User1352407'nin bu soruya verdiği yanıt ).

Ayrıca, görüntüyü hangi klasöre koyduğunuza dikkat edin, Android görüntüleri otomatik olarak ölçeklendirebilir. Bu soruya aşağıdaki Pilot_51'in cevabına bir göz atın .


23
Bu durumda, Galeri uygulaması kamerayla çekilen görüntülerin görüntülenmesine ve değiştirilmesine nasıl izin verir? 2048x2048 yalnızca 4MP bir görüntüdür ve birçok Android telefon bundan daha büyük fotoğraflar çeker ve Galeri uygulamasında sorun yoktur.
Ollie C

3
Çünkü GL_MAX_TEXTURE_SIZE aygıta bağlıdır.
jptsetung

24
Bu gerçekten bir anlam ifade etmiyor. Şimdi aynı sorunla karşılaştım - 1286x835 piksel görüntü ile. VE: sadece Galaxy Nexus'ta bu hata mesajını alıyorum ve görüntü yok! Üst düzey bir akıllı telefonun bu kadar küçük bir görüntü gösterememesi çok saçma görünüyor! HTC Hero cihazım bunu gösterme yeteneğine sahip! Ne yapabilirim?
Zordid

1
Romain'in cevabını buradan görebilirsiniz: stackoverflow.com/questions/7428996/…
Ben Lee

3
@OllieC Ayrıca galeri uygulamalarının nasıl yaptığını bilmek istiyorum. Bu yüzden, büyük resimleri göstermek için bir kişi bilir veya bir örneği varsa, bu harika olurdu.
Innova

408

Bu soruya doğrudan bir cevap değildir (görüntüleri yüklemek> 2048), ancak hatayı yaşayan herkes için olası bir çözümdür.

Benim durumumda, görüntü her iki boyutta (tam olarak 1280x727) 2048'den küçüktü ve sorun özellikle bir Galaxy Nexus'ta yaşanıyordu. Görüntü drawableklasördeydi ve hiçbir nitelikli klasör yoktu. Android, yoğunluk niteleyicisi olmayan çekmecelerin mdpi olduğunu varsayar ve bunları diğer yoğunluklar için yukarı veya aşağı ölçeklendirir, bu durumda xhdpi için 2x ölçeklendirilir. drawable-nodpiÖlçeklenmeyi önlemek için suçlu görüntüsünü taşımak sorunu çözdü.


3
Çekmeceleri yüklemeye çalışırken bellek sorunları yaşıyordum. Bunun neden olduğunu anlamaya çalışırken 2 saat geçirdim. Dolaylı cevap için teşekkürler.
TrueCoke

16
Bu doğru cevaptır ve bu şekilde işaretlenmelidir.
wblaschko

3
Yaklaşık üç buçuk aydır Android'de neredeyse tam zamanlı olarak program yapıyorum ve şimdi bunu fark ettim. drawableAslında gizli bir drawable-mdpiklasör yapmak aptal gibi görünüyor . Bu da benim özel harita işaretleyicileri neden korkunç görünüyordu açıkladı (onlar ölçeklendirilmiş, sonra ölçeksiz edildi).
theblang

10
evet ne oluyor! Bence android programcıları% 99 "çekilebilir" anlamına gelir "ölçek yok" anlamına gelir.
Matt Logan

3
Bu, gördüğüm en yararlı cevap, her yerde. Söyleyebileceğim tek şey bir lütuf gönderiyorum! TEŞEKKÜRLER.
Fattie

105

Görüntüyü şu şekilde ölçeklendirdim:

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
teşekkürler, createScaledBitmap çok büyük bir bitmap gösterebilmem için bana yardımcı oldu
Boy

Sorunumu çözdü .. teşekkürler. Aslında görüntüyü kameradan alıyordum ve Samsung Galaxy S4'te 4.4.2 ile ImageView'de gösterdim
Mitesh Shah

üzgünüm, ama "w" ne olduğunu tespit
edemiyorum

1
Üzgünüm, bu ne ctxanlama geliyor?
Ameer Sabith

1
@AmeerSabith, ctx bir Bağlam nesnesidir (örneğin, çalışan Etkinliğiniz)
Matt

34

Tüm bu altörnekleme kodunu elle yazmaya / hata ayıklamaya çalışırken saatlerce saatler harcamak yerine neden kullanmıyorsunuz Picasso? Her bitmapstür ve / veya boyutta işlem yapmak için yapılmıştır .

Benim "bit eşlem çok büyük ...." sorununu kaldırmak için bu tek satır kod kullandım :

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

Resize () çağrılmadan centerCrop () kullanılması IllegalStateException özel durumu ile sonuçlanır. Kütüphane, merkezi kırpma kullanıldığında yeniden boyutlandırmayı çağırmaya zorlar.
Zsolt Boldizsár

Bu mükemmel bir mantıklı, çünkü kırpma, görüntüyü yeniden boyutlandırdığınızı ima ediyor.
Phileo99

2
Hızlı, kolay ve basit bir çözüm. En iyi olup olmadığından emin değilim, ama istediğimi aldım. Çok teşekkür ederim
Nabin

Picasso ile hedef kullanıldığında daha büyük boyutlu görüntüler için hala aynı hatayı alıyorum :(
Narendra Singh

2.5.3-SNAPSHOT sürümünü kullanmaya çalışın, şimdi büyük görüntülerle doğru şekilde çalışıyor gibi görünüyor
Anton Malmygin

20

( AndroidManifest.xml) İçine aşağıdaki 2 özelliğin eklenmesi benim için çalıştı:

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

Bu, Samsung cihazındaki sorunumu düzeltti. Teşekkürler
Hitesh Bisht

16

Görüntü dosyasını drawable-nodpiklasörden klasöre değiştirmek drawablebenim için çalıştı.


Bu, Android'in görüntüyü cihazın boyutlarına ve ekran yoğunluğuna göre otomatik olarak ölçeklemeye çalışmasını önleyecektir; bu yüzden bu çözüm işe yarıyor. Android, drawableklasördeki herhangi bir şeyi otomatik olarak ölçeklendirmeye çalışır .
Chris Cirefice

10

Picasso'yu kullandım ve aynı problemi yaşadım. görüntü en azından boyut, genişlik veya yükseklik bakımından çok büyüktü. sonunda çözümü burada buldum. büyük resmi ekran boyutuna göre ölçeklendirebilir ve en boy oranını koruyabilirsiniz:

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

ve Picasso tarafından resim yüklemek için bu yöntemi kullanın:

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

ayrıca daha iyi performans için görüntüyü ekranın genişliğine ve yüksekliğine göre indirebilirsiniz, görüntünün tamamını değil:

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

ve sonra:

    Picasso.with(this)
                .load(newImageUlr)
                .resize(size, size)
                .centerInside()
                .into(imageViewd);

EDIT: getDisplaySize ()

display.getWidth()/getHeight()kullanımdan kaldırıldı. Yerine Displaykullanımı DisplayMetrics.

public Point getDisplaySize(DisplayMetrics displayMetrics) {
        int width = displayMetrics.widthPixels;
        int height = displayMetrics.heightPixels;
        return new Point(width, height);
}

6

BitmapRegionDecoder hile yapar.

Geçersiz kılabilir onDraw(Canvas canvas), yeni bir Konu başlatabilir ve kullanıcının görebileceği alanın kodunu çözebilirsiniz.


5

Larcho'un işaret ettiği gibi, API seviye 10'dan başlayarak, BitmapRegionDecoderbir görüntüden belirli bölgeleri yüklemek için kullanabilirsiniz ve bununla birlikte, belleğe sadece gerekli bölgeleri tahsis ederek yüksek çözünürlükte büyük bir görüntü göstermeyi başarabilirsiniz. Yakın zamanda, büyük görüntülerin dokunma hareketi ile görselleştirilmesini sağlayan bir lib geliştirdim. Kaynak kodu ve örnekleri burada bulabilirsiniz .


3

Görüntüleme seviyesi

Aşağıdaki kodla çalışma zamanında tek bir görünüm için donanım hızlandırmayı devre dışı bırakabilirsiniz:

myView.setLayerType (Görünüm.LAYER_TYPE_SOFTWARE, boş);


3

Aynı problemden geçtim, işte benim çözümüm. görüntünün genişliğini android ekran genişliğiyle aynı şekilde ayarlayın ve ardından yüksekliği ölçeklendirin

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

Bu herhangi bir boyut android ekran için daha iyidir. sizin için işe yarayıp yaramadığını bana bildirin.


2

Görüntüyü küçült:

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

Görüntü reqHeight ve reqWidth boyutlarında küçültülür. Anladığım gibi inSampleSize sadece 2 değer bir güç almak.


reqHeight ve reqWidth nasıl bilinir? Yani statik değere sabitlememiz gerekiyor mu? veya bu wrt cihazlarını değiştirebilir miyiz?
Prashanth Debbadwar

2

Doğrudan görüntüleme alanına yüklemek yerine Glide kitaplığını kullanın

Kayma: https://github.com/bumptech/glide

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

2
Picasso yerine Glide kullanmak yardımcı oldu. Glide varsayılan olarak bu tür sorunları ele alıyor gibi görünüyor
Johnny Five

1

Yukarıdaki tüm çözümleri, birbiri ardına, uzun saatler boyunca denedim ve hiçbiri işe yaramadı! Sonunda, Android kamera ile görüntü yakalama ve görüntüleme ile ilgili resmi bir örnek aramaya karar verdim. Resmi örnek ( burada ), nihayet bana işe yarayan tek yöntemi verdi. Aşağıda bu örnek uygulamada bulduğum çözümü sunuyoruz:

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

KÜÇÜK BOY GÖRÜNTÜLERİ KOYMAK İSTEYENLER İÇİN NOT:

Pilot_51'in çözümü (resimlerinizi drawable-nodpiklasöre taşıma ) çalışıyor, ancak başka bir sorunu var: Görüntüleri ÇOK KÜÇÜK yapar ekrana sığacak şekilde çok büyük (2000 x 3800 gibi) bir çözünürlükle yeniden boyutlandırılmadığı sürece yapar - sonra uygulamanızı ağırlaştırır .

ÇÖZÜM : görüntü dosyalarınızı yerleştirin drawable-hdpi- Benim için bir cazibe gibi çalıştı.


1
Sadece görüntü yoğunluğu probleminizi maskeliyorsunuz. Düşük yoğunluklu donanımlarda görüntüleriniz daha büyük görünür.
16:40

Ayrıca Pilot_51'in çözümünün herhangi bir sorunu olduğunu düşünmüyorum, ihtiyaçlarınıza göre uygun görüntü boyutlarını kullanmalısınız
Nilabja

0

Doğru çekilebilir alt klasörü kullanmak benim için çözdü. Benim çözümüm içine benim tam çözünürlüğü (1920x1200) koymak oldu çekilebilir-xhdpi yerine, klasörün çekilebilir klasörde.

Ayrıca çizilebilir hdpi klasörüne küçültülmüş bir görüntü (1280x800) koydum .

Bu iki çözünürlük, programladığım 2013 ve 2012 Nexus 7 tabletleriyle eşleşiyor. Çözümü başka tabletlerde de test ettim.


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

    }
}

Bu kod işe yarıyor

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.