image viewer: ppm:
[kugel-rb.git] / apps / plugins / imageviewer / ppm / ppm.c
blob20200d812ea2a6d194377c5fe3d0b26cc6fde02a
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Marcin Bukat
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
23 #include "lcd.h"
24 #include <lib/pluginlib_bmp.h>
25 #include "../imageviewer.h"
26 #include "ppm_decoder.h"
27 #include "bmp.h"
29 static char print[32]; /* use a common snprintf() buffer */
31 /* decompressed image in the possible sizes (1,2,4,8), wasting the other */
32 static unsigned char *disp[9];
33 static unsigned char *disp_buf;
34 static struct ppm_info ppm;
36 #if defined(HAVE_LCD_COLOR)
37 #define resize_bitmap smooth_resize_bitmap
38 #else
39 #define resize_bitmap grey_resize_bitmap
40 #endif
42 #if defined(USEGSLIB) && (CONFIG_PLATFORM & PLATFORM_HOSTED)
43 /* hack: fix error "undefined reference to `_grey_info'". */
44 GREY_INFO_STRUCT
45 #endif /* USEGSLIB */
47 static void draw_image_rect(struct image_info *info,
48 int x, int y, int width, int height)
50 unsigned char **pdisp = (unsigned char **)info->data;
52 #ifdef HAVE_LCD_COLOR
53 rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y,
54 STRIDE(SCREEN_MAIN, info->width, info->height),
55 x + MAX(0, (LCD_WIDTH-info->width)/2),
56 y + MAX(0, (LCD_HEIGHT-info->height)/2),
57 width, height);
58 #else
59 mylcd_ub_gray_bitmap_part(*pdisp,
60 info->x + x, info->y + y, info->width,
61 x + MAX(0, (LCD_WIDTH-info->width)/2),
62 y + MAX(0, (LCD_HEIGHT-info->height)/2),
63 width, height);
64 #endif
67 static int img_mem(int ds)
70 #ifdef USEGSLIB
71 return (ppm.x/ds) * (ppm.y/ds);
72 #else
73 return (ppm.x/ds) * (ppm.y/ds) * FB_DATA_SZ;
74 #endif
77 static int load_image(char *filename, struct image_info *info,
78 unsigned char *buf, ssize_t *buf_size)
80 int fd;
81 int rc = PLUGIN_OK;
82 long time = 0; /* measured ticks */
83 int w, h; /* used to center output */
85 unsigned char *memory, *memory_max;
86 size_t memory_size, file_size;
88 /* cleanup */
89 memset(&disp, 0, sizeof(disp));
91 /* align buffer */
92 memory = (unsigned char *)((intptr_t)(buf + 3) & ~3);
93 memory_max = (unsigned char *)((intptr_t)(memory + *buf_size) & ~3);
94 memory_size = memory_max - memory;
96 fd = rb->open(filename, O_RDONLY);
97 if (fd < 0)
99 rb->splashf(HZ, "err opening %s: %d", filename, fd);
100 return PLUGIN_ERROR;
103 file_size = rb->filesize(fd);
104 DEBUGF("reading file '%s'\n", filename);
106 if (!iv->running_slideshow)
108 rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
109 rb->lcd_putsf(0, 1, "loading %zu bytes", file_size);
110 rb->lcd_update();
113 /* init decoder struct */
114 ppm.buf = memory;
115 ppm.buf_size = memory_size;
117 /* the actual decoding */
118 time = *rb->current_tick;
119 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
120 rb->cpu_boost(true);
121 rc = read_ppm(fd, &ppm);
122 rb->cpu_boost(false);
123 #else
124 rc = read_ppm(fd, &ppm);
125 #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
126 time = *rb->current_tick - time;
128 rb->close(fd);
130 if (rc != PLUGIN_OK)
132 return rc;
135 if (!iv->running_slideshow)
137 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
138 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
139 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
140 rb->lcd_update();
143 info->x_size = ppm.x;
144 info->y_size = ppm.y;
146 ppm.native_img_size = (ppm.native_img_size + 3) & ~3;
147 disp_buf = buf + ppm.native_img_size;
148 *buf_size = memory_max - disp_buf;
150 return PLUGIN_OK;
153 static int get_image(struct image_info *info, int ds)
155 unsigned char **p_disp = &disp[ds]; /* short cut */
156 struct ppm_info *p_ppm = &ppm;
158 info->width = ppm.x / ds;
159 info->height = ppm.y / ds;
160 info->data = p_disp;
162 if (*p_disp != NULL)
164 /* we still have it */
165 return PLUGIN_OK;
168 /* assign image buffer */
169 if (ds > 1)
171 if (!iv->running_slideshow)
173 rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height);
174 rb->lcd_update();
177 struct bitmap bmp_src, bmp_dst;
178 int size = img_mem(ds);
180 if (disp_buf + size >= p_ppm->buf + p_ppm->buf_size)
182 /* have to discard the current */
183 int i;
184 for (i=1; i<=8; i++)
185 disp[i] = NULL; /* invalidate all bitmaps */
187 /* start again from the beginning of the buffer */
188 disp_buf = p_ppm->buf + p_ppm->native_img_size;
191 *p_disp = disp_buf;
192 disp_buf += size;
194 bmp_src.width = ppm.x;
195 bmp_src.height = ppm.y;
196 bmp_src.data = ppm.buf;
198 bmp_dst.width = info->width;
199 bmp_dst.height = info->height;
200 bmp_dst.data = *p_disp;
201 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
202 rb->cpu_boost(true);
203 resize_bitmap(&bmp_src, &bmp_dst);
204 rb->cpu_boost(false);
205 #else
206 resize_bitmap(&bmp_src, &bmp_dst);
207 #endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
209 else
211 *p_disp = p_ppm->buf;
214 return PLUGIN_OK;
217 const struct image_decoder image_decoder = {
218 true,
219 img_mem,
220 load_image,
221 get_image,
222 draw_image_rect,
225 IMGDEC_HEADER