2012-06-26 4 views
4

Мне нужно получить высоту и ширину изображения, найденного во входном потоке. Вот что я сделал:Получение размера изображения inputstream

private Boolean testSize(InputStream inputStream){ 
     BitmapFactory.Options Bitmp_Options = new BitmapFactory.Options(); 
     Bitmp_Options.inJustDecodeBounds = true; 
     BitmapFactory.decodeResourceStream(getResources(), new TypedValue(), inputStream, new Rect(), Bitmp_Options); 
     int currentImageHeight = Bitmp_Options.outHeight; 
     int currentImageWidth = Bitmp_Options.outWidth; 
     Bitmp_Options.inJustDecodeBounds = false; 
    if(currentImageHeight < 200 || currentImageWidth < 200){ 
     Object obj = map.remove(pageCounter); 
     Log.i("Page recycled", obj.toString()); 
     return true; 
    } 
    return false;} 

Переход к задаче в точке:

Это изменить BitmapFactory.Options даже если я заставил его быть ложным после расчета на моем втором методе ниже.

private Bitmap getBitmap(InputStream InpStream){ 
    Bitmap originalBitmap = BitmapFactory.decodeStream(InpStream);//Null. 
    return originalBitmap; 
} 

Теперь, к моему вопросу, есть другой способ получения размера и ширины изображения из входного потока? Мне очень нужна помощь в этом, любая помощь очень ценится.

   ZipInputStream zip = null; 
       zip = new ZipInputStream(new FileInputStream(getFileLocation())); 
       for(ZipEntry zip_e = zip.getNextEntry(); zip_e != null ; zip_e = zip.getNextEntry()){ 
        if(zip_e.isDirectory()) { 
         continue; 
        } 
        String file_zip = zip_e.getName(); 
        String comparison = map.get(pageCounter).getHref(); 
        if(file_zip.endsWith(comparison)){ 
         SpannableString Spanable_String = new SpannableString("abc"); 
         if(testSize(zip)){ 
          map.remove(pageCounter); 
          return false; 
         } 
         Bitmap bitmap = getBitmap(zip); 
         if(bitmap == null){ 
          map.remove(pageCounter); 
          return false; 
         } 
         image_page.put(zip_e.getName(), zip); 
         Drawable drawable_image = new FastBitmapDrawable(bitmap); 
         drawable_image.setBounds(0,0,drawable_image.getIntrinsicWidth(), drawable_image.getIntrinsicHeight()); 
         ImageSpan imageSpan = new ImageSpan(drawable_image, ImageSpan.ALIGN_BASELINE); 
         Spanable_String.setSpan(imageSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 
         tv.setText(Spanable_String); 
         return false; 
        } 
       } 
+0

Вы хотите сказать, что параметр Bitmp_Options.inJustDecodeBounds для true сохраняется для последующих вызовов 'BitmapFactory.decodeStream()'? –

+0

Да, я говорю, что это правда. По какой-то причине без метода testSize он будет корректно работать с одним входным потоком и с тем же источником. Мне очень странно, что я должен был сообщить об этом как об ошибке. –

+0

Да, я бы сказал, что это, конечно, не было ожидаемым поведением. Я не уверен, что есть другой (хороший) способ получить размер изображения из входного потока. –

ответ

9

Основная проблема заключается не в BitmapFactory.Options, но с InputStream. Поток является последовательным, поэтому, когда вы читаете поток для декодирования изображения только для размера, указатель в потоке перемещается. Затем, когда вы снова вызываете decode, чтобы фактически декодировать растровое изображение, указатель потока больше не находится в начале растрового изображения, и вы получаете null, потому что частичный поток не может быть декодирован.

Вам нужно будет сбросить поток. В зависимости от того, что этот поток, вы могли бы использовать .mark и .reset на нем. По сути, вы могли бы сделать что-то вроде этого:

private Boolean testSize(InputStream inputStream) { 
    BitmapFactory.Options Bitmp_Options = new BitmapFactory.Options(); 
    Bitmp_Options.inJustDecodeBounds = true; 

    inputStream.mark(inputSteram.available()); 

    BitmapFactory.decodeResourceStream(getResources(), new TypedValue(), inputStream, new Rect(), Bitmp_Options); 

    inputSteram.reset(); 

    int currentImageHeight = Bitmp_Options.outHeight; 
    int currentImageWidth = Bitmp_Options.outWidth; 
    Bitmp_Options.inJustDecodeBounds = false; 

    if(currentImageHeight < 200 || currentImageWidth < 200){ 
     Object obj = map.remove(pageCounter); 
     Log.i("Page recycled", obj.toString()); 
     return true; 
    } 

    return false; 
} 

Вы можете проверить, поддерживает ли InputStream это или не вызывая markSupported на нем. Если это возвращает true, вы можете использовать вышеупомянутую технику. Если он возвращает false, то указанный выше метод не будет работать, и вам действительно нужно будет закрыть и снова открыть поток снова, прежде чем декодировать полный битмап.

+0

Спасибо. Ты спас мне много часов, пытаясь понять это. Еще раз спасибо за то, что рассказали мне, что это последовательное. –

+0

Ах, не понимал, что вы вызываете это в том же экземпляре входного потока. В этом есть смысл. –

+0

хороший ответ! unfortunatly markSupported устанавливается в false в моем случае :( – Zhar