Как эффективно анализировать блок JPEG с энтропийным кодированием?

Я просто пытаюсь перейти через блок SOS_MT в файле .JPEG, я не хочу использовать данные ни для чего, я просто хочу знать, где они заканчиваются. Насколько я понимаю из статьи о JPEG в Википедии, в то время как все остальные блоки в файле JPEG начните с нескольких байтов, которые указывают длину блоков, блок SOS_MT - это... ну, злое болото, в котором у вас нет другого выбора, кроме как анализировать байт за байтом, пока вы не дойдете до его конца.

Поэтому я пришел со следующим кодом, чтобы сделать именно это:

entropyCoded :: Parser Int
entropyCoded = do
    list_of_lengths <-  many' $
         (
           do
             _ <- notWord8 0xFF
             return 1
         )
         <|>
         (
           do
             _ <- word8 0xFF
             _ <- word8 0
             return 2
         )
         <|>
         (
           do
             l <- many1 (word8 0xFF)
             _ <- satisfy (\x -> ( x >= 0xD0 && x < 0xD7 ))
             return $ 1 + length l
         )
         <|>
         (
           do
             _ <- word8 0xFF
             maybe_ff <- peekWord8'
             if maybe_ff == 0xFF
               then
                 return 1
               else
                 fail "notthere"
         )
    foldM (\ nn n -> nn `seq` return (nn + n) ) 0 list_of_lengths

В этом коде используется Atoparsec, и, насколько мне удалось убедиться, это правильно. Это просто медленно. Любые советы о том, как улучшить производительность этого парсера?


person dsign    schedule 26.02.2016    source источник
comment
Сжатые данные изображения помещаются между FFDA и FFD9. Проблема в том, что FFD9 может отсутствовать и файл все равно должен там заканчиваться. Я не понимаю, с какой целью вы прыгаете «сквозь» блок SOS_MT. Нет ничего «сквозного» и ничего «по ту сторону».   -  person BitBank    schedule 26.02.2016
comment
Во-первых, (потенциально) с помощью библиотеки, предназначенной для двоичной сериализации (я неравнодушен к cereal ). Во-вторых, каждая ветвь безоговорочно разбирает слово. Вместо того, чтобы анализировать это слово и возвращаться назад, если вы потерпите неудачу позже, вы должны проанализировать это слово и решить, что вы собираетесь делать дальше, основываясь на его значении. Наконец (не уверен в этом) вместо вычисления и суммирования длины используйте match, чтобы получить проанализированную строку, они просто вычисляют ее длину.   -  person user2407038    schedule 26.02.2016
comment
@BitBank Простите, если я не правильно понял, но как насчет нескольких проходов для прогрессивного .JPEG? Разве каждый проход не использует другой блок SOS_MT?   -  person dsign    schedule 26.02.2016
comment
Спасибо @ user2407038, ваше предложение о том, чтобы исключить слово синтаксический анализ, хорошо.   -  person dsign    schedule 26.02.2016
comment
Для прогрессивных изображений есть сигнал SOS (FFDA) в начале каждого сканирования. Эта последовательность байтов (FFDA) может интерпретироваться только как маркер SOS; сжатые данные с последовательностью FFDA будут закодированы как FF00DA.   -  person BitBank    schedule 26.02.2016


Ответы (2)


Если вы хотите пропустить рынок SOS, просто найдите следующий маркер, который не является маркером перезапуска.

Читайте байты, пока не найдете и FF. Если следующее значение 00, это сжатое значение FF и его пропускают. Если это маркер перезапуска, пропустите его. В противном случае FF должен начать следующий блок.

person user3344003    schedule 26.02.2016

небольшое дополнение к предыдущему ответу, согласно ISO/IEC 10918-1 : 1993(E) стандарт:

B.1.1.5 Сегменты данных с энтропийным кодированием

Сегмент данных с энтропийным кодированием содержит выходные данные процедуры энтропийного кодирования. Он состоит из целого числа байтов, независимо от того, используется ли процедура энтропийного кодирования по методу Хаффмана или арифметическому.

ПРИМЕЧАНИЕ 1

Преобразование сегментов с энтропийным кодированием в целое число байтов выполняется следующим образом: для кодирования Хаффмана 1-биты используются, если необходимо, для дополнения конца сжатых данных для завершения последнего байта сегмента. Для арифметического кодирования выравнивание байтов выполняется в процедуре, завершающей энтропийно-кодированный сегмент (см. D.1.8).

ЗАМЕТКА 2

Чтобы гарантировать, что маркер не встречается в сегменте с энтропийным кодированием, любой байт X'FF', сгенерированный кодером Хаффмана или арифметическим кодировщиком, или байт X'FF', сгенерированный путем заполнения 1-битов, описанных в примечании 1 выше, за ним следует "заполненный" нулевой байт (см. D.1.6 и F.1.2.3).

поэтому, когда вы встречаете 0xFF в энтропийно-кодированной части в позиции N, читайте вперед еще один байт. если следующий байт 0x00, то это "заполненный" ноль. если это другой 0xFF, то есть заполнение, перепроверить от N+1. каждый второй байт (0x01-0xFE) является частью следующего маркера.

person ThatsMe    schedule 17.11.2018