diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/jpeg.c | 233 |
1 files changed, 222 insertions, 11 deletions
diff --git a/apps/plugins/jpeg.c b/apps/plugins/jpeg.c index e24c048ae8..408f5d1ea1 100644 --- a/apps/plugins/jpeg.c +++ b/apps/plugins/jpeg.c | |||
@@ -669,7 +669,7 @@ struct jpeg | |||
669 | int x_phys, y_phys; /* physical size, block aligned */ | 669 | int x_phys, y_phys; /* physical size, block aligned */ |
670 | int x_mbl; /* x dimension of MBL */ | 670 | int x_mbl; /* x dimension of MBL */ |
671 | int y_mbl; /* y dimension of MBL */ | 671 | int y_mbl; /* y dimension of MBL */ |
672 | int blocks; /* blocks per MBL */ | 672 | int blocks; /* blocks per MB */ |
673 | int restart_interval; /* number of MCUs between RSTm markers */ | 673 | int restart_interval; /* number of MCUs between RSTm markers */ |
674 | int store_pos[4]; /* for Y block ordering */ | 674 | int store_pos[4]; /* for Y block ordering */ |
675 | 675 | ||
@@ -688,6 +688,8 @@ struct jpeg | |||
688 | 688 | ||
689 | int mcu_membership[6]; /* info per block */ | 689 | int mcu_membership[6]; /* info per block */ |
690 | int tab_membership[6]; | 690 | int tab_membership[6]; |
691 | int subsample_x[3]; /* info per component */ | ||
692 | int subsample_y[3]; | ||
691 | }; | 693 | }; |
692 | 694 | ||
693 | 695 | ||
@@ -1126,14 +1128,20 @@ void build_lut(struct jpeg* p_jpeg) | |||
1126 | p_jpeg->x_phys = p_jpeg->x_mbl * 16; | 1128 | p_jpeg->x_phys = p_jpeg->x_mbl * 16; |
1127 | p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; | 1129 | p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; |
1128 | p_jpeg->y_phys = p_jpeg->y_mbl * 8; | 1130 | p_jpeg->y_phys = p_jpeg->y_mbl * 8; |
1129 | p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=2, V=3 */ | 1131 | p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */ |
1130 | p_jpeg->mcu_membership[1] = 0; | 1132 | p_jpeg->mcu_membership[1] = 0; |
1131 | p_jpeg->mcu_membership[2] = 2; | 1133 | p_jpeg->mcu_membership[2] = 1; |
1132 | p_jpeg->mcu_membership[3] = 3; | 1134 | p_jpeg->mcu_membership[3] = 2; |
1133 | p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ | 1135 | p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ |
1134 | p_jpeg->tab_membership[1] = 0; | 1136 | p_jpeg->tab_membership[1] = 0; |
1135 | p_jpeg->tab_membership[2] = 1; | 1137 | p_jpeg->tab_membership[2] = 1; |
1136 | p_jpeg->tab_membership[3] = 1; | 1138 | p_jpeg->tab_membership[3] = 1; |
1139 | p_jpeg->subsample_x[0] = 1; | ||
1140 | p_jpeg->subsample_x[1] = 2; | ||
1141 | p_jpeg->subsample_x[2] = 2; | ||
1142 | p_jpeg->subsample_y[0] = 1; | ||
1143 | p_jpeg->subsample_y[1] = 1; | ||
1144 | p_jpeg->subsample_y[2] = 1; | ||
1137 | } | 1145 | } |
1138 | if (p_jpeg->frameheader[0].horizontal_sampling == 1 | 1146 | if (p_jpeg->frameheader[0].horizontal_sampling == 1 |
1139 | && p_jpeg->frameheader[0].vertical_sampling == 2) | 1147 | && p_jpeg->frameheader[0].vertical_sampling == 2) |
@@ -1145,14 +1153,20 @@ void build_lut(struct jpeg* p_jpeg) | |||
1145 | p_jpeg->x_phys = p_jpeg->x_mbl * 8; | 1153 | p_jpeg->x_phys = p_jpeg->x_mbl * 8; |
1146 | p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16; | 1154 | p_jpeg->y_mbl = (p_jpeg->y_size+15) / 16; |
1147 | p_jpeg->y_phys = p_jpeg->y_mbl * 16; | 1155 | p_jpeg->y_phys = p_jpeg->y_mbl * 16; |
1148 | p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=2, V=3 */ | 1156 | p_jpeg->mcu_membership[0] = 0; /* Y1=Y2=0, U=1, V=2 */ |
1149 | p_jpeg->mcu_membership[1] = 0; | 1157 | p_jpeg->mcu_membership[1] = 0; |
1150 | p_jpeg->mcu_membership[2] = 2; | 1158 | p_jpeg->mcu_membership[2] = 1; |
1151 | p_jpeg->mcu_membership[3] = 3; | 1159 | p_jpeg->mcu_membership[3] = 2; |
1152 | p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ | 1160 | p_jpeg->tab_membership[0] = 0; /* DC, DC, AC, AC */ |
1153 | p_jpeg->tab_membership[1] = 0; | 1161 | p_jpeg->tab_membership[1] = 0; |
1154 | p_jpeg->tab_membership[2] = 1; | 1162 | p_jpeg->tab_membership[2] = 1; |
1155 | p_jpeg->tab_membership[3] = 1; | 1163 | p_jpeg->tab_membership[3] = 1; |
1164 | p_jpeg->subsample_x[0] = 1; | ||
1165 | p_jpeg->subsample_x[1] = 1; | ||
1166 | p_jpeg->subsample_x[2] = 1; | ||
1167 | p_jpeg->subsample_y[0] = 1; | ||
1168 | p_jpeg->subsample_y[1] = 2; | ||
1169 | p_jpeg->subsample_y[2] = 2; | ||
1156 | } | 1170 | } |
1157 | else if (p_jpeg->frameheader[0].horizontal_sampling == 2 | 1171 | else if (p_jpeg->frameheader[0].horizontal_sampling == 2 |
1158 | && p_jpeg->frameheader[0].vertical_sampling == 2) | 1172 | && p_jpeg->frameheader[0].vertical_sampling == 2) |
@@ -1166,14 +1180,20 @@ void build_lut(struct jpeg* p_jpeg) | |||
1166 | p_jpeg->mcu_membership[1] = 0; | 1180 | p_jpeg->mcu_membership[1] = 0; |
1167 | p_jpeg->mcu_membership[2] = 0; | 1181 | p_jpeg->mcu_membership[2] = 0; |
1168 | p_jpeg->mcu_membership[3] = 0; | 1182 | p_jpeg->mcu_membership[3] = 0; |
1169 | p_jpeg->mcu_membership[4] = 2; | 1183 | p_jpeg->mcu_membership[4] = 1; |
1170 | p_jpeg->mcu_membership[5] = 3; | 1184 | p_jpeg->mcu_membership[5] = 2; |
1171 | p_jpeg->tab_membership[0] = 0; | 1185 | p_jpeg->tab_membership[0] = 0; |
1172 | p_jpeg->tab_membership[1] = 0; | 1186 | p_jpeg->tab_membership[1] = 0; |
1173 | p_jpeg->tab_membership[2] = 0; | 1187 | p_jpeg->tab_membership[2] = 0; |
1174 | p_jpeg->tab_membership[3] = 0; | 1188 | p_jpeg->tab_membership[3] = 0; |
1175 | p_jpeg->tab_membership[4] = 1; | 1189 | p_jpeg->tab_membership[4] = 1; |
1176 | p_jpeg->tab_membership[5] = 1; | 1190 | p_jpeg->tab_membership[5] = 1; |
1191 | p_jpeg->subsample_x[0] = 1; | ||
1192 | p_jpeg->subsample_x[1] = 2; | ||
1193 | p_jpeg->subsample_x[2] = 2; | ||
1194 | p_jpeg->subsample_y[0] = 1; | ||
1195 | p_jpeg->subsample_y[1] = 2; | ||
1196 | p_jpeg->subsample_y[2] = 2; | ||
1177 | } | 1197 | } |
1178 | else if (p_jpeg->frameheader[0].horizontal_sampling == 1 | 1198 | else if (p_jpeg->frameheader[0].horizontal_sampling == 1 |
1179 | && p_jpeg->frameheader[0].vertical_sampling == 1) | 1199 | && p_jpeg->frameheader[0].vertical_sampling == 1) |
@@ -1184,11 +1204,21 @@ void build_lut(struct jpeg* p_jpeg) | |||
1184 | p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; | 1204 | p_jpeg->y_mbl = (p_jpeg->y_size+7) / 8; |
1185 | p_jpeg->y_phys = p_jpeg->y_mbl * 8; | 1205 | p_jpeg->y_phys = p_jpeg->y_mbl * 8; |
1186 | p_jpeg->mcu_membership[0] = 0; | 1206 | p_jpeg->mcu_membership[0] = 0; |
1187 | p_jpeg->mcu_membership[1] = 2; | 1207 | p_jpeg->mcu_membership[1] = 1; |
1188 | p_jpeg->mcu_membership[2] = 3; | 1208 | p_jpeg->mcu_membership[2] = 2; |
1189 | p_jpeg->tab_membership[0] = 0; | 1209 | p_jpeg->tab_membership[0] = 0; |
1190 | p_jpeg->tab_membership[1] = 1; | 1210 | p_jpeg->tab_membership[1] = 1; |
1191 | p_jpeg->tab_membership[2] = 1; | 1211 | p_jpeg->tab_membership[2] = 1; |
1212 | p_jpeg->subsample_x[0] = 1; | ||
1213 | p_jpeg->subsample_x[1] = 1; | ||
1214 | p_jpeg->subsample_x[2] = 1; | ||
1215 | p_jpeg->subsample_y[0] = 1; | ||
1216 | p_jpeg->subsample_y[1] = 1; | ||
1217 | p_jpeg->subsample_y[2] = 1; | ||
1218 | } | ||
1219 | else | ||
1220 | { | ||
1221 | // error | ||
1192 | } | 1222 | } |
1193 | 1223 | ||
1194 | } | 1224 | } |
@@ -1523,6 +1553,187 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel, int downscale, | |||
1523 | } | 1553 | } |
1524 | 1554 | ||
1525 | 1555 | ||
1556 | #ifdef HAVE_LCD_COLOR | ||
1557 | |||
1558 | /* JPEG decoder variant for YUV decoding, into 3 different planes */ | ||
1559 | /* Note: it keeps the original color subsampling, even if resized. */ | ||
1560 | int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | ||
1561 | int downscale, void (*pf_progress)(int current, int total)) | ||
1562 | { | ||
1563 | struct bitstream bs; /* bitstream "object" */ | ||
1564 | static int block[64]; /* decoded DCT coefficients */ | ||
1565 | |||
1566 | int width, height; | ||
1567 | int skip_line[3]; /* bytes from one line to the next (skip_line) */ | ||
1568 | int skip_strip[3], skip_mcu[3]; /* bytes to next DCT row / column */ | ||
1569 | |||
1570 | int i, x, y; /* loop counter */ | ||
1571 | |||
1572 | unsigned char* p_line[3] = {p_pixel[0], p_pixel[1], p_pixel[2]}; | ||
1573 | unsigned char* p_byte[3]; /* bitmap pointer */ | ||
1574 | |||
1575 | void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */ | ||
1576 | int k_need; /* AC coefficients needed up to here */ | ||
1577 | int zero_need; /* init the block with this many zeros */ | ||
1578 | |||
1579 | int last_dc_val[3] = {0, 0, 0}; // or 128 for chroma? | ||
1580 | int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */ | ||
1581 | int restart = p_jpeg->restart_interval; /* MCUs until restart marker */ | ||
1582 | |||
1583 | /* pick the IDCT we want, determine how to work with coefs */ | ||
1584 | if (downscale == 1) | ||
1585 | { | ||
1586 | pf_idct = idct8x8; | ||
1587 | k_need = 64; /* all */ | ||
1588 | zero_need = 63; /* all */ | ||
1589 | } | ||
1590 | else if (downscale == 2) | ||
1591 | { | ||
1592 | pf_idct = idct4x4; | ||
1593 | k_need = 25; /* this far in zig-zag to cover 4*4 */ | ||
1594 | zero_need = 27; /* clear this far in linear order */ | ||
1595 | } | ||
1596 | else if (downscale == 4) | ||
1597 | { | ||
1598 | pf_idct = idct2x2; | ||
1599 | k_need = 5; /* this far in zig-zag to cover 2*2 */ | ||
1600 | zero_need = 9; /* clear this far in linear order */ | ||
1601 | } | ||
1602 | else if (downscale == 8) | ||
1603 | { | ||
1604 | pf_idct = idct1x1; | ||
1605 | k_need = 0; /* no AC, not needed */ | ||
1606 | zero_need = 0; /* no AC, not needed */ | ||
1607 | } | ||
1608 | else return -1; /* not supported */ | ||
1609 | |||
1610 | /* init bitstream, fake a restart to make it start */ | ||
1611 | bs.next_input_byte = p_jpeg->p_entropy_data; | ||
1612 | bs.bits_left = 0; | ||
1613 | bs.input_end = p_jpeg->p_entropy_end; | ||
1614 | |||
1615 | width = p_jpeg->x_phys / downscale; | ||
1616 | height = p_jpeg->y_phys / downscale; | ||
1617 | for (i=0; i<3; i++) /* calculate some strides */ | ||
1618 | { | ||
1619 | skip_line[i] = width / p_jpeg->subsample_x[i]; | ||
1620 | skip_strip[i] = skip_line[i] | ||
1621 | * (height / p_jpeg->y_mbl) / p_jpeg->subsample_y[i]; | ||
1622 | skip_mcu[i] = width/p_jpeg->x_mbl / p_jpeg->subsample_x[i]; | ||
1623 | } | ||
1624 | |||
1625 | /* prepare offsets about where to store the different blocks */ | ||
1626 | store_offs[p_jpeg->store_pos[0]] = 0; | ||
1627 | store_offs[p_jpeg->store_pos[1]] = 8 / downscale; /* to the right */ | ||
1628 | store_offs[p_jpeg->store_pos[2]] = width * 8 / downscale; /* below */ | ||
1629 | store_offs[p_jpeg->store_pos[3]] = store_offs[1] + store_offs[2]; /* r+b */ | ||
1630 | |||
1631 | for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++) | ||
1632 | { | ||
1633 | for (i=0; i<3; i++) // scan line init | ||
1634 | { | ||
1635 | p_byte[i] = p_line[i]; | ||
1636 | p_line[i] += skip_strip[i]; | ||
1637 | } | ||
1638 | for (x=0; x<p_jpeg->x_mbl; x++) | ||
1639 | { | ||
1640 | int blkn; | ||
1641 | |||
1642 | /* Outer loop handles each block in the MCU */ | ||
1643 | for (blkn = 0; blkn < p_jpeg->blocks; blkn++) | ||
1644 | { /* Decode a single block's worth of coefficients */ | ||
1645 | int k = 1; /* coefficient index */ | ||
1646 | int s, r; /* huffman values */ | ||
1647 | int ci = p_jpeg->mcu_membership[blkn]; /* component index */ | ||
1648 | int ti = p_jpeg->tab_membership[blkn]; /* table index */ | ||
1649 | struct derived_tbl* dctbl = &p_jpeg->dc_derived_tbls[ti]; | ||
1650 | struct derived_tbl* actbl = &p_jpeg->ac_derived_tbls[ti]; | ||
1651 | |||
1652 | /* Section F.2.2.1: decode the DC coefficient difference */ | ||
1653 | s = huff_decode_dc(&bs, dctbl); | ||
1654 | |||
1655 | last_dc_val[ci] += s; | ||
1656 | block[0] = last_dc_val[ci]; /* output it (assumes zag[0] = 0) */ | ||
1657 | |||
1658 | /* coefficient buffer must be cleared */ | ||
1659 | MEMSET(block+1, 0, zero_need*sizeof(block[0])); | ||
1660 | |||
1661 | /* Section F.2.2.2: decode the AC coefficients */ | ||
1662 | for (; k < k_need; k++) | ||
1663 | { | ||
1664 | s = huff_decode_ac(&bs, actbl); | ||
1665 | r = s >> 4; | ||
1666 | s &= 15; | ||
1667 | |||
1668 | if (s) | ||
1669 | { | ||
1670 | k += r; | ||
1671 | check_bit_buffer(&bs, s); | ||
1672 | r = get_bits(&bs, s); | ||
1673 | block[zag[k]] = HUFF_EXTEND(r, s); | ||
1674 | } | ||
1675 | else | ||
1676 | { | ||
1677 | if (r != 15) | ||
1678 | { | ||
1679 | k = 64; | ||
1680 | break; | ||
1681 | } | ||
1682 | k += r; | ||
1683 | } | ||
1684 | } /* for k */ | ||
1685 | /* In this path we just discard the values */ | ||
1686 | for (; k < 64; k++) | ||
1687 | { | ||
1688 | s = huff_decode_ac(&bs, actbl); | ||
1689 | r = s >> 4; | ||
1690 | s &= 15; | ||
1691 | |||
1692 | if (s) | ||
1693 | { | ||
1694 | k += r; | ||
1695 | check_bit_buffer(&bs, s); | ||
1696 | drop_bits(&bs, s); | ||
1697 | } | ||
1698 | else | ||
1699 | { | ||
1700 | if (r != 15) | ||
1701 | break; | ||
1702 | k += r; | ||
1703 | } | ||
1704 | } /* for k */ | ||
1705 | |||
1706 | if (ci == 0) | ||
1707 | { /* Y component needs to bother about block store */ | ||
1708 | pf_idct(p_byte[0]+store_offs[blkn], block, | ||
1709 | p_jpeg->qt_idct[ti], skip_line[0]); | ||
1710 | } | ||
1711 | else | ||
1712 | { /* chroma */ | ||
1713 | pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti], | ||
1714 | skip_line[ci]); | ||
1715 | } | ||
1716 | } /* for blkn */ | ||
1717 | p_byte[0] += skip_mcu[0]; // unrolled for (i=0; i<3; i++) loop | ||
1718 | p_byte[1] += skip_mcu[1]; | ||
1719 | p_byte[2] += skip_mcu[2]; | ||
1720 | if (p_jpeg->restart_interval && --restart == 0) | ||
1721 | { /* if a restart marker is due: */ | ||
1722 | restart = p_jpeg->restart_interval; /* count again */ | ||
1723 | search_restart(&bs); /* align the bitstream */ | ||
1724 | last_dc_val[0] = last_dc_val[1] = | ||
1725 | last_dc_val[2] = 0; /* reset decoder */ | ||
1726 | } | ||
1727 | } /* for x */ | ||
1728 | if (pf_progress != NULL) | ||
1729 | pf_progress(y, p_jpeg->y_mbl-1); /* notify about decoding progress */ | ||
1730 | } /* for y */ | ||
1731 | |||
1732 | return 0; /* success */ | ||
1733 | } | ||
1734 | |||
1735 | #endif /* #ifdef HAVE_LCD_COLOR */ | ||
1736 | |||
1526 | /**************** end JPEG code ********************/ | 1737 | /**************** end JPEG code ********************/ |
1527 | 1738 | ||
1528 | 1739 | ||