2016-09-04 25 views
5

Android 7のAssetディレクトリからビットマップをデコードするにはどうすればよいですか?Android 7のBitmapFactory.decodeStreamがAndroid 7でnullを返す

私のアプリケーションは、マシュマロまでのAndroidバージョンでうまく動作しています。 Android 7では、Assetディレクトリから画像を読み込むことができません。その結果、

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

} 

(のみアンドロイド7)BitmapFactory.decodeStreamがnull:

マイコード。それは古いAndroid APIを正しく動作させます。

09-04:10:10:--- SkAndroidCodec :: NewFromStreamがnull

を返しました:50.384 6274から6610/myappというのD/skia私は次のメッセージを参照してくださいデバッグモードで

誰かが私に理由とコーディングを修正する方法を教えてもらえますか?

編集:一方で、inJustDecodeBounds = trueで最初のBitmapFactory.decodeStreamを削除すると、後でinJustDecodeBounds = falseで正常なBitmapFactory.decodeStreamが作成されます。その理由を知らず、ビットマップサイズの測定方法をどのように置き換えるかを知らない。

+0

私の推測によれば、あなたの問題はあなたの資産に特有です。 Android 7.0を実行しているNexus 9で、アセットから画像を読み込む[自分のブックサンプルの1つ(https://github.com/commonsguy/cw-omnibus/tree/master/Bitmaps/InSampleSize)]をテストしました。それはうまくいくようです。 – CommonsWare

答えて

8

(コードの残りの部分は、私は画像のサイズを変更することができます。)その新しい方法の例については、以下のresizeImage()の最初の2行を参照してください。私のチームはあなたのようにしばらくの間この問題に突き当たった。

BitmapFactory.cpp(https://android.googlesource.com/platform/frameworks/base.git/+/master/core/jni/android/graphics/BitmapFactory.cpp)に問題があるようです。Android 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"); 
} 

そして、私たちはinJustDecodeBounds=falseを設定した後BitmapFactory.decodeStream方法は、ビットマップを作成していないが、私はバウンドデコードせずにビットマップを作成しようとすると分かりました。それは作品です!問題は、BitmapFactory.decodeStreamを再度呼び出すとInputStreamが更新されないというBitmapOptionsです。

だから私は、それはだ、デコード前の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

これはトリックでした。 InputStreamをリセットするだけです。ご協力ありがとうございました。 – Savari

+0

私はこのトリックを試みましたが、restを呼び出すと、 "mark/reset not supported" IOExceptionが発生し続けます。しかし、私はSDカードからビットマップをロードしようとすると、FileInputStreamを使用します。 –

+0

FileInputStream以外の方法でストレージからファイルを開くことはできますか? –

0

これは誰でも助けてくれるかもしれませんが、イメージのサイズを変更するために以前に働いていた古いコードを更新して同様の問題が起きていました。 私の問題は、イメージファイルからデータを読み込んでいたスタックの上にさらに上がっていました。私はIOUtils.toByteArray(Reader)を使用しましたが、廃止されました。私はURIから直接バイト配列への変換に切り替えましたが、今はうまくいきます。私たちは同じ船に乗っていると思う

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; 
} 
関連する問題