我正在为我们的业务应用程序编写一个小插件,目标是使用条形码阅读器拍照。
一切正常,但问题是条形码阅读器每隔一定时间发送图片,它们非常随机(取决于图像的大小和波特率)。如果没有对我收到的字节进行全面分析,就无法判断图片是否已加载。
目前,我的逻辑尝试通过分别搜索 FF D8
和 FF D9
字节来查找 JPEG 的开始/结束。问题是字节 FF D9
可能出现在图像内部。
我显然可以对字节进行一些具体的分析,但是随着Barcodereader不断发送数据,在接收字节时执行耗时的操作(调试、CPU、IO等)将最终导致蓝屏.
我真正想要的是
读取显示图像大小的字节(我无法 甚至研究尺寸是否会采用页眉/页脚本身 考虑到它本身......我必须为此进行计算吗? )。
检查我是否收到所有字节。
我将把我接收和使用字节的代码(它在数据接收事件,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/