Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > компрессия lzw для gif


Автор: SATYR 25.5.2007, 15:22
Народ подскажите пожалуста модуль(если такой есть) в котором можно глянуть реализацию алгоритма lzw для gif на Перл ? А то весь CPAN перерыл  smile, результата ноль. Конкретно интересует реализация чтения кодов переменной длинны из входного потока при декодировании.

Попытался сам реализовать алгоритм согласно его описаниюhttp://www.compression.ru/arctest/descript/lzw-gif.htm, но возникла такая проблема при обработке входного потока находится несколько кодов окончания потока данных smile .
На всякий случай привожу код, может кто по конкретной ситуации поможет, заранее спасибо:
Код

##Decode grafic data from LZW 
...
{
     my $lzw_size;                # текущий размер кода в битах
     my $ost;                         #остаток от предыдещего слова 
     my $ost_size;                 #размер остатка от предыдущего слова
     my @table;                      #таблица кодов

     sub decode_lzw_{
         my $frame=$_[0];           #gif парсится и представляется в виде структуры данных  собс-но $frame это указатель на соответствующий узел структуры
         my $word;                       #cлово фиксированного размера извлекаемое из кодированного потока
         my $word_size;               # размер этого слова
         my $i=0;
         for(0..bytes::length($$frame{body})-1){
               $lzw_size||=$$frame{lzw_size}+1;      #используем сначала "код размера"  указанный в потоке данных
               $word=vec($$frame{body},$_,8);        # извлекаем слово
               $word_size=8;                                      # размера 8-бит
             if(defined($ost_size)){                                  #если предыдущее слово обработано не полностью 
                 $word=($word<<$ost_size)|$ost;             # добавляем остаток 
                 $word_size+=$ost_size;                            # и корректируем размер
                 undef $ost_size;
             }     
             while(($word_size-$word_size % $lzw_size)/$lzw_size > 0){
                    my $code=$word & 2**$lzw_size-1;                                  #из полученного слова из младших разрядов извлекаем коды текущей длинны
                       $word=$word>>$lzw_size;                                              # выбрав код сдвигаем  
                       $word_size-=$lzw_size;                                                 
                       if($code==2**$$frame{lzw_size}){                       
                         #здесь если встретили код очистки таблици делаем что необходимо...
                       }elsif($code==2**$$frame{lzw_size}+1){
                         #сюда попадаем если конец потока данных
                       }else{ 
                          #а сюда иначе
                            $lzw_size++ if($code==2**$lzw_size-1); # если все коды длинны 2^текщая длинна исчерпаны 
                             $lzw_size=$$frame{lzw_size}+1 if($code==4095);  #если мы исчерпали коды длинны 12-бит (за ним должен следовать код очистки)
                           #ниже должно следовать процедура обрабатывающая полученный код
                       }
            }
            if($word_size!=0){      # и наконец здесь сохраняем остаток для обработки его со следующим словом
                $ost=$word;
                $ost_size=$word_size;
            }

           }
      }    

}



ЗЫ Не судите строго, возможно, изобретаю велосипед, но тем не менее... smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)