sl@0: /* sl@0: * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #include sl@0: #include sl@0: sl@0: #include "jpeg_huffman.h" sl@0: #include "jpeg_debug.h" sl@0: sl@0: /* misc helper function definitions */ sl@0: sl@0: static char *sprintbits (char *str, unsigned int bits, int n); sl@0: sl@0: sl@0: #define TRUE 1 sl@0: #define FALSE 0 sl@0: sl@0: void sl@0: huffman_table_dump (HuffmanTable * table) sl@0: { sl@0: unsigned int n_bits; sl@0: unsigned int code; sl@0: char str[33]; sl@0: int i; sl@0: HuffmanEntry *entry; sl@0: sl@0: OIL_DEBUG ("dumping huffman table %p", table); sl@0: for (i = 0; i < table->len; i++) { sl@0: entry = table->entries + i; sl@0: n_bits = entry->n_bits; sl@0: code = entry->symbol >> (16 - n_bits); sl@0: sprintbits (str, code, n_bits); sl@0: OIL_DEBUG ("%s --> %d", str, entry->value); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: void sl@0: huffman_table_init (HuffmanTable *table) sl@0: { sl@0: memset (table, 0, sizeof(HuffmanTable)); sl@0: } sl@0: sl@0: void sl@0: huffman_table_add (HuffmanTable * table, uint32_t code, int n_bits, int value) sl@0: { sl@0: HuffmanEntry *entry = table->entries + table->len; sl@0: sl@0: entry->value = value; sl@0: entry->symbol = code << (16 - n_bits); sl@0: entry->mask = 0xffff ^ (0xffff >> n_bits); sl@0: entry->n_bits = n_bits; sl@0: sl@0: table->len++; sl@0: } sl@0: sl@0: unsigned int sl@0: huffman_table_decode_jpeg (HuffmanTable * tab, JpegBits * bits) sl@0: { sl@0: unsigned int code; sl@0: int i; sl@0: char str[33]; sl@0: HuffmanEntry *entry; sl@0: sl@0: code = peekbits (bits, 16); sl@0: for (i = 0; i < tab->len; i++) { sl@0: entry = tab->entries + i; sl@0: if ((code & entry->mask) == entry->symbol) { sl@0: code = getbits (bits, entry->n_bits); sl@0: sprintbits (str, code, entry->n_bits); sl@0: OIL_DEBUG ("%s --> %d", str, entry->value); sl@0: return entry->value; sl@0: } sl@0: } sl@0: printf ("huffman sync lost"); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: int sl@0: huffman_table_decode_macroblock (short *block, HuffmanTable * dc_tab, sl@0: HuffmanTable * ac_tab, JpegBits * bits) sl@0: { sl@0: int r, s, x, rs; sl@0: int k; sl@0: char str[33]; sl@0: sl@0: memset (block, 0, sizeof (short) * 64); sl@0: sl@0: s = huffman_table_decode_jpeg (dc_tab, bits); sl@0: if (s < 0) sl@0: return -1; sl@0: x = getbits (bits, s); sl@0: if ((x >> (s - 1)) == 0) { sl@0: x -= (1 << s) - 1; sl@0: } sl@0: OIL_DEBUG ("s=%d (block[0]=%d)", s, x); sl@0: block[0] = x; sl@0: sl@0: for (k = 1; k < 64; k++) { sl@0: rs = huffman_table_decode_jpeg (ac_tab, bits); sl@0: if (rs < 0) { sl@0: OIL_DEBUG ("huffman error"); sl@0: return -1; sl@0: } sl@0: if (bits->ptr > bits->end) { sl@0: OIL_DEBUG ("overrun"); sl@0: return -1; sl@0: } sl@0: s = rs & 0xf; sl@0: r = rs >> 4; sl@0: if (s == 0) { sl@0: if (r == 15) { sl@0: OIL_DEBUG ("r=%d s=%d (skip 16)", r, s); sl@0: k += 15; sl@0: } else { sl@0: OIL_DEBUG ("r=%d s=%d (eob)", r, s); sl@0: break; sl@0: } sl@0: } else { sl@0: k += r; sl@0: if (k >= 64) { sl@0: printf ("macroblock overrun"); sl@0: return -1; sl@0: } sl@0: x = getbits (bits, s); sl@0: sprintbits (str, x, s); sl@0: if ((x >> (s - 1)) == 0) { sl@0: x -= (1 << s) - 1; sl@0: } sl@0: block[k] = x; sl@0: OIL_DEBUG ("r=%d s=%d (%s -> block[%d]=%d)", r, s, str, k, x); sl@0: } sl@0: } sl@0: return 0; sl@0: } sl@0: sl@0: int sl@0: huffman_table_decode (HuffmanTable * dc_tab, HuffmanTable * ac_tab, sl@0: JpegBits * bits) sl@0: { sl@0: int16_t zz[64]; sl@0: int ret; sl@0: sl@0: while (bits->ptr < bits->end) { sl@0: ret = huffman_table_decode_macroblock (zz, dc_tab, ac_tab, bits); sl@0: if (ret < 0) sl@0: return -1; sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* misc helper functins */ sl@0: sl@0: static char * sl@0: sprintbits (char *str, unsigned int bits, int n) sl@0: { sl@0: int i; sl@0: int bit = 1 << (n - 1); sl@0: sl@0: for (i = 0; i < n; i++) { sl@0: str[i] = (bits & bit) ? '1' : '0'; sl@0: bit >>= 1; sl@0: } sl@0: str[i] = 0; sl@0: sl@0: return str; sl@0: }