Frage

Als Projekt, um mein Wissen und mein Komfort mit Haskell zu fördern, arbeite ich an der Implementierung eines JPEG -Decoders, der für zukünftige Computer -Vision -Arbeiten nützlich sein wird.

Der erste Schritt, den ich ausgewählt habe, besteht darin, alle "Marker" innerhalb des Bildes zu analysieren. Diese werden durch das Byte 0xff angezeigt, gefolgt von einem Nicht-0-Byte. Ein 0xff -Byte, gefolgt von einem 0x00 -Byte, muss als normale Daten behandelt werden.

Das Problem, in das ich mich begegnung habe Bildmarkierung wie häufig 0xff 0x00 tritt innerhalb der Bilddaten selbst auf).

import System.Environment
import System.IO

import Control.Applicative hiding (many)
import Data.Attoparsec as A
import qualified Data.ByteString as BS

parseMarker = do
  part1 <- word8 0xFF
  part2 <- notWord8 0x0
  return (part1, part2)

parseSection = do
  A.skipWhile (\x -> x /= 0xFF) *> parseMarker

parseBody = do
  many parseSection

parseJPEG jpeg = do
  handleParseResult $ feed (parse parseBody jpeg) BS.empty

handleParseResult result = do
  case result of
    Fail _ _ msg -> msg
    Done _ r -> show r
    _ -> ""

main = do
  (filename : _ ) <- getArgs
  handle <- openFile filename ReadMode
  contents <- BS.hGetContents handle
  putStrLn $ parseJPEG contents
  hClose handle

https://gist.github.com/767488

War es hilfreich?

Lösung

Seit parseMarker Eingänge konsumiert, aber es kann möglicherweise gleichbleibend nicht bestehen. Sie müssen in der Lage sein, "zurückzuspulen" und einen anderen Analyse wiederholen zu können, wenn Sie auf einen 0xff 0x00 stoßen.

Ich habe keine Attoparsec installiert, aber ich gehe davon aus, dass es Parsec ähnelt, was standardmäßig nicht zurückverfolgt.

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

Andere Tipps

Das Problem ist, dass Sie es nicht sagen, eine Sequenz von 0xff, 0x00 zu analysieren, es ist spät. Hoffentlich wird der nächste Answereter Worte geben (es hilft Ihnen vielleicht genug), aber hier ist eine Alternative parseMarker und begleitet 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)
-- ...

Nebenbei bemerkt, in Fragen hilft es leicht, einen voll funktionsfähigen Test im Code zu haben, so etwas wie:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top