"बिटमैप एक बनावट में अपलोड करने के लिए बहुत बड़ा है"


154

मैं एक ImageView में एक बिटमैप लोड कर रहा हूं, और इस त्रुटि को देखकर। मैं इस सीमा को OpenGL हार्डवेयर बनावट (2048x2048) के लिए एक आकार सीमा से संबंधित करता हूं। मुझे जिस छवि को लोड करने की आवश्यकता है वह लगभग 4,000 पिक्सेल ऊँची एक चुटकी-ज़ूम छवि है।

मैंने प्रकट में हार्डवेयर त्वरण को बंद करने की कोशिश की है, लेकिन कोई खुशी नहीं है।

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

क्या 2048 पिक्सेल से अधिक की छवि को ImageView में लोड करना संभव है?


1
यहां किसी को भी देखने के लिए, अपनी छवि को स्क्रॉल दृश्य में रखना न भूलें यदि आप इसे स्क्रॉल करना चाहते हैं। उस त्रुटि से छुटकारा मिलेगा। मुझे यह महसूस करने से पहले कुछ समय बर्बाद हो गया कि मेरी समस्या थी।
जेसन रिज

छवि गुणवत्ता को बनाए रखते हुए बड़ी छवियों को प्रदर्शित करने के इच्छुक किसी भी व्यक्ति के लिए, नीचे दिए गए उत्तर में @stoefln में लाइब्रेरी देखें। मैंने इसका इस्तेमाल किया और कोशिश करने लायक है। निश्चित रूप से inSampleSizeदृष्टिकोण से बेहतर है ।
महेंद्र लिया

1
@ जो ब्लो करंट उत्तर आपके मामले में काम नहीं आया? यदि नहीं, तो कृपया इस प्रश्न के संदर्भ में आपके द्वारा सामना किए गए मुद्दे के बारे में विस्तार से बताएं?
प्रवीण दिवारन्या

1
हे @ VC.One - यह मेरे आदमी के बारे में काम करने के लिए एक अजीब बात है। मुझे "मौजूदा जवाब को पुरस्कृत" पर क्लिक करना चाहिए था। किसी ने भी थकाऊ रूप से उस एसओ पॉपअप पर "सबसे अच्छा" बटन दबाने की कोशिश नहीं की, क्योंकि यह मूर्खतापूर्ण है :) यह सब अब हल हो गया है क्योंकि मैंने इनाम पर क्लिक किया है। चीयर्स !!
फटी डे

1
मैं हमेशा इनामों का भुगतान करने की कोशिश करता हूं (मुझे अंक इकट्ठा करना पसंद नहीं है)। मुझे लगता है, अगर आप मेरी प्रोफ़ाइल पर क्लिक करते हैं, तो बाउंस, @ VC.One आप इतने वर्षों में SO से बहुत बढ़िया QA देखेंगे !!!!!!!!!!!!!!!
फेटी

जवाबों:


48

सभी रेंडरिंग ओपनजीएल पर आधारित है, इसलिए आप इस सीमा पर नहीं जा सकते हैं ( GL_MAX_TEXTURE_SIZEडिवाइस पर निर्भर करता है, लेकिन न्यूनतम 2048x2048 है, इसलिए 2048x2048 से कम कोई भी छवि फिट होगी)।

ऐसी बड़ी छवियों के साथ, यदि आप बाहर ज़ूम करना चाहते हैं, और एक मोबाइल में, आपको उदाहरण के लिए गूगल मैप्स में जो दिख रहा है, उसके समान एक सिस्टम सेटअप करना चाहिए। छवि कई टुकड़ों में विभाजित है, और कई परिभाषाओं के साथ।

या आप इसे प्रदर्शित करने से पहले छवि को स्केल कर सकते हैं ( इस सवाल पर user1352407 का जवाब देखें )।

और यह भी, ध्यान रखें कि आप किस फ़ोल्डर में छवि डालते हैं, एंड्रॉइड स्वचालित रूप से छवियों को स्केल कर सकता है। इस प्रश्न पर नीचे Pilot_51 के उत्तर पर एक नज़र डालें ।


