Haskell 用attoparsec解析JPEG标记

Haskell 用attoparsec解析JPEG标记,haskell,attoparsec,Haskell,Attoparsec,作为一个加深我对Haskell的了解和了解的项目,我正在努力实现一个JPEG解码器,它将在未来的计算机视觉工作中派上用场 我选择的第一步是解析图像中的所有“标记”。这些由字节0xFF后跟非0字节表示。0xFF字节后跟0x00字节应视为正常数据 我遇到的问题是,当遇到0xFF 0x00组合时,解析似乎完全完成,并且找不到更多有效的标记(如果在标准JPEG上运行,您将看到解析的图像标记的开始,而不是图像标记的结束,因为0xFF 0x00经常出现在图像数据本身中) 导入系统环境 导入系统.IO 导入控

作为一个加深我对Haskell的了解和了解的项目,我正在努力实现一个JPEG解码器,它将在未来的计算机视觉工作中派上用场

我选择的第一步是解析图像中的所有“标记”。这些由字节0xFF后跟非0字节表示。0xFF字节后跟0x00字节应视为正常数据

我遇到的问题是,当遇到0xFF 0x00组合时,解析似乎完全完成,并且找不到更多有效的标记(如果在标准JPEG上运行,您将看到解析的图像标记的开始,而不是图像标记的结束,因为0xFF 0x00经常出现在图像数据本身中)

导入系统环境
导入系统.IO
导入控制。应用程序隐藏(多个)
将Data.Attoparsec作为
将符合条件的数据.ByteString作为BS导入
parseMarker=do
第1部分解析标记
parseBody=do
多语法段
parseJPEG=do
handleParseResult$feed(解析解析体jpeg)BS.empty
handleParseResult结果=do
案例结果
失败消息->消息
完成ur->显示r
_ -> ""
main=do

(文件名:)由于
parseMarker
使用输入,但可能中途失败,因此当遇到0xFF 0x00时,必须能够“倒带”并重试其他解析

我没有安装Attoparsec,但我假设它类似于Parsec,默认情况下不会回溯

parseSection =
    skipMany (notWord8 0xFF <|> try (word8 0xFF >> word8 0x0)) >> parseMarker
parseSection=
skipMany(notWord8 0xFF try(word8 0xFF>>word8 0x0))>>parseMarker

问题是你没有告诉它去解析一个0xFF,0x00的序列,它已经晚了,所以希望下一个回答者会给它加上一些词(这也许对你有足够的帮助),但是这里有一个替代的
解析标记
和附带的
handleParseResult

parseMarker = do   -- or call it "parsePotentialMarker"
  part1 <- word8 0xFF
  part2 <- anyWord8
  return $
    if (part2 /= 0)
        then [(part1, part2)]
        else []

-- ... skipping other functions...
handleParseResult result = do
  case result of
    Fail _ _ msg -> msg
    Done _ r -> show (concat r)
-- ...

依我看,你应该在这里内联发布你的代码。它不会太长,而且更容易回复。很好的一点,下次我会确保这样做。非常感谢,这非常有效,非常有意义。我曾经尝试过使用try,但是由于没有处理0xFF 0x0案例,它当然失败了。谢谢,这也非常有用
parseMarker = do   -- or call it "parsePotentialMarker"
  part1 <- word8 0xFF
  part2 <- anyWord8
  return $
    if (part2 /= 0)
        then [(part1, part2)]
        else []

-- ... skipping other functions...
handleParseResult result = do
  case result of
    Fail _ _ msg -> msg
    Done _ r -> show (concat r)
-- ...
main =
  let contents = BS.pack [1,2,3,4,0xFF,1 {- marker 1 -},0xFF,0x00,0xFF,2 {- marker 2 -},31,13,0xFF,0x00]
  in putStrLn $ parseJPEG contents