2016-09-27 2 views
1

ヘッダ(22バイト)で送信された画像を受け取るために、以下のクラスを開発しました。画像のデコードを行い、すべての画像が復号化されることがありますが、それはSkImageDecoder::Factory returned nullで返されることがあります。私はthis AndroidチュートリアルinSampleImageを使用しています。ビットマップデコードの戻り値SkImageDecoder :: Factoryがnullを返し、壊れた画像が表示される

public class SocketServerStreamDataThread extends Thread { 

    private Socket streamSocket; 
    MainActivity mainActivity ; 
    ImageView displayedImage ; 

    Bitmap bitmapImageToDisplay = null; 
    byte[] dataBuffer = new byte[1048576]; 

    boolean result ; 

    protected static boolean mReceivingStop; // Flag used to start and stop transmitting data 

    SocketServerStreamDataThread(Socket socket, MainActivity mainActivityReceived, ImageView displayedImageView) { 
     streamSocket = socket; 
     // received activity to work on it in our java file 
     mainActivity = mainActivityReceived ; 
     // received image UI component to display 
     displayedImage = displayedImageView; 
    } 

    @Override 
    public void run() { 
     /* Receiving the image */ 
     try { 
      DecodeData decodeData = new DecodeData(); 
      // call DecodeData to get Image data from stream 
      while (mReceivingStop == false) { 
       if (bitmapImageToDisplay == null) { 
        InputStream inputStream = streamSocket.getInputStream(); 
        if (inputStream.read(dataBuffer) > -1) { 
         // Call the class to decode received stream and return integer with the state of the decoding of the received data 
         // result = 0 ; means that decoding header is successful. 
         // result = -1 ; means that there is a problem in decoding header. 
         byte [] dataHeaderReceived = Arrays.copyOf(dataBuffer, 23) ; 
         result = decodeData.iDecodeReceiveData(dataHeaderReceived); 
         // Evalute the received data 
         if (result == false) { 
          /* Fault on application */ 
          /* Close socket */ 
          streamSocket.close(); 
          mReceivingStop = true; 
         } 

         if (result == true) { 
          /* Data have been received */ 
          /* Show image */ 
          BitmapFactory.Options imageOption = new BitmapFactory.Options(); 
          imageOption.inJustDecodeBounds = true; 
          BitmapFactory.decodeResource(mainActivity.getResources(), R.id.display_image, imageOption); 
          imageOption.inSampleSize = calculateInSampleSize (imageOption, 550, 435) ; 
          imageOption.inJustDecodeBounds = false; 
          bitmapImageToDisplay = BitmapFactory.decodeByteArray(dataBuffer, 23, decodeData.imageSize, imageOption); 

          if (bitmapImageToDisplay != null) { 
           mainActivity.runOnUiThread(new Runnable() { 
            @Override 
            public void run() { 
             //try to display to image 
             displayedImage.setImageBitmap(bitmapImageToDisplay); 
            } 
           }); 
          } 
         } 
        } 
        SystemClock.sleep(300); 
        bitmapImageToDisplay = null ; 
       } 
      } 
      streamSocket.close(); 
      mReceivingStop = true; 

      mainActivity.runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        Toast.makeText(mainActivity, "Finished", Toast.LENGTH_LONG).show(); 
       } 
      }); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      StringBuilder eMsg = new StringBuilder(); 
      eMsg.append("Something wrong: " + e.getMessage()); 
      final String eMessage=eMsg.toString(); 
      // final String eMsg = "Something wrong: " + e.getMessage(); 

      mainActivity.runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        Toast.makeText(mainActivity, eMessage, Toast.LENGTH_LONG).show(); 
       } 
      }); 
     } finally { 
      if(streamSocket != null){ 
       try { 
        streamSocket.close(); 
        mReceivingStop = true ; 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

Logcat出力:Android上

GC_FOR_ALLOC freed 1307K, 27% free 13676K/18596K, paused 34ms, total 34ms 
D/dalvikvm: GC_FOR_ALLOC freed 1306K, 27% free 13676K/18596K, paused 8ms, total 8ms 
D/skia: --- SkImageDecoder::Factory returned null 
D/skia: --- SkImageDecoder::Factory returned null 
D/dalvikvm: GC_FOR_ALLOC freed 1607K, 29% free 13376K/18596K, paused 24ms, total 24ms 
D/skia: --- SkImageDecoder::Factory returned null 
D/dalvikvm: GC_FOR_ALLOC freed 1255K, 27% free 13728K/18596K, paused 9ms, total 9ms 
+0

私はSystemClock.sleep(300)を使用しました。前にデコードにキャッチしていなかったように、デコードプロセスの時間を与え、デコード戻りのメッセージが表示されていました。 – zelf

+0

'DecodeData'とは何ですか?そしてあなたはどこから 'resId'を取得していますか? – Bryan

+0

DecodeDataは受信した画像のヘッダをデコードして画像の属性を取得することもできます。 – zelf

答えて

0

ロードビットマップは、大規模でかなり複雑なトピックです。だから私はあなたのためにそれを処理するための実績のあるライブラリの1つを使用することをお勧めします。 Glide,PicassoまたはFrescoなどです。これらのライブラリは、あなたのためにビットマップを読み込むことに伴う落とし穴の多くを処理します。メモリの制約、キャッシング、スレッディングなどがあります。


あなたが本当に一人で行きたい場合は、あなた自身でこれらの問題に直面する必要があります。 SkImageDecoder::Factory returned nullは、ビットマップが正しくデコードできない場合に、多くの問題によって引き起こされる可能性のある方法のうち、BitmapFactory.decode...メソッドが吐き出すものです。私はこれを引き起こしていることを正確にはわかりませんが、あなたのコードにはいくつかの問題があります。

最初にMainActivityThreadに渡します。これは問題の発生を尋ねています。代わりにImageViewThreadに渡すだけで済みます。そして、そうでない場合は、あなたのContextの漏洩リスク、あなたはWeakReferenceを使用してください:

WeakReference<ImageView> mDisplayedImageView; 

SocketServerStreamDataThread(Socket socket, ImageView imageView) { 
    mDisplayedImageView = new WeakReference<>(imageView); 
    ... 
} 

次は、Bitmapの境界を復号化するために描画可能リソースを使用しているが、その後、あなたはSocketからBitmapを取得しようとしています接続。 、

options.inJustDecodeBounds = false; 

BufferedInputStream in = new BufferedInputStream(streamSocket.getInputStream()); 

Bitmap bitmap = BitmapFactory.decodeStream(in, null, options); 

in.close(); 

最後に:代わりに、InputStreamを使用して境界をデコードする必要があります。

BufferedInputStream inBounds = new BufferedInputStream(streamSocket.getInputStream()); 

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
BitmapFactory.decodeStream(inBounds, null, options); 

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

inBounds.close(); 

をそしてBitmapFactoryが同様にストリームをデコードする方法を持っているとして、あなたは、別のDecodeDataクラスを持っている必要はありません障害を克服するためにThread.sleep()またはSystemClock.sleep()を使用している場合は、おそらくソリューションを考え直すべきです。これらはただちに私が気づいた問題です。ライブラリの助けを借りずに続行したい場合は、ビットマップを効率的に読み込む方法をさらに研究することをおすすめします。良い出発点はthe documentationです。

+0

あなたのおかげでありがとうございますが、最初に受信した画像にデコードする必要があるので、DecodeData BitmapFactoryでデコードすることはできませんので、まず特殊なデータを読み取るために最初の22バイトを読み取る必要があります。私は '私はそれについて検索するWeakReference'について知っていない 'runOnUiThread'を使用するために 'MainActivity'を渡しているit.Alsoのソースを見つけることができないこの問題を克服するために 'SystemClock.sleep()'を使用していますそれが解決策であれば。 – zelf

+0

私は質問があります.PicassoやGlideには、BitmapFactory.decodeの代わりにイメージデコーダが含まれていますか? – zelf

+1

Picassoが知っている限り、GlideとFrescoはすべてBitmapFactory.decode ...メソッドを使って画像をデコードしますが、別々のデコーダは含まれていません。 – Bryan

関連する問題