23
यदि यह मामला है, तो गैलरी ऐप कैमरे के साथ ली गई छवियों के प्रदर्शन और हेरफेर की अनुमति कैसे देता है? 2048x2048 केवल 4MP की छवि है, और कई Android फ़ोन इससे बहुत बड़ी तस्वीरें लेते हैं और गैलरी ऐप में कोई समस्या नहीं है।
Ollie C

3
क्योंकि GL_MAX_TEXTURE_SIZE डिवाइस पर निर्भर करता है।
जिप्सेटुंग

24
यह वास्तव में कोई मतलब नहीं है। मुझे अब एक ही समस्या का सामना करना पड़ा - 1286x835 पिक्सेल की छवि के साथ। और: केवल एक गैलेक्सी नेक्सस पर मुझे यह त्रुटि संदेश मिलता है और कोई छवि नहीं! यह सिर्फ हास्यास्पद लगता है कि एक शीर्ष-किनारे वाला स्मार्टफोन इतनी छोटी छवि प्रदर्शित नहीं कर सकता है! मेरा HTC हीरो प्रदर्शित करने में सक्षम है! मैं क्या कर सकता हूँ?
जोर्डिड

1
यहां देखें रोमेन का जवाब: stackoverflow.com/questions/7428996/…
बेन ली

3
@OllieC मैं यह भी जानना चाहूंगा कि गैलरी ऐप इसे कैसे करते हैं। इसलिए अगर किसी को पता है, या बड़ी छवियों को दिखाने के लिए एक उदाहरण है, तो यह बहुत अच्छा होगा।
इनोवा

408

यह प्रश्न का सीधा उत्तर नहीं है (चित्र लोड हो रहा है> 2048), लेकिन त्रुटि का सामना करने वाले किसी भी व्यक्ति के लिए एक संभावित समाधान।

मेरे मामले में, दोनों आयामों में छवि 2048 से छोटी थी (1280x727 सटीक होना) और इस मुद्दे को विशेष रूप से गैलेक्सी नेक्सस पर अनुभव किया गया था। छवि drawableफ़ोल्डर में थी और योग्य फ़ोल्डर में से कोई भी नहीं। एक घनत्व क्वालीफायर के बिना एंड्रॉइड अवलंबन mdpi हैं और अन्य घनत्वों के लिए उन्हें ऊपर या नीचे तराजू करते हैं, इस मामले में xhdpi के लिए 2x बढ़ाया गया है। drawable-nodpiस्केलिंग को रोकने के लिए अपराधी की छवि को आगे बढ़ाने से समस्या हल हो गई।


3
मैं स्मृति मुद्दों को आकर्षित करने की कोशिश कर रहा था। 2 घंटे बिताए यह समझने की कोशिश कर रहा है कि ऐसा क्यों हो रहा था। अप्रत्यक्ष उत्तर के लिए धन्यवाद।
ट्रूकोक

16
यह सही उत्तर है और इसे इस तरह चिह्नित किया जाना चाहिए।
wblaschko

3
लगभग साढ़े तीन महीने अब मुझे एंड्रॉइड पर लगभग पूरा समय मिल रहा है और मुझे अभी इसका एहसास हुआ है। drawableअनिवार्य रूप से एक छिपे हुए drawable-mdpiफ़ोल्डर बनाने के लिए गूंगा लगता है । इसने यह भी बताया कि मेरे कस्टम मानचित्र मार्कर भयानक क्यों दिख रहे थे (वे अपस्कूल किए जा रहे थे, फिर डाउनस्केल्ड)।
दिबांग

10
हाँ, क्या बकवास है! मुझे लगता है कि 99% एंड्रॉइड प्रोग्रामर सोचते हैं कि "ड्रॉबल" का अर्थ है "इस पैमाने पर नहीं"।
मैट लोगन

3
यह सबसे उपयोगी उत्तर मैंने कभी भी, कहीं भी देखा है। सब मैं कह सकता हूँ कि मैं एक इनाम भेज रहा हूँ! धन्यवाद।
फटी

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 मेरे लिए बहुत बड़े बिटमैप को दिखाने में सक्षम होने में मददगार था
लड़का

