Опознайте алгоритм

Тема в разделе "WASM.A&O", создана пользователем reverser, 8 июл 2005.

  1. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    Есть алгоритм распаковки. Надо сделать упаковку. Вроде бы и не хаффман, и не LZ...
    Код (Text):
    1. in_index = 0;
    2. while (in_index < comp_size)
    3. {
    4.    for (i = 0; i < 0x100; i++) left[i] = i; //set all nodes to leaves
    5.    tree_index = 0;
    6.    while (tree_index != 0x100) {
    7.       cmp_byte = in_buffer[in_index++];
    8.       if (cmp_byte > 0x7F) {
    9.          tree_index += (cmp_byte - 0x7F);
    10.          cmp_byte = 0;
    11.       }
    12.       if (tree_index != 0x100) {
    13.          do {
    14.             left[tree_index] = in_buffer[in_index++];
    15.             if (tree_index != left[tree_index])  //not a leaf
    16.                right[tree_index] = in_buffer[in_index++];  //add right child
    17.             tree_index++;
    18.          } while (cmp_byte--);
    19.       }
    20.    }
    21.    chunk_size = (in_buffer[in_index] << 8) | in_buffer[in_index+1];
    22.    in_index+=2;
    23.    stack_size = 0;
    24.    while (chunk_size>0 || stack_size>0) {
    25.       if (stack_size > 0)
    26.          node = stack[--stack_size];
    27.       else {
    28.          chunk_size--;
    29.          node = in_buffer[in_index++];
    30.       }
    31.       child = left[node];
    32.       if (node == child) //reached a leaf, output it
    33.          out_buffer[out_index++] = child;
    34.       else  {  //add both children to stack
    35.          stack[stack_size++] = right[node];
    36.          stack[stack_size++] = child;
    37.       }            
    38.    }
    39. }
    40.  
     
  2. _staier

    _staier New Member

    Публикаций:
    0
    Регистрация:
    3 окт 2003
    Сообщения:
    738
    Адрес:
    Ukraine
  3. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    Спасибо, но тут не обычный RLE.

    Только что наткнулся на splay trees, немного похоже... может оно?
     
  4. Dr.Golova

    Dr.Golova New Member

    Публикаций:
    0
    Регистрация:
    7 сен 2002
    Сообщения:
    348
    Помница копирование фраз в обратную сторону через stack обычно применяется в методе Shrinking (LZW). Но там вроде поболее кода должно быть.
     
  5. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев
    reverser

    очень похоже на LZW, может только модифицированный какой-то, лень разбираться
     
  6. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    Вот пара реальных деревьев, получаемых при распаковке (запись немного упростил для экономии места). Может натолкнёт на какую мысль...
    Код (Text):
    1. ff -> (00, 00) = [00 00 ]
    2. fe -> (ff, ff) = [00 00 00 00 ]
    3. fd -> (fe, fe) = [00 00 00 00 00 00 00 00 ]
    4. fc -> (fd, fd) = [00 ] x 16
    5. fb -> (fc, fc) = [00 ] x 32
    6. fa -> (fb, fb) = [00 ] x 64
    7. f9 -> (fa, fa) = [00 ] x 128
    8.  

    Код (Text):
    1.  
    2. fe -> (00, 00) = 00 00
    3. fd -> (fe, fe) = 00 00 00 00
    4. fc -> (fd, fd) = 00 00 00 00 00 00 00 00
    5. fb -> (3b, 05) = 3b 05
    6. fa -> (fb, 00) = 3b 05 00
    7. f9 -> (fa, fa) = 3b 05 00 3b 05 00
    8. f8 -> (fc, fc) = [00 ] x 16
    9. f7 -> (f9, f9) = [3b 05 00 ] x 4
    10. f6 -> (f8, f8) = [00 ] x 32
    11. f5 -> (ff, ff) = ff ff
    12. f4 -> (f6, f6) = [00 ] x 64
    13. f2 -> (f7, f7) = [3b 05 00 ] x 8
    14. f1 -> (f5, ff) = ff ff ff
    15. f0 -> (f4, f4) = [00 ] x 128
    16. ee -> (cf, c2) = cf c2
    17. ed -> (ee, c0) = cf c2 c0
    18. ec -> (f2, f2) = [3b 05 00 ] x 16
    19. eb -> (4e, 4a) = 4e 4a
    20. ea -> (75, eb) = 75 4e 4a
    21. e9 -> (f9, fa) = [3b 05 00 ] x 3
    22. e8 -> (78, 75) = 78 75
    23.  
     
  7. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев
    Лучше дай небольшой кусок запакованных данных, ну или начало хотя бы, или проверь сам - сможет ли он с помощью LZW распаковаться
     
  8. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    Если это и LZW, то явно нестандартный, т.к. коды восьмибитные, а не переменной длины.

    Вот пример данных

    Дерево (первый цикл алгоритма):
    Код (Text):
    1. FE 7F F7 F9 F9 06 FA FA FB FB FC FC FD FD FE FE FF FF 00 00


    При расшифровке получается первое из тех, что я привёл.

    Собственно данные (второй цикл):
    Код (Text):
    1.  
    2. 00 25 42 4D 38 00 03 FE 00 36 FF 00 28 FE 01 FF
    3. 00 01 FF 01 00 18 FD 00 C3 0E FF C3 0E F8 F8 F8
    4. F8 F8 F8 F8 F9 FB FE
    5.  


    (00 25) - длина следующего фрагмента кодов (chunk_size).

    После распаковки получается:
    Код (Text):
    1. 42 4D 38 00 03 00 00 00 00 00 36 00 00 00 28 00
    2. 00 00 00 01 00 00 00 01 00 00 01 00 18 00 00 00
    3. 00 00 00 00 00 00 C3 0E 00 00 C3 0E 00 00 00 00
    4. ...и ещё много нулей...
    5.  
     
  9. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    Ой, я там немного ошибся при печати деревьев. В первом ещё добавляется f8 -> (f9, f9) = [00 ] x 256
     
  10. OLS

    OLS New Member

    Публикаций:
    0
    Регистрация:
    8 янв 2005
    Сообщения:
    322
    Адрес:
    Russia
    Итак, имеем :

    1) строится дерево с 255 узлами (для всех букв появившихся в сжимаемом блоке, зарезервированы узлы + оставшиеся номера узлов используются для более длинных комбинаций)

    2) в выходной поток идут только номера узлов - явный признак того, что за основу взят LZW

    3) но в качестве узлов для склейки используются как сочетания (нода+символ) - LZW, так и (нода+нода) - LZMV

    4) практически все в алгоритме ориентировано на размерность байта (в т.ч. индексы нод в дереве) - очень напоминает какую-то специализированную разновидность LZW наподобие того как в DOS-овских EXE-паковщиках на основе LZ77 был построен очень красивый байт-ориентированный алгоритм сжатия с объектным кодом функции распаковки в 77 байт.



    Offtopic : с трудом верю в практическую значимость подобного алгоритма из-за слишком маленького для LZW-семейства размера дерева. Насколько хорошо он сжимает данные ?
     
  11. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    OLS

    Во, это уже ближе к делу. Не подскажешь, как примерно это дерево строить? Я что-то пытался прикинуть на бумажке, но выходит не очень.

    Насчёт эффективности есть такие данные: 90 файлов общим размером 28673111 байт (28666991 если отбросить заголовки) распаковываются в 66128936. Получается где-то 43%. Причём, по-моему, алгоритм используется не на полную мощность, т.к. в этих файлах максимальная длина кодируемых строк ограничена 256 байтами.
     
  12. reverser

    reverser New Member

    Публикаций:
    0
    Регистрация:
    27 янв 2004
    Сообщения:
    615
    Так, кажись нашёл публикацию в которой описан этот самый алгоритм. Правда только японский вариант, но это не страшно :)
    Код (Text):
    1. constant K=256;
    2. procedure code;
    3.  begin
    4.    initialize(T);
    5.    readfile(M);
    6.    while maxn(M,ci,cj) >= 2 do begin
    7.       enter(T,ci,cj,(ci·cj),nil);
    8.       change(M,ci,cj,(ci·cj));
    9.    end;
    10.    Cmax:=K - 1;
    11.    for i:=l to length(M) do writetree(element(M,i));
    12.  end;
    13. procedure wrltetree(c);
    14.  begin
    15.    if c<K then
    16.      writetreecode(0); writecode(e);
    17.    else if assignedcode(T,c) <> nil then
    18.      writetreecode(0); writecode(assignedcode(T,c));
    19.    else
    20.      writetreecode(1);
    21.      writetree(left(c)); writetree(right(c));
    22.      Cmax:=Cmax + 1;
    23.      reenter (left(c),right(c), c, Cmax);
    24.    fi;
    25.  end;
    26.  
    27. constant K=256;
    28. procedure decode;
    29.  begin
    30.    initialize(T);
    31.    Cmax:=K - 1;
    32.    while not end of file do dummy:=readtree;
    33.  end;
    34. function readtree;
    35.  begin
    36.    t:=readtreecode;
    37.    if t=0 then
    38.       n:=readcode; writestr(c); return(c);
    39.    else
    40.       cl:=readtree; cr:=readtree;
    41.       Cmax=Cmax+1; enter(T, cl, cr, (cl·er),Cmax);
    42.       return(Cmax);
    43.    fi;
    44.  end;
    45. procedure writestr(c);
    46.  begin
    47.    if c<K then
    48.      write(c);
    49.    else
    50.      writestr(left(T,c)); writestr(right(T,c));
    51.    fi;
    52.  end;


    Всем спасибо, будем копать...