2012-05-24 3 views
3

Я пытаюсь принять bitmap resizing учебник - единственное различие заключается в том, что я использую decodeStream вместо decodeResource. Это странно, но decodeStream, без каких-либо манипуляций, дает мне bitmap obj, но когда я иду через decodeSampledBitmapFromStream, он почему-то возвращает null. Как это исправить?decodeStream возвращает null

Вот код, я использую:

protected Handler _onPromoBlocksLoad = new Handler() { 
     @Override 
     public void dispatchMessage(Message msg) { 
      PromoBlocksContainer c = (PromoBlocksContainer) _promoBlocksFactory.getResponse(); 
      HttpRequest request = new HttpRequest(c.getPromoBlocks().get(0).getSmallThumbnail()); 

      BitmapFactory.Options options = new BitmapFactory.Options(); 
      options.inJustDecodeBounds = true; 
      InputStream stream; 
      ImageView v = (ImageView) findViewById(R.id.banner); 
      try { 
       stream = request.getStream(); 

       //v.setImageBitmap(BitmapFactory.decodeStream(stream)); Works fine 
       Bitmap img = decodeSampledBitmapFromStream(stream, v.getWidth(), v.getHeight()); 
       v.setImageBitmap(img); 
      } catch (IOException e1) { 
       // TODO Auto-generated catch block 
       e1.printStackTrace(); 
      } 
     } 
    }; 

    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) { 
      if (width > height) { 
       inSampleSize = Math.round((float)height/(float)reqHeight); 
      } else { 
       inSampleSize = Math.round((float)width/(float)reqWidth); 
      } 
     } 
     return inSampleSize; 
    } 

    public static Bitmap decodeSampledBitmapFromStream(InputStream res, int reqWidth, int reqHeight) { 
     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeStream(res, null, options); 
     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 
     options.inJustDecodeBounds = false; 
     Bitmap img = BitmapFactory.decodeStream(res, null, options); // Gives null 
     return img; 
    } 

ответ

4

Проблема заключалась в том, что как только вы использовали InputStream из HttpURLConnection, вы не можете перемотать и использовать тот же InputStream снова. Поэтому вам необходимо создать новый InputStream для фактической выборки изображения. В противном случае мы должны прервать запрос http.

request.abort(); 
6

Поскольку InputStream объект можно употреблять только один раз, вы должны сделать глубокую копию InputStream объекта, если вы хотите, чтобы изменить размер растрового изображения из InputStream в HttpURLConnection, в противном случае decodeStream будет возвращает null.Here является один из возможных решений:

 HttpURLConnection urlConnection = null; 
     InputStream in = null; 
     InputStream in2 = null; 
     try { 
      final URL imgUrl = new URL(url); 
      urlConnection = (HttpURLConnection) imgUrl.openConnection(); 
      in = urlConnection.getInputStream(); 

      ByteArrayOutputStream out = new ByteArrayOutputStream(); 
      copy(in,out); 
      in2 = new ByteArrayInputStream(out.toByteArray()); 

      // resize the bitmap 
      bitmap = decodeSampledBitmapFromInputStream(in,in2);     

     } catch (Exception e) { 
      Log.e(TAG, "Error in down and process Bitmap - " + e); 
     } finally { 
      if (urlConnection != null) { 
       urlConnection.disconnect(); 
      } 
      try { 
       if (in != null) { 
        in.close(); 
       } 
       if (in2 != null){ 
        in2.close(); 
       } 
      } catch (final IOException e) { 
      Log.e(TAG, "Error in when close the inputstream." + e); 
      } 
     } 
    } 

соус код метода копирования выглядит следующим образом:

public static int copy(InputStream input, OutputStream output) throws IOException{ 

    byte[] buffer = new byte[IO_BUFFER_SIZE]; 

    int count = 0; 

    int n = 0; 

    while (-1 != (n = input.read(buffer))) { 

     output.write(buffer, 0, n); 

     count += n; 

    } 

    return count; 
} 

соус код метода decodeSampledBitmapFromInputStream выглядит следующим образом:

public static Bitmap decodeSampledBitmapFromInputStream(InputStream in, 
InputStream copyOfin, int reqWidth, int reqHeight) { 

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

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeStream(copyOfin, null, options); 
} 
+1

Это работает для меня, получить эту проблему при декодировании потока чтения из частной storeage моего приложения на диске. Однако вместо копирования я просто открываю файл для чтения дважды и передаю оба потока для decodeSampledBitmapFromInputStream. То есть нет необходимости в копировании(). Спасибо, я застрял с этим слишком долго! –

+0

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

+0

Спасибо, ваш подход прекрасно работает. Это помогло мне. – testCoder

1

Есть некоторые проблемы в ответах на второй этаж. Поскольку в методе copy() используется inputstream, поэтому в методе decodeSampledBitmapFromInputStream(in,copyOfIn) мы не можем поймать значение options.outWidth.

Здесь я сделал некоторые исправления, мы можем преобразовать друг друга между byte[] и inputstream Таким образом, мы можем преобразовать inputstream в byte[], это может быть использовано несколько раз.

код следующим образом:

HttpURLConnection connection = null; 
InputStream inputStream = null; 
InputStream copyiInputStream1 = null; 
InputStream copyiInputStream2 = null; 
Bitmap bitmap = null; 
try { 
    URL url=new URL(imageUrl); 
    connection=(HttpURLConnection) url.openConnection(); 
    connection.setConnectTimeout(8000);//设置连接超时 
    inputStream = connection.getInputStream(); 
    byte[] data = InputStreamTOByte(inputStream); 
    try { 
      copyiInputStream1 = byteTOInputStream(data); 
      copyiInputStream2 = byteTOInputStream(data); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
bitmap = decodeSampledBitmapFromInputStream(copyiInputStream1,copyiInputStream2); 
/** 
* 将InputStream转换成byte数组 
* @param in InputStream 
* @return byte[] 
* @throws IOException 
*/ 
public byte[] InputStreamTOByte(InputStream in) throws IOException{ 

    ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 
    byte[] data = new byte[1024*16]; 
    int count = -1; 
    while((count = in.read(data,0,1024*16)) != -1) 
     outStream.write(data, 0, count); 

    data = null; 
    return outStream.toByteArray(); 
} 

/** 
* 将byte数组转换成InputStream 
* @param in 
* @return 
* @throws Exception 
*/ 
public InputStream byteTOInputStream(byte[] in) throws Exception{ 

    ByteArrayInputStream is = new ByteArrayInputStream(in); 
    return is; 
} 
+0

Это должен быть принятый ответ. Полное решение для получения ширины и высоты. – bajicdusko

Смежные вопросы