5

पर अशक्त रिटर्न एंड्रॉयड 7 में एसेट निर्देशिका से बिटमैप्स डिकोड करने के लिए कैसे?BitmapFactory.decodeStream एंड्रॉयड 7

मेरे एप्लिकेशन Marshmallow अप करने के लिए Android संस्करण पर अच्छी तरह से चल रहा है। एंड्रॉइड 7 के साथ यह संपत्ति निर्देशिका से छवियों को लोड करने में विफल रहता है।

मेरे कोड:

private Bitmap getImage(String imagename) { 
    // Log.dd(logger, "AsyncImageLoader: " + ORDNER_IMAGES + imagename); 

    AssetManager asset = context.getAssets(); 
    InputStream is = null; 
    try { 
     is = asset.open(ORDNER_IMAGES + imagename); 
    } catch (IOException e) { 
     // Log.de(logger, "image konnte nicht gelesen werden: " + ORDNER_IMAGES + imagename); 
     return null; 
    } 


    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeStream(is, null, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, PW, PH); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 

    // Lesen des Bitmaps in der optimierten Groesse 
    return BitmapFactory.decodeStream(is, null, options); 

} 

नतीजतन (केवल Android 7) BitmapFactory.decodeStream रिक्त है। यह सही ढंग से एक पुराने एंड्रॉइड एपीआई काम करता है।

डिबग मोड मैं निम्नलिखित संदेश को देखने में:

09-04 10: 10: 50.384 6274-6610/MyApp डी/skia: --- SkAndroidCodec :: NewFromStream लौटे अशक्त

क्या कोई मुझे कारण बता सकता है और कोडिंग को कैसे ठीक किया जाए?

संपादित करें: इस बीच मैंने पाया, कि पहले BitmapFactory.decodeStream को हटाने के लिए जस्ट डीकोडबॉड्स = सत्य के साथ एक सफल बिटमैप फैक्टरी.decodeStream बाद में JustDecodeBounds = false के साथ होता है। कारण को नहीं जानते और बिटमैप आकार के माप को प्रतिस्थापित करने के बारे में नहीं जानते।

+0

मेरा अनुमान है कि आपकी समस्या आपके संपत्ति के लिए विशेष रूप से है। मैं तो बस का परीक्षण [मेरी किताब के नमूने में से एक] (https://github.com/commonsguy/cw-omnibus/tree/master/Bitmaps/InSampleSize) है कि संपत्ति से छवियों को लोड करता है, एक नेक्सस 9 एंड्रॉयड 7.0 चल रहा है पर। यह काम तो ठीक करता है। – CommonsWare

उत्तर

8

मुझे लगता है कि हम एक ही नाव में हैं। मेरी टीम थोड़ी देर के लिए इस समस्या में फंस गई।

यह बिटमैपफ़ैक्टरी.cpp (https://android.googlesource.com/platform/frameworks/base.git/+/master/core/jni/android/graphics/BitmapFactory.cpp) में एक समस्या प्रतीत होता है कुछ एंड्रॉइड 7.0 में जोड़ा गया था और समस्या आई थी।

// Create the codec. 
NinePatchPeeker peeker; 
std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(streamDeleter.release(), &peeker)); 
if (!codec.get()) { 
    return nullObjectReturn("SkAndroidCodec::NewFromStream returned null"); 
} 

और मैं BitmapFactory.decodeStream विधि हम inJustDecodeBounds=false सेट लेकिन बाद बिटमैप का निर्माण नहीं किया पता चला जब मैं बाध्य डिकोडिंग बिना बिटमैप बनाने का प्रयास करें। यह कार्य करता है! समस्या बिटमैपऑप्शन के बारे में है कि इनपुटस्ट्रीम अपडेट नहीं होता है जब हम BitmapFactory.decodeStream फिर से कॉल करते हैं।

तो मैं फिर से डिकोड करने से पहले उस InputStream रीसेट

private Bitmap getBitmapFromAssets(Context context, String fileName, int width, int height) { 
    AssetManager asset = context.getAssets(); 
    InputStream is; 
    try { 
     is = asset.open(fileName); 
    } catch (IOException e) { 
     return null; 
    } 
    BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeStream(is, null, options); 
    try { 
     is.reset(); 
    } catch (IOException e) { 
     return null; 
    } 
    options.inSampleSize = calculateInSampleSize(options, width, height); 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeStream(is, null, options); 
} 

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 
     final int halfHeight = height/2; 
     final int halfWidth = width/2; 
     while ((halfHeight/inSampleSize) >= reqHeight 
       && (halfWidth/inSampleSize) >= reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 
    return inSampleSize; 
} 

यह लगता है कि हम InputStream हर बार रीसेट करने के लिए इससे पहले कि यह पुन: उपयोग कर सकते है।

+0

यह चाल है। बस इनपुटस्ट्रीम को रीसेट कर रहा है। आपके सहयोग के लिए धन्यवाद। – Savari

+0

मैंने इस चाल की कोशिश की, लेकिन मैं आराम करते समय "चिह्न/रीसेट समर्थित नहीं" IOException प्राप्त कर रहा हूं। लेकिन मैं FileInputStream का उपयोग करता हूं, क्योंकि मैं एसडी कार्ड से बिटमैप लोड करने का प्रयास करता हूं। –

+0

क्या कोई अन्य तरीका है लेकिन फाइलइनपुटस्ट्रीम को स्टोरेज से फाइल खोलने के लिए? –

0

मामले में यह किसी को भी मदद करता है, मैं बड़ा कोड है कि पहले छवियों का आकार के लिए काम किया था को अद्यतन करने के लिए एक समान मुद्दे के खिलाफ जोड़ने से किया गया था। मेरी समस्या उस स्टैक को आगे बढ़ा दी गई थी जहां मैं छवि फ़ाइल से डेटा पढ़ रहा था। मैंने IOUtils.toByteArray(Reader) का उपयोग किया, जिसे हटा दिया गया है। मैंने यूआरआई से सीधे बाइट सरणी में परिवर्तित करने के लिए स्विच किया और अब यह अच्छी तरह से काम कर रहा है। कि नई विधि के उदाहरण के लिए नीचे resizeImage() की पहली दो पंक्तियों देखें (कोड के बाकी मुझे छवि का आकार बदलने की अनुमति देता है।)

public static Bitmap resizeImage(Uri imageUri, int targetWidth, int targetHeight) { 
    // Convert the image to a byte array 
    java.net.URI tempUri = new URI(uri.toString()); 
    byte[] imageData = IOUtils.toByteArray(tempUri); 

    // First decode with inJustDecodeBounds=true to check dimensions 
    BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, targetWidth, targetHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    Bitmap reducedBitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options); 
    Bitmap resizedBitmap = Bitmap.createScaledBitmap(reducedBitmap, targetWidth, targetHeight, false); 

    return resizedBitmap; 
} 

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 
     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a 
     // power of 2 and keeps both height and width larger 
     // than the requested height and width. 
     while ((halfHeight/inSampleSize) > reqHeight 
       && (halfWidth/inSampleSize) > reqWidth) { 
      inSampleSize *= 2; 
     } 
    } 

    return inSampleSize; 
} 
संबंधित मुद्दे