summaryrefslogtreecommitdiff
path: root/apps/plugins/imageviewer/bmp/bmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/imageviewer/bmp/bmp.c')
-rw-r--r--apps/plugins/imageviewer/bmp/bmp.c323
1 files changed, 323 insertions, 0 deletions
diff --git a/apps/plugins/imageviewer/bmp/bmp.c b/apps/plugins/imageviewer/bmp/bmp.c
new file mode 100644
index 0000000000..73a4d738ac
--- /dev/null
+++ b/apps/plugins/imageviewer/bmp/bmp.c
@@ -0,0 +1,323 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * BMP image viewer
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "plugin.h"
23#include "bmp.h"
24#include "resize.h"
25#include <lib/feature_wrappers.h>
26#include <lib/pluginlib_bmp.h>
27
28#include "../imageviewer.h"
29
30#ifdef HAVE_LCD_COLOR
31#define resize_bitmap smooth_resize_bitmap
32#elif defined(USEGSLIB)
33#define resize_bitmap grey_resize_bitmap
34#else
35#define resize_bitmap simple_resize_bitmap
36#endif
37
38/**************** begin Application ********************/
39
40
41/************************* Types ***************************/
42
43struct t_disp
44{
45 unsigned char* bitmap;
46};
47
48/************************* Globals ***************************/
49
50/* decompressed image in the possible sizes (1,2,4,8), wasting the other */
51static struct t_disp disp[9];
52
53/* my memory pool (from the mp3 buffer) */
54static char print[32]; /* use a common snprintf() buffer */
55
56/* the root of the images, hereafter are decompresed ones */
57static unsigned char* buf_root;
58static int root_size;
59
60/* up to here currently used by image(s) */
61static unsigned char* buf_images;
62static ssize_t buf_images_size;
63
64struct bitmap bmp;
65
66/************************* Implementation ***************************/
67
68#ifdef USEGSLIB
69/* copied & pasted from lib/pluginlib_bmp.c. */
70static void grey_resize_bitmap(struct bitmap *src, struct bitmap *dst)
71{
72 const int srcw = src->width;
73 const int srch = src->height;
74 const int dstw = dst->width;
75 const int dsth = dst->height;
76 unsigned char *srcd = src->data;
77 unsigned char *dstd = dst->data;
78
79 const long xrstep = ((srcw-1) << 8) / (dstw-1);
80 const long yrstep = ((srch-1) << 8) / (dsth-1);
81 unsigned char *src_row, *dst_row;
82 long xr, yr = 0;
83 int src_x, src_y, dst_x, dst_y;
84 for (dst_y=0; dst_y < dsth; dst_y++)
85 {
86 src_y = (yr >> 8);
87 src_row = &srcd[src_y * srcw];
88 dst_row = &dstd[dst_y * dstw];
89 for (xr=0,dst_x=0; dst_x < dstw; dst_x++)
90 {
91 src_x = (xr >> 8);
92 dst_row[dst_x] = src_row[src_x];
93 xr += xrstep;
94 }
95 yr += yrstep;
96 }
97}
98#endif /* USEGSLIB */
99
100bool img_ext(const char *ext)
101{
102 if (!ext)
103 return false;
104 if (!rb->strcasecmp(ext,".bmp"))
105 return true;
106 else
107 return false;
108}
109
110void draw_image_rect(struct image_info *info,
111 int x, int y, int width, int height)
112{
113 struct t_disp* pdisp = (struct t_disp*)info->data;
114#ifdef HAVE_LCD_COLOR
115 rb->lcd_bitmap_part(
116 (fb_data*)pdisp->bitmap, info->x + x, info->y + y,
117 STRIDE(SCREEN_MAIN, info->width, info->height),
118 x + MAX(0, (LCD_WIDTH-info->width)/2),
119 y + MAX(0, (LCD_HEIGHT-info->height)/2),
120 width, height);
121#else
122 MYXLCD(gray_bitmap_part)(
123 pdisp->bitmap, info->x + x, info->y + y, info->width,
124 x + MAX(0, (LCD_WIDTH-info->width)/2),
125 y + MAX(0, (LCD_HEIGHT-info->height)/2),
126 width, height);
127#endif
128}
129
130int img_mem(int ds)
131{
132#ifndef USEGSLIB
133 return (bmp.width/ds) * (bmp.height/ds) * sizeof (fb_data);
134#else
135 return (bmp.width/ds) * (bmp.height/ds);
136#endif
137}
138
139int load_image(char *filename, struct image_info *info,
140 unsigned char *buf, ssize_t *buf_size)
141{
142 int w, h; /* used to center output */
143 long time; /* measured ticks */
144 int fd;
145 int size;
146 int format = FORMAT_NATIVE;
147#ifdef USEGSLIB
148 const struct custom_format *cformat = &format_grey;
149#else
150 const struct custom_format *cformat = &format_native;
151#endif
152
153 rb->memset(&disp, 0, sizeof(disp));
154 rb->memset(&bmp, 0, sizeof(bmp)); /* clear info struct */
155
156 if ((intptr_t)buf & 3)
157 {
158 *buf_size -= 4-((intptr_t)buf&3);
159 buf += 4-((intptr_t)buf&3);
160 }
161 fd = rb->open(filename, O_RDONLY);
162 if (fd < 0)
163 {
164 rb->splashf(HZ, "err opening %s: %d", filename, fd);
165 return PLUGIN_ERROR;
166 }
167 int ds = 1;
168 /* check size of image needed to load image. */
169 size = scaled_read_bmp_fd(fd, &bmp, 0, format | FORMAT_RETURN_SIZE, cformat);
170#ifdef USE_PLUG_BUF
171 if (!plug_buf)
172#endif
173 {
174 while (size > *buf_size && bmp.width >= 2 && bmp.height >= 2 && ds < 8)
175 {
176 /* too large for the buffer. resize on load. */
177 format |= FORMAT_RESIZE|FORMAT_KEEP_ASPECT;
178 ds *= 2;
179 bmp.width /= 2;
180 bmp.height /= 2;
181 rb->lseek(fd, 0, SEEK_SET);
182 size = scaled_read_bmp_fd(fd, &bmp, 0, format | FORMAT_RETURN_SIZE, cformat);
183 }
184 }
185 if (size <= 0)
186 {
187 rb->close(fd);
188 rb->splashf(HZ, "read error %d", size);
189 return PLUGIN_ERROR;
190 }
191
192 if (size > *buf_size)
193 {
194 rb->close(fd);
195 return PLUGIN_OUTOFMEM;
196 }
197
198 if (!running_slideshow)
199 {
200 rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
201 rb->lcd_update();
202
203 rb->snprintf(print, sizeof(print), "loading %dx%d%s",
204 bmp.width, bmp.height, ds == 1?"":"(resize on load)");
205 rb->lcd_puts(0, 1, print);
206 rb->lcd_update();
207 }
208
209 /* allocate bitmap buffer */
210 bmp.data = buf;
211
212 /* actual loading */
213 time = *rb->current_tick;
214 rb->lseek(fd, 0, SEEK_SET);
215#ifdef HAVE_ADJUSTABLE_CPU_FREQ
216 rb->cpu_boost(true);
217 size = scaled_read_bmp_fd(fd, &bmp, *buf_size, format, cformat);
218 rb->cpu_boost(false);
219#else
220 size = scaled_read_bmp_fd(fd, &bmp, *buf_size, format, cformat);
221#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
222 rb->close(fd);
223 time = *rb->current_tick - time;
224
225 if (size <= 0)
226 {
227 rb->splashf(HZ, "load error %d", size);
228 return PLUGIN_ERROR;
229 }
230
231 if (!running_slideshow)
232 {
233 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
234 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
235 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
236 rb->lcd_update();
237 }
238#ifdef DISK_SPINDOWN
239 else if (immediate_ata_off)
240 {
241 /* running slideshow and time is long enough: power down disk */
242 rb->storage_sleep();
243 }
244#endif
245
246 /* we can start the resized images behind it */
247 buf_images = buf_root = buf + size;
248 buf_images_size = root_size = *buf_size - size;
249
250 if (!running_slideshow)
251 {
252 rb->snprintf(print, sizeof(print), "image %dx%d", bmp.width, bmp.height);
253 rb->lcd_puts(0, 2, print);
254 rb->lcd_update();
255 }
256
257 info->x_size = bmp.width;
258 info->y_size = bmp.height;
259 *buf_size = buf_images_size;
260 return PLUGIN_OK;
261}
262
263int get_image(struct image_info *info, int ds)
264{
265 struct t_disp* p_disp = &disp[ds]; /* short cut */
266
267 info->width = bmp.width/ds;
268 info->height = bmp.height/ds;
269 info->data = p_disp;
270
271 if (p_disp->bitmap != NULL)
272 {
273 /* we still have it */
274 return PLUGIN_OK;
275 }
276
277 /* assign image buffer */
278 if (ds > 1)
279 {
280 int size; /* resized image size */
281 struct bitmap bmp_dst;
282
283 size = img_mem(ds);
284 if (buf_images_size <= size)
285 {
286 /* have to discard the current */
287 int i;
288 for (i=1; i<=8; i++)
289 disp[i].bitmap = NULL; /* invalidate all bitmaps */
290 buf_images = buf_root; /* start again from the beginning of the buffer */
291 buf_images_size = root_size;
292 }
293
294 p_disp->bitmap = buf_images;
295 buf_images += size;
296 buf_images_size -= size;
297
298 if (!running_slideshow)
299 {
300 rb->snprintf(print, sizeof(print), "resizing %d*%d",
301 info->width, info->height);
302 rb->lcd_puts(0, 3, print);
303 rb->lcd_update();
304 }
305
306 bmp_dst.width = info->width;
307 bmp_dst.height = info->height;
308 bmp_dst.data = p_disp->bitmap;
309#ifdef HAVE_ADJUSTABLE_CPU_FREQ
310 rb->cpu_boost(true);
311 resize_bitmap(&bmp, &bmp_dst);
312 rb->cpu_boost(false);
313#else
314 resize_bitmap(&bmp, &bmp_dst);
315#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
316 }
317 else
318 {
319 p_disp->bitmap = bmp.data;
320 }
321
322 return PLUGIN_OK;
323}