Android 有时位图解码返回SkImageDecoder::Factory返回null,它显示损坏的图像
我开发了下面的类来接收使用头发送的图像(22字节),首先我解码头以检查图像的正确性,然后我解码图像,但并非所有图像都被解码,有时它会返回Android 有时位图解码返回SkImageDecoder::Factory返回null,它显示损坏的图像,android,sockets,android-bitmap,bitmapfactory,skia,Android,Sockets,Android Bitmap,Bitmapfactory,Skia,我开发了下面的类来接收使用头发送的图像(22字节),首先我解码头以检查图像的正确性,然后我解码图像,但并非所有图像都被解码,有时它会返回SkImageDecoder::Factory returned null。我正在使用Android教程来inSampleImage public class SocketServerStreamDataThread extends Thread { private Socket streamSocket; MainActivity mainA
SkImageDecoder::Factory returned null
。我正在使用Android教程来inSampleImage
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输出:
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
在Android上加载位图是一个庞大而相当复杂的主题。这就是为什么我建议使用一个经过验证的库来为您处理它;比如,或者。这些库将处理为您加载位图时出现的许多陷阱;包括内存限制、缓存和线程
如果你真的想单独行动,你就必须自己面对这些问题。如果位图无法正确解码,则
SkImageDecoder::Factory返回null
就是BitmapFactory.decode…
方法所输出的,这可能是由许多问题造成的。我不知道到底是什么导致了这种情况,但我确实看到了代码中的一些问题
首先,将main活动
传递到线程
,这只是自找麻烦。相反,您只需将图像视图
传递到线程
。并确保使用WeakReference
,否则您可能会泄漏上下文:
WeakReference<ImageView> mDisplayedImageView;
SocketServerStreamDataThread(Socket socket, ImageView imageView) {
mDisplayedImageView = new WeakReference<>(imageView);
...
}
而且您不需要单独的decodeddata
类,因为BitmapFactory
也有一种解码流的方法:
options.inJustDecodeBounds = false;
BufferedInputStream in = new BufferedInputStream(streamSocket.getInputStream());
Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
in.close();
最后,如果您正在使用Thread.sleep()
或SystemClock.sleep()
来克服一些障碍,您可能应该重新考虑您的解决方案。这些就是我在快速浏览时注意到的问题。如果你真的想在没有库的帮助下继续,我建议你做一些关于如何高效加载位图的研究;一个好的起点是。在Android上加载位图是一个庞大而相当复杂的主题。这就是为什么我建议使用一个经过验证的库来为您处理它;比如,或者。这些库将处理为您加载位图时出现的许多陷阱;包括内存限制、缓存和线程
如果你真的想单独行动,你就必须自己面对这些问题。如果位图无法正确解码,则SkImageDecoder::Factory返回null
就是BitmapFactory.decode…
方法所输出的,这可能是由许多问题造成的。我不知道到底是什么导致了这种情况,但我确实看到了代码中的一些问题
首先,将main活动
传递到线程
,这只是自找麻烦。相反,您只需将图像视图
传递到线程
。并确保使用WeakReference
,否则您可能会泄漏上下文:
WeakReference<ImageView> mDisplayedImageView;
SocketServerStreamDataThread(Socket socket, ImageView imageView) {
mDisplayedImageView = new WeakReference<>(imageView);
...
}
而且您不需要单独的decodeddata
类,因为BitmapFactory
也有一种解码流的方法:
options.inJustDecodeBounds = false;
BufferedInputStream in = new BufferedInputStream(streamSocket.getInputStream());
Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
in.close();
最后,如果您正在使用Thread.sleep()
或SystemClock.sleep()
来克服一些障碍,您可能应该重新考虑您的解决方案。这些就是我在快速浏览时注意到的问题。如果你真的想在没有库的帮助下继续,我建议你做一些关于如何高效加载位图的研究;一个好的起点是。我使用了SystemClock.sleep(300);如前所述,为解码过程留出时间,无法捕获解码,出现解码返回false的消息。什么是decodeddata
?您从何处获得resId?DecodeData是一个类,用于解码接收图像的头部,以获得图像属性,还用于了解图像大小i使用的SystemClock.sleep(300);如前所述,为解码过程留出时间,无法捕获解码,出现解码返回false的消息。什么是decodeddata
?您从何处获取resId
信息?DecodeData是一个类,用于解码接收图像的标题,获取图像属性,还用于了解图像大小,以供帮助,但首先,接收到的图像添加了22个需要解码的特殊字节头,因此我使用的是DecodeData类。它无法使用BitmapFactory进行解码,因此我需要首先读取前22个字节来读取特殊数据。第二,我正在使用“SystemClock.sleep()”来解决这个问题,因为我找不到问题的根源。另外,我正在通过“MainActivity”来使用“RunUnuithRead”我不知道“WeakReference”,如果这是一个解决方案,我将搜索它。我有一个问题,毕加索或Glide内部是否包含图像解码器而不是“BitmapFactory.decode”?据我所知,毕加索、Glide和Fresco都使用BitmapFactory.decode…
方法对图像进行解码,它们不包含单独的解码器。您还应该使用,不要到处传递main活动
。谢谢您的帮助,但首先接收到的图像添加了22个需要解码的特殊字节头,因此我使用的是DecodeData类。无法使用BitmapFactory对其进行解码,因此我需要先读取前22个字节来读取特殊数据。第二,我正在使用“SystemClock.sleep()”来解决这个问题,因为我找不到问题的根源。另外,我正在通过“MainActivity”来使用“RunUnuithRead”我不知道“WeakReference”,如果这是一个解决方案,我将搜索它。我有一个问题,毕加索或Glide内部是否包含图像解码器而不是“BitmapFactory.decode”?据我所知,毕加索、Glide和Fresco都使用BitmapFactory.decode…
方法对图像进行解码,它们不包含单独的解码器。您还应该使用,而不是传递main活动。