#include "bytesource.h"
#include "choice.h"
#include "dehuff.h"
+#include "driver.h"
#include "idct.h"
#include "input.h"
#include "zigzag.h"
-struct jpeg_image {
- unsigned precision;
- unsigned width, height;
- unsigned num_components;
- unsigned hsample[256], vsample[256], qtable[256];
- unsigned max_hsample, max_vsample;
- unsigned stride[256];
- unsigned num_blocks_horizontal, num_blocks_vertical;
- uint32_t qvalues[256][DCTSIZE2];
- void* idct_data[256];
- uint8_t* pixel_data[256];
- uint8_t* pixel_write_pointer[256];
-};
-
ssize_t stdio_read(void* userdata, uint8_t* buf, size_t count)
{
return fread(buf, 1, count, (FILE*)userdata);
void decode_ac_coefficients(const struct huffman_table* tbl, struct bit_source* bits, int16_t* coeff)
{
- for (unsigned i = 1; i < DCTSIZE2; ++i) {
- possibly_refill(bits, DEHUF_AC_TABLE_BITS);
+ 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];
- assert(length == AC_DEHUF_SLOW_PATH || (length > 0 && length <= DEHUF_AC_TABLE_BITS));
-
- if (__builtin_expect(code == AC_DEHUF_SLOW_PATH, 0)) {
+ if (code == AC_DEHUF_SLOW_PATH) {
unsigned rs = read_huffman_symbol_no_refill(tbl, bits);
- unsigned r = rs >> 4;
- unsigned s = rs & 0xf;
- i += r;
- possibly_refill(bits, s);
-
if (rs == 0x00) {
- assert(code == AC_DEHUF_SLOW_PATH || code == AC_END_OF_BLOCK);
/* end of block */
break;
}
- if (rs == 0xf0) {
- assert(code == AC_DEHUF_SLOW_PATH || code == AC_SIXTEEN_ZEROS);
- /* 16 zero coefficients */
- continue;
- }
+ 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 {
- int length = tbl->ac_table_length[lookup];
- int r = tbl->ac_table_skip[lookup];
- assert(r >= 0);
- i += r;
assert(bits->bits_available >= length);
read_bits(bits, length);
- if (code == AC_END_OF_BLOCK) {
- break;
- }
- if (code == AC_SIXTEEN_ZEROS) {
- continue;
- }
+ possibly_refill(bits, DEHUF_AC_TABLE_BITS);
+
+ assert(r >= 1);
+ i += r;
coeff[unzigzag[i]] = code;
}
}
unsigned cn = component_num[c];
image->pixel_write_pointer[cn] += (image->vsample[cn] * DCTSIZE - 1) * image->stride[cn];
}
-
- // Some debug code.
- const int c = 1;
if (mcu_y == image->num_blocks_vertical) {
- unsigned stride = image->num_blocks_horizontal * image->hsample[c] * DCTSIZE;
- unsigned height = image->num_blocks_vertical * image->vsample[c] * DCTSIZE;
- printf("P5\n%u %u\n255\n", stride, height);
- fwrite(image->pixel_data[c], stride * height, 1, stdout);
+ return;
}
}
}
}
}
-int main(void)
+void read_jpeg(struct jpeg_image* jpeg, FILE *input)
{
- struct jpeg_image jpeg;
- memset(&jpeg, 0, sizeof(jpeg));
- init_choices();
-
+ memset(jpeg, 0, sizeof(*jpeg));
+
struct byte_source source;
- init_byte_source(&source, stdio_read, stdin);
+ init_byte_source(&source, stdio_read, input);
huffman_tables_t tables;
break;
case 0xdb:
/* DQT */
- read_dqt(&source, &jpeg);
+ read_dqt(&source, jpeg);
break;
case 0xc0:
/* SOF0 (baseline DCT, Huffman encoded) */
- read_sof(&source, &jpeg);
+ read_sof(&source, jpeg);
break;
case 0xd8:
/* SOI */
break;
case 0xd9:
/* EOI */
- exit(0);
+ return;
case 0xc4:
/* DHT (define Huffman tables) */
read_huffman_tables(&tables, byte_source_input_func, &source);
break;
case 0xda:
/* SOS (start of scan) */
- read_scan(&source, &jpeg, &tables);
+ read_scan(&source, jpeg, &tables);
break;
default:
fprintf(stderr, "Error: Unknown marker 0x%02x\n", m2);
}
}
}
+
+int main(void)
+{
+ init_choices();
+
+ struct jpeg_image jpeg;
+ read_jpeg(&jpeg, stdin);
+
+ // Some debug code.
+ const int c = 1;
+ unsigned stride = jpeg.num_blocks_horizontal * jpeg.hsample[c] * DCTSIZE;
+ unsigned height = jpeg.num_blocks_vertical * jpeg.vsample[c] * DCTSIZE;
+ printf("P5\n%u %u\n255\n", stride, height);
+ fwrite(jpeg.pixel_data[c], stride * height, 1, stdout);
+}