【问题标题】:Using decodeByteArray to convert bitmap: Showing a black image and LogCat shows skimagedecoder factory returned null使用 decodeByteArray 转换位图:显示黑色图像和 LogCat 显示 skimagedecoder 工厂返回 null
【发布时间】:2014-10-17 03:16:34
【问题描述】:

我正在尝试从每 5 秒发送一次图像的远程服务器接收图像。现在,在 Android 端,我正在使用 decodeByteArray() 将其转换为位图。运行时,有时会在屏幕上显示图像,有时会显示黑屏,LogCat 显示skimagedecoder 工厂返回null。我不知道问题是什么。

这是我的代码:

public class connection extends AsyncTask {

    @Override
    protected Object doInBackground(Object... arg0) {

        int i = 0;
        try {
            clientSocket = new Socket("134.129.125.126", 8080);
            input = clientSocket.getInputStream();

        } catch (UnknownHostException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        while (true) {
            data = new byte[2048 * 2048];

            try {
                read = input.read(data, 0, data.length);

                System.out.println("getInputStream()");
                bitmap = BitmapFactory.decodeByteArray(data, 0, read);

                System.out.println("deco");

            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
                System.out.println(e);
            }
            runOnUiThread(new Runnable() {
                public void run() {

                    image.setImageBitmap(bitmap);
                    System.out.println("setImage at less than 500");

                }
            });
        }

    }

}

更新 现在,尝试从服务器接收图像的大小,并使其成为正确大小的字节数组。然后decodeByteArray(),又变成Factory返回Null。这是我修改后的代码:

public class connection extends AsyncTask {

        @Override
        protected Object doInBackground(Object... arg0) {

            try {
                clientSocket = new Socket("134.129.125.126", 8080);
                System.out.println("client connect to server");
                input = clientSocket.getInputStream();
                System.out.println("getinputstream");
            } catch (UnknownHostException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

            // while (true) {
            int totalBytesRead = 0;
            int chunkSize = 0;
            int tempRead = 0;
            String msg = null;
            // byte[] data = null;
            byte[] tempByte = new byte[1024 * 1024 * 4];
            try {
                tempRead = input.read(tempByte);
                System.out.println("read:" + tempRead);

            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            if (tempRead < 2000) {
                String message = new String(tempByte, 0, tempRead);
                msg = message.substring(0, 6);
                System.out.println("message head:" + msg);
                byteSize = Integer.parseInt(msg);
                System.out.println("ByteSize:" + byteSize);
                data = new byte[byteSize];
            }

            try {

                while (chunkSize > -1) {
                    System.out.println("data length:" + data.length);
                    chunkSize = input.read(data, totalBytesRead, data.length
                            - totalBytesRead);
                    System.out.println("chunkSize is " + chunkSize);
                    totalBytesRead += chunkSize;
                    System.out.println("Total byte read " + totalBytesRead);
                    if (totalBytesRead == data.length) {
                        if (input.read() != -1) {
                            // error, the file is larger than our buffer
                            throw new RuntimeException("Buffer overflow error!");
                        }

                    }
                }
            } catch (Exception e) {

            }

            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

            System.out.println("deco");

            runOnUiThread(new Runnable() {
                public void run() {

                    image.setImageBitmap(bitmap);
                    System.out.println("setImage at less than 500");

                }
            });

            return null;
        }

    }

【问题讨论】:

    标签: android image-processing bitmap


    【解决方案1】:

    一方面,不能保证您的读取命令正在读取整个图像。 InputStreams 倾向于读取当前可用的字节数,这可能会或可能不会直到文件末尾,这取决于实现。

    您应该继续读入您的字节数组,直到从input.read() 返回的值是-1。这显然需要对一些循环逻辑进行返工,直到您返回 -1 并有一个变量来跟踪读取的总字节数作为所有读取调用的总和。

    例如,从流中读取所有内容

    int totalBytesRead = 0;
    int chunkSize = 0;
    byte[] fileBuffer = new byte[4 * 1024 * 1024];  // 4MB buffer
    
    while (chunkSize > -1) {
        chunkSize = inputStream.read(fileBuffer, totalBytesRead, fileBuffer.length - totalBytesRead);
        totalBytesRead += chunkSize;
        if (totalBytesRead == fileBuffer.length) {
            if (inputStream.read() != -1) {
                // error, the file is larger than our buffer
                throw new RuntimeException("Buffer overflow error!");
            }
        }
    }
    

    【讨论】:

    • 你能给我一些提示或例子吗?我不知道如何确保一次读取所有输入流。
    • 这个文件缓冲区大小应该和我从服务器发送的文件一样吗?因为我的图像大小是动态的,所以 Idk 它对我有用。
    • 现在,我认为问题是确保来自服务器的文件大小需要与客户端的文件缓冲区相匹配。您认为我可以确定然后发送到客户端的文件大小,并将此大小用于 Filebuffer 吗?也许这是一个愚蠢的想法,Idk,如果有任何更聪明的方法?
    • 这取决于服务器在做什么,我相信内容大小是您可以设置的 HTTP 标头。或者,您可以读入一些较小的块,将它们组合成一个块列表,然后在读取所有内容后分配一个新数组,该数组是读取的总字节数,并将每个块复制到最终数组中。
    • 太好了,我想我现在可以应付了。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 2014-06-09
    • 2012-06-01
    • 1970-01-01
    • 2015-02-22
    • 2014-06-13
    相关资源
    最近更新 更多