{"id":20160167,"url":"https://github.com/trizen/compression-util","last_synced_at":"2026-05-08T20:32:53.528Z","repository":{"id":228895038,"uuid":"775213747","full_name":"trizen/Compression-Util","owner":"trizen","description":"Implementation of various techniques used in data compression.","archived":false,"fork":false,"pushed_at":"2024-04-13T15:04:15.000Z","size":200,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-14T13:07:40.792Z","etag":null,"topics":["bwt","bzip2","compression","data-compression","deflate","huffman","lossless-data-compression","lz77","lzss","mtf","rle"],"latest_commit_sha":null,"homepage":"https://trizenx.blogspot.com/2023/09/lossless-data-compression.html","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"artistic-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trizen.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-21T00:55:17.000Z","updated_at":"2024-05-02T21:43:42.570Z","dependencies_parsed_at":"2024-05-02T21:43:32.917Z","dependency_job_id":"30f8b020-d4d5-490d-a3a9-34c8c20b3100","html_url":"https://github.com/trizen/Compression-Util","commit_stats":null,"previous_names":["trizen/compression-util"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trizen%2FCompression-Util","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trizen%2FCompression-Util/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trizen%2FCompression-Util/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trizen%2FCompression-Util/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trizen","download_url":"https://codeload.github.com/trizen/Compression-Util/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241597919,"owners_count":19988335,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bwt","bzip2","compression","data-compression","deflate","huffman","lossless-data-compression","lz77","lzss","mtf","rle"],"created_at":"2024-11-14T00:12:36.129Z","updated_at":"2026-05-08T20:32:53.518Z","avatar_url":"https://github.com/trizen.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nCompression::Util - Implementation of various techniques used in data compression.\n\n# SYNOPSIS\n\n```perl\nuse 5.036;\nuse Getopt::Std       qw(getopts);\nuse Compression::Util qw(:all);\n\nuse constant {CHUNK_SIZE =\u003e 1 \u003c\u003c 17};\n\nlocal $Compression::Util::VERBOSE = 0;\n\ngetopts('d', \\my %opts);\n\nsub compress ($fh, $out_fh) {\n    while (read($fh, (my $chunk), CHUNK_SIZE)) {\n        print $out_fh bwt_compress($chunk);\n    }\n}\n\nsub decompress ($fh, $out_fh) {\n    while (!eof($fh)) {\n        print $out_fh bwt_decompress($fh);\n    }\n}\n\n$opts{d} ? decompress(\\*STDIN, \\*STDOUT) : compress(\\*STDIN, \\*STDOUT);\n```\n\n# DESCRIPTION\n\n**Compression::Util** is a function-based module, implementing various techniques used in data compression, such as:\n\n    * Burrows-Wheeler transform\n    * Move-to-front transform\n    * Huffman Coding\n    * Arithmetic Coding (in fixed bits)\n    * Run-length encoding\n    * Fibonacci coding\n    * Elias gamma/omega coding\n    * Delta coding\n    * BWT-based (de)compression\n    * LZ77/LZSS (de)compression\n    * LZW (de)compression\n    * Bzip2 (de)compression\n    * GZIP (de)compression\n    * ZLIB (de)compression\n    * LZ4 (de)compression\n\nThe provided techniques can be easily combined in various ways to create powerful compressors, such as the Bzip2 compressor, which is a pipeline of the following methods:\n\n    1. Run-length encoding (RLE4)\n    2. Burrows-Wheeler transform (BWT)\n    3. Move-to-front transform (MTF)\n    4. Zero run-length encoding (ZRLE)\n    5. Huffman coding\n\nA simple BWT-based compression method (similar to Bzip2) is provided by the function `bwt_compress()`, which can be explicitly implemented as:\n\n```perl\nuse 5.036;\nuse Compression::Util qw(:all);\n\nmy $data = do { open my $fh, '\u003c:raw', $^X; local $/; \u003c$fh\u003e };\nmy $rle4 = rle4_encode(string2symbols($data));\nmy ($bwt, $idx) = bwt_encode(symbols2string($rle4));\n\nmy ($mtf, $alphabet) = mtf_encode(string2symbols($bwt));\nmy $rle = zrle_encode($mtf);\n\nmy $enc = pack('N', $idx)\n        . encode_alphabet($alphabet)\n        . create_huffman_entry($rle);\n\nsay \"Original size  : \", length($data);\nsay \"Compressed size: \", length($enc);\n\n# Decompress the result\nbwt_decompress($enc) eq $data or die \"decompression error\";\n```\n\n## TERMINOLOGY\n\n### bit\n\nA bit value is either `1` or `0`.\n\n### bitstring\n\nA bitstring is a string containing only 1s and 0s.\n\n### byte\n\nA byte value is an integer between `0` and `255`, inclusive.\n\n### string\n\nA string means a binary (non-UTF\\*) string.\n\n### symbols\n\nAn array of symbols means an array of non-negative integer values.\n\n### filehandle\n\nA filehandle is denoted by `$fh`.\n\nThe encoding of file-handles must be set to `:raw`.\n\n# PACKAGE VARIABLES\n\n**Compression::Util** provides the following package variables:\n\n```perl\n    $Compression::Util::VERBOSE = 0;           # true to enable verbose/debug mode\n\n    $Compression::Util::LZ_MIN_LEN = 4;        # minimum match length in LZ parsing\n    $Compression::Util::LZ_MAX_LEN = 1 \u003c\u003c 15;  # maximum match length in LZ parsing\n\n    $Compression::Util::LZ_MAX_DIST = ~0;      # maximum back-reference distance allowed\n    $Compression::Util::LZ_MAX_CHAIN_LEN = 32; # how many recent positions to remember for each match in LZ parsing\n```\n\nThese package variables can also be imported as:\n\n```perl\n    use Compression::Util qw(\n        $LZ_MIN_LEN\n        $LZ_MAX_LEN\n        $LZ_MAX_DIST\n        $LZ_MAX_CHAIN_LEN\n    );\n```\n\n## $LZ\\_MIN\\_LEN\n\nMinimum length of a match in LZ parsing. The value must be an integer greater than or equal to `2`. Larger values will result in faster parsing, but lower compression ratio.\n\nBy default, `$LZ_MIN_LEN` is set to `4`.\n\n**NOTE:** for `lzss_encode_fast()` is recommended to set `$LZ_MIN_LEN = 5`, which will result in slightly better compression ratio.\n\n## $LZ\\_MAX\\_LEN\n\nMaximum length of a match in LZ parsing. The value must be an integer greater than or equal to `0`.\n\nBy default, `$LZ_MAX_LEN` is set to `32768`.\n\n**NOTE:** the functions `lz77_encode()` and `lzb_compress()` will ignore this value and will always use unlimited match lengths.\n\n## $LZ\\_MAX\\_DIST\n\nMaximum back-reference distance allowed in LZ parsing. Smaller values will result in faster parsing, but lower compression ratio.\n\nBy default, the value is unlimited, meaning that arbitrarily large back-references will be generated.\n\n**NOTE:** the function `lzb_compress()` will ignore this value and will always use the value `2**16 - 1` as the maximum back-reference distance.\n\n## $LZ\\_MAX\\_CHAIN\\_LEN\n\nThe value of `$LZ_MAX_CHAIN_LEN` controls the amount of recent positions to remember for each matched prefix. A larger value results in better compression, finding longer matches, at the expense of speed.\n\nBy default, `$LZ_MAX_CHAIN_LEN` is set to `32`.\n\n**NOTE:** the function `lzss_encode_fast()` will ignore this value, always using a value of `1`.\n\n# HIGH-LEVEL FUNCTIONS\n\n```perl\n      create_huffman_entry(\\@symbols)      # Create a Huffman Coding block\n      decode_huffman_entry($fh)            # Decode a Huffman Coding block\n\n      create_ac_entry(\\@symbols)           # Create an Arithmetic Coding block\n      decode_ac_entry($fh)                 # Decode an Arithmetic Coding block\n\n      create_adaptive_ac_entry(\\@symbols)  # Create an Adaptive Arithmetic Coding block\n      decode_adaptive_ac_entry($fh)        # Decode an Adaptive Arithmetic Coding block\n\n      mrl_compress($string)                # MRL compression (MTF+ZRLE+RLE4+Huffman coding)\n      mrl_decompress($fh)                  # Inverse of the above method\n\n      mrl_compress_symbolic(\\@symbols)     # Symbolic MRL compression (MTF+ZRLE+RLE4+Huffman coding)\n      mrl_decompress_symbolic($fh)         # Inverse of the above method\n\n      bwt_compress($string)                # BWT-based compression (RLE4+BWT+MTF+ZRLE+Huffman coding)\n      bwt_decompress($fh)                  # Inverse of the above method\n\n      bwt_compress_symbolic(\\@symbols)     # Symbolic BWT-based compression (RLE4+sBWT+MTF+ZRLE+Huffman coding)\n      bwt_decompress_symbolic($fh)         # Inverse of the above method\n\n      bzip2_compress($string)              # Compress a given string using the Bzip2 format\n      bzip2_decompress($fh)                # Inverse of the above method\n\n      gzip_compress($string)               # Compress a given string using the GZIP format\n      gzip_decompress($fh)                 # Inverse of the above method\n\n      zlib_compress($string)               # Compress a given string using the ZLIB format\n      zlib_decompress($fh)                 # Inverse of the above method\n\n      lzss_compress($string)               # LZSS + DEFLATE-like encoding of lengths and distances\n      lzss_decompress($fh)                 # Inverse of the above method\n\n      lzss_compress_symbolic(\\@symbols)    # Symbolic LZSS + DEFLATE-like encoding of lengths and distances\n      lzss_decompress_symbolic($fh)        # Inverse of the above method\n\n      lz77_compress($string)               # LZ77 + Huffman coding of lengths and literals + OBH for distances\n      lz77_decompress($fh)                 # Inverse of the above method\n\n      lz77_compress_symbolic(\\@symbols)    # Symbolic LZ77 + Huffman coding of lengths and literals + OBH for distances\n      lz77_decompress_symbolic($fh)        # Inverse of the above method\n\n      lzb_compress($string)                # LZSS compression, using a byte-aligned encoding method, similar to LZ4\n      lzb_decompress($fh)                  # Inverse of the above method\n\n      lzw_compress($string)                # LZW + abc_encode() compression\n      lzw_decompress($fh)                  # Inverse of the above method\n\n      lz4_compress($string)                # Compress a given string using the LZ4 frame format\n      lz4_decompress($fh)                  # Inverse of the above method\n```\n\n# MEDIUM-LEVEL FUNCTIONS\n\n```perl\n      deltas(\\@ints)                       # Computes the differences between integers\n      accumulate(\\@deltas)                 # Inverse of the above method\n\n      delta_encode(\\@ints)                 # Delta+RLE encoding of an array-ref of integers\n      delta_decode($fh)                    # Inverse of the above method\n\n      fibonacci_encode(\\@symbols)          # Fibonacci coding of an array-ref of symbols\n      fibonacci_decode($fh)                # Inverse of the above method\n\n      elias_gamma_encode(\\@symbols)        # Elias Gamma coding method of an array-ref of symbols\n      elias_gamma_decode($fh)              # Inverse of the above method\n\n      elias_omega_encode(\\@symbols)        # Elias Omega coding method of an array-ref of symbols\n      elias_omega_decode($fh)              # Inverse of the above method\n\n      abc_encode(\\@symbols)                # Adaptive Binary Concatenation method of an array-ref of symbols\n      abc_decode($fh)                      # Inverse of the above method\n\n      obh_encode(\\@symbols)                # Offset bits + Huffman coding of an array-ref of symbols\n      obh_decode($fh)                      # Inverse of the above method\n\n      bwt_encode($string)                  # Burrows-Wheeler transform\n      bwt_decode($bwt, $idx)               # Inverse of Burrows-Wheeler transform\n\n      bwt_encode_symbolic(\\@symbols)       # Burrows-Wheeler transform over an array-ref of symbols\n      bwt_decode_symbolic(\\@bwt, $idx)     # Inverse of symbolic Burrows-Wheeler transform\n\n      mtf_encode(\\@symbols)                # Move-to-front transform\n      mtf_decode(\\@mtf, \\@alphabet)        # Inverse of the above method\n\n      encode_alphabet(\\@alphabet)          # Encode an alphabet of symbols into a binary string\n      decode_alphabet($fh)                 # Inverse of the above method\n\n      encode_alphabet_256(\\@alphabet)      # Encode an alphabet of symbols (limited to [0..255]) into a binary string\n      decode_alphabet_256($fh)             # Inverse of the above method\n\n      frequencies(\\@symbols)               # Returns a dictionary with symbol frequencies\n      run_length(\\@symbols, $max=undef)    # Run-length encoding, returning a 2D array-ref\n\n      rle4_encode(\\@symbols, $max=255)     # Run-length encoding with 4 or more consecutive characters\n      rle4_decode(\\@rle4)                  # Inverse of the above method\n\n      zrle_encode(\\@symbols)               # Run-length encoding of zeros\n      zrle_decode(\\@zrle)                  # Inverse of the above method\n\n      ac_encode(\\@symbols)                 # Arithmetic Coding applied on an array-ref of symbols\n      ac_decode($bitstring, \\%freq)        # Inverse of the above method\n\n      adaptive_ac_encode(\\@symbols)               # Adaptive Arithmetic Coding applied on an array-ref of symbols\n      adaptive_ac_decode($bitstring, \\@alphabet)  # Inverse of the above method\n\n      lzw_encode($string)                  # LZW encoding of a given string\n      lzw_decode(\\@symbols)                # Inverse of the above method\n```\n\n# LOW-LEVEL FUNCTIONS\n\n```perl\n      crc32($string, $prev_crc = 0)        # Compute the CRC32 value of a given string\n\n      read_bit($fh, \\$buffer)              # Read one bit from file-handle (MSB)\n      read_bit_lsb($fh, \\$buffer)          # Read one bit from file-handle (LSB)\n\n      read_bits($fh, $len)                 # Read `$len` bits from file-handle (MSB)\n      read_bits_lsb($fh, $len)             # Read `$len` bits from file-handle (LSB)\n\n      int2bits($symbol, $size)             # Convert an integer to bits of width `$size` (MSB)\n      int2bits_lsb($symbol, $size)         # Convert an integer to bits of width `$size` (LSB)\n\n      bits2int($fh, $size, \\$buffer)       # Inverse of `int2bits()`\n      bits2int_lsb($fh, $size, \\$buffer)   # Inverse of `int2bits_lsb()`\n\n      bytes2int($fh, $n)                   # Read `$n` bytes from file-handle as an integer (MSB)\n      bytes2int_lsb($fh, $n)               # Read `$n` bytes from file-handle as an integer (LSB)\n\n      int2bytes($symbol, $size)            # Convert an integer into `$size` bytes. (MSB)\n      int2bytes_lsb($symbol, $size)        # Convert an integer into `$size` bytes. (LSB)\n\n      string2symbols($string)              # Returns an array-ref of code points\n      symbols2string(\\@symbols)            # Returns a string, given an array-ref of code points\n\n      read_null_terminated($fh)            # Read a binary string that ends with NULL (\"\\0\")\n\n      binary_vrl_encode($bitstring)        # Binary variable run-length encoding\n      binary_vrl_decode($bitstring)        # Binary variable run-length decoding\n\n      bwt_sort($string)                    # Burrows-Wheeler sorting\n      bwt_sort_symbolic(\\@symbols)         # Burrows-Wheeler sorting, applied on an array-ref of symbols\n\n      huffman_encode(\\@symbols, \\%dict)    # Huffman encoding\n      huffman_decode($bitstring, \\%dict)   # Huffman decoding, given a string of bits\n\n      huffman_from_freq(\\%freq)            # Create Huffman dictionaries, given an hash-ref of frequencies\n      huffman_from_symbols(\\@symbols)      # Create Huffman dictionaries, given an array-ref of symbols\n      huffman_from_code_lengths(\\@lens)    # Create canonical Huffman codes, given an array-ref of code lengths\n\n      make_deflate_tables($max_dist, $max_len) # Returns the DEFLATE tables for distance and length symbols\n      find_deflate_index($value, \\@table)      # Returns the index in a DEFLATE table, given a numerical value\n\n      lzss_encode($string)                     # LZSS encoding into literals, distances and lengths\n      lzss_encode_symbolic(\\@symbols)          # LZSS encoding into literals, distances and lengths (symbolic)\n\n      lzss_encode_fast($string)                # Fast-LZSS encoding into literals, distances and lengths\n      lzss_encode_fast_symbolic(\\@symbols)     # Fast-LZSS encoding into literals, distances and lengths (symbolic)\n\n      lzss_decode(\\@lits, \\@dist, \\@lens)          # Inverse of lzss_encode() and lzss_encode_fast()\n      lzss_decode_symbolic(\\@lits, \\@dist, \\@lens) # Inverse of lzss_encode_symbolic() and lzss_encode_fast_symbolic()\n\n      lz77_encode($string)                         # LZ77 encoding into literals, distances, lengths and matches\n      lz77_encode_symbolic(\\@symbols)              # LZ77 encoding into literals, distances, lengths and matches (symbolic)\n\n      lz77_decode(\\@lits, \\@dist, \\@lens, \\@matches)           # Inverse of lz77_encode()\n      lz77_decode_symbolic(\\@lits, \\@dist, \\@lens, \\@matches)  # Inverse of lz77_encode_symbolic()\n\n      deflate_encode(\\@lits, \\@dist, \\@lens)   # DEFLATE-like encoding of values returned by lzss_encode()\n      deflate_decode($fh)                      # Inverse of the above method\n```\n\n# INTERFACE FOR HIGH-LEVEL FUNCTIONS\n\n## create\\_huffman\\_entry\n\n```perl\n    my $string = create_huffman_entry(\\@symbols);\n```\n\nHigh-level function that generates a Huffman coding block, given an array-ref of symbols.\n\n## decode\\_huffman\\_entry\n\n```perl\n    my $symbols = decode_huffman_entry($fh);\n    my $symbols = decode_huffman_entry($string);\n```\n\nInverse of `create_huffman_entry()`.\n\n## create\\_ac\\_entry\n\n```perl\n    my $string = create_ac_entry(\\@symbols);\n```\n\nHigh-level function that generates an Arithmetic Coding block, given an array-ref of symbols.\n\n## decode\\_ac\\_entry\n\n```perl\n    my $symbols = decode_ac_entry($fh);\n    my $symbols = decode_ac_entry($string);\n```\n\nInverse of `create_ac_entry()`.\n\n## create\\_adaptive\\_ac\\_entry\n\n```perl\n    my $string = create_adaptive_ac_entry(\\@symbols);\n```\n\nHigh-level function that generates an Adaptive Arithmetic Coding block, given an array-ref of symbols.\n\n## decode\\_adaptive\\_ac\\_entry\n\n```perl\n    my $symbols = decode_adaptive_ac_entry($fh);\n    my $symbols = decode_adaptive_ac_entry($string);\n```\n\nInverse of `create_adaptive_ac_entry()`.\n\n## lz77\\_compress / lz77\\_compress\\_symbolic\n\n```perl\n    # With Huffman coding\n    my $string = lz77_compress($data);\n    my $string = lz77_compress(\\@symbols);\n\n    # With Arithmetic Coding\n    my $string = lz77_compress($data, \\\u0026create_ac_entry);\n\n    # Using Fast-LZSS parsing + Huffman coding\n    my $string = lz77_compress($data, \\\u0026create_huffman_entry, \\\u0026lzss_encode_fast);\n```\n\nHigh-level function that performs LZ77 compression on the provided data, using the pipeline:\n\n    1. lz77_encode\n    2. create_huffman_entry(literals)\n    3. create_huffman_entry(lengths)\n    4. create_huffman_entry(matches)\n    5. obh_encode(distances)\n\nThe function accepts either a string or an array-ref of symbols as the first argument.\n\n## lz77\\_decompress / lz77\\_decompress\\_symbolic\n\n```perl\n    # With Huffman coding\n    my $data = lz77_decompress($fh);\n    my $data = lz77_decompress($string);\n\n    # With Arithemtic coding\n    my $data = lz77_decompress($fh, \\\u0026decode_ac_entry);\n    my $data = lz77_decompress($string, \\\u0026decode_ac_entry);\n\n    # Symbolic, with Huffman coding\n    my $symbols = lz77_decompress_symbolic($fh);\n    my $symbols = lz77_decompress_symbolic($string);\n```\n\nInverse of `lz77_compress()` and `lz77_compress_symbolic()`, respectively.\n\n## lzss\\_compress / lzss\\_compress\\_symbolic\n\n```perl\n    # With Huffman coding\n    my $string = lzss_compress($data);\n    my $string = lzss_compress(\\@symbols);\n\n    # With Arithmetic Coding\n    my $string = lzss_compress($data, \\\u0026create_ac_entry);\n\n    # Using Fast-LZSS parsing + Huffman coding\n    my $string = lzss_compress($data, \\\u0026create_huffman_entry, \\\u0026lzss_encode_fast);\n```\n\nHigh-level function that performs LZSS (Lempel-Ziv-Storer-Szymanski) compression on the provided data, using the pipeline:\n\n    1. lzss_encode\n    2. deflate_encode\n\nThe function accepts either a string or an array-ref of symbols as the first argument.\n\n## lzss\\_decompress / lzss\\_decompress\\_symbolic\n\n```perl\n    # With Huffman coding\n    my $data = lzss_decompress($fh);\n    my $data = lzss_decompress($string);\n\n    # With Arithmetic coding\n    my $data = lzss_decompress($fh, \\\u0026decode_ac_entry);\n    my $data = lzss_decompress($string, \\\u0026decode_ac_entry);\n\n    # Symbolic, with Huffman coding\n    my $symbols = lzss_decompress_symbolic($fh);\n    my $symbols = lzss_decompress_symbolic($string);\n```\n\nInverse of `lzss_compress()` and `lzss_compress_symbolic()`, respectively.\n\n## lzb\\_compress\n\n```perl\n    my $string = lzb_compress($data);\n    my $string = lzb_compress($data, \\\u0026lzss_encode_fast);   # with fast-LZ parsing\n```\n\nHigh-level function that performs byte-oriented LZSS compression, inspired by LZ4.\n\n## lzb\\_decompress\n\n```perl\n    my $data = lzb_decompress($fh);\n    my $data = lzb_decompress($string);\n```\n\nInverse of `lzb_compress()`.\n\n## lz4\\_compress\n\n```perl\n    my $string = lz4_compress($fh);\n    my $string = lz4_compress($data);\n    my $string = lz4_compress($data, \\\u0026lzss_encode_fast);   # with fast-LZ parsing\n```\n\nValid LZ4 compressor, using the LZ4 Frame format, given either a string or an input file-handle.\n\nThe input data is split into chunks of length `2**17` and compressed into independent LZ4 blocks.\n\n## lz4\\_decompress\n\n```perl\n    my $data = lz4_decompress($fh);\n    my $data = lz4_decompress($string);\n```\n\nDecompress LZ4 Frame data, given either a string or an input file-handle. Concatenated LZ4 Frames are also supported.\n\n## lzw\\_compress\n\n```perl\n    my $string = lzw_compress($data);\n```\n\nHigh-level function that performs LZW (Lempel-Ziv-Welch) compression on the provided data, using the pipeline:\n\n    1. lzw_encode\n    2. abc_encode\n\n## lzw\\_decompress\n\n```perl\n    my $data = lzw_decompress($fh);\n    my $data = lzw_decompress($string);\n```\n\nPerforms Lempel-Ziv-Welch (LZW) decompression on the provided string or file-handle. Inverse of `lzw_compress()`.\n\n## bwt\\_compress\n\n```perl\n    # Using Huffman Coding\n    my $string = bwt_compress($data);\n\n    # Using Arithmetic Coding\n    my $string = bwt_compress($data, \\\u0026create_ac_entry);\n```\n\nHigh-level function that performs BWT-based compression on the provided data, using the pipeline:\n\n    1. rle4_encode\n    2. bwt_encode\n    3. mtf_encode\n    4. zrle_encode\n    5. create_huffman_entry\n\n## bwt\\_decompress\n\n```perl\n    # With Huffman coding\n    my $data = bwt_decompress($fh);\n    my $data = bwt_decompress($string);\n\n    # With Arithmetic coding\n    my $data = bwt_decompress($fh, \\\u0026decode_ac_entry);\n    my $data = bwt_decompress($string, \\\u0026decode_ac_entry);\n```\n\nInverse of `bwt_compress()`.\n\n## bwt\\_compress\\_symbolic\n\n```perl\n    # Does Huffman coding\n    my $string = bwt_compress_symbolic(\\@symbols);\n\n    # Does Arithmetic coding\n    my $string = bwt_compress_symbolic(\\@symbols, \\\u0026create_ac_entry);\n```\n\nSimilar to `bwt_compress()`, except that it accepts an arbitrary array-ref of non-negative integer values as input. It is also a bit slower on large inputs.\n\n## bwt\\_decompress\\_symbolic\n\n```perl\n    # Using Huffman coding\n    my $symbols = bwt_decompress_symbolic($fh);\n    my $symbols = bwt_decompress_symbolic($string);\n\n    # Using Arithmetic coding\n    my $symbols = bwt_decompress_symbolic($fh, \\\u0026decode_ac_entry);\n    my $symbols = bwt_decompress_symbolic($string, \\\u0026decode_ac_entry);\n```\n\nInverse of `bwt_compress_symbolic()`.\n\n## bzip2\\_compress\n\n```perl\n    my $string = bzip2_compress($data);\n    my $string = bzip2_compress($fh);\n```\n\nValid Bzip2 compressor, given a string or an input file-handle.\n\n## bzip2\\_decompress\n\n```perl\n    my $data = bzip2_decompress($string);\n    my $data = bzip2_decompress($fh);\n```\n\nValid Bzip2 decompressor, given a string or an input file-handle.\n\n## gzip\\_compress\n\n```perl\n    my $string = gzip_compress($fh);\n    my $string = gzip_compress($data);\n    my $string = gzip_compress($data, \\\u0026lzss_encode_fast);  # using fast LZ-parsing\n```\n\nValid GZIP compressor (RFC 1952), given a string or an input file-handle.\n\n## gzip\\_decompress\n\n```perl\n    my $data = gzip_decompress($string);\n    my $data = gzip_decompress($fh);\n```\n\nValid GZIP decompressor (RFC 1952), given a string or an input file-handle.\n\n## zlib\\_compress\n\n```perl\n    my $string = zlib_compress($fh);\n    my $string = zlib_compress($data);\n    my $string = zlib_compress($data, \\\u0026lzss_encode_fast);  # using fast LZ-parsing\n```\n\nValid ZLIB compressor (RFC 1950), given a string or an input file-handle.\n\n## zlib\\_decompress\n\n```perl\n    my $data = zlib_decompress($string);\n    my $data = zlib_decompress($fh);\n```\n\nValid ZLIB decompressor (RFC 1950), given a string or an input file-handle.\n\n## mrl\\_compress / mrl\\_compress\\_symbolic\n\n```perl\n    # Does Huffman coding\n    my $enc = mrl_compress($str);\n    my $enc = mrl_compress(\\@symbols);\n\n    # Does Arithmetic coding\n    my $enc = mrl_compress($str, \\\u0026create_ac_entry);\n    my $enc = mrl_compress(\\@symbols, \\\u0026create_ac_entry);\n```\n\nA fast compression method, using the following pipeline:\n\n    1. mtf_encode\n    2. zrle_encode\n    3. rle4_encode\n    4. create_huffman_entry\n\nIt accepts an arbitrary array-ref of non-negative integer values as input.\n\n## mrl\\_decompress / mrl\\_decompress\\_symbolic\n\n```perl\n    # With Huffman coding\n    my $data = mrl_decompress($fh);\n    my $data = mrl_decompress($string);\n\n    # Symbolic, with Huffman coding\n    my $symbols = mrl_decompress_symbolic($fh);\n    my $symbols = mrl_decompress_symbolic($string);\n\n    # Symbolic, with Arithmetic coding\n    my $symbols = mrl_decompress_symbolic($fh, \\\u0026decode_ac_entry);\n    my $symbols = mrl_decompress_symbolic($string, \\\u0026decode_ac_entry);\n```\n\nInverse of `mrl_decompress()` and `mrl_compress_symbolic()`.\n\n# INTERFACE FOR MEDIUM-LEVEL FUNCTIONS\n\n## frequencies\n\n```perl\n    my $freq = frequencies(\\@symbols);\n```\n\nReturns an hash ref dictionary with frequencies, given an array-ref of symbols.\n\n## deltas\n\n```perl\n    my $deltas = deltas(\\@integers);\n```\n\nComputes the differences between consecutive integers, returning an array.\n\n## accumulate\n\n```perl\n    my $integers = accumulate(\\@deltas);\n```\n\nInverse of `deltas()`.\n\n## delta\\_encode\n\n```perl\n    my $string = delta_encode(\\@integers);\n```\n\nEncodes a sequence of integers (including negative integers) using Delta + Run-length + Elias omega coding, returning a binary string.\n\nDelta encoding calculates the difference between consecutive integers in the sequence and encodes these differences using Elias omega coding. When it's beneficial, runs of identical symbols are collapsed with RLE.\n\nThis method supports both positive and negative integers.\n\n## delta\\_decode\n\n```perl\n    # Given a file-handle\n    my $integers = delta_decode($fh);\n\n    # Given a string\n    my $integers = delta_decode($string);\n```\n\nInverse of `delta_encode()`.\n\n## fibonacci\\_encode\n\n```perl\n    my $string = fibonacci_encode(\\@symbols);\n```\n\nEncodes a sequence of non-negative integers using Fibonacci coding, returning a binary string.\n\n## fibonacci\\_decode\n\n```perl\n    # Given a file-handle\n    my $symbols = fibonacci_decode($fh);\n\n    # Given a binary string\n    my $symbols = fibonacci_decode($string);\n```\n\nInverse of `fibonacci_encode()`.\n\n## elias\\_gamma\\_encode\n\n```perl\n    my $string = elias_gamma_encode(\\@symbols);\n```\n\nEncodes a sequence of non-negative integers using Elias Gamma coding, returning a binary string.\n\n## elias\\_gamma\\_decode\n\n```perl\n    # Given a file-handle\n    my $symbols = elias_gamma_decode($fh);\n\n    # Given a binary string\n    my $symbols = elias_gamma_decode($string);\n```\n\nInverse of `elias_gamma_encode()`.\n\n## elias\\_omega\\_encode\n\n```perl\n    my $string = elias_omega_encode(\\@symbols);\n```\n\nEncodes a sequence of non-negative integers using Elias Omega coding, returning a binary string.\n\n## elias\\_omega\\_decode\n\n```perl\n    # Given a file-handle\n    my $symbols = elias_omega_decode($fh);\n\n    # Given a binary string\n    my $symbols = elias_omega_decode($string);\n```\n\nInverse of `elias_omega_encode()`.\n\n## abc\\_encode\n\n```perl\n    my $string = abc_encode(\\@symbols);\n```\n\nEncodes a sequence of non-negative integers using the Adaptive Binary Concatenation encoding method.\n\nThis method is particularly effective in encoding a sequence of integers that are in ascending order or have roughly the same size in binary.\n\n## abc\\_decode\n\n```perl\n    # Given a file-handle\n    my $symbols = abc_decode($fh);\n\n    # Given a binary string\n    my $symbols = abc_decode($string);\n```\n\nInverse of `abc_encode()`.\n\n## obh\\_encode\n\n```perl\n    # With Huffman Coding\n    my $string = obh_encode(\\@symbols);\n\n    # With Arithmetic Coding\n    my $string = obh_encode(\\@symbols, \\\u0026create_ac_entry);\n```\n\nEncodes a sequence of non-negative integers using offset bits and Huffman coding.\n\nThis method is particularly effective in encoding a sequence of moderately large random integers, such as the list of distances returned by `lzss_encode()`.\n\n## obh\\_decode\n\n```perl\n    # Given a file-handle\n    my $symbols = obh_decode($fh);                        # Huffman decoding\n    my $symbols = obh_decode($fh, \\\u0026decode_ac_entry);     # Arithmetic decoding\n\n    # Given a binary string\n    my $symbols = obh_decode($string);                    # Huffman decoding\n    my $symbols = obh_decode($string, \\\u0026decode_ac_entry); # Arithmetic decoding\n```\n\nInverse of `obh_encode()`.\n\n## bwt\\_encode\n\n```perl\n    my ($bwt, $idx) = bwt_encode($string);\n    my ($bwt, $idx) = bwt_encode($string, $lookahead_len);\n```\n\nApplies the Burrows-Wheeler Transform (BWT) to a given string.\n\n## bwt\\_decode\n\n```perl\n    my $string = bwt_decode($bwt, $idx);\n```\n\nReverses the Burrows-Wheeler Transform (BWT) applied to a string.\n\nThe function returns the original string.\n\n## bwt\\_encode\\_symbolic\n\n```perl\n    my ($bwt_symbols, $idx) = bwt_encode_symbolic(\\@symbols);\n```\n\nApplies the Burrows-Wheeler Transform (BWT) to a sequence of symbolic elements.\n\n## bwt\\_decode\\_symbolic\n\n```perl\n    my $symbols = bwt_decode_symbolic(\\@bwt_symbols, $idx);\n```\n\nReverses the Burrows-Wheeler Transform (BWT) applied to a sequence of symbolic elements.\n\n## mtf\\_encode\n\n```perl\n    my $mtf = mtf_encode(\\@symbols, \\@alphabet);\n    my ($mtf, $alphabet) = mtf_encode(\\@symbols);\n```\n\nPerforms Move-To-Front (MTF) encoding on a sequence of symbols.\n\nThe function returns the encoded MTF sequence and the sorted list of unique symbols in the input data, representing the alphabet.\n\nOptionally, the alphabet can be provided as a second argument. When two arguments are provided, only the MTF sequence is returned.\n\n## mtf\\_decode\n\n```perl\n    my $symbols = mtf_decode(\\@mtf, \\@alphabet);\n```\n\nInverse of `mtf_encode()`.\n\n## encode\\_alphabet / encode\\_alphabet\\_256\n\n```perl\n    my $string = encode_alphabet(\\@alphabet);        # supports arbitrarily large symbols\n    my $string = encode_alphabet_256(\\@alphabet);    # limited to symbols [0..255]\n```\n\nEncode a sorted alphabet of symbols into a binary string.\n\n## decode\\_alphabet / decode\\_alphabet\\_256\n\n```perl\n    my $alphabet = decode_alphabet($fh);\n    my $alphabet = decode_alphabet($string);\n\n    my $alphabet = decode_alphabet_256($fh);\n    my $alphabet = decode_alphabet_256($string);\n```\n\nDecodes an encoded alphabet, given a file-handle or a binary string, returning an array-ref of symbols. Inverse of `encode_alphabet()`.\n\n## run\\_length\n\n```perl\n    my $rl = run_length(\\@symbols);\n    my $rl = run_length(\\@symbols, $max_run);\n```\n\nPerforms Run-Length Encoding (RLE) on a sequence of symbolic elements.\n\nIt takes two parameters: `\\@symbols`, representing an array of symbols, and `$max_run`, indicating the maximum run length allowed.\n\nThe function returns a 2D-array, with pairs: `[symbol, run_length]`, such that the following code reconstructs the `\\@symbols` array:\n\n```perl\n    my @symbols = map { ($_-\u003e[0]) x $_-\u003e[1] } @$rl;\n```\n\nBy default, the maximum run-length is unlimited.\n\n## rle4\\_encode\n\n```perl\n    my $rle4 = rle4_encode($string);\n    my $rle4 = rle4_encode(\\@symbols);\n    my $rle4 = rle4_encode(\\@symbols, $max_run);\n```\n\nPerforms Run-Length Encoding (RLE) on a sequence of symbolic elements, specifically designed for runs of four or more consecutive symbols.\n\nIt takes two parameters: `\\@symbols`, representing an array of symbols, and `$max_run`, indicating the maximum run length allowed during encoding.\n\nThe function returns the encoded RLE sequence as an array-ref of symbols.\n\nBy default, the maximum run-length is limited to `255`.\n\n## rle4\\_decode\n\n```perl\n    my $symbols = rle4_decode(\\@rle4);\n    my $symbols = rle4_decode($rle4_string);\n```\n\nInverse of `rle4_encode()`.\n\n## zrle\\_encode\n\n```perl\n    my $zrle = zrle_encode(\\@symbols);\n```\n\nPerforms Zero-Run-Length Encoding (ZRLE) on a sequence of symbolic elements, returning the encoded ZRLE sequence as an array-ref of symbols.\n\nThis function efficiently encodes runs of zeros, but also increments each symbol by `1`.\n\n## zrle\\_decode\n\n```perl\n    my $symbols = zrle_decode($zrle);\n```\n\nInverse of `zrle_encode()`.\n\n## ac\\_encode\n\n```perl\n    my ($bitstring, $freq) = ac_encode(\\@symbols);\n```\n\nPerforms Arithmetic Coding on the provided symbols.\n\nIt takes a single parameter, `\\@symbols`, representing the symbols to be encoded.\n\nThe function returns two values: `$bitstring`, which is a string of 1s and 0s, and `$freq`, representing the frequency table used for encoding.\n\n## ac\\_decode\n\n```perl\n    my $symbols = ac_decode($bits_fh, \\%freq);\n    my $symbols = ac_decode($bitstring, \\%freq);\n```\n\nPerforms Arithmetic Coding decoding using the provided frequency table and a string of 1s and 0s. Inverse of `ac_encode()`.\n\nIt takes two parameters: `$bitstring`, representing a string of 1s and 0s containing the arithmetic coded data, and `\\%freq`, representing the frequency table used for encoding.\n\nThe function returns the decoded sequence of symbols.\n\n## adaptive\\_ac\\_encode\n\n```perl\n    my ($bitstring, $alphabet) = adaptive_ac_encode(\\@symbols);\n```\n\nPerforms Adaptive Arithmetic Coding on the provided symbols.\n\nIt takes a single parameter, `\\@symbols`, representing the symbols to be encoded.\n\nThe function returns two values: `$bitstring`, which is a string of 1s and 0s, and `$alphabet`, which is an array-ref of distinct sorted symbols.\n\n## adaptive\\_ac\\_decode\n\n```perl\n    my $symbols = adaptive_ac_decode($bits_fh, \\@alphabet);\n    my $symbols = adaptive_ac_decode($bitstring, \\@alphabet);\n```\n\nPerforms Adaptive Arithmetic Coding decoding using the provided frequency table and a string of 1s and 0s.\n\nIt takes two parameters: `$bitstring`, representing a string of 1s and 0s containing the adaptive arithmetic coded data, and `\\@alphabet`, representing the array of distinct sorted symbols that appear in the encoded data.\n\nThe function returns the decoded sequence of symbols.\n\n## lzw\\_encode\n\n```perl\n    my $symbols = lzw_encode($string);\n```\n\nPerforms Lempel-Ziv-Welch (LZW) encoding on the provided string.\n\nIt takes a single parameter, `$string`, representing the data to be encoded.\n\nThe function returns an array-ref of symbols.\n\n## lzw\\_decode\n\n```perl\n    my $string = lzw_decode(\\@symbols);\n```\n\nPerforms Lempel-Ziv-Welch (LZW) decoding on the provided symbols. Inverse of `lzw_encode()`.\n\nThe function returns the decoded string.\n\n# INTERFACE FOR LOW-LEVEL FUNCTIONS\n\n## crc32\n\n```perl\n    my $int32 = crc32($data);\n    my $int32 = crc32($data, $prev_crc32);\n```\n\nCompute the CRC32 checksum of a given string.\n\n## adler32\n\n```perl\n    my $int32 = adler32($data);\n    my $int32 = adler32($data, $prev_adler32);\n```\n\nCompute the Adler32 checksum of a given string.\n\n## read\\_bit\n\n```perl\n    my $bit = read_bit($fh, \\$buffer);\n```\n\nReads a single bit from a file-handle `$fh` (MSB order).\n\nThe function stores the extra bits inside the `$buffer`, reading one character at a time from the file-handle.\n\n## read\\_bit\\_lsb\n\n```perl\n    my $bit = read_bit_lsb($fh, \\$buffer);\n```\n\nReads a single bit from a file-handle `$fh` (LSB order).\n\nThe function stores the extra bits inside the `$buffer`, reading one character at a time from the file-handle.\n\n## read\\_bits\n\n```perl\n    my $bitstring = read_bits($fh, $bits_len);\n```\n\nReads a specified number of bits (`$bits_len`) from a file-handle (`$fh`) and returns them as a string, in MSB order.\n\n## read\\_bits\\_lsb\n\n```perl\n    my $bitstring = read_bits_lsb($fh, $bits_len);\n```\n\nReads a specified number of bits (`$bits_len`) from a file-handle (`$fh`) and returns them as a string, in LSB order.\n\n## int2bits\n\n```perl\n    my $bitstring = int2bits($symbol, $size)\n```\n\nConvert a non-negative integer to a bitstring of width `$size`, in MSB order.\n\n## int2bits\\_lsb\n\n```perl\n    my $bitstring = int2bits_lsb($symbol, $size)\n```\n\nConvert a non-negative integer to a bitstring of width `$size`, in LSB order.\n\n## int2bytes\n\n```perl\n    my $string = int2bytes($symbol, $size);\n```\n\nConvert a non-negative integer to a byte-string of width `$size`, in MSB order.\n\n## int2bytes\\_lsb\n\n```perl\n    my $string = int2bytes_lsb($symbol, $size);\n```\n\nConvert a non-negative integer to a byte-string of width `$size`, in LSB order.\n\n## bits2int\n\n```perl\n    my $integer = bits2int($fh, $size, \\$buffer);\n```\n\nRead `$size` bits from a file-handle `$fh` and convert them to an integer, in MSB order. Inverse of `int2bits()`.\n\nThe function stores the extra bits inside the `$buffer`, reading one character at a time from the file-handle.\n\n## bits2int\\_lsb\n\n```perl\n    my $integer = bits2int_lsb($fh, $size, \\$buffer);\n```\n\nRead `$size` bits from a file-handle `$fh` and convert them to an integer, in LSB order. Inverse of `int2bits_lsb()`.\n\nThe function stores the extra bits inside the `$buffer`, reading one character at a time from the file-handle.\n\n## bytes2int\n\n```perl\n    my $integer = bytes2int($fh, $n);\n    my $integer = bytes2int($str, $n);\n```\n\nRead `$n` bytes from a file-handle `$fh` or from a string `$str` and convert them to an integer, in MSB order.\n\n## bytes2int\\_lsb\n\n```perl\n    my $integer = bytes2int_lsb($fh, $n);\n    my $integer = bytes2int_lsb($str, $n);\n```\n\nRead `$n` bytes from a file-handle `$fh` or from a string `$str` and convert them to an integer, in LSB order.\n\n## string2symbols\n\n```perl\n    my $symbols = string2symbols($string)\n```\n\nReturns an array-ref of code points, given a string.\n\n## symbols2string\n\n```perl\n    my $string = symbols2string(\\@symbols)\n```\n\nReturns a string, given an array-ref of code points.\n\n## read\\_null\\_terminated\n\n```perl\n    my $string = read_null_terminated($fh)\n```\n\nRead a string from file-handle `$fh` that ends with a NULL character (\"\\\\0\").\n\n## binary\\_vrl\\_encode\n\n```perl\n    my $bitstring_enc = binary_vrl_encode($bitstring);\n```\n\nGiven a string of 1s and 0s, returns back a bitstring of 1s and 0s encoded using variable run-length encoding.\n\n## binary\\_vrl\\_decode\n\n```perl\n    my $bitstring = binary_vrl_decode($bitstring_enc);\n```\n\nGiven an encoded bitstring, returned by `binary_vrl_encode()`, gives back the decoded string of 1s and 0s.\n\n## bwt\\_sort\n\n```perl\n    my $indices = bwt_sort($string);\n    my $indices = bwt_sort($string, $lookahead_len);\n```\n\nLow-level function that sorts the rotations of a given string using the Burrows-Wheeler Transform (BWT) algorithm.\n\nIt takes two parameters: `$string`, which is the input string to be transformed, and `$LOOKAHEAD_LEN` (optional), representing the length of look-ahead during sorting.\n\nThe function returns an array-ref of indices.\n\nThere is probably no need to call this function explicitly. Use `bwt_encode()` instead!\n\n## bwt\\_sort\\_symbolic\n\n```perl\n    my $indices = bwt_sort_symbolic(\\@symbols);\n```\n\nLow-level function that sorts the rotations of a sequence of symbolic elements using the Burrows-Wheeler Transform (BWT) algorithm.\n\nIt takes a single parameter `\\@symbols`, which represents the input sequence of symbolic elements. The function returns an array of indices.\n\nThere is probably no need to call this function explicitly. Use `bwt_encode_symbolic()` instead!\n\n## huffman\\_from\\_freq\n\n```perl\n    my $dict = huffman_from_freq(\\%freq);\n    my ($dict, $rev_dict) = huffman_from_freq(\\%freq);\n```\n\nLow-level function that constructs Huffman prefix codes, based on the frequency of symbols provided in a hash table.\n\nIt takes a single parameter, `\\%freq`, representing the hash table where keys are symbols, and values are their corresponding frequencies.\n\nThe function returns two values: `$dict`, which is the mapping of symbols to Huffman codes, and `$rev_dict`, which holds the reverse mapping of Huffman codes to symbols.\n\nThe prefix codes are in canonical form, as defined in RFC 1951 (Section 3.2.2).\n\n## huffman\\_from\\_symbols\n\n```perl\n    my $dict = huffman_from_symbols(\\@symbols);\n    my ($dict, $rev_dict) = huffman_from_symbols(\\@symbols);\n```\n\nLow-level function that constructs Huffman prefix codes, given an array-ref of symbols.\n\nIt takes a single parameter, `\\@symbols`, from which it computes the frequency of each symbol and generates the corresponding Huffman prefix codes.\n\nThe function returns two values: `$dict`, which is the mapping of symbols to Huffman codes, and `$rev_dict`, which holds the reverse mapping of Huffman codes to symbols.\n\nThe prefix codes are in canonical form, as defined in RFC 1951 (Section 3.2.2).\n\n## huffman\\_from\\_code\\_lengths\n\n```perl\n    my $dict = huffman_from_code_lengths(\\@code_lengths);\n    my ($dict, $rev_dict) = huffman_from_code_lengths(\\@code_lengths);\n```\n\nLow-level function that constructs a dictionary of canonical prefix codes, given an array of code lengths, as defined in RFC 1951 (Section 3.2.2).\n\nIt takes a single parameter, `\\@code_lengths`, where entry `$i` in the array corresponds to the code length for symbol `$i`.\n\nThe function returns two values: `$dict`, which is the mapping of symbols to Huffman codes, and `$rev_dict`, which holds the reverse mapping of Huffman codes to symbols.\n\n## huffman\\_encode\n\n```perl\n    my $bitstring = huffman_encode(\\@symbols, $dict);\n```\n\nLow-level function that performs Huffman encoding on a sequence of symbols using a provided dictionary, returned by `huffman_from_freq()`.\n\nIt takes two parameters: `\\@symbols`, representing the sequence of symbols to be encoded, and `$dict`, representing the Huffman dictionary mapping symbols to their corresponding Huffman codes.\n\nThe function returns a concatenated string of 1s and 0s, representing the Huffman-encoded sequence of symbols.\n\n## huffman\\_decode\n\n```perl\n    my $symbols = huffman_decode($bitstring, $rev_dict);\n```\n\nLow-level function that decodes a Huffman-encoded binary string into a sequence of symbols using a provided reverse dictionary.\n\nIt takes two parameters: `$bitstring`, representing the Huffman-encoded string of 1s and 0s, as returned by `huffman_encode()`, and `$rev_dict`, representing the reverse dictionary mapping Huffman codes to their corresponding symbols.\n\nThe function returns the decoded sequence of symbols as an array-ref.\n\n## lz77\\_encode / lz77\\_encode\\_symbolic\n\n```perl\n    my ($literals, $distances, $lengths, $matches) = lz77_encode($string);\n    my ($literals, $distances, $lengths, $matches) = lz77_encode(\\@symbols);\n```\n\nLow-level function that combines LZSS with ideas from the LZ4 method.\n\nThe function returns four values:\n\n```perl\n    $literals   # array-ref of uncompressed symbols\n    $distances  # array-ref of back-reference distances\n    $lengths    # array-ref of literal lengths\n    $matches    # array-ref of match lengths\n```\n\nThe output can be decoded with `lz77_decode()` and `lz77_decode_symbolic()`, respectively.\n\n## lz77\\_decode / lz77\\_decode\\_symbolic\n\n```perl\n    my $string  = lz77_decode(\\@literals, \\@distances, \\@lengths, \\@matches);\n    my $symbols = lz77_decode_symbolic(\\@literals, \\@distances, \\@lengths, \\@matches);\n```\n\nLow-level function that performs decoding using the provided literals, distances, lengths and matches, returned by LZ77 encoding.\n\nInverse of `lz77_encode()` and `lz77_encode_symbolic()`, respectively.\n\n## lzss\\_encode / lzss\\_encode\\_fast / lzss\\_encode\\_symbolic / lzss\\_encode\\_fast\\_symbolic\n\n```perl\n    # Standard version\n    my ($literals, $distances, $lengths) = lzss_encode($data, %params);\n    my ($literals, $distances, $lengths) = lzss_encode(\\@symbols, %params);\n\n    # Faster version\n    my ($literals, $distances, $lengths) = lzss_encode_fast($data, %params);\n    my ($literals, $distances, $lengths) = lzss_encode_fast(\\@symbols, %params);\n```\n\nLow-level function that applies the LZSS (Lempel-Ziv-Storer-Szymanski) algorithm on the provided data.\n\nThe accepted `%params` are:\n\n```perl\n    min_len         =\u003e $LZ_MIN_LEN,\n    max_len         =\u003e $LZ_MAX_LEN,\n    max_dist        =\u003e $LZ_MAX_DIST,\n    max_chain_len   =\u003e $LZ_MAX_CHAIN_LEN,\n```\n\nThe function returns three values:\n\n```perl\n    $literals   # array-ref of uncompressed symbols\n    $distances  # array-ref of back-reference distances\n    $lengths    # array-ref of match lengths\n```\n\nThe output can be decoded with `lzss_decode()` and `lzss_decode_symbolic()`, respectively.\n\n## lzss\\_decode / lzss\\_decode\\_symbolic\n\n    my $string  = lzss_decode(\\@literals, \\@distances, \\@lengths);\n    my $symbols = lzss_decode_symbolic(\\@literals, \\@distances, \\@lengths);\n\nLow-level function that decodes the LZSS encoding, using the provided literals, distances, and lengths of matched sub-strings.\n\nInverse of `lzss_encode()` and `lzss_encode_fast()`.\n\n## deflate\\_encode\n\n```perl\n    # Returns a binary string\n    my $string = deflate_encode(\\@literals, \\@distances, \\@lengths);\n    my $string = deflate_encode(\\@literals, \\@distances, \\@lengths, \\\u0026create_ac_entry);\n```\n\nLow-level function that encodes the results returned by `lzss_encode()` and `lzss_encode_fast()`, using a DEFLATE-like approach, combined with Huffman coding.\n\n## deflate\\_decode\n\n```perl\n    # Huffman decoding\n    my ($literals, $distances, $lengths) = deflate_decode($fh);\n    my ($literals, $distances, $lengths) = deflate_decode($string);\n\n    # Arithmetic decoding\n    my ($literals, $distances, $lengths) = deflate_decode($fh, \\\u0026decode_ac_entry);\n    my ($literals, $distances, $lengths) = deflate_decode($string, \\\u0026decode_ac_entry);\n```\n\nInverse of `deflate_encode()`.\n\n## make\\_deflate\\_tables\n\n```perl\n    my ($DISTANCE_SYMBOLS, $LENGTH_SYMBOLS, $LENGTH_INDICES) = make_deflate_tables($max_dist, $max_len);\n```\n\nLow-level function that returns a list of tables used in encoding the relative back-reference distances and lengths returned by `lzss_encode()` and `lzss_encode_fast()`.\n\nWhen no arguments are provided:\n\n```perl\n    $max_dist = $Compression::Util::LZ_MAX_DIST\n    $max_len  = $Compression::Util::LZ_MAX_LEN\n```\n\nThere is no need to call this function explicitly. Use `deflate_encode()` instead!\n\n## find\\_deflate\\_index\n\n```perl\n    my $index = find_deflate_index($value, $DISTANCE_SYMBOLS);\n```\n\nLow-level function that returns the index inside the DEFLATE tables for a given value.\n\n## deflate\\_create\\_block\\_type\\_0\\_header\n\n```perl\n    my $bt0_header = deflate_create_block_type_0_header($chunk);\n```\n\nCreates the header for a DEFLATE block of type 0 (uncompressed), as a bitstring, without including the block code number `00`.\n\nThe length of the `$chunk` must not exceed `2^16 - 1`.\n\nTo create a DEFLATE block of type 0, including the content, use:\n\n```perl\n    my $block_type_0 = pack('b*', '00') . pack('b*', $bt0_header) . $chunk;\n```\n\nwhich can be recovered as:\n\n```perl\n    open my $fh, '\u003c:raw', \\$block_type_0;\n    my ($buffer, $search_window) = ('', '');\n    my $chunk = deflate_extract_next_block($fh, \\$buffer, \\$search_window);\n```\n\n## deflate\\_create\\_block\\_type\\_1\n\n```perl\n    my $bitstring = deflate_create_block_type_1($literals, $distances, $lengths);\n```\n\nCreates a DEFLATE block of type 1 (fixed prefix-codes), as a bitstring, given the ARRAY-refs of literals, distances and lengths, returned by `lzss_encode()`.\n\nThis type of block uses fixed prefix-codes and is pretty fast.\n\n## deflate\\_create\\_block\\_type\\_2\n\n```perl\n    my $bitstring = deflate_create_block_type_1($literals, $distances, $lengths);\n```\n\nCreates a DEFLATE block of type 2 (dynamic prefix-codes), as a bitstring, given the ARRAY-refs of literals, distances and lengths, returned by `lzss_encode()`.\n\nThis type of block uses dynamic prefix-codes (Huffman codes) and produces good compression ratio on most inputs.\n\n## deflate\\_extract\\_block\\_type\\_0\n\n```perl\n    my $data = deflate_extract_block_type_0($fh, \\$buffer, \\$search_window);\n```\n\nGiven an input filehandle, it extracts a DEFLATE block of type 0 (uncompressed).\n\n```perl\n    my ($buffer, $search_window) = ('', '');\n    my $block_type = bits2int_lsb($fh, 2, \\$buffer);\n    $block_type == 0 or die \"Not a block of type 0\";\n    my $decoded_chunk = deflate_extract_block_type_0($fh, \\$buffer, \\$search_window);\n```\n\n## deflate\\_extract\\_block\\_type\\_1\n\n```perl\n    my $data = deflate_extract_block_type_1($fh, \\$buffer, \\$search_window);\n```\n\nGiven an input filehandle, a bitstring buffer and a search window, it extracts a DEFLATE block of type 1 (fixed prefix-codes).\n\n```perl\n    my ($buffer, $search_window) = ('', '');\n    my $block_type = bits2int_lsb($fh, 2, \\$buffer);\n    $block_type == 1 or die \"Not a block of type 1\";\n    my $decoded_chunk = deflate_extract_block_type_1($fh, \\$buffer, \\$search_window);\n```\n\n## deflate\\_extract\\_block\\_type\\_2\n\n```perl\n    my $data = deflate_extract_block_type_2($fh, \\$buffer, \\$search_window);\n```\n\nGiven an input filehandle, a bitstring buffer and a search window, it extracts a DEFLATE block of type 2 (dynamic prefix-codes).\n\n```perl\n    my ($buffer, $search_window) = ('', '');\n    my $block_type = bits2int_lsb($fh, 2, \\$buffer);\n    $block_type == 2 or die \"Not a block of type 2\";\n    my $decoded_chunk = deflate_extract_block_type_2($fh, \\$buffer, \\$search_window);\n```\n\n## deflate\\_extract\\_next\\_block\n\n```perl\n    my $data = deflate_extract_next_block($fh, \\$buffer, \\$search_window);\n```\n\nGiven an input filehandle, a bitstring buffer and a search window, it extracts the next DEFLATE block. The next two bits in the input file-handle (or in the bitstring buffer) must contain the block-type number.\n\n# EXPORT\n\nEach function can be exported individually, as:\n\n```perl\n    use Compression::Util qw(bwt_compress);\n```\n\nBy specifying the **:all** keyword, will export all the exportable functions:\n\n```perl\n    use Compression::Util qw(:all);\n```\n\nNothing is exported by default.\n\n# EXAMPLES\n\nThe functions can be combined in various ways, easily creating novel compression methods, as illustrated in the following examples.\n\n## Combining LZSS + MRL compression:\n\n```perl\n    my $enc = lzss_compress($str, \\\u0026mrl_compress_symbolic);\n    my $dec = lzss_decompress($enc, \\\u0026mrl_decompress_symbolic);\n```\n\n## Combining LZ77 + OBH encoding:\n\n```perl\n    my $enc = lz77_compress($str, \\\u0026obh_encode);\n    my $dec = lz77_decompress($enc, \\\u0026obh_decode);\n```\n\n## Combining LZSS + symbolic BWT compression:\n\n```perl\n    my $enc = lzss_compress($str, \\\u0026bwt_compress_symbolic);\n    my $dec = lzss_decompress($enc, \\\u0026bwt_decompress_symbolic);\n```\n\n## Combining BWT + symbolic LZSS:\n\n```perl\n    my $enc = bwt_compress($str, \\\u0026lzss_compress_symbolic);\n    my $dec = bwt_decompress($enc, \\\u0026lzss_decompress_symbolic);\n```\n\n## Combining LZW + Fibonacci encoding:\n\n```perl\n    my $enc = lzw_compress($str, \\\u0026fibonacci_encode);\n    my $dec = lzw_decompress($enc, \\\u0026fibonacci_decode);\n```\n\n## Combining BWT + symbolic LZ77 + symbolic MRL:\n\n```perl\n    my $enc = bwt_compress($str, sub ($s) { lz77_compress_symbolic($s, \\\u0026mrl_compress_symbolic) });\n    my $dec = bwt_decompress($enc, sub ($s) { lz77_decompress_symbolic($s, \\\u0026mrl_decompress_symbolic) });\n```\n\n## Combining LZ77 + BWT compression + Fibonacci encoding + Huffman coding + OBH encoding + MRL compression:\n\n```perl\n    # Compression\n    my $enc = do {\n        my ($literals, $distances, $lengths, $matches) = lz77_encode($str);\n        bwt_compress(symbols2string($literals))\n          . fibonacci_encode($lengths)\n          . create_huffman_entry($matches)\n          . obh_encode($distances, \\\u0026mrl_compress_symbolic);\n    };\n\n    # Decompression\n    my $dec = do {\n        open my $fh, '\u003c:raw', \\$enc;\n        my $literals  = string2symbols(bwt_decompress($fh));\n        my $lengths   = fibonacci_decode($fh);\n        my $matches   = decode_huffman_entry($fh);\n        my $distances = obh_decode($fh, \\\u0026mrl_decompress_symbolic);\n        lz77_decode($literals, $distances, $lengths, $matches);\n    };\n```\n\n# REFERENCES\n\n- DEFLATE Compressed Data Format Specification\n    * [https://datatracker.ietf.org/doc/html/rfc1951](https://datatracker.ietf.org/doc/html/rfc1951)\n- GZIP file format specification\n    * [https://datatracker.ietf.org/doc/html/rfc1952](https://datatracker.ietf.org/doc/html/rfc1952)\n- ZLIB Compressed Data Format Specification\n    * [https://datatracker.ietf.org/doc/html/rfc1950](https://datatracker.ietf.org/doc/html/rfc1950)\n- BZIP2 Format Specification, by Joe Tsai:\n    * [https://github.com/dsnet/compress/blob/master/doc/bzip2-format.pdf](https://github.com/dsnet/compress/blob/master/doc/bzip2-format.pdf)\n- LZ4 Frame format\n    * [https://github.com/lz4/lz4/blob/dev/doc/lz4\\_Frame\\_format.md](https://github.com/lz4/lz4/blob/dev/doc/lz4_Frame_format.md)\n- LZ4 Block format\n    * [https://github.com/lz4/lz4/blob/dev/doc/lz4\\_Block\\_format.md](https://github.com/lz4/lz4/blob/dev/doc/lz4_Block_format.md)\n- Data Compression (Summer 2023) - Lecture 4 - The Unix 'compress' Program:\n    * [https://youtube.com/watch?v=1cJL9Va80Pk](https://youtube.com/watch?v=1cJL9Va80Pk)\n- Data Compression (Summer 2023) - Lecture 5 - Basic Techniques:\n    * [https://youtube.com/watch?v=TdFWb8mL5Gk](https://youtube.com/watch?v=TdFWb8mL5Gk)\n- Data Compression (Summer 2023) - Lecture 11 - DEFLATE (gzip):\n    * [https://youtube.com/watch?v=SJPvNi4HrWQ](https://youtube.com/watch?v=SJPvNi4HrWQ)\n- Data Compression (Summer 2023) - Lecture 12 - The Burrows-Wheeler Transform (BWT):\n    * [https://youtube.com/watch?v=rQ7wwh4HRZM](https://youtube.com/watch?v=rQ7wwh4HRZM)\n- Data Compression (Summer 2023) - Lecture 13 - BZip2:\n    * [https://youtube.com/watch?v=cvoZbBZ3M2A](https://youtube.com/watch?v=cvoZbBZ3M2A)\n- Data Compression (Summer 2023) - Lecture 15 - Infinite Precision in Finite Bits:\n    * [https://youtube.com/watch?v=EqKbT3QdtOI](https://youtube.com/watch?v=EqKbT3QdtOI)\n- Information Retrieval WS 17/18, Lecture 4: Compression, Codes, Entropy:\n    * [https://youtube.com/watch?v=A\\_F94FV21Ek](https://youtube.com/watch?v=A_F94FV21Ek)\n- COMP526 7-5 SS7.4 Run length encoding:\n    * [https://youtube.com/watch?v=3jKLjmV1bL8](https://youtube.com/watch?v=3jKLjmV1bL8)\n- COMP526 Unit 7-6 2020-03-24 Compression - Move-to-front transform:\n    * [https://youtube.com/watch?v=Q2pinaj3i9Y](https://youtube.com/watch?v=Q2pinaj3i9Y)\n- Basic arithmetic coder in C++:\n    * [https://github.com/billbird/arith32](https://github.com/billbird/arith32)\n\n# REPOSITORY\n\n- GitHub: [https://github.com/trizen/Compression-Util](https://github.com/trizen/Compression-Util)\n\n# BUGS AND LIMITATIONS\n\nPlease report any bugs or feature requests to: [https://github.com/trizen/Compression-Util](https://github.com/trizen/Compression-Util).\n\n# AUTHOR\n\nDaniel \"Trizen\" Șuteu\n\n# ACKNOWLEDGEMENTS\n\nSpecial thanks to professor Bill Bird for the awesome YouTube lectures on data compression.\n\n# LICENSE\n\nThis library is free software; you can redistribute it and/or modify\nit under the same terms as Perl itself, either Perl version 5.38.2 or,\nat your option, any later version of Perl 5 you may have available.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrizen%2Fcompression-util","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrizen%2Fcompression-util","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrizen%2Fcompression-util/lists"}