summaryrefslogtreecommitdiff
path: root/apps/plugins/imageviewer/ppm/ppm.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/imageviewer/ppm/ppm.c')
-rw-r--r--apps/plugins/imageviewer/ppm/ppm.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/apps/plugins/imageviewer/ppm/ppm.c b/apps/plugins/imageviewer/ppm/ppm.c
new file mode 100644
index 0000000000..100a00ac84
--- /dev/null
+++ b/apps/plugins/imageviewer/ppm/ppm.c
@@ -0,0 +1,233 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Marcin Bukat
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 "lcd.h"
24#include <lib/pluginlib_bmp.h>
25#include "../imageviewer.h"
26#include "ppm_decoder.h"
27#include "bmp.h"
28
29static char print[32]; /* use a common snprintf() buffer */
30
31/* decompressed image in the possible sizes (1,2,4,8), wasting the other */
32static unsigned char *disp[9];
33static unsigned char *disp_buf;
34static struct ppm_info ppm;
35
36#if defined(HAVE_LCD_COLOR)
37#define resize_bitmap smooth_resize_bitmap
38#else
39#define resize_bitmap grey_resize_bitmap
40#endif
41
42#if defined(USEGSLIB) && (CONFIG_PLATFORM & PLATFORM_HOSTED)
43/* hack: fix error "undefined reference to `_grey_info'". */
44GREY_INFO_STRUCT
45#endif /* USEGSLIB */
46
47static void draw_image_rect(struct image_info *info,
48 int x, int y, int width, int height)
49{
50 unsigned char **pdisp = (unsigned char **)info->data;
51
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
65}
66
67static int img_mem(int ds)
68{
69
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
75}
76
77static int load_image(char *filename, struct image_info *info,
78 unsigned char *buf, ssize_t *buf_size)
79{
80 int fd;
81 int rc = PLUGIN_OK;
82 long time = 0; /* measured ticks */
83 int w, h; /* used to center output */
84
85 unsigned char *memory, *memory_max;
86 size_t memory_size, file_size;
87
88 /* cleanup */
89 memset(&disp, 0, sizeof(disp));
90
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;
95
96 fd = rb->open(filename, O_RDONLY);
97 if (fd < 0)
98 {
99 rb->splashf(HZ, "err opening %s: %d", filename, fd);
100 return PLUGIN_ERROR;
101 }
102
103 file_size = rb->filesize(fd);
104 DEBUGF("reading file '%s'\n", filename);
105
106 if (!iv->running_slideshow)
107 {
108 rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
109 rb->lcd_update();
110 }
111
112 if (!iv->running_slideshow)
113 {
114 rb->lcd_putsf(0, 1, "loading %zu bytes", file_size);
115 rb->lcd_update();
116 }
117
118 /* init decoder struct */
119 ppm.buf = memory;
120 ppm.buf_size = memory_size;
121
122 /* the actual decoding */
123 time = *rb->current_tick;
124#ifdef HAVE_ADJUSTABLE_CPU_FREQ
125 rb->cpu_boost(true);
126 rc = read_ppm(fd, &ppm);
127 rb->cpu_boost(false);
128#else
129 rc = read_ppm(fd, &ppm);
130#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
131 time = *rb->current_tick - time;
132
133 /* close file descriptor */
134 rb->close(fd);
135
136 /* check return value from decoder */
137 if ( rc == PLUGIN_ERROR )
138 {
139 rb->splashf(HZ, "ppm decoder error");
140 return PLUGIN_ERROR;
141 }
142
143 if (!iv->running_slideshow)
144 {
145 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
146 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
147 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
148 rb->lcd_update();
149 }
150
151 info->x_size = ppm.x;
152 info->y_size = ppm.y;
153
154 ppm.native_img_size = (ppm.native_img_size + 3) & ~3;
155 disp_buf = buf + ppm.native_img_size;
156 *buf_size = memory_max - disp_buf;
157
158 return PLUGIN_OK;
159}
160
161static int get_image(struct image_info *info, int ds)
162{
163 unsigned char **p_disp = &disp[ds]; /* short cut */
164 struct ppm_info *p_ppm = &ppm;
165
166 info->width = ppm.x / ds;
167 info->height = ppm.y / ds;
168 info->data = p_disp;
169
170 if (*p_disp != NULL)
171 {
172 /* we still have it */
173 return PLUGIN_OK;
174 }
175
176 /* assign image buffer */
177 if (ds > 1)
178 {
179 if (!iv->running_slideshow)
180 {
181 rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height);
182 rb->lcd_update();
183 }
184
185 struct bitmap bmp_src, bmp_dst;
186 int size = img_mem(ds);
187
188 if (disp_buf + size >= p_ppm->buf + p_ppm->buf_size)
189 {
190 /* have to discard the current */
191 int i;
192 for (i=1; i<=8; i++)
193 disp[i] = NULL; /* invalidate all bitmaps */
194
195 /* start again from the beginning of the buffer */
196 disp_buf = p_ppm->buf + p_ppm->native_img_size;
197 }
198
199 *p_disp = disp_buf;
200 disp_buf += size;
201
202 bmp_src.width = ppm.x;
203 bmp_src.height = ppm.y;
204 bmp_src.data = ppm.buf;
205
206 bmp_dst.width = info->width;
207 bmp_dst.height = info->height;
208 bmp_dst.data = *p_disp;
209#ifdef HAVE_ADJUSTABLE_CPU_FREQ
210 rb->cpu_boost(true);
211 resize_bitmap(&bmp_src, &bmp_dst);
212 rb->cpu_boost(false);
213#else
214 resize_bitmap(&bmp_src, &bmp_dst);
215#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
216 }
217 else
218 {
219 *p_disp = p_ppm->buf;
220 }
221
222 return PLUGIN_OK;
223}
224
225const struct image_decoder image_decoder = {
226 true,
227 img_mem,
228 load_image,
229 get_image,
230 draw_image_rect,
231};
232
233IMGDEC_HEADER