c# - 如何有效读取流上 JPEG 图像的大小

标签 c# stream serial-port jpeg barcode-scanner

我正在为我们的业务应用程序编写一个小插件,目标是使用条形码阅读器拍照。

一切正常,但问题是条形码阅读器每隔一定时间发送图片,它们非常随机(取决于图像的大小和波特率)。如果没有对我收到的字节进行全面分析,就无法判断图片是否已加载。

目前,我的逻辑尝试通过分别搜索 FF D8FF D9 字节来查找 JPEG 的开始/结束。问题是字节 FF D9 可能出现在图像内部。

我显然可以对字节进行一些具体的分析,但是随着Barcodereader不断发送数据,在接收字节时执行耗时的操作(调试、CPU、IO等)将最终导致蓝屏.

我真正想要的是

  1. 读取显示图像大小的字节(我无法 甚至研究尺寸是否会采用页眉/页脚本身 考虑到它本身......我必须为此进行计算吗? )。

  2. 检查我是否收到所有字节。

我将把我接收和使用字节的代码(它在数据接收事件,serialPortish)和正确的完整图像(以字节为单位)和损坏的图像也许会有帮助。

数据接收事件

        private void ScannerPort_DataReceived(object sender, DataReceivedEventArgs e)
        {
            if (_WaitingForImage)
            {
                List<byte> imageBufferList = new List<byte>(e.RawBuffer);
                {

                    if (imageBufferList[0] == 0x24 && imageBufferList[1] == 0x69)
                    {
                        for (int i = 0; i < 17; i++)
                        {
                            imageBufferList.RemoveAt(0);
                        }
                    }

                    byte[] imageBuffer = imageBufferList.ToArray();
                    _ImageReceiving = false;
                    _WaitingForImage = false;
                    this.OnImageReceived(imageBuffer);
                }

                //imageBufferList.AddRange(e.RawBuffer);

            }

完整字节数组

https://codepen.io/NicolaiWalsemann/pen/KKzxaXg

损坏的字节数组

https://codepen.io/NicolaiWalsemann/pen/YzqONxd

解决方案1

我可以轻松地创建一个在首次调用 DataReceived 事件后等待 500ms-2000ms 的计时器。这将确保我拥有一切,然后我可以根据需要解析它。但显然总是要无理地等待并不是我想要的。

最佳答案

我认为有人已经回答了这个问题:Detect Eof for JPG images

我无法说得更好。

由于您将接收大量数据,因此您需要随时进行解析。像下面这样的东西。它未经测试,我可能会向后计算计数(大端与小端)。它还假设一个 block 可能跨越 2 个图像,或者 block 可能会分割 FFxx 代码和计数。它也没有以任何方式优化,但对于小图像可能没问题。

    private List<byte> imageBuffer = new List<byte>();
    private int imageState = 0;
    private int skipBytes = 0;

    private void ScannerPort_DataReceived(object sender, DataReceivedEventArgs e)
    {
        List<byte> tempBuffer = new List<byte>(e.RawBuffer);

        foreach (byte b in tempBuffer)
        {
            _ImageReceiving = true;
            imageBuffer.Add(b);

            switch (imageState)
            {
                case 0: // Searching for FF
                    if(b == 0xFF)
                        imageState = 1;
                    break;
                case 1: // First byte after FF
                    if (b == 0 || b == 1 || (b <= 0xD8 && b >= 0xD1))
                    {
                        // Code is not followed by a count
                        imageState = 0;
                    }
                    else if (b == 0xD9)
                    {
                        // End of image
                        _ImageReceiving = false;
                        this.OnImageReceived(imageBuffer.ToArray());
                        imageBuffer = new List<byte>();
                        imageState = 0;
                    }
                    else
                    {
                        // Code is 
                        imageState = 2;
                    }

                    break;
                case 2: // First count byte,  big endian?
                    skipBytes = ((int) b) * 0x100;
                    imageState = 3;
                    break;
                case 3: // Second count byte
                    skipBytes += b;
                    imageState = 4;
                    break;
                case 4: // skip
                    skipBytes--;
                    if (skipBytes == 0) imageState = 0;
                    break;
            }
        }
    }

关于c# - 如何有效读取流上 JPEG 图像的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63933704/

相关文章:

c# - 带有 C# 示例的 Google BigQuery

c# - 为什么 Stream.ReadByte 返回 int?

c# - 将流包装在流中 - 包装后的流会被正确处理吗?

c# - 流、字符串和空字符

c# - 是哪个属性使背景变白?

c# - 无法使用 oData 查询选项

c# - 初学者的数据库问题

java - 如何结合Java绘图代码和Java串行代码来读取Arduino传感器值?

python - 如何在不重启的情况下打开Arduino串口

java - 如何使用 Javax.Comm 串行事件监听器接收 SMS 消息