diff options
author | Jens Arnold <amiconn@rockbox.org> | 2006-02-17 16:55:23 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2006-02-17 16:55:23 +0000 |
commit | 41f1ab2710d8a3f06630491c80f7c98469f4723d (patch) | |
tree | 882be0fbda009127a7c940aa9d28b188fd9679fd /apps | |
parent | 9131c4a326b7c6b0cd8905c5bfb1f0f62648bf29 (diff) | |
download | rockbox-41f1ab2710d8a3f06630491c80f7c98469f4723d.tar.gz rockbox-41f1ab2710d8a3f06630491c80f7c98469f4723d.zip |
Colour JPEG display on colour targets.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8715 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/jpeg.c | 515 |
1 files changed, 374 insertions, 141 deletions
diff --git a/apps/plugins/jpeg.c b/apps/plugins/jpeg.c index 408f5d1ea1..28c7aebbe8 100644 --- a/apps/plugins/jpeg.c +++ b/apps/plugins/jpeg.c | |||
@@ -1389,26 +1389,30 @@ INLINE int huff_decode_ac(struct bitstream* bs, struct derived_tbl* tbl) | |||
1389 | } | 1389 | } |
1390 | 1390 | ||
1391 | 1391 | ||
1392 | /* a JPEG decoder specialized in decoding only the luminance (b&w) */ | 1392 | #ifdef HAVE_LCD_COLOR |
1393 | int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel, int downscale, | 1393 | |
1394 | void (*pf_progress)(int current, int total)) | 1394 | /* JPEG decoder variant for YUV decoding, into 3 different planes */ |
1395 | /* Note: it keeps the original color subsampling, even if resized. */ | ||
1396 | int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | ||
1397 | int downscale, void (*pf_progress)(int current, int total)) | ||
1395 | { | 1398 | { |
1396 | struct bitstream bs; /* bitstream "object" */ | 1399 | struct bitstream bs; /* bitstream "object" */ |
1397 | static int block[64]; /* decoded DCT coefficients */ | 1400 | static int block[64]; /* decoded DCT coefficients */ |
1398 | 1401 | ||
1399 | int width, height; | 1402 | int width, height; |
1400 | int skip_line; /* bytes from one line to the next (skip_line) */ | 1403 | int skip_line[3]; /* bytes from one line to the next (skip_line) */ |
1401 | int skip_strip, skip_mcu; /* bytes to next DCT row / column */ | 1404 | int skip_strip[3], skip_mcu[3]; /* bytes to next DCT row / column */ |
1402 | 1405 | ||
1403 | int x, y; /* loop counter */ | 1406 | int i, x, y; /* loop counter */ |
1404 | 1407 | ||
1405 | unsigned char* p_byte; /* bitmap pointer */ | 1408 | unsigned char* p_line[3] = {p_pixel[0], p_pixel[1], p_pixel[2]}; |
1409 | unsigned char* p_byte[3]; /* bitmap pointer */ | ||
1406 | 1410 | ||
1407 | void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */ | 1411 | void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */ |
1408 | int k_need; /* AC coefficients needed up to here */ | 1412 | int k_need; /* AC coefficients needed up to here */ |
1409 | int zero_need; /* init the block with this many zeros */ | 1413 | int zero_need; /* init the block with this many zeros */ |
1410 | 1414 | ||
1411 | int last_dc_val = 0; | 1415 | int last_dc_val[3] = {0, 0, 0}; // or 128 for chroma? |
1412 | int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */ | 1416 | int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */ |
1413 | int restart = p_jpeg->restart_interval; /* MCUs until restart marker */ | 1417 | int restart = p_jpeg->restart_interval; /* MCUs until restart marker */ |
1414 | 1418 | ||
@@ -1446,9 +1450,13 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel, int downscale, | |||
1446 | 1450 | ||
1447 | width = p_jpeg->x_phys / downscale; | 1451 | width = p_jpeg->x_phys / downscale; |
1448 | height = p_jpeg->y_phys / downscale; | 1452 | height = p_jpeg->y_phys / downscale; |
1449 | skip_line = width; | 1453 | for (i=0; i<3; i++) /* calculate some strides */ |
1450 | skip_strip = skip_line * (height / p_jpeg->y_mbl); | 1454 | { |
1451 | skip_mcu = (width/p_jpeg->x_mbl); | 1455 | skip_line[i] = width / p_jpeg->subsample_x[i]; |
1456 | skip_strip[i] = skip_line[i] | ||
1457 | * (height / p_jpeg->y_mbl) / p_jpeg->subsample_y[i]; | ||
1458 | skip_mcu[i] = width/p_jpeg->x_mbl / p_jpeg->subsample_x[i]; | ||
1459 | } | ||
1452 | 1460 | ||
1453 | /* prepare offsets about where to store the different blocks */ | 1461 | /* prepare offsets about where to store the different blocks */ |
1454 | store_offs[p_jpeg->store_pos[0]] = 0; | 1462 | store_offs[p_jpeg->store_pos[0]] = 0; |
@@ -1458,8 +1466,11 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel, int downscale, | |||
1458 | 1466 | ||
1459 | for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++) | 1467 | for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++) |
1460 | { | 1468 | { |
1461 | p_byte = p_pixel; | 1469 | for (i=0; i<3; i++) // scan line init |
1462 | p_pixel += skip_strip; | 1470 | { |
1471 | p_byte[i] = p_line[i]; | ||
1472 | p_line[i] += skip_strip[i]; | ||
1473 | } | ||
1463 | for (x=0; x<p_jpeg->x_mbl; x++) | 1474 | for (x=0; x<p_jpeg->x_mbl; x++) |
1464 | { | 1475 | { |
1465 | int blkn; | 1476 | int blkn; |
@@ -1477,39 +1488,36 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel, int downscale, | |||
1477 | /* Section F.2.2.1: decode the DC coefficient difference */ | 1488 | /* Section F.2.2.1: decode the DC coefficient difference */ |
1478 | s = huff_decode_dc(&bs, dctbl); | 1489 | s = huff_decode_dc(&bs, dctbl); |
1479 | 1490 | ||
1480 | if (ci == 0) /* only for Y component */ | 1491 | last_dc_val[ci] += s; |
1481 | { | 1492 | block[0] = last_dc_val[ci]; /* output it (assumes zag[0] = 0) */ |
1482 | last_dc_val += s; | ||
1483 | block[0] = last_dc_val; /* output it (assumes zag[0] = 0) */ | ||
1484 | 1493 | ||
1485 | /* coefficient buffer must be cleared */ | 1494 | /* coefficient buffer must be cleared */ |
1486 | MEMSET(block+1, 0, zero_need*sizeof(block[0])); | 1495 | MEMSET(block+1, 0, zero_need*sizeof(block[0])); |
1487 | 1496 | ||
1488 | /* Section F.2.2.2: decode the AC coefficients */ | 1497 | /* Section F.2.2.2: decode the AC coefficients */ |
1489 | for (; k < k_need; k++) | 1498 | for (; k < k_need; k++) |
1490 | { | 1499 | { |
1491 | s = huff_decode_ac(&bs, actbl); | 1500 | s = huff_decode_ac(&bs, actbl); |
1492 | r = s >> 4; | 1501 | r = s >> 4; |
1493 | s &= 15; | 1502 | s &= 15; |
1494 | 1503 | ||
1495 | if (s) | 1504 | if (s) |
1496 | { | 1505 | { |
1497 | k += r; | 1506 | k += r; |
1498 | check_bit_buffer(&bs, s); | 1507 | check_bit_buffer(&bs, s); |
1499 | r = get_bits(&bs, s); | 1508 | r = get_bits(&bs, s); |
1500 | block[zag[k]] = HUFF_EXTEND(r, s); | 1509 | block[zag[k]] = HUFF_EXTEND(r, s); |
1501 | } | 1510 | } |
1502 | else | 1511 | else |
1512 | { | ||
1513 | if (r != 15) | ||
1503 | { | 1514 | { |
1504 | if (r != 15) | 1515 | k = 64; |
1505 | { | 1516 | break; |
1506 | k = 64; | ||
1507 | break; | ||
1508 | } | ||
1509 | k += r; | ||
1510 | } | 1517 | } |
1511 | } /* for k */ | 1518 | k += r; |
1512 | } | 1519 | } |
1520 | } /* for k */ | ||
1513 | /* In this path we just discard the values */ | 1521 | /* In this path we just discard the values */ |
1514 | for (; k < 64; k++) | 1522 | for (; k < 64; k++) |
1515 | { | 1523 | { |
@@ -1532,17 +1540,25 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel, int downscale, | |||
1532 | } /* for k */ | 1540 | } /* for k */ |
1533 | 1541 | ||
1534 | if (ci == 0) | 1542 | if (ci == 0) |
1535 | { /* only for Y component */ | 1543 | { /* Y component needs to bother about block store */ |
1536 | pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti], | 1544 | pf_idct(p_byte[0]+store_offs[blkn], block, |
1537 | skip_line); | 1545 | p_jpeg->qt_idct[ti], skip_line[0]); |
1546 | } | ||
1547 | else | ||
1548 | { /* chroma */ | ||
1549 | pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti], | ||
1550 | skip_line[ci]); | ||
1538 | } | 1551 | } |
1539 | } /* for blkn */ | 1552 | } /* for blkn */ |
1540 | p_byte += skip_mcu; | 1553 | p_byte[0] += skip_mcu[0]; // unrolled for (i=0; i<3; i++) loop |
1554 | p_byte[1] += skip_mcu[1]; | ||
1555 | p_byte[2] += skip_mcu[2]; | ||
1541 | if (p_jpeg->restart_interval && --restart == 0) | 1556 | if (p_jpeg->restart_interval && --restart == 0) |
1542 | { /* if a restart marker is due: */ | 1557 | { /* if a restart marker is due: */ |
1543 | restart = p_jpeg->restart_interval; /* count again */ | 1558 | restart = p_jpeg->restart_interval; /* count again */ |
1544 | search_restart(&bs); /* align the bitstream */ | 1559 | search_restart(&bs); /* align the bitstream */ |
1545 | last_dc_val = 0; /* reset decoder */ | 1560 | last_dc_val[0] = last_dc_val[1] = |
1561 | last_dc_val[2] = 0; /* reset decoder */ | ||
1546 | } | 1562 | } |
1547 | } /* for x */ | 1563 | } /* for x */ |
1548 | if (pf_progress != NULL) | 1564 | if (pf_progress != NULL) |
@@ -1551,32 +1567,29 @@ int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel, int downscale, | |||
1551 | 1567 | ||
1552 | return 0; /* success */ | 1568 | return 0; /* success */ |
1553 | } | 1569 | } |
1570 | #else /* !HAVE_LCD_COLOR */ | ||
1554 | 1571 | ||
1555 | 1572 | /* a JPEG decoder specialized in decoding only the luminance (b&w) */ | |
1556 | #ifdef HAVE_LCD_COLOR | 1573 | int jpeg_decode(struct jpeg* p_jpeg, unsigned char* p_pixel[1], int downscale, |
1557 | 1574 | void (*pf_progress)(int current, int total)) | |
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 | { | 1575 | { |
1563 | struct bitstream bs; /* bitstream "object" */ | 1576 | struct bitstream bs; /* bitstream "object" */ |
1564 | static int block[64]; /* decoded DCT coefficients */ | 1577 | static int block[64]; /* decoded DCT coefficients */ |
1565 | 1578 | ||
1566 | int width, height; | 1579 | int width, height; |
1567 | int skip_line[3]; /* bytes from one line to the next (skip_line) */ | 1580 | int skip_line; /* bytes from one line to the next (skip_line) */ |
1568 | int skip_strip[3], skip_mcu[3]; /* bytes to next DCT row / column */ | 1581 | int skip_strip, skip_mcu; /* bytes to next DCT row / column */ |
1569 | 1582 | ||
1570 | int i, x, y; /* loop counter */ | 1583 | int x, y; /* loop counter */ |
1571 | 1584 | ||
1572 | unsigned char* p_line[3] = {p_pixel[0], p_pixel[1], p_pixel[2]}; | 1585 | unsigned char* p_line = p_pixel[0]; |
1573 | unsigned char* p_byte[3]; /* bitmap pointer */ | 1586 | unsigned char* p_byte; /* bitmap pointer */ |
1574 | 1587 | ||
1575 | void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */ | 1588 | void (*pf_idct)(unsigned char*, int*, int*, int); /* selected IDCT */ |
1576 | int k_need; /* AC coefficients needed up to here */ | 1589 | int k_need; /* AC coefficients needed up to here */ |
1577 | int zero_need; /* init the block with this many zeros */ | 1590 | int zero_need; /* init the block with this many zeros */ |
1578 | 1591 | ||
1579 | int last_dc_val[3] = {0, 0, 0}; // or 128 for chroma? | 1592 | int last_dc_val = 0; |
1580 | int store_offs[4]; /* memory offsets: order of Y11 Y12 Y21 Y22 U V */ | 1593 | 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 */ | 1594 | int restart = p_jpeg->restart_interval; /* MCUs until restart marker */ |
1582 | 1595 | ||
@@ -1614,13 +1627,9 @@ int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | |||
1614 | 1627 | ||
1615 | width = p_jpeg->x_phys / downscale; | 1628 | width = p_jpeg->x_phys / downscale; |
1616 | height = p_jpeg->y_phys / downscale; | 1629 | height = p_jpeg->y_phys / downscale; |
1617 | for (i=0; i<3; i++) /* calculate some strides */ | 1630 | skip_line = width; |
1618 | { | 1631 | skip_strip = skip_line * (height / p_jpeg->y_mbl); |
1619 | skip_line[i] = width / p_jpeg->subsample_x[i]; | 1632 | skip_mcu = (width/p_jpeg->x_mbl); |
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 | 1633 | ||
1625 | /* prepare offsets about where to store the different blocks */ | 1634 | /* prepare offsets about where to store the different blocks */ |
1626 | store_offs[p_jpeg->store_pos[0]] = 0; | 1635 | store_offs[p_jpeg->store_pos[0]] = 0; |
@@ -1630,11 +1639,8 @@ int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | |||
1630 | 1639 | ||
1631 | for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++) | 1640 | for(y=0; y<p_jpeg->y_mbl && bs.next_input_byte <= bs.input_end; y++) |
1632 | { | 1641 | { |
1633 | for (i=0; i<3; i++) // scan line init | 1642 | p_byte = p_line; |
1634 | { | 1643 | p_line += skip_strip; |
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++) | 1644 | for (x=0; x<p_jpeg->x_mbl; x++) |
1639 | { | 1645 | { |
1640 | int blkn; | 1646 | int blkn; |
@@ -1652,36 +1658,39 @@ int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | |||
1652 | /* Section F.2.2.1: decode the DC coefficient difference */ | 1658 | /* Section F.2.2.1: decode the DC coefficient difference */ |
1653 | s = huff_decode_dc(&bs, dctbl); | 1659 | s = huff_decode_dc(&bs, dctbl); |
1654 | 1660 | ||
1655 | last_dc_val[ci] += s; | 1661 | if (ci == 0) /* only for Y component */ |
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 | { | 1662 | { |
1664 | s = huff_decode_ac(&bs, actbl); | 1663 | last_dc_val += s; |
1665 | r = s >> 4; | 1664 | block[0] = last_dc_val; /* output it (assumes zag[0] = 0) */ |
1666 | s &= 15; | ||
1667 | 1665 | ||
1668 | if (s) | 1666 | /* coefficient buffer must be cleared */ |
1669 | { | 1667 | MEMSET(block+1, 0, zero_need*sizeof(block[0])); |
1670 | k += r; | 1668 | |
1671 | check_bit_buffer(&bs, s); | 1669 | /* Section F.2.2.2: decode the AC coefficients */ |
1672 | r = get_bits(&bs, s); | 1670 | for (; k < k_need; k++) |
1673 | block[zag[k]] = HUFF_EXTEND(r, s); | ||
1674 | } | ||
1675 | else | ||
1676 | { | 1671 | { |
1677 | if (r != 15) | 1672 | s = huff_decode_ac(&bs, actbl); |
1673 | r = s >> 4; | ||
1674 | s &= 15; | ||
1675 | |||
1676 | if (s) | ||
1678 | { | 1677 | { |
1679 | k = 64; | 1678 | k += r; |
1680 | break; | 1679 | check_bit_buffer(&bs, s); |
1680 | r = get_bits(&bs, s); | ||
1681 | block[zag[k]] = HUFF_EXTEND(r, s); | ||
1681 | } | 1682 | } |
1682 | k += r; | 1683 | else |
1683 | } | 1684 | { |
1684 | } /* for k */ | 1685 | if (r != 15) |
1686 | { | ||
1687 | k = 64; | ||
1688 | break; | ||
1689 | } | ||
1690 | k += r; | ||
1691 | } | ||
1692 | } /* for k */ | ||
1693 | } | ||
1685 | /* In this path we just discard the values */ | 1694 | /* In this path we just discard the values */ |
1686 | for (; k < 64; k++) | 1695 | for (; k < 64; k++) |
1687 | { | 1696 | { |
@@ -1704,25 +1713,17 @@ int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | |||
1704 | } /* for k */ | 1713 | } /* for k */ |
1705 | 1714 | ||
1706 | if (ci == 0) | 1715 | if (ci == 0) |
1707 | { /* Y component needs to bother about block store */ | 1716 | { /* only for Y component */ |
1708 | pf_idct(p_byte[0]+store_offs[blkn], block, | 1717 | pf_idct(p_byte+store_offs[blkn], block, p_jpeg->qt_idct[ti], |
1709 | p_jpeg->qt_idct[ti], skip_line[0]); | 1718 | skip_line); |
1710 | } | ||
1711 | else | ||
1712 | { /* chroma */ | ||
1713 | pf_idct(p_byte[ci], block, p_jpeg->qt_idct[ti], | ||
1714 | skip_line[ci]); | ||
1715 | } | 1719 | } |
1716 | } /* for blkn */ | 1720 | } /* for blkn */ |
1717 | p_byte[0] += skip_mcu[0]; // unrolled for (i=0; i<3; i++) loop | 1721 | p_byte += skip_mcu; |
1718 | p_byte[1] += skip_mcu[1]; | ||
1719 | p_byte[2] += skip_mcu[2]; | ||
1720 | if (p_jpeg->restart_interval && --restart == 0) | 1722 | if (p_jpeg->restart_interval && --restart == 0) |
1721 | { /* if a restart marker is due: */ | 1723 | { /* if a restart marker is due: */ |
1722 | restart = p_jpeg->restart_interval; /* count again */ | 1724 | restart = p_jpeg->restart_interval; /* count again */ |
1723 | search_restart(&bs); /* align the bitstream */ | 1725 | search_restart(&bs); /* align the bitstream */ |
1724 | last_dc_val[0] = last_dc_val[1] = | 1726 | last_dc_val = 0; /* reset decoder */ |
1725 | last_dc_val[2] = 0; /* reset decoder */ | ||
1726 | } | 1727 | } |
1727 | } /* for x */ | 1728 | } /* for x */ |
1728 | if (pf_progress != NULL) | 1729 | if (pf_progress != NULL) |
@@ -1731,8 +1732,7 @@ int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | |||
1731 | 1732 | ||
1732 | return 0; /* success */ | 1733 | return 0; /* success */ |
1733 | } | 1734 | } |
1734 | 1735 | #endif /* !HAVE_LCD_COLOR */ | |
1735 | #endif /* #ifdef HAVE_LCD_COLOR */ | ||
1736 | 1736 | ||
1737 | /**************** end JPEG code ********************/ | 1737 | /**************** end JPEG code ********************/ |
1738 | 1738 | ||
@@ -1745,7 +1745,12 @@ int jpeg_decode_color(struct jpeg* p_jpeg, unsigned char* p_pixel[3], | |||
1745 | 1745 | ||
1746 | struct t_disp | 1746 | struct t_disp |
1747 | { | 1747 | { |
1748 | unsigned char* bitmap; | 1748 | #ifdef HAVE_LCD_COLOR |
1749 | unsigned char* bitmap[3]; /* Y, Cr, Cb */ | ||
1750 | int csub_x, csub_y; | ||
1751 | #else | ||
1752 | unsigned char* bitmap[1]; /* Y only */ | ||
1753 | #endif | ||
1749 | int width; | 1754 | int width; |
1750 | int height; | 1755 | int height; |
1751 | int stride; | 1756 | int stride; |
@@ -1767,6 +1772,151 @@ int root_size; | |||
1767 | 1772 | ||
1768 | /************************* Implementation ***************************/ | 1773 | /************************* Implementation ***************************/ |
1769 | 1774 | ||
1775 | #ifdef HAVE_LCD_COLOR | ||
1776 | |||
1777 | #if (LCD_DEPTH == 16) && \ | ||
1778 | ((LCD_PIXELFORMAT == RGB565) || (LCD_PIXELFORMAT == RGB565SWAPPED)) | ||
1779 | #define RYFAC (31*257) | ||
1780 | #define GYFAC (63*257) | ||
1781 | #define BYFAC (31*257) | ||
1782 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | ||
1783 | #define GVFAC (-11563) /* 63 * 257 * -0.714136 */ | ||
1784 | #define GUFAC (-5572) /* 63 * 257 * -0.344136 */ | ||
1785 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | ||
1786 | #endif | ||
1787 | |||
1788 | /* Draw a partial YUV colour bitmap */ | ||
1789 | void yuv_bitmap_part(unsigned char *src[3], int csub_x, int csub_y, | ||
1790 | int src_x, int src_y, int stride, | ||
1791 | int x, int y, int width, int height) | ||
1792 | { | ||
1793 | fb_data *dst, *dst_end; | ||
1794 | |||
1795 | /* nothing to draw? */ | ||
1796 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
1797 | || (x + width <= 0) || (y + height <= 0)) | ||
1798 | return; | ||
1799 | |||
1800 | /* clipping */ | ||
1801 | if (x < 0) | ||
1802 | { | ||
1803 | width += x; | ||
1804 | src_x -= x; | ||
1805 | x = 0; | ||
1806 | } | ||
1807 | if (y < 0) | ||
1808 | { | ||
1809 | height += y; | ||
1810 | src_y -= y; | ||
1811 | y = 0; | ||
1812 | } | ||
1813 | if (x + width > LCD_WIDTH) | ||
1814 | width = LCD_WIDTH - x; | ||
1815 | if (y + height > LCD_HEIGHT) | ||
1816 | height = LCD_HEIGHT - y; | ||
1817 | |||
1818 | dst = rb->lcd_framebuffer + LCD_WIDTH * y + x; | ||
1819 | dst_end = dst + LCD_WIDTH * height; | ||
1820 | |||
1821 | do | ||
1822 | { | ||
1823 | fb_data *dst_row = dst; | ||
1824 | fb_data *row_end = dst_row + width; | ||
1825 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | ||
1826 | int y, u, v; | ||
1827 | int red, green, blue; | ||
1828 | unsigned rbits, gbits, bbits; | ||
1829 | |||
1830 | if (csub_y) /* colour */ | ||
1831 | { | ||
1832 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | ||
1833 | const unsigned char *usrc = src[1] + (stride/csub_x) * (src_y/csub_y) | ||
1834 | + (src_x/csub_x); | ||
1835 | const unsigned char *vsrc = src[2] + (stride/csub_x) * (src_y/csub_y) | ||
1836 | + (src_x/csub_x); | ||
1837 | int xphase = src_x % csub_x; | ||
1838 | int rc, gc, bc; | ||
1839 | |||
1840 | u = *usrc++ - 128; | ||
1841 | v = *vsrc++ - 128; | ||
1842 | rc = RVFAC * v + 32639; | ||
1843 | gc = GVFAC * v + GUFAC * u + 32639; | ||
1844 | bc = BUFAC * u + 32639; | ||
1845 | |||
1846 | do | ||
1847 | { | ||
1848 | y = *ysrc++; | ||
1849 | red = RYFAC * y + rc; | ||
1850 | green = GYFAC * y + gc; | ||
1851 | blue = BYFAC * y + bc; | ||
1852 | |||
1853 | if ((unsigned)red > (RYFAC*255+32639)) | ||
1854 | { | ||
1855 | if (red < 0) | ||
1856 | red = 0; | ||
1857 | else | ||
1858 | red = (RYFAC*255+32639); | ||
1859 | } | ||
1860 | if ((unsigned)green > (GYFAC*255+32639)) | ||
1861 | { | ||
1862 | if (green < 0) | ||
1863 | green = 0; | ||
1864 | else | ||
1865 | green = (GYFAC*255+32639); | ||
1866 | } | ||
1867 | if ((unsigned)blue > (BYFAC*255+32639)) | ||
1868 | { | ||
1869 | if (blue < 0) | ||
1870 | blue = 0; | ||
1871 | else | ||
1872 | blue = (BYFAC*255+32639); | ||
1873 | } | ||
1874 | rbits = ((unsigned)red) >> 16 ; | ||
1875 | gbits = ((unsigned)green) >> 16 ; | ||
1876 | bbits = ((unsigned)blue) >> 16 ; | ||
1877 | #if LCD_PIXELFORMAT == RGB565 | ||
1878 | *dst_row++ = (rbits << 11) | (gbits << 5) | bbits; | ||
1879 | #elif LCD_PIXELFORMAT == RGB565SWAPPED | ||
1880 | *dst_row++ = swap16((rbits << 11) | (gbits << 5) | bbits); | ||
1881 | #endif | ||
1882 | |||
1883 | if (++xphase >= csub_x) | ||
1884 | { | ||
1885 | u = *usrc++ - 128; | ||
1886 | v = *vsrc++ - 128; | ||
1887 | rc = RVFAC * v + 32639; | ||
1888 | gc = GVFAC * v + GUFAC * u + 32639; | ||
1889 | bc = BUFAC * u + 32639; | ||
1890 | xphase = 0; | ||
1891 | } | ||
1892 | } | ||
1893 | while (dst_row < row_end); | ||
1894 | } | ||
1895 | else /* monochrome */ | ||
1896 | { | ||
1897 | do | ||
1898 | { | ||
1899 | y = *ysrc++; | ||
1900 | red = RYFAC * y + 32639; /* blue == red */ | ||
1901 | green = GYFAC * y + 32639; | ||
1902 | rbits = ((unsigned)red) >> 16; | ||
1903 | gbits = ((unsigned)green) >> 16; | ||
1904 | #if LCD_PIXELFORMAT == RGB565 | ||
1905 | *dst_row++ = (rbits << 11) | (gbits << 5) | rbits; | ||
1906 | #elif LCD_PIXELFORMAT == RGB565SWAPPED | ||
1907 | *dst_row++ = swap16((rbits << 11) | (gbits << 5) | rbits); | ||
1908 | #endif | ||
1909 | } | ||
1910 | while (dst_row < row_end); | ||
1911 | } | ||
1912 | |||
1913 | src_y++; | ||
1914 | dst += LCD_WIDTH; | ||
1915 | } | ||
1916 | while (dst < dst_end); | ||
1917 | } | ||
1918 | #endif | ||
1919 | |||
1770 | /* switch off overlay, for handling SYS_ events */ | 1920 | /* switch off overlay, for handling SYS_ events */ |
1771 | void cleanup(void *parameter) | 1921 | void cleanup(void *parameter) |
1772 | { | 1922 | { |
@@ -1806,10 +1956,18 @@ int scroll_bmp(struct t_disp* pdisp) | |||
1806 | { | 1956 | { |
1807 | MYXLCD(scroll_right)(move); /* scroll right */ | 1957 | MYXLCD(scroll_right)(move); /* scroll right */ |
1808 | pdisp->x -= move; | 1958 | pdisp->x -= move; |
1959 | #ifdef HAVE_LCD_COLOR | ||
1960 | yuv_bitmap_part( | ||
1961 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
1962 | pdisp->x, pdisp->y, pdisp->stride, | ||
1963 | 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
1964 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | ||
1965 | #else | ||
1809 | MYXLCD(gray_bitmap_part)( | 1966 | MYXLCD(gray_bitmap_part)( |
1810 | pdisp->bitmap, pdisp->x, pdisp->y, pdisp->stride, | 1967 | pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride, |
1811 | 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | 1968 | 0, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ |
1812 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | 1969 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ |
1970 | #endif | ||
1813 | MYLCD_UPDATE(); | 1971 | MYLCD_UPDATE(); |
1814 | } | 1972 | } |
1815 | break; | 1973 | break; |
@@ -1821,11 +1979,19 @@ int scroll_bmp(struct t_disp* pdisp) | |||
1821 | { | 1979 | { |
1822 | MYXLCD(scroll_left)(move); /* scroll left */ | 1980 | MYXLCD(scroll_left)(move); /* scroll left */ |
1823 | pdisp->x += move; | 1981 | pdisp->x += move; |
1982 | #ifdef HAVE_LCD_COLOR | ||
1983 | yuv_bitmap_part( | ||
1984 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
1985 | pdisp->x + LCD_WIDTH - move, pdisp->y, pdisp->stride, | ||
1986 | LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | ||
1987 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | ||
1988 | #else | ||
1824 | MYXLCD(gray_bitmap_part)( | 1989 | MYXLCD(gray_bitmap_part)( |
1825 | pdisp->bitmap, pdisp->x + LCD_WIDTH - move, | 1990 | pdisp->bitmap[0], pdisp->x + LCD_WIDTH - move, |
1826 | pdisp->y, pdisp->stride, | 1991 | pdisp->y, pdisp->stride, |
1827 | LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ | 1992 | LCD_WIDTH - move, MAX(0, (LCD_HEIGHT-pdisp->height)/2), /* x, y */ |
1828 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ | 1993 | move, MIN(LCD_HEIGHT, pdisp->height)); /* w, h */ |
1994 | #endif | ||
1829 | MYLCD_UPDATE(); | 1995 | MYLCD_UPDATE(); |
1830 | } | 1996 | } |
1831 | break; | 1997 | break; |
@@ -1837,10 +2003,18 @@ int scroll_bmp(struct t_disp* pdisp) | |||
1837 | { | 2003 | { |
1838 | MYXLCD(scroll_down)(move); /* scroll down */ | 2004 | MYXLCD(scroll_down)(move); /* scroll down */ |
1839 | pdisp->y -= move; | 2005 | pdisp->y -= move; |
2006 | #ifdef HAVE_LCD_COLOR | ||
2007 | yuv_bitmap_part( | ||
2008 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, | ||
2009 | pdisp->x, pdisp->y, pdisp->stride, | ||
2010 | MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */ | ||
2011 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | ||
2012 | #else | ||
1840 | MYXLCD(gray_bitmap_part)( | 2013 | MYXLCD(gray_bitmap_part)( |
1841 | pdisp->bitmap, pdisp->x, pdisp->y, pdisp->stride, | 2014 | pdisp->bitmap[0], pdisp->x, pdisp->y, pdisp->stride, |
1842 | MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */ | 2015 | MAX(0, (LCD_WIDTH-pdisp->width)/2), 0, /* x, y */ |
1843 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | 2016 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ |
2017 | #endif | ||
1844 | MYLCD_UPDATE(); | 2018 | MYLCD_UPDATE(); |
1845 | } | 2019 | } |
1846 | break; | 2020 | break; |
@@ -1852,11 +2026,19 @@ int scroll_bmp(struct t_disp* pdisp) | |||
1852 | { | 2026 | { |
1853 | MYXLCD(scroll_up)(move); /* scroll up */ | 2027 | MYXLCD(scroll_up)(move); /* scroll up */ |
1854 | pdisp->y += move; | 2028 | pdisp->y += move; |
2029 | #ifdef HAVE_LCD_COLOR | ||
2030 | yuv_bitmap_part( | ||
2031 | pdisp->bitmap, pdisp->csub_x, pdisp->csub_y, pdisp->x, | ||
2032 | pdisp->y + LCD_HEIGHT - move, pdisp->stride, | ||
2033 | MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */ | ||
2034 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | ||
2035 | #else | ||
1855 | MYXLCD(gray_bitmap_part)( | 2036 | MYXLCD(gray_bitmap_part)( |
1856 | pdisp->bitmap, pdisp->x, | 2037 | pdisp->bitmap[0], pdisp->x, |
1857 | pdisp->y + LCD_HEIGHT - move, pdisp->stride, | 2038 | pdisp->y + LCD_HEIGHT - move, pdisp->stride, |
1858 | MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */ | 2039 | MAX(0, (LCD_WIDTH-pdisp->width)/2), LCD_HEIGHT - move, /* x, y */ |
1859 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ | 2040 | MIN(LCD_WIDTH, pdisp->width), move); /* w, h */ |
2041 | #endif | ||
1860 | MYLCD_UPDATE(); | 2042 | MYLCD_UPDATE(); |
1861 | } | 2043 | } |
1862 | break; | 2044 | break; |
@@ -1927,35 +2109,50 @@ void align(unsigned char** ppbuf, int* plen, int align) | |||
1927 | *ppbuf = (unsigned char*)aligned; | 2109 | *ppbuf = (unsigned char*)aligned; |
1928 | } | 2110 | } |
1929 | 2111 | ||
2112 | int jpegmem(struct jpeg *p_jpg, int ds) | ||
2113 | { | ||
2114 | int size; | ||
2115 | |||
2116 | size = (p_jpg->x_phys/ds/p_jpg->subsample_x[0]) | ||
2117 | * (p_jpg->y_phys/ds/p_jpg->subsample_y[0]); | ||
2118 | #ifdef HAVE_LCD_COLOR | ||
2119 | if (p_jpg->blocks > 1) /* colour, add requirements for chroma */ | ||
2120 | { | ||
2121 | size += (p_jpg->x_phys/ds/p_jpg->subsample_x[1]) | ||
2122 | * (p_jpg->y_phys/ds/p_jpg->subsample_y[1]); | ||
2123 | size += (p_jpg->x_phys/ds/p_jpg->subsample_x[2]) | ||
2124 | * (p_jpg->y_phys/ds/p_jpg->subsample_y[2]); | ||
2125 | } | ||
2126 | #endif | ||
2127 | return size; | ||
2128 | } | ||
1930 | 2129 | ||
1931 | /* how far can we zoom in without running out of memory */ | 2130 | /* how far can we zoom in without running out of memory */ |
1932 | int min_downscale(int x, int y, int bufsize) | 2131 | int min_downscale(struct jpeg *p_jpg, int bufsize) |
1933 | { | 2132 | { |
1934 | int downscale = 8; | 2133 | int downscale = 8; |
1935 | 2134 | ||
1936 | if ((x/8) * (y/8) > bufsize) | 2135 | if (jpegmem(p_jpg, 8) > bufsize) |
1937 | return 0; /* error, too large, even 1:8 doesn't fit */ | 2136 | return 0; /* error, too large, even 1:8 doesn't fit */ |
1938 | 2137 | ||
1939 | while ((x*2/downscale) * (y*2/downscale) < bufsize | 2138 | while (downscale > 1 && jpegmem(p_jpg, downscale/2) <= bufsize) |
1940 | && downscale > 1) | ||
1941 | { | ||
1942 | downscale /= 2; | 2139 | downscale /= 2; |
1943 | } | 2140 | |
1944 | return downscale; | 2141 | return downscale; |
1945 | } | 2142 | } |
1946 | 2143 | ||
1947 | 2144 | ||
1948 | /* how far can we zoom out, to fit image into the LCD */ | 2145 | /* how far can we zoom out, to fit image into the LCD */ |
1949 | int max_downscale(int x, int y) | 2146 | int max_downscale(struct jpeg *p_jpg) |
1950 | { | 2147 | { |
1951 | int downscale = 1; | 2148 | int downscale = 1; |
1952 | 2149 | ||
1953 | while ((x/downscale > LCD_WIDTH || y/downscale > LCD_HEIGHT) | 2150 | while (downscale < 8 && (p_jpg->x_size > LCD_WIDTH*downscale |
1954 | && downscale < 8) | 2151 | || p_jpg->y_size > LCD_HEIGHT*downscale)) |
1955 | { | 2152 | { |
1956 | downscale *= 2; | 2153 | downscale *= 2; |
1957 | } | 2154 | } |
1958 | 2155 | ||
1959 | return downscale; | 2156 | return downscale; |
1960 | } | 2157 | } |
1961 | 2158 | ||
@@ -1970,7 +2167,7 @@ struct t_disp* get_image(struct jpeg* p_jpg, int ds) | |||
1970 | 2167 | ||
1971 | struct t_disp* p_disp = &disp[ds]; /* short cut */ | 2168 | struct t_disp* p_disp = &disp[ds]; /* short cut */ |
1972 | 2169 | ||
1973 | if (p_disp->bitmap != NULL) | 2170 | if (p_disp->bitmap[0] != NULL) |
1974 | { | 2171 | { |
1975 | return p_disp; /* we still have it */ | 2172 | return p_disp; /* we still have it */ |
1976 | } | 2173 | } |
@@ -1978,19 +2175,41 @@ struct t_disp* get_image(struct jpeg* p_jpg, int ds) | |||
1978 | /* assign image buffer */ | 2175 | /* assign image buffer */ |
1979 | 2176 | ||
1980 | /* physical size needed for decoding */ | 2177 | /* physical size needed for decoding */ |
1981 | size = (p_jpg->x_phys/ds) * (p_jpg->y_phys / ds); | 2178 | size = jpegmem(p_jpg, ds); |
1982 | if (buf_size <= size) | 2179 | if (buf_size <= size) |
1983 | { /* have to discard the current */ | 2180 | { /* have to discard the current */ |
1984 | int i; | 2181 | int i; |
1985 | for (i=1; i<=8; i++) | 2182 | for (i=1; i<=8; i++) |
1986 | disp[i].bitmap = NULL; /* invalidate all bitmaps */ | 2183 | disp[i].bitmap[0] = NULL; /* invalidate all bitmaps */ |
1987 | buf = buf_root; /* start again from the beginning of the buffer */ | 2184 | buf = buf_root; /* start again from the beginning of the buffer */ |
1988 | buf_size = root_size; | 2185 | buf_size = root_size; |
1989 | } | 2186 | } |
2187 | |||
2188 | #ifdef HAVE_LCD_COLOR | ||
2189 | if (p_jpg->blocks > 1) /* colour jpeg */ | ||
2190 | { | ||
2191 | int i; | ||
1990 | 2192 | ||
2193 | for (i = 1; i < 3; i++) | ||
2194 | { | ||
2195 | size = (p_jpg->x_phys / ds / p_jpg->subsample_x[i]) | ||
2196 | * (p_jpg->y_phys / ds / p_jpg->subsample_y[i]); | ||
2197 | p_disp->bitmap[i] = buf; | ||
2198 | buf += size; | ||
2199 | buf_size -= size; | ||
2200 | } | ||
2201 | p_disp->csub_x = p_jpg->subsample_x[1]; | ||
2202 | p_disp->csub_y = p_jpg->subsample_y[1]; | ||
2203 | } | ||
2204 | else | ||
2205 | { | ||
2206 | p_disp->csub_x = p_disp->csub_y = 0; | ||
2207 | p_disp->bitmap[1] = p_disp->bitmap[2] = buf; | ||
2208 | } | ||
2209 | #endif | ||
1991 | /* size may be less when decoded (if height is not block aligned) */ | 2210 | /* size may be less when decoded (if height is not block aligned) */ |
1992 | size = (p_jpg->x_phys/ds) * (p_jpg->y_size / ds); | 2211 | size = (p_jpg->x_phys/ds) * (p_jpg->y_size / ds); |
1993 | p_disp->bitmap = buf; | 2212 | p_disp->bitmap[0] = buf; |
1994 | buf += size; | 2213 | buf += size; |
1995 | buf_size -= size; | 2214 | buf_size -= size; |
1996 | 2215 | ||
@@ -2000,9 +2219,9 @@ struct t_disp* get_image(struct jpeg* p_jpg, int ds) | |||
2000 | rb->lcd_update(); | 2219 | rb->lcd_update(); |
2001 | 2220 | ||
2002 | /* update image properties */ | 2221 | /* update image properties */ |
2003 | p_disp->width = p_jpg->x_size/ds; | 2222 | p_disp->width = p_jpg->x_size / ds; |
2004 | p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */ | 2223 | p_disp->stride = p_jpg->x_phys / ds; /* use physical size for stride */ |
2005 | p_disp->height = p_jpg->y_size/ds; | 2224 | p_disp->height = p_jpg->y_size / ds; |
2006 | 2225 | ||
2007 | /* the actual decoding */ | 2226 | /* the actual decoding */ |
2008 | time = *rb->current_tick; | 2227 | time = *rb->current_tick; |
@@ -2106,7 +2325,7 @@ int plugin_main(char* filename) | |||
2106 | 2325 | ||
2107 | /* allocate JPEG buffer */ | 2326 | /* allocate JPEG buffer */ |
2108 | align(&buf, &buf_size, 2); /* 16 bit align */ | 2327 | align(&buf, &buf_size, 2); /* 16 bit align */ |
2109 | buf_jpeg = (unsigned char*)(((int)buf + 1) & ~1); | 2328 | buf_jpeg = buf; |
2110 | buf += filesize; | 2329 | buf += filesize; |
2111 | buf_size -= filesize; | 2330 | buf_size -= filesize; |
2112 | buf_root = buf; /* we can start the decompressed images behind it */ | 2331 | buf_root = buf; /* we can start the decompressed images behind it */ |
@@ -2117,6 +2336,12 @@ int plugin_main(char* filename) | |||
2117 | rb->close(fd); | 2336 | rb->close(fd); |
2118 | return PLUGIN_ERROR; | 2337 | return PLUGIN_ERROR; |
2119 | } | 2338 | } |
2339 | |||
2340 | #ifdef HAVE_LCD_COLOR | ||
2341 | rb->lcd_set_foreground(LCD_WHITE); | ||
2342 | rb->lcd_set_background(LCD_BLACK); | ||
2343 | rb->lcd_clear_display(); | ||
2344 | #endif | ||
2120 | 2345 | ||
2121 | rb->snprintf(print, sizeof(print), "loading %d bytes", filesize); | 2346 | rb->snprintf(print, sizeof(print), "loading %d bytes", filesize); |
2122 | rb->lcd_puts(0, 0, print); | 2347 | rb->lcd_puts(0, 0, print); |
@@ -2145,10 +2370,8 @@ int plugin_main(char* filename) | |||
2145 | rb->lcd_puts(0, 2, print); | 2370 | rb->lcd_puts(0, 2, print); |
2146 | rb->lcd_update(); | 2371 | rb->lcd_update(); |
2147 | 2372 | ||
2148 | /* check display constraint */ | 2373 | ds_max = max_downscale(&jpg); /* check display constraint */ |
2149 | ds_max = max_downscale(jpg.x_size, jpg.y_size); | 2374 | ds_min = min_downscale(&jpg, buf_size); /* check memory constraint */ |
2150 | /* check memory constraint */ | ||
2151 | ds_min = min_downscale(jpg.x_phys, jpg.y_phys, buf_size); | ||
2152 | if (ds_min == 0) | 2375 | if (ds_min == 0) |
2153 | { | 2376 | { |
2154 | rb->splash(HZ*2, true, "too large"); | 2377 | rb->splash(HZ*2, true, "too large"); |
@@ -2172,12 +2395,22 @@ int plugin_main(char* filename) | |||
2172 | rb->lcd_update(); | 2395 | rb->lcd_update(); |
2173 | 2396 | ||
2174 | MYLCD(clear_display)(); | 2397 | MYLCD(clear_display)(); |
2398 | #ifdef HAVE_LCD_COLOR | ||
2399 | yuv_bitmap_part( | ||
2400 | p_disp->bitmap, p_disp->csub_x, p_disp->csub_y, | ||
2401 | p_disp->x, p_disp->y, p_disp->stride, | ||
2402 | MAX(0, (LCD_WIDTH - p_disp->width) / 2), | ||
2403 | MAX(0, (LCD_HEIGHT - p_disp->height) / 2), | ||
2404 | MIN(LCD_WIDTH, p_disp->width), | ||
2405 | MIN(LCD_HEIGHT, p_disp->height)); | ||
2406 | #else | ||
2175 | MYXLCD(gray_bitmap_part)( | 2407 | MYXLCD(gray_bitmap_part)( |
2176 | p_disp->bitmap, p_disp->x, p_disp->y, p_disp->stride, | 2408 | p_disp->bitmap[0], p_disp->x, p_disp->y, p_disp->stride, |
2177 | MAX(0, (LCD_WIDTH - p_disp->width) / 2), | 2409 | MAX(0, (LCD_WIDTH - p_disp->width) / 2), |
2178 | MAX(0, (LCD_HEIGHT - p_disp->height) / 2), | 2410 | MAX(0, (LCD_HEIGHT - p_disp->height) / 2), |
2179 | MIN(LCD_WIDTH, p_disp->width), | 2411 | MIN(LCD_WIDTH, p_disp->width), |
2180 | MIN(LCD_HEIGHT, p_disp->height)); | 2412 | MIN(LCD_HEIGHT, p_disp->height)); |
2413 | #endif | ||
2181 | MYLCD_UPDATE(); | 2414 | MYLCD_UPDATE(); |
2182 | 2415 | ||
2183 | #ifdef USEGSLIB | 2416 | #ifdef USEGSLIB |