मेरे मुद्दे को हल किया .. धन्यवाद। वास्तव में मैं कैमरे से छवि ले रहा था और 4.4.2 के साथ सैमसंग गैलेक्सी एस 4 में इमेज व्यू में प्रदर्शित कर रहा था
मितेश शाह

क्षमा करें, लेकिन मुझे पता नहीं है कि "w" क्या है
Bobbelinio

1
क्षमा करें, ctxइसका मतलब क्या है ?
अमीर सबिथ

1
@AmeerSabith दिखता है जैसे ctx एक Context ऑब्जेक्ट है (उदाहरण के लिए आपकी रनिंग गतिविधि)
मैट

34

मैन्युअल रूप से इस सभी डाउनसम्पलिंग कोड को लिखने / डिबग करने की कोशिश करने में घंटों खर्च करने के बजाय, उपयोग क्यों नहीं Picasso? यह bitmapsसभी प्रकारों और / या आकारों से निपटने के लिए बनाया गया था ।

मैंने अपने "बिटमैप बहुत बड़े ...." समस्या को दूर करने के लिए इस एकल पंक्ति का उपयोग किया है:

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

CenterCrop () का उपयोग बिना कॉल किए हुए आकार () के परिणामस्वरूप IllegalStateException में होगा। जब केंद्र की फसल का उपयोग किया जाता है तो लाइब्रेरी को आकार बदलने के लिए मजबूर करना पड़ता है।
Zsolt Boldizsár

यह सही समझ में आता है, क्योंकि फसल का मतलब है कि आप छवि का आकार बदल रहे हैं।
Phileo99

2
तेज, आसान और सरल उपाय। यकीन नहीं होता कि यह सबसे अच्छा है, लेकिन मुझे वह मिला जो मैं चाहता था। बहुत बहुत धन्यवाद
नबीन

पिकासो के साथ लक्ष्य का उपयोग करते समय अभी भी वही त्रुटि हो रही है, बड़े आकार की छवियों के लिए :(
नरेंद्र सिंह

संस्करण 2.5.3-स्नैपशॉट का उपयोग करने का प्रयास करें, ऐसा लगता है कि यह अब बड़ी छवियों के साथ सही ढंग से काम कर रहा है
एंटोन मैल्मिनिन

20

निम्नलिखित 2 विशेषताओं का जोड़ ( AndroidManifest.xml) मेरे लिए काम करता है:

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

इसने सैमसंग डिवाइस पर मेरा मुद्दा ठीक कर दिया। धन्यवाद
हितेश बिष्ट

16

छवि फ़ाइल को drawable-nodpiफ़ोल्डर से drawableफ़ोल्डर में बदलना मेरे लिए काम करता है।


यह एंड्रॉइड को डिवाइस के आयाम और स्क्रीन घनत्व के आधार पर छवि को ऑटो-स्केल करने की कोशिश से रोक देगा; यही कारण है कि यह समाधान काम करता है। Android drawableफ़ोल्डर में कुछ भी ऑटो-स्केल करने की कोशिश करेगा ।
क्रिस क्रेफ़िस

10

मैंने पिकासो का उपयोग किया और उसी समस्या थी। कम से कम आकार, चौड़ाई या ऊंचाई में छवि बहुत बड़ी थी। आखिरकार मुझे इसका हल मिल गया। आप बड़े आकार को डिस्प्ले साइज के अनुसार घटा सकते हैं और पहलू अनुपात भी रख सकते हैं:

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

6

BitmapRegionDecoder उसने चाल चली।

आप ओवरराइड कर सकते हैं onDraw(Canvas canvas), एक नया थ्रेड शुरू कर सकते हैं और उपयोगकर्ता को दिखाई देने वाले क्षेत्र को डीकोड कर सकते हैं।


5

जैसा कि लार्चो द्वारा बताया गया है, एपीआई स्तर 10 से शुरू होकर, आप BitmapRegionDecoderएक छवि से विशिष्ट क्षेत्रों को लोड करने के लिए उपयोग कर सकते हैं और उसके साथ, आप केवल आवश्यक क्षेत्रों में मेमोरी आवंटित करके उच्च रिज़ॉल्यूशन में एक बड़ी छवि दिखाने के लिए पूरा कर सकते हैं। मैंने हाल ही में एक लिब विकसित किया है जो टच जेस्चर हैंडलिंग के साथ बड़ी छवियों के दृश्य प्रदान करता है। स्रोत कोड और नमूने यहां उपलब्ध हैं


3

स्तर देखें

आप निम्न कोड के साथ रनटाइम पर एक व्यक्तिगत दृश्य के लिए हार्डवेयर त्वरण को अक्षम कर सकते हैं:

myView.setLayerType (View.LAYER_TYPE_SOFTWARE, नल);


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 के आकार में छोटा किया जाएगा। जैसा कि मैं समझता हूँ कि नमूना केवल 2 मानों की शक्ति में लेते हैं।


कैसे पता करने के लिए reqHeight और reqWidth? मेरा मतलब है कि हमें इसे स्थिर मूल्य पर ठीक करने की आवश्यकता है? या हम उन wrt उपकरणों को बदल सकते हैं?
प्रशांत देवबदवार २५'१६

2

Imageview में सीधे लोड करने के बजाय ग्लाइड लाइब्रेरी का उपयोग करें

ग्लाइड: https://github.com/bumptech/glide

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

2
पिकासो के बजाय ग्लाइड का उपयोग करने से मदद मिली। ग्लिड जैसे लगते हैं डिफ़ॉल्ट रूप से इस तरह की समस्याओं को संभालते हैं
जॉनी फाइव

1

मैंने ऊपर दिए गए सभी समाधानों की कोशिश की, एक के बाद एक, कई घंटों तक, और कोई भी काम नहीं कर पाया! अंत में, मैंने एंड्रॉइड के कैमरे के साथ छवियों को कैप्चर करने और उन्हें प्रदर्शित करने के बारे में एक आधिकारिक उदाहरण के लिए चारों ओर देखने का फैसला किया। आधिकारिक उदाहरण ( यहां ), अंत में मुझे केवल वही तरीका दिया गया जिसने काम किया। नीचे मैं उस उदाहरण ऐप में पाया गया समाधान प्रस्तुत करता हूं:

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

छोटे आकार के IMEES भरने के लिए कौन चाहता है:

Pilot_51 का समाधान (आपकी छवियों को drawable-nodpiफ़ोल्डर में ले जाना) काम करता है, लेकिन इसकी एक और समस्या है: यह स्क्रीन पर छवियों को बहुत छोटा बनाता है जब तक कि छवियों को स्क्रीन पर फिट करने के लिए एक बहुत बड़े (जैसे 2000 x 3800) संकल्प का आकार बदल नहीं दिया जाता है - तब यह आपके ऐप को अधिक गतिशील बनाता है ।

समाधान : अपनी छवि फ़ाइलों को डालें drawable-hdpi- यह मेरे लिए एक आकर्षण की तरह काम करती है।


1
आप बस अपनी छवि घनत्व की समस्या का सामना कर रहे हैं। कम घनत्व वाले हार्डवेयर पर आपकी छवियां बड़ी दिखाई देंगी।
बर्बाद

मुझे यह भी नहीं लगता कि Pilot_51 के समाधान में कोई समस्या है, आपको अपनी आवश्यकताओं के अनुसार उपयुक्त छवि आकारों का उपयोग करना चाहिए
नीलाबजा

0

सही ड्रॉबल सबफ़ोल्डर का उपयोग करके इसे मेरे लिए हल किया गया। मेरा समाधान यह था कि मैं अपनी पूरी रिज़ॉल्यूशन इमेज (1920x1200) को ड्रॉबल फोल्डर की जगह ड्रॉबल-एक्सएचडीपीआई फोल्डर में डालूं

मैंने ड्रॉबल-एचडीपीआई फ़ोल्डर में एक स्केल्ड डाउन इमेज (1280x800) भी डाला ।

ये दो संकल्प 2013 और 2012 के नेक्सस 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);

    }
}

यह कोड काम है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.