mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-09 23:53:28 -04:00
jpeg: use the quantization table each component selects
Both JPEG decoders ignored the Tq selector in the frame header and always dequantized luma with table 0 and chroma with table 1. Files with a single shared table multiplied chroma by an empty table, and files with separate Cb and Cr tables used the wrong one for Cr. imageviewer/jpeg: build one dequantization table per component (3 instead of 2, +256 bytes) from the table it selects. tab_membership is no longer used and is removed. Core loader: the raw tables are pre-scaled in place for the IDCT, and luma and chroma can use different IDCT scales. fix_quant_tables() now maps each component to a table slot, copying a table that luma and chroma share at different scales to a slot no component uses (there are 4 slots and at most 3 components, so one is always free), and rewrites quanttable_select to that slot. No extra memory. Selectors above 3 are rejected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Change-Id: If04c61fb0fef95da11d98d9918ea7225d8a440b0
This commit is contained in:
parent
b897766a7a
commit
0e50ed3c43
3 changed files with 65 additions and 41 deletions
|
|
@ -533,6 +533,8 @@ int process_markers(unsigned char* p_src, long size, struct jpeg* p_jpeg)
|
|||
p_jpeg->frameheader[i].horizontal_sampling = *p_src >> 4;
|
||||
p_jpeg->frameheader[i].vertical_sampling = *p_src++ & 0x0F;
|
||||
p_jpeg->frameheader[i].quanttable_select = *p_src++;
|
||||
if (p_jpeg->frameheader[i].quanttable_select > 3)
|
||||
return -8; /* Unsupported quantization table */
|
||||
if (p_jpeg->frameheader[i].horizontal_sampling > 2
|
||||
|| p_jpeg->frameheader[i].vertical_sampling > 2)
|
||||
return -3; /* Unsupported SOF0 subsampling */
|
||||
|
|
@ -890,7 +892,7 @@ static const int zag[] =
|
|||
|
||||
void build_lut(struct jpeg* p_jpeg)
|
||||
{
|
||||
int i;
|
||||
int i, c;
|
||||
fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_dc,
|
||||
&p_jpeg->dc_derived_tbls[0]);
|
||||
fix_huff_tbl(p_jpeg->hufftable[0].huffmancodes_ac,
|
||||
|
|
@ -900,11 +902,14 @@ void build_lut(struct jpeg* p_jpeg)
|
|||
fix_huff_tbl(p_jpeg->hufftable[1].huffmancodes_ac,
|
||||
&p_jpeg->ac_derived_tbls[1]);
|
||||
|
||||
/* build the dequantization tables for the IDCT (De-ZiZagged) */
|
||||
for (i=0; i<64; i++)
|
||||
/* build each component's dequantization table for the IDCT
|
||||
(De-ZiZagged); p_jpeg->blocks is still the component count here */
|
||||
for (c=0; c<p_jpeg->blocks; c++)
|
||||
{
|
||||
p_jpeg->qt_idct[0][zag[i]] = p_jpeg->quanttable[0][i];
|
||||
p_jpeg->qt_idct[1][zag[i]] = p_jpeg->quanttable[1][i];
|
||||
const int* qt = p_jpeg->quanttable[
|
||||
p_jpeg->frameheader[c].quanttable_select];
|
||||
for (i=0; i<64; i++)
|
||||
p_jpeg->qt_idct[c][zag[i]] = qt[i];
|
||||
}
|
||||
|
||||
for (i=0; i<4; i++)
|
||||
|
|
@ -923,10 +928,6 @@ void build_lut(struct jpeg* p_jpeg)
|
|||
p_jpeg->mcu_membership[1] = 0;
|
||||
p_jpeg->mcu_membership[2] = 1;
|
||||
p_jpeg->mcu_membership[3] = 2;
|
||||
p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */
|
||||
p_jpeg->tab_membership[1] = 0;
|
||||
p_jpeg->tab_membership[2] = 1;
|
||||
p_jpeg->tab_membership[3] = 1;
|
||||
p_jpeg->subsample_x[0] = 1;
|
||||
p_jpeg->subsample_x[1] = 2;
|
||||
p_jpeg->subsample_x[2] = 2;
|
||||
|
|
@ -948,10 +949,6 @@ void build_lut(struct jpeg* p_jpeg)
|
|||
p_jpeg->mcu_membership[1] = 0;
|
||||
p_jpeg->mcu_membership[2] = 1;
|
||||
p_jpeg->mcu_membership[3] = 2;
|
||||
p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */
|
||||
p_jpeg->tab_membership[1] = 0;
|
||||
p_jpeg->tab_membership[2] = 1;
|
||||
p_jpeg->tab_membership[3] = 1;
|
||||
p_jpeg->subsample_x[0] = 1;
|
||||
p_jpeg->subsample_x[1] = 1;
|
||||
p_jpeg->subsample_x[2] = 1;
|
||||
|
|
@ -973,12 +970,6 @@ void build_lut(struct jpeg* p_jpeg)
|
|||
p_jpeg->mcu_membership[3] = 0;
|
||||
p_jpeg->mcu_membership[4] = 1;
|
||||
p_jpeg->mcu_membership[5] = 2;
|
||||
p_jpeg->tab_membership[0] = 0;
|
||||
p_jpeg->tab_membership[1] = 0;
|
||||
p_jpeg->tab_membership[2] = 0;
|
||||
p_jpeg->tab_membership[3] = 0;
|
||||
p_jpeg->tab_membership[4] = 1;
|
||||
p_jpeg->tab_membership[5] = 1;
|
||||
p_jpeg->subsample_x[0] = 1;
|
||||
p_jpeg->subsample_x[1] = 2;
|
||||
p_jpeg->subsample_x[2] = 2;
|
||||
|
|
@ -997,9 +988,6 @@ void build_lut(struct jpeg* p_jpeg)
|
|||
p_jpeg->mcu_membership[0] = 0;
|
||||
p_jpeg->mcu_membership[1] = 1;
|
||||
p_jpeg->mcu_membership[2] = 2;
|
||||
p_jpeg->tab_membership[0] = 0;
|
||||
p_jpeg->tab_membership[1] = 1;
|
||||
p_jpeg->tab_membership[2] = 1;
|
||||
p_jpeg->subsample_x[0] = 1;
|
||||
p_jpeg->subsample_x[1] = 1;
|
||||
p_jpeg->subsample_x[2] = 1;
|
||||
|
|
@ -1286,7 +1274,6 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
|
|||
int k = 1; /* coefficient index */
|
||||
int s, r; /* huffman values */
|
||||
int ci = p_jpeg->mcu_membership[blkn]; /* component index */
|
||||
int ti = p_jpeg->tab_membership[blkn]; /* table index */
|
||||
struct derived_tbl* dctbl =
|
||||
&p_jpeg->dc_derived_tbls[p_jpeg->scanheader[ci].DC_select];
|
||||
struct derived_tbl* actbl =
|
||||
|
|
@ -1349,11 +1336,11 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3],
|
|||
if (ci == 0)
|
||||
{ /* Y component needs to bother about block store */
|
||||
pf_idct(p_byte[0]+store_offs[blkn], block,
|
||||
p_jpeg->qt_idct[ti], skip_line[0]);
|
||||
p_jpeg->qt_idct[ci], skip_line[0]);
|
||||
}
|
||||
else
|
||||
{ /* chroma */
|
||||
pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti],
|
||||
pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ci],
|
||||
skip_line[ci]);
|
||||
}
|
||||
} /* for blkn */
|
||||
|
|
@ -1459,7 +1446,6 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale,
|
|||
int k = 1; /* coefficient index */
|
||||
int s, r; /* huffman values */
|
||||
int ci = p_jpeg->mcu_membership[blkn]; /* component index */
|
||||
int ti = p_jpeg->tab_membership[blkn]; /* table index */
|
||||
struct derived_tbl* dctbl =
|
||||
&p_jpeg->dc_derived_tbls[p_jpeg->scanheader[ci].DC_select];
|
||||
struct derived_tbl* actbl =
|
||||
|
|
@ -1524,7 +1510,7 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale,
|
|||
|
||||
if (ci == 0)
|
||||
{ /* only for Y component */
|
||||
pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti],
|
||||
pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ci],
|
||||
skip_line);
|
||||
}
|
||||
} /* for blkn */
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ struct jpeg
|
|||
unsigned char* p_entropy_end;
|
||||
|
||||
int quanttable[4][QUANT_TABLE_LENGTH]; /* raw quantization tables 0-3 */
|
||||
int qt_idct[2][QUANT_TABLE_LENGTH]; /* quantization tables for IDCT */
|
||||
int qt_idct[3][QUANT_TABLE_LENGTH]; /* per component, for IDCT */
|
||||
|
||||
struct huffman_table hufftable[2]; /* Huffman tables */
|
||||
struct derived_tbl dc_derived_tbls[2]; /* Huffman-LUTs */
|
||||
|
|
@ -52,7 +52,6 @@ struct jpeg
|
|||
struct scan_component scanheader[3]; /* Huffman tables per component */
|
||||
|
||||
int mcu_membership[6]; /* info per block */
|
||||
int tab_membership[6];
|
||||
int subsample_x[3]; /* info per component */
|
||||
int subsample_y[3];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1043,6 +1043,8 @@ static int process_markers(struct jpeg* p_jpeg)
|
|||
p_jpeg->frameheader[i].vertical_sampling = c & 0x0F;
|
||||
p_jpeg->frameheader[i].quanttable_select =
|
||||
e_getc(p_jpeg, -1);
|
||||
if (p_jpeg->frameheader[i].quanttable_select > 3)
|
||||
return -8; /* Unsupported quantization table */
|
||||
if (p_jpeg->frameheader[i].horizontal_sampling > 2
|
||||
|| p_jpeg->frameheader[i].vertical_sampling > 2)
|
||||
return -3; /* Unsupported SOF0 subsampling */
|
||||
|
|
@ -1567,23 +1569,60 @@ INLINE void fix_huff_tables(struct jpeg *p_jpeg)
|
|||
* quantization table when one of these IDCT routines is used, rather than
|
||||
* have the IDCT shift each value it processes.
|
||||
*/
|
||||
/* Pre-scale the quantization tables for the IDCT. Luma and chroma can use
|
||||
* different IDCT scales, so a table that both select is copied to a slot no
|
||||
* component selects before scaling; each component's quanttable_select is
|
||||
* rewritten to the slot it should use. There are 4 slots and at most 3
|
||||
* components, so when a table is shared a free slot always exists. */
|
||||
INLINE void fix_quant_tables(struct jpeg *p_jpeg)
|
||||
{
|
||||
int shift, i, j;
|
||||
int want[4] = { -1, -1, -1, -1 }; /* scale shift wanted for each slot */
|
||||
int orig[4] = { 0, 1, 2, 3 }; /* table each slot holds */
|
||||
int c, c2, f, j;
|
||||
|
||||
#ifdef HAVE_LCD_COLOR
|
||||
const int k = 2;
|
||||
const int nc = p_jpeg->blocks > 1 ? 3 : 1;
|
||||
#else
|
||||
const int k = 1;
|
||||
const int nc = 1; /* chroma is not decoded */
|
||||
#endif
|
||||
|
||||
for (i = 0; i < k; i++)
|
||||
for (c = 0; c < nc; c++)
|
||||
{
|
||||
shift = idct_tbl[p_jpeg->v_scale[i]].scale;
|
||||
if (shift)
|
||||
int t = p_jpeg->frameheader[c].quanttable_select;
|
||||
int shift = idct_tbl[p_jpeg->v_scale[!!c]].scale;
|
||||
|
||||
for (f = 0; f < 4; f++) /* a slot already holding t at this scale? */
|
||||
if (orig[f] == t && want[f] == shift)
|
||||
break;
|
||||
if (f == 4 && want[t] < 0)
|
||||
f = t; /* first use of t */
|
||||
if (f == 4)
|
||||
{ /* t is in use at another scale: copy it to a free slot that no
|
||||
later component still needs */
|
||||
for (f = 0; f < 4; f++)
|
||||
{
|
||||
if (want[f] >= 0)
|
||||
continue;
|
||||
for (c2 = c + 1; c2 < nc; c2++)
|
||||
if (p_jpeg->frameheader[c2].quanttable_select == f)
|
||||
break;
|
||||
if (c2 == nc)
|
||||
break;
|
||||
}
|
||||
MEMCPY(p_jpeg->quanttable[f], p_jpeg->quanttable[t],
|
||||
sizeof(p_jpeg->quanttable[f]));
|
||||
orig[f] = t;
|
||||
}
|
||||
want[f] = shift;
|
||||
p_jpeg->frameheader[c].quanttable_select = f;
|
||||
}
|
||||
|
||||
for (f = 0; f < 4; f++)
|
||||
{
|
||||
if (want[f] > 0)
|
||||
{
|
||||
for (j = 0; j < 64; j++)
|
||||
p_jpeg->quanttable[i][j] <<= shift;
|
||||
p_jpeg->quanttable[f][j] <<= want[f];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1841,6 +1880,8 @@ static struct img_part *store_row_jpeg(void *jpeg_args)
|
|||
&p_jpeg->dc_derived_tbls[p_jpeg->scanheader[ci].DC_select];
|
||||
struct derived_tbl* actbl =
|
||||
&p_jpeg->ac_derived_tbls[p_jpeg->scanheader[ci].AC_select];
|
||||
const int16_t *qt = p_jpeg->quanttable[
|
||||
p_jpeg->frameheader[ci].quanttable_select];
|
||||
|
||||
/* Section F.2.2.1: decode the DC coefficient difference */
|
||||
huff_decode_dc(p_jpeg, dctbl, s, r);
|
||||
|
|
@ -1853,13 +1894,11 @@ static struct img_part *store_row_jpeg(void *jpeg_args)
|
|||
#ifdef HAVE_LCD_COLOR
|
||||
p_jpeg->last_dc_val[ci] += s;
|
||||
/* output it (assumes zag[0] = 0) */
|
||||
block[0] = MULTIPLY16(p_jpeg->last_dc_val[ci],
|
||||
p_jpeg->quanttable[!!ci][0]);
|
||||
block[0] = MULTIPLY16(p_jpeg->last_dc_val[ci], qt[0]);
|
||||
#else
|
||||
p_jpeg->last_dc_val += s;
|
||||
/* output it (assumes zag[0] = 0) */
|
||||
block[0] = MULTIPLY16(p_jpeg->last_dc_val,
|
||||
p_jpeg->quanttable[0][0]);
|
||||
block[0] = MULTIPLY16(p_jpeg->last_dc_val, qt[0]);
|
||||
#endif
|
||||
/* coefficient buffer must be cleared */
|
||||
MEMSET(block+1, 0, p_jpeg->zero_need[!!ci] * sizeof(int));
|
||||
|
|
@ -1877,7 +1916,7 @@ static struct img_part *store_row_jpeg(void *jpeg_args)
|
|||
goto skip_rest;
|
||||
r = get_bits(p_jpeg, s);
|
||||
r = HUFF_EXTEND(r, s);
|
||||
r = MULTIPLY16(r, p_jpeg->quanttable[!!ci][k]);
|
||||
r = MULTIPLY16(r, qt[k]);
|
||||
#ifdef JPEG_IDCT_TRANSPOSE
|
||||
block[zag[transpose ? k : k + 64]] = r ;
|
||||
#else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue