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.zip
rockbox-ce63faa8d4d7fc7dfb710a4d5847b4bd5ac61242.tar.gz
rockbox-ce63faa8d4d7fc7dfb710a4d5847b4bd5ac61242.tar.bz2
rockbox-ce63faa8d4d7fc7dfb710a4d5847b4bd5ac61242.tar.xz
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 e506057..e24434f 100644
--- a/apps/plugins/png/png.c
+++ b/apps/plugins/png/png.c
@@ -141,6 +141,7 @@ typedef struct LodePNG_Decoder
long error;
char error_msg[128];
int x,y;
+ int width,height;
} LodePNG_Decoder;
#define VERSION_STRING "20080927"
@@ -1519,11 +1520,11 @@ int show_menu(void) /* return 1 to quit */
void draw_image(struct LodePNG_Decoder* decoder)
{
- rb->lcd_bitmap_part(resized_image, decoder->x, decoder->y, decoder->infoPng.width/ds /*stride*/,
- MAX(0, (LCD_WIDTH - (int)decoder->infoPng.width/(int)ds) / 2),
- MAX(0, (LCD_HEIGHT - (int)decoder->infoPng.height/(int)ds) / 2),
- decoder->infoPng.width/ds - decoder->x,
- decoder->infoPng.height/ds - decoder->y);
+ rb->lcd_bitmap_part(resized_image, decoder->x, decoder->y, decoder->width,
+ MAX(0, (LCD_WIDTH - decoder->width) / 2),
+ MAX(0, (LCD_HEIGHT - decoder->height) / 2),
+ decoder->width - decoder->x,
+ decoder->height - decoder->y);
}
/* 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)
{
int move;
- move = MIN(HSCROLL, (int)(decoder->infoPng.width/ds) - decoder->x - LCD_WIDTH);
+ move = MIN(HSCROLL, decoder->width - decoder->x - LCD_WIDTH);
if (move > 0)
{
decoder->x += move;
@@ -1578,7 +1579,7 @@ static void pan_view_down(struct LodePNG_Decoder* decoder)
{
int move;
- move = MIN(VSCROLL, (int)(decoder->infoPng.height/ds) - decoder->y - LCD_HEIGHT);
+ move = MIN(VSCROLL, decoder->height - decoder->y - LCD_HEIGHT);
if (move > 0)
{
decoder->y += move;
@@ -1604,16 +1605,16 @@ int scroll_bmp(struct LodePNG_Decoder* decoder)
switch (button)
{
case PNG_LEFT:
- if (entries > 1 && decoder->infoPng.width/ds <= LCD_WIDTH
- && decoder->infoPng.height/ds <= LCD_HEIGHT)
+ if (entries > 1 && decoder->width <= LCD_WIDTH
+ && decoder->height <= LCD_HEIGHT)
return change_filename(DIR_PREV);
case PNG_LEFT | BUTTON_REPEAT:
pan_view_left(decoder);
break;
case PNG_RIGHT:
- if (entries > 1 && decoder->infoPng.width/ds <= LCD_WIDTH
- && decoder->infoPng.height/ds <= LCD_HEIGHT)
+ if (entries > 1 && decoder->width <= LCD_WIDTH
+ && decoder->height <= LCD_HEIGHT)
return change_filename(DIR_NEXT);
case PNG_RIGHT | BUTTON_REPEAT:
pan_view_right(decoder);
@@ -1699,28 +1700,6 @@ int scroll_bmp(struct LodePNG_Decoder* decoder)
} /* while (true) */
}
-/* set the view to the given center point, limit if necessary */
-void set_view (struct LodePNG_Decoder* decoder, int cx, int cy)
-{
- int x, y;
-
- /* plain center to available width/height */
- x = cx - MIN(LCD_WIDTH, decoder->infoPng.width/ds) / 2;
- y = cy - MIN(LCD_HEIGHT, decoder->infoPng.height/ds) / 2;
-
- /* limit against upper image size */
- x = MIN((int)(decoder->infoPng.width/ds) - LCD_WIDTH, x);
- y = MIN((int)(decoder->infoPng.height/ds) - LCD_HEIGHT, y);
-
- /* limit against negative side */
- x = MAX(0, x);
- y = MAX(0, y);
-
- decoder->x = x; /* set the values */
- decoder->y = y;
-
-}
-
/* callback updating a progress meter while PNG decoding */
void cb_progress(int current, int total)
{
@@ -1776,18 +1755,14 @@ unsigned max_downscale(struct LodePNG_Decoder* decoder)
return downscale;
}
-/* calculate the view center based on the bitmap position */
-void get_view(struct LodePNG_Decoder* decoder, int* p_cx, int* p_cy)
-{
- *p_cx = decoder->x + MIN(LCD_WIDTH, decoder->infoPng.width/ds) / 2;
- *p_cy = decoder->y + MIN(LCD_HEIGHT, decoder->infoPng.height/ds) / 2;
-}
-
/* return decoded or cached image */
-fb_data *get_image(struct LodePNG_Decoder* decoder)
+fb_data *get_image(struct LodePNG_Decoder* decoder, int ds)
{
fb_data * p_disp = disp[ds]; /* short cut */
+ decoder->width = decoder->infoPng.width / ds;
+ decoder->height = decoder->infoPng.height / ds;
+
if (p_disp != NULL)
{
DEBUGF("Found an image in cache\n");
@@ -1799,39 +1774,41 @@ fb_data *get_image(struct LodePNG_Decoder* decoder)
if (!running_slideshow)
{
rb->snprintf(print, sizeof(print), "resizing %d*%d",
- decoder->infoPng.width/ds, decoder->infoPng.height/ds);
+ decoder->width, decoder->height);
rb->lcd_puts(0, 3, print);
rb->lcd_update();
}
static struct bitmap bmp_src, bmp_dst;
- int size = (decoder->infoPng.width/ds) * (decoder->infoPng.height/ds);
+ int size = decoder->width * decoder->height;
+
+ if ((unsigned char *)(disp_buf + size) >= memory_max) {
+ /* have to discard the current */
+ int i;
+ for (i=1; i<=8; i++)
+ disp[i] = NULL; /* invalidate all bitmaps */
+ /* start again from the beginning of the buffer */
+ disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3);
+ }
+
disp[ds] = disp_buf;
- if ((unsigned char *)(disp[ds] + size) >= memory_max) {
- //rb->splash(HZ, "Out of Memory");
- // Still display the original image which is already decoded in RAM
- disp[ds] = converted_image;
- ds = 1;
- return converted_image;
- } else {
- bmp_src.width = decoder->infoPng.width;
- bmp_src.height = decoder->infoPng.height;
- bmp_src.data = (unsigned char *)converted_image;
+ bmp_src.width = decoder->infoPng.width;
+ bmp_src.height = decoder->infoPng.height;
+ bmp_src.data = (unsigned char *)converted_image;
- bmp_dst.width = decoder->infoPng.width/ds;
- bmp_dst.height = decoder->infoPng.height/ds;
- bmp_dst.data = (unsigned char *)disp[ds];
+ bmp_dst.width = decoder->width;
+ bmp_dst.height = decoder->height;
+ bmp_dst.data = (unsigned char *)disp[ds];
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
- rb->cpu_boost(true);
- smooth_resize_bitmap(&bmp_src, &bmp_dst);
- rb->cpu_boost(false);
+ rb->cpu_boost(true);
+ smooth_resize_bitmap(&bmp_src, &bmp_dst);
+ rb->cpu_boost(false);
#else
- smooth_resize_bitmap(&bmp_src, &bmp_dst);
+ smooth_resize_bitmap(&bmp_src, &bmp_dst);
#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
- disp_buf = (fb_data *)((intptr_t)(disp[ds] + size + 3) & ~3);
- }
+ disp_buf = (fb_data *)((intptr_t)(disp[ds] + size + 3) & ~3);
} else {
disp[ds] = converted_image;
return converted_image;
@@ -1840,6 +1817,34 @@ fb_data *get_image(struct LodePNG_Decoder* decoder)
return disp[ds];
}
+/* set the view to the given center point, limit if necessary */
+void set_view (struct LodePNG_Decoder* decoder, int cx, int cy)
+{
+ int x, y;
+
+ /* plain center to available width/height */
+ x = cx - MIN(LCD_WIDTH, decoder->width) / 2;
+ y = cy - MIN(LCD_HEIGHT, decoder->height) / 2;
+
+ /* limit against upper image size */
+ x = MIN(decoder->width - LCD_WIDTH, x);
+ y = MIN(decoder->height - LCD_HEIGHT, y);
+
+ /* limit against negative side */
+ x = MAX(0, x);
+ y = MAX(0, y);
+
+ decoder->x = x; /* set the values */
+ decoder->y = y;
+}
+
+/* calculate the view center based on the bitmap position */
+void get_view(struct LodePNG_Decoder* decoder, int* p_cx, int* p_cy)
+{
+ *p_cx = decoder->x + MIN(LCD_WIDTH, decoder->width) / 2;
+ *p_cy = decoder->y + MIN(LCD_HEIGHT, decoder->height) / 2;
+}
+
/* load, decode, display the image */
int load_and_show(char* filename)
{
@@ -1922,15 +1927,12 @@ int load_and_show(char* filename)
if (!decoder.error) {
if (!running_slideshow) {
- rb->snprintf(print, sizeof(print), "image %dx%d", decoder.infoPng.width, decoder.infoPng.height);
+ rb->snprintf(print, sizeof(print), "image %dx%d",
+ decoder.infoPng.width, decoder.infoPng.height);
rb->lcd_puts(0, 2, print);
rb->lcd_update();
}
- ds_max = max_downscale(&decoder); /* check display constraint */
-
- ds = ds_max; /* initials setting */
-
if (!running_slideshow)
{
rb->snprintf(print, sizeof(print), "decoding %d*%d",
@@ -1948,14 +1950,6 @@ int load_and_show(char* filename)
#else
LodePNG_decode(&decoder, image, image_size, cb_progress);
#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
-
- disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3);
- ds_min = min_downscale(&decoder, memory_max - (unsigned char*)disp_buf); /* check memory constraint */
-
- if (ds_min == 0) {
- // Could not resize the image
- ds_min = ds = ds_max = 1;
- }
}
}
@@ -2117,18 +2111,29 @@ int load_and_show(char* filename)
}
}
- do {
- resized_image = get_image(&decoder); /* decode or fetch from cache */
+ disp_buf = (fb_data *)((intptr_t)(converted_image + converted_image_size + 3) & ~3);
+ ds_max = max_downscale(&decoder); /* check display constraint */
+ ds_min = min_downscale(&decoder, memory_max - (unsigned char*)disp_buf); /* check memory constraint */
+ if (ds_min == 0) {
+ /* Can not resize the image */
+ ds_min = ds_max = 1;
+ } else if (ds_max < ds_min) {
+ ds_max = ds_min;
+ }
- cx = decoder.infoPng.width/ds/2; /* center the view */
- cy = decoder.infoPng.height/ds/2;
+ ds = ds_max; /* initials setting */
+ cx = decoder.infoPng.width/ds/2; /* center the view */
+ cy = decoder.infoPng.height/ds/2;
+
+ do {
+ resized_image = get_image(&decoder, ds); /* decode or fetch from cache */
set_view(&decoder, cx, cy);
if (!running_slideshow)
{
rb->snprintf(print, sizeof(print), "showing %dx%d",
- decoder.infoPng.width/ds, decoder.infoPng.height/ds);
+ decoder.width, decoder.height);
rb->lcd_puts(0, 3, print);
rb->lcd_update();
}
@@ -2145,16 +2150,14 @@ int load_and_show(char* filename)
status = scroll_bmp(&decoder);
if (status == ZOOM_IN)
{
- if (ds > ds_min)
+ if (ds > 1)
{
- while (1)
- {
- ds /= 2; /* reduce downscaling to zoom in */
- get_view(&decoder, &cx, &cy);
- cx *= 2; /* prepare the position in the new image */
- cy *= 2;
- if (disp[ds] != converted_image || ds <= ds_min) break;
- }
+ /* as 1/1 is always available, jump ds to 1 if ds is ds_min. */
+ int zoom = (ds == ds_min)? ds_min: 2;
+ ds /= zoom; /* reduce downscaling to zoom in */
+ get_view(&decoder, &cx, &cy);
+ cx *= zoom; /* prepare the position in the new image */
+ cy *= zoom;
}
else
continue;
@@ -2164,14 +2167,12 @@ int load_and_show(char* filename)
{
if (ds < ds_max)
{
- while (1)
- {
- ds *= 2; /* increase downscaling to zoom out */
- get_view(&decoder, &cx, &cy);
- cx /= 2; /* prepare the position in the new image */
- cy /= 2;
- if (disp[ds] != converted_image || ds >= ds_max) break;
- }
+ /* if ds is 1 and ds_min is greater than 1, jump ds to ds_min. */
+ int zoom = (ds < ds_min)? ds_min: 2;
+ ds *= zoom; /* increase downscaling to zoom out */
+ get_view(&decoder, &cx, &cy);
+ cx /= zoom; /* prepare the position in the new image */
+ cy /= zoom;
}
else
continue;