summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeruaki Kawashima <teru@rockbox.org>2009-12-04 13:38:51 +0000
committerTeruaki Kawashima <teru@rockbox.org>2009-12-04 13:38:51 +0000
commitce63faa8d4d7fc7dfb710a4d5847b4bd5ac61242 (patch)
treede1b6cf6f94286abf8ee775ef0d9854855933c00
parent8db32ddfee2577cd338e88134eb52823c04dec80 (diff)
downloadrockbox-ce63faa8d4d7fc7dfb710a4d5847b4bd5ac61242.tar.gz
rockbox-ce63faa8d4d7fc7dfb710a4d5847b4bd5ac61242.zip
png: Change zoom in/out method and don't center the view on zoom.
Don't recalculate resized width or height each time. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23847 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/png/png.c195
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
1520void draw_image(struct LodePNG_Decoder* decoder) 1521void 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 */
1703void 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 */
1725void cb_progress(int current, int total) 1704void 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 */
1780void 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 */
1787fb_data *get_image(struct LodePNG_Decoder* decoder) 1759fb_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 */
1821void 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 */
1842void 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 */
1844int load_and_show(char* filename) 1849int 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;