diff options
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/png/png.c | 195 |
1 files changed, 98 insertions, 97 deletions
diff --git a/apps/plugins/png/png.c b/apps/plugins/png/png.c index e50605776c..e24434fc72 100644 --- a/apps/plugins/png/png.c +++ b/apps/plugins/png/png.c | |||
@@ -141,6 +141,7 @@ typedef struct LodePNG_Decoder | |||
141 | long error; | 141 | long error; |
142 | char error_msg[128]; | 142 | char error_msg[128]; |
143 | int x,y; | 143 | int x,y; |
144 | int width,height; | ||
144 | } LodePNG_Decoder; | 145 | } LodePNG_Decoder; |
145 | 146 | ||
146 | #define VERSION_STRING "20080927" | 147 | #define VERSION_STRING "20080927" |
@@ -1519,11 +1520,11 @@ int show_menu(void) /* return 1 to quit */ | |||
1519 | 1520 | ||
1520 | void draw_image(struct LodePNG_Decoder* decoder) | 1521 | void draw_image(struct LodePNG_Decoder* decoder) |
1521 | { | 1522 | { |
1522 | rb->lcd_bitmap_part(resized_image, decoder->x, decoder->y, decoder->infoPng.width/ds /*stride*/, | 1523 | rb->lcd_bitmap_part(resized_image, decoder->x, decoder->y, decoder->width, |
1523 | MAX(0, (LCD_WIDTH - (int)decoder->infoPng.width/(int)ds) / 2), | 1524 | MAX(0, (LCD_WIDTH - decoder->width) / 2), |
1524 | MAX(0, (LCD_HEIGHT - (int)decoder->infoPng.height/(int)ds) / 2), | 1525 | MAX(0, (LCD_HEIGHT - decoder->height) / 2), |
1525 | decoder->infoPng.width/ds - decoder->x, | 1526 | decoder->width - decoder->x, |
1526 | decoder->infoPng.height/ds - decoder->y); | 1527 | decoder->height - decoder->y); |
1527 | } | 1528 | } |
1528 | 1529 | ||
1529 | /* Pan the viewing window right - move image to the left and fill in | 1530 | /* Pan the viewing window right - move image to the left and fill in |
@@ -1532,7 +1533,7 @@ static void pan_view_right(struct LodePNG_Decoder* decoder) | |||
1532 | { | 1533 | { |
1533 | int move; | 1534 | int move; |
1534 | 1535 | ||
1535 | move = MIN(HSCROLL, (int)(decoder->infoPng.width/ds) - decoder->x - LCD_WIDTH); | 1536 | move = MIN(HSCROLL, decoder->width - decoder->x - LCD_WIDTH); |
1536 | if (move > 0) | 1537 | if (move > 0) |
1537 | { | 1538 | { |
1538 | decoder->x += move; | 1539 | decoder->x += move; |
@@ -1578,7 +1579,7 @@ static void pan_view_down(struct LodePNG_Decoder* decoder) | |||
1578 | { | 1579 | { |
1579 | int move; | 1580 | int move; |
1580 | 1581 | ||
1581 | move = MIN(VSCROLL, (int)(decoder->infoPng.height/ds) - decoder->y - LCD_HEIGHT); | 1582 | move = MIN(VSCROLL, decoder->height - decoder->y - LCD_HEIGHT); |
1582 | if (move > 0) | 1583 | if (move > 0) |
1583 | { | 1584 | { |
1584 | decoder->y += move; | 1585 | decoder->y += move; |
@@ -1604,16 +1605,16 @@ int scroll_bmp(struct LodePNG_Decoder* decoder) | |||
1604 | switch (button) | 1605 | switch (button) |
1605 | { | 1606 | { |
1606 | case PNG_LEFT: | 1607 | case PNG_LEFT: |
1607 | if (entries > 1 && decoder->infoPng.width/ds <= LCD_WIDTH | 1608 | if (entries > 1 && decoder->width <= LCD_WIDTH |
1608 | && decoder->infoPng.height/ds <= LCD_HEIGHT) | 1609 | && decoder->height <= LCD_HEIGHT) |
1609 | return change_filename(DIR_PREV); | 1610 | return change_filename(DIR_PREV); |
1610 | case PNG_LEFT | BUTTON_REPEAT: | 1611 | case PNG_LEFT | BUTTON_REPEAT: |
1611 | pan_view_left(decoder); | 1612 | pan_view_left(decoder); |
1612 | break; | 1613 | break; |
1613 | 1614 | ||
1614 | case PNG_RIGHT: | 1615 | case PNG_RIGHT: |
1615 | if (entries > 1 && decoder->infoPng.width/ds <= LCD_WIDTH | 1616 | if (entries > 1 && decoder->width <= LCD_WIDTH |
1616 | && decoder->infoPng.height/ds <= LCD_HEIGHT) | 1617 | && decoder->height <= LCD_HEIGHT) |
1617 | return change_filename(DIR_NEXT); | 1618 | return change_filename(DIR_NEXT); |
1618 | case PNG_RIGHT | BUTTON_REPEAT: | 1619 | case PNG_RIGHT | BUTTON_REPEAT: |
1619 | pan_view_right(decoder); | 1620 | pan_view_right(decoder); |
@@ -1699,28 +1700,6 @@ int scroll_bmp(struct LodePNG_Decoder* decoder) | |||
1699 | } /* while (true) */ | 1700 | } /* while (true) */ |
1700 | } | 1701 | } |
1701 | 1702 | ||
1702 | /* set the view to the given center point, limit if necessary */ | ||
1703 | void set_view (struct LodePNG_Decoder* decoder, int cx, int cy) | ||
1704 | { | ||
1705 | int x, y; | ||
1706 | |||
1707 | /* plain center to available width/height */ | ||
1708 | x = cx - MIN(LCD_WIDTH, decoder->infoPng.width/ds) / 2; | ||
1709 | y = cy - MIN(LCD_HEIGHT, decoder->infoPng.height/ds) / 2; | ||
1710 | |||
1711 | /* limit against upper image size */ | ||
1712 | x = MIN((int)(decoder->infoPng.width/ds) - LCD_WIDTH, x); | ||
1713 | y = MIN((int)(decoder->infoPng.height/ds) - LCD_HEIGHT, y); | ||
1714 | |||
1715 | /* limit against negative side */ | ||
1716 | x = MAX(0, x); | ||
1717 | y = MAX(0, y); | ||
1718 | |||
1719 | decoder->x = x; /* set the values */ | ||
1720 | decoder->y = y; | ||
1721 | |||
1722 | } | ||
1723 | |||
1724 | /* callback updating a progress meter while PNG decoding */ | 1703 | /* callback updating a progress meter while PNG decoding */ |
1725 | void cb_progress(int current, int total) | 1704 | void cb_progress(int current, int total) |
1726 | { | 1705 | { |
@@ -1776,18 +1755,14 @@ unsigned max_downscale(struct LodePNG_Decoder* decoder) | |||
1776 | return downscale; | 1755 | return downscale; |
1777 | } | 1756 | } |
1778 | 1757 | ||
1779 | /* calculate the view center based on the bitmap position */ | ||
1780 | void get_view(struct LodePNG_Decoder* decoder, int* p_cx, int* p_cy) | ||
1781 | { | ||
1782 | *p_cx = decoder->x + MIN(LCD_WIDTH, decoder->infoPng.width/ds) / 2; | ||
1783 | *p_cy = decoder->y + MIN(LCD_HEIGHT, decoder->infoPng.height/ds) / 2; | ||
1784 | } | ||
1785 | |||
1786 | /* return decoded or cached image */ | 1758 | /* return decoded or cached image */ |
1787 | fb_data *get_image(struct LodePNG_Decoder* decoder) | 1759 | fb_data *get_image(struct LodePNG_Decoder* decoder, int ds) |
1788 | { | 1760 | { |
1789 | fb_data * p_disp = disp[ds]; /* short cut */ | 1761 | fb_data * p_disp = disp[ds]; /* short cut */ |
1790 | 1762 | ||
1763 | decoder->width = decoder->infoPng.width / ds; | ||
1764 | decoder->height = decoder->infoPng.height / ds; | ||
1765 | |||
1791 | if (p_disp != NULL) | 1766 | if (p_disp != NULL) |
1792 | { | 1767 | { |
1793 | DEBUGF("Found an image in cache\n"); | 1768 | DEBUGF("Found an image in cache\n"); |
@@ -1799,39 +1774,41 @@ fb_data *get_image(struct LodePNG_Decoder* decoder) | |||
1799 | if (!running_slideshow) | 1774 | if (!running_slideshow) |
1800 | { | 1775 | { |
1801 | rb->snprintf(print, sizeof(print), "resizing %d*%d", | 1776 | rb->snprintf(print, sizeof(print), "resizing %d*%d", |
1802 | decoder->infoPng.width/ds, decoder->infoPng.height/ds); | 1777 | decoder->width, decoder->height); |
1803 | rb->lcd_puts(0, 3, print); | 1778 | rb->lcd_puts(0, 3, print); |
1804 | rb->lcd_update(); | 1779 | rb->lcd_update(); |
1805 | } | 1780 | } |
1806 | static struct bitmap bmp_src, bmp_dst; | 1781 | static struct bitmap bmp_src, bmp_dst; |
1807 | 1782 | ||
1808 | int size = (decoder->infoPng.width/ds) * (decoder->infoPng.height/ds); | 1783 | int size = decoder->width * decoder->height; |
1784 | |||
1785 | if ((unsigned char *)(disp_buf + size) >= memory_max) { | ||
1786 | /* have to discard the current */ | ||
1787 | int i; | ||
1788 | for (i=1; i<=8; i++) | ||
1789 | disp[i] = NULL; /* invalidate all bitmaps */ | ||
1790 | /* start again from the beginning of the buffer */ | ||
1791 | disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3); | ||
1792 | } | ||
1793 | |||
1809 | disp[ds] = disp_buf; | 1794 | disp[ds] = disp_buf; |
1810 | 1795 | ||
1811 | if ((unsigned char *)(disp[ds] + size) >= memory_max) { | 1796 | bmp_src.width = decoder->infoPng.width; |
1812 | //rb->splash(HZ, "Out of Memory"); | 1797 | bmp_src.height = decoder->infoPng.height; |
1813 | // Still display the original image which is already decoded in RAM | 1798 | bmp_src.data = (unsigned char *)converted_image; |
1814 | disp[ds] = converted_image; | ||
1815 | ds = 1; | ||
1816 | return converted_image; | ||
1817 | } else { | ||
1818 | bmp_src.width = decoder->infoPng.width; | ||
1819 | bmp_src.height = decoder->infoPng.height; | ||
1820 | bmp_src.data = (unsigned char *)converted_image; | ||
1821 | 1799 | ||
1822 | bmp_dst.width = decoder->infoPng.width/ds; | 1800 | bmp_dst.width = decoder->width; |
1823 | bmp_dst.height = decoder->infoPng.height/ds; | 1801 | bmp_dst.height = decoder->height; |
1824 | bmp_dst.data = (unsigned char *)disp[ds]; | 1802 | bmp_dst.data = (unsigned char *)disp[ds]; |
1825 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 1803 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
1826 | rb->cpu_boost(true); | 1804 | rb->cpu_boost(true); |
1827 | smooth_resize_bitmap(&bmp_src, &bmp_dst); | 1805 | smooth_resize_bitmap(&bmp_src, &bmp_dst); |
1828 | rb->cpu_boost(false); | 1806 | rb->cpu_boost(false); |
1829 | #else | 1807 | #else |
1830 | smooth_resize_bitmap(&bmp_src, &bmp_dst); | 1808 | smooth_resize_bitmap(&bmp_src, &bmp_dst); |
1831 | #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ | 1809 | #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ |
1832 | 1810 | ||
1833 | disp_buf = (fb_data *)((intptr_t)(disp[ds] + size + 3) & ~3); | 1811 | disp_buf = (fb_data *)((intptr_t)(disp[ds] + size + 3) & ~3); |
1834 | } | ||
1835 | } else { | 1812 | } else { |
1836 | disp[ds] = converted_image; | 1813 | disp[ds] = converted_image; |
1837 | return converted_image; | 1814 | return converted_image; |
@@ -1840,6 +1817,34 @@ fb_data *get_image(struct LodePNG_Decoder* decoder) | |||
1840 | return disp[ds]; | 1817 | return disp[ds]; |
1841 | } | 1818 | } |
1842 | 1819 | ||
1820 | /* set the view to the given center point, limit if necessary */ | ||
1821 | void set_view (struct LodePNG_Decoder* decoder, int cx, int cy) | ||
1822 | { | ||
1823 | int x, y; | ||
1824 | |||
1825 | /* plain center to available width/height */ | ||
1826 | x = cx - MIN(LCD_WIDTH, decoder->width) / 2; | ||
1827 | y = cy - MIN(LCD_HEIGHT, decoder->height) / 2; | ||
1828 | |||
1829 | /* limit against upper image size */ | ||
1830 | x = MIN(decoder->width - LCD_WIDTH, x); | ||
1831 | y = MIN(decoder->height - LCD_HEIGHT, y); | ||
1832 | |||
1833 | /* limit against negative side */ | ||
1834 | x = MAX(0, x); | ||
1835 | y = MAX(0, y); | ||
1836 | |||
1837 | decoder->x = x; /* set the values */ | ||
1838 | decoder->y = y; | ||
1839 | } | ||
1840 | |||
1841 | /* calculate the view center based on the bitmap position */ | ||
1842 | void get_view(struct LodePNG_Decoder* decoder, int* p_cx, int* p_cy) | ||
1843 | { | ||
1844 | *p_cx = decoder->x + MIN(LCD_WIDTH, decoder->width) / 2; | ||
1845 | *p_cy = decoder->y + MIN(LCD_HEIGHT, decoder->height) / 2; | ||
1846 | } | ||
1847 | |||
1843 | /* load, decode, display the image */ | 1848 | /* load, decode, display the image */ |
1844 | int load_and_show(char* filename) | 1849 | int load_and_show(char* filename) |
1845 | { | 1850 | { |
@@ -1922,15 +1927,12 @@ int load_and_show(char* filename) | |||
1922 | if (!decoder.error) { | 1927 | if (!decoder.error) { |
1923 | 1928 | ||
1924 | if (!running_slideshow) { | 1929 | if (!running_slideshow) { |
1925 | rb->snprintf(print, sizeof(print), "image %dx%d", decoder.infoPng.width, decoder.infoPng.height); | 1930 | rb->snprintf(print, sizeof(print), "image %dx%d", |
1931 | decoder.infoPng.width, decoder.infoPng.height); | ||
1926 | rb->lcd_puts(0, 2, print); | 1932 | rb->lcd_puts(0, 2, print); |
1927 | rb->lcd_update(); | 1933 | rb->lcd_update(); |
1928 | } | 1934 | } |
1929 | 1935 | ||
1930 | ds_max = max_downscale(&decoder); /* check display constraint */ | ||
1931 | |||
1932 | ds = ds_max; /* initials setting */ | ||
1933 | |||
1934 | if (!running_slideshow) | 1936 | if (!running_slideshow) |
1935 | { | 1937 | { |
1936 | rb->snprintf(print, sizeof(print), "decoding %d*%d", | 1938 | rb->snprintf(print, sizeof(print), "decoding %d*%d", |
@@ -1948,14 +1950,6 @@ int load_and_show(char* filename) | |||
1948 | #else | 1950 | #else |
1949 | LodePNG_decode(&decoder, image, image_size, cb_progress); | 1951 | LodePNG_decode(&decoder, image, image_size, cb_progress); |
1950 | #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ | 1952 | #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/ |
1951 | |||
1952 | disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3); | ||
1953 | ds_min = min_downscale(&decoder, memory_max - (unsigned char*)disp_buf); /* check memory constraint */ | ||
1954 | |||
1955 | if (ds_min == 0) { | ||
1956 | // Could not resize the image | ||
1957 | ds_min = ds = ds_max = 1; | ||
1958 | } | ||
1959 | } | 1953 | } |
1960 | } | 1954 | } |
1961 | 1955 | ||
@@ -2117,18 +2111,29 @@ int load_and_show(char* filename) | |||
2117 | } | 2111 | } |
2118 | } | 2112 | } |
2119 | 2113 | ||
2120 | do { | 2114 | disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3); |
2121 | resized_image = get_image(&decoder); /* decode or fetch from cache */ | 2115 | ds_max = max_downscale(&decoder); /* check display constraint */ |
2116 | ds_min = min_downscale(&decoder, memory_max - (unsigned char*)disp_buf); /* check memory constraint */ | ||
2117 | if (ds_min == 0) { | ||
2118 | /* Can not resize the image */ | ||
2119 | ds_min = ds_max = 1; | ||
2120 | } else if (ds_max < ds_min) { | ||
2121 | ds_max = ds_min; | ||
2122 | } | ||
2122 | 2123 | ||
2123 | cx = decoder.infoPng.width/ds/2; /* center the view */ | 2124 | ds = ds_max; /* initials setting */ |
2124 | cy = decoder.infoPng.height/ds/2; | 2125 | cx = decoder.infoPng.width/ds/2; /* center the view */ |
2126 | cy = decoder.infoPng.height/ds/2; | ||
2127 | |||
2128 | do { | ||
2129 | resized_image = get_image(&decoder, ds); /* decode or fetch from cache */ | ||
2125 | 2130 | ||
2126 | set_view(&decoder, cx, cy); | 2131 | set_view(&decoder, cx, cy); |
2127 | 2132 | ||
2128 | if (!running_slideshow) | 2133 | if (!running_slideshow) |
2129 | { | 2134 | { |
2130 | rb->snprintf(print, sizeof(print), "showing %dx%d", | 2135 | rb->snprintf(print, sizeof(print), "showing %dx%d", |
2131 | decoder.infoPng.width/ds, decoder.infoPng.height/ds); | 2136 | decoder.width, decoder.height); |
2132 | rb->lcd_puts(0, 3, print); | 2137 | rb->lcd_puts(0, 3, print); |
2133 | rb->lcd_update(); | 2138 | rb->lcd_update(); |
2134 | } | 2139 | } |
@@ -2145,16 +2150,14 @@ int load_and_show(char* filename) | |||
2145 | status = scroll_bmp(&decoder); | 2150 | status = scroll_bmp(&decoder); |
2146 | if (status == ZOOM_IN) | 2151 | if (status == ZOOM_IN) |
2147 | { | 2152 | { |
2148 | if (ds > ds_min) | 2153 | if (ds > 1) |
2149 | { | 2154 | { |
2150 | while (1) | 2155 | /* as 1/1 is always available, jump ds to 1 if ds is ds_min. */ |
2151 | { | 2156 | int zoom = (ds == ds_min)? ds_min: 2; |
2152 | ds /= 2; /* reduce downscaling to zoom in */ | 2157 | ds /= zoom; /* reduce downscaling to zoom in */ |
2153 | get_view(&decoder, &cx, &cy); | 2158 | get_view(&decoder, &cx, &cy); |
2154 | cx *= 2; /* prepare the position in the new image */ | 2159 | cx *= zoom; /* prepare the position in the new image */ |
2155 | cy *= 2; | 2160 | cy *= zoom; |
2156 | if (disp[ds] != converted_image || ds <= ds_min) break; | ||
2157 | } | ||
2158 | } | 2161 | } |
2159 | else | 2162 | else |
2160 | continue; | 2163 | continue; |
@@ -2164,14 +2167,12 @@ int load_and_show(char* filename) | |||
2164 | { | 2167 | { |
2165 | if (ds < ds_max) | 2168 | if (ds < ds_max) |
2166 | { | 2169 | { |
2167 | while (1) | 2170 | /* if ds is 1 and ds_min is greater than 1, jump ds to ds_min. */ |
2168 | { | 2171 | int zoom = (ds < ds_min)? ds_min: 2; |
2169 | ds *= 2; /* increase downscaling to zoom out */ | 2172 | ds *= zoom; /* increase downscaling to zoom out */ |
2170 | get_view(&decoder, &cx, &cy); | 2173 | get_view(&decoder, &cx, &cy); |
2171 | cx /= 2; /* prepare the position in the new image */ | 2174 | cx /= zoom; /* prepare the position in the new image */ |
2172 | cy /= 2; | 2175 | cy /= zoom; |
2173 | if (disp[ds] != converted_image || ds >= ds_max) break; | ||
2174 | } | ||
2175 | } | 2176 | } |
2176 | else | 2177 | else |
2177 | continue; | 2178 | continue; |