+
+ image->num_blocks_horizontal = (image->width + image->max_hsample * DCTSIZE - 1) / (image->max_hsample * DCTSIZE);
+ image->num_blocks_vertical = (image->height + image->max_vsample * DCTSIZE - 1) / (image->max_vsample * DCTSIZE);
+
+ for (unsigned c = 0; c < 256; ++c) {
+ if (image->hsample[c] == 0) {
+ continue;
+ }
+
+ unsigned width = image->num_blocks_horizontal * image->hsample[c] * DCTSIZE;
+ unsigned height = image->num_blocks_vertical * image->vsample[c] * DCTSIZE;
+ image->stride[c] = width;
+ image->pixel_data[c] = (uint8_t*)malloc(width * height);
+ assert(image->pixel_data[c] != NULL);
+ image->pixel_write_pointer[c] = image->pixel_data[c];
+
+ fprintf(stderr, "Component %u: allocating %d x %d\n", c, width, height);
+ }
+}
+
+void decode_ac_coefficients(const struct huffman_table* tbl, struct bit_source* bits, int16_t* coeff)
+{
+ possibly_refill(bits, DEHUF_AC_TABLE_BITS);
+ for (unsigned i = 0; i < DCTSIZE2 - 1; ) {
+ unsigned lookup = peek_bits(bits, DEHUF_AC_TABLE_BITS);
+ int code = tbl->ac_table_codes[lookup];
+ unsigned length = tbl->ac_table_length[lookup];
+ unsigned r = tbl->ac_table_skip[lookup];
+
+ if (__builtin_expect(code == AC_DEHUF_SLOW_PATH, 0)) {
+ unsigned rs = read_huffman_symbol_no_refill(tbl, bits);
+ if (rs == 0x00) {
+ /* end of block */
+ break;
+ }
+
+ unsigned r = rs >> 4;
+ unsigned s = rs & 0xf;
+ i += r + 1;
+ possibly_refill(bits, s);
+ coeff[unzigzag[i]] = extend(read_bits(bits, s), s);
+ possibly_refill(bits, DEHUF_AC_TABLE_BITS);
+ } else {
+ assert(bits->bits_available >= length);
+ read_bits(bits, length);
+ possibly_refill(bits, DEHUF_AC_TABLE_BITS);
+
+ assert(r >= 1);
+ i += r;
+ coeff[unzigzag[i]] = code;
+ }
+ }