Esempio n. 1
0
void deflate_parse_htrees(bitstream_t *bitstream,
    htree_t **htree_lit, htree_t **htree_dist)
{
    int hlit = read_bits(bitstream, 5) + 257;
    int hdist = read_bits(bitstream, 5) + 1;
    int hclen = read_bits(bitstream, 4) + 4;

    int cl_order[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
    int cl_lengths[19] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };

    for (int i = 0; i < hclen; i++) {
        cl_lengths[cl_order[i]] = read_bits(bitstream, 3);
    }

    htree_t *ht_cl = huffman_create_tree(19, cl_lengths);

    int tot = hlit + hdist;
    int *lengths = calloc(tot, sizeof(int));
    int cur_len = 0;

    while (cur_len < tot) {
        htree_t *cur_cl = huffman_get_symbol(ht_cl, bitstream);
        int symbol = 0, repeats = 1;

        if (cur_cl->symbol == 16) {
            /* Symbol 16: Copy previous length 3-6 times. */
            symbol = lengths[cur_len - 1];
            repeats = read_bits(bitstream, 2) + 3;
        } else if (cur_cl->symbol == 17) {
            /* Symbol 17: Repeat 0 for 3-10 times. */
            repeats = read_bits(bitstream, 3) + 3;
        } else if (cur_cl->symbol == 18) {
            /* Symbol 18: Repeat 0 for 11-138 times. */
            repeats = read_bits(bitstream, 7) + 11;
        } else {
            /* Otherwise: Emit length. */
            symbol = cur_cl->symbol;
        }

        for (int i = 0; i < repeats; i++) {
            lengths[cur_len++] = symbol;
        }
    }

    if (cur_len > tot) {
        printf("Error: Code tree lengths defined too far\n");
    }

    /* We don't need the code length Huffman tree anymore. */
    huffman_free_tree(ht_cl);

    int *lit_lengths = &lengths[0];
    int *dist_lengths = &lengths[hlit];

    *htree_lit = huffman_create_tree(hlit, lit_lengths);
    *htree_dist = huffman_create_tree(hdist, dist_lengths);

    /* Free the data arrays used to create the Huffman trees. */
    free(lengths);
}
Esempio n. 2
0
void deflate_get_fixed_htrees(htree_t **htree_lit, htree_t **htree_dist)
{
    int lengths[288];

    for (int i = 0; i < 288; i++) {
        if (i < 144) {
            lengths[i] = 8;
        } else if (i < 256) {
            lengths[i] = 9;
        } else if (i < 280) {
            lengths[i] = 7;
        } else {
            lengths[i] = 8;
        }
    }

   *htree_lit = huffman_create_tree(288, lengths);

   for (int i = 0; i < 32; i++) {
       lengths[i] = 5;
   }

   *htree_dist = huffman_create_tree(32, lengths);
}
Esempio n. 3
0
unsigned int alpng_inflate(struct input_data* data, unsigned char* unpacked_data, unsigned int unpacked_length, char** error_msg) {
    int bfinal, btype; /* as defined by the deflate spec */
    int code, length, distance, i;
    unsigned int unpacked_index = 0;
    struct huffman_tree* main_tree = huffman_create_tree();
    struct huffman_tree* distances_tree = huffman_create_tree();
    struct huffman_tree* helper_tree = huffman_create_tree();  /* for codelengths */

    *error_msg = "OK";
    
    data->i = 2; /* ignore zlib header */

    do {
        bfinal = input_read_bit(data);
        if (data->error) {
            *error_msg = "Data shorter than one bit!";
            huffman_destroy_tree(main_tree);
            huffman_destroy_tree(distances_tree);
            huffman_destroy_tree(helper_tree);
            return 0;
        }
        btype = input_read_bits(data, 2);
        if (data->error) {
            *error_msg = "Data shorter than one byte!";
            huffman_destroy_tree(main_tree);
            huffman_destroy_tree(distances_tree);
            huffman_destroy_tree(helper_tree);
            return 0;
        }
        switch (btype) {
            case 0:
                length = input_read_bytes(data, 2);
                if (data->error) {
                    *error_msg = "Cannot read length of uncompressed block!";
                    huffman_destroy_tree(main_tree);
                    huffman_destroy_tree(distances_tree);
                    huffman_destroy_tree(helper_tree);
                    return 0;
                }
                i = input_read_bytes(data, 2);
                if (data->error) {
                    *error_msg = "Cannot read length of uncompressed block!";
                    huffman_destroy_tree(main_tree);
                    huffman_destroy_tree(distances_tree);
                    huffman_destroy_tree(helper_tree);
                    return 0;
                }
                if (length != (i ^ 0xFFFF)) {
                    *error_msg = "Uncompressed block corruption detected!";
                    huffman_destroy_tree(main_tree);
                    huffman_destroy_tree(distances_tree);
                    huffman_destroy_tree(helper_tree);
                    return 0;
                }
                for (i = 0; i < length; i++) {
                    code = input_read_byte(data);
                    if (data->error) {
                        *error_msg = "Uncompressed block incomplete!";
                        huffman_destroy_tree(main_tree);
                        huffman_destroy_tree(distances_tree);
                        huffman_destroy_tree(helper_tree);
                        return 0;
                    }
                    if (unpacked_index >= unpacked_length) {
                        *error_msg = "Too much data!";
                        huffman_destroy_tree(main_tree);
                        huffman_destroy_tree(distances_tree);
                        huffman_destroy_tree(helper_tree);
                        return 0;
                    } else {
                        unpacked_data[unpacked_index++] = code;
                    }
                }
                break;
            case 1:
                if (!load_fixed_tree(main_tree, distances_tree)) {
                    *error_msg = "Cannot load fixed Huffman tree!";
                    huffman_destroy_tree(main_tree);
                    huffman_destroy_tree(distances_tree);
                    huffman_destroy_tree(helper_tree);
                    return 0;
                }
                break;
            case 2:
                if (!load_dynamic_tree(main_tree, distances_tree, helper_tree, data)) {
                    *error_msg = "Cannot load dynamic Huffman tree!";
                    huffman_destroy_tree(main_tree);
                    huffman_destroy_tree(distances_tree);
                    huffman_destroy_tree(helper_tree);
                    return 0;
                }
                break;
            case 3:
                *error_msg = "Unsupported (non-existing) type of compression!";
                huffman_destroy_tree(main_tree);
                huffman_destroy_tree(distances_tree);
                huffman_destroy_tree(helper_tree);
                return 0;
                break;
        }
        if (btype > 0) {
            code = huffman_read_next_code(main_tree, data);
            if (code == -1) {
                huffman_destroy_tree(main_tree);
                huffman_destroy_tree(distances_tree);
                huffman_destroy_tree(helper_tree);
                *error_msg = "Invalid data!";
                return 0;
            }
            while (code != 256) {
                if (code < 256) {
                    if (unpacked_index >= unpacked_length) {
                        huffman_destroy_tree(main_tree);
                        huffman_destroy_tree(distances_tree);
                        huffman_destroy_tree(helper_tree);
                        *error_msg = "Too much data!";
                        return 0;
                    }
                    unpacked_data[unpacked_index++] = code;
                } else {
                    length = 0;
                    distance = 0;
                    if (code >= 257 && code <= 264) {
                        length = code - 257 + 3;
                    } else if (code >= 265 && code <= 268) {
                        length = (code - 265) * 2 + 11 + input_read_bit(data);
                    } else if (code >= 269 && code <= 272) {
                        length = (code - 269) * 4 + 19 + input_read_bits(data, 2);
                    } else if (code >= 273 && code <= 276) {
                        length = (code - 273) * 8 + 35 + input_read_bits(data, 3);
                    } else if (code >= 277 && code <= 280) {
                        length = (code - 277) * 16 + 67 + input_read_bits(data, 4);
                    } else if (code >= 281 && code <= 284) {
                        length = (code - 281) * 32 + 131 + input_read_bits(data, 5);
                    } else if (code == 285) {
                        length = 258;
                    } else {
                        huffman_destroy_tree(main_tree);
                        huffman_destroy_tree(distances_tree);
                        huffman_destroy_tree(helper_tree);
                        *error_msg = "Algorithm error: unknown length!";
                        return 0;
                    }
                    if (data->error) {
                        huffman_destroy_tree(main_tree);
                        huffman_destroy_tree(distances_tree);
                        huffman_destroy_tree(helper_tree);
                        *error_msg = "Cannot read length!";
                        return 0;
                    }

                    distance = get_distance(distances_tree, data);
                    if (distance == -1) {
                        huffman_destroy_tree(main_tree);
                        huffman_destroy_tree(distances_tree);
                        huffman_destroy_tree(helper_tree);
                        *error_msg = "Algorithm error: bad distance!";
                        return 0;
                    }

                    for (i = 0; i < length; i++) {
                        code = unpacked_data[unpacked_index - distance];
                        if (unpacked_index >= unpacked_length) {
                            huffman_destroy_tree(main_tree);
                            huffman_destroy_tree(distances_tree);
                            huffman_destroy_tree(helper_tree);
                            *error_msg = "Too much data!";
                            return 0;
                        }
                        unpacked_data[unpacked_index++] = code;
                    }
                }
                code = huffman_read_next_code(main_tree, data);
                if (code == -1) {
                    huffman_destroy_tree(main_tree);
                    huffman_destroy_tree(distances_tree);
                    huffman_destroy_tree(helper_tree);
                    *error_msg = "Invalid data!";
                    return 0;
                }
            }
        }
    } while (bfinal == 0);
    huffman_destroy_tree(main_tree);
    huffman_destroy_tree(distances_tree);
    huffman_destroy_tree(helper_tree);
    return unpacked_index;
}