summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/filetypes.c3
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/imageviewer/SUBDIRS1
-rw-r--r--apps/plugins/imageviewer/bmp/SOURCES2
-rw-r--r--apps/plugins/imageviewer/bmp/bmp.c323
-rw-r--r--apps/plugins/imageviewer/bmp/bmp.make21
-rw-r--r--apps/plugins/imageviewer/bmp/bmp_ui.c5
-rw-r--r--apps/plugins/imageviewer/jpeg/jpeg.c2
-rw-r--r--apps/plugins/imageviewer/png/png.c2
-rw-r--r--apps/plugins/viewers.config1
-rw-r--r--apps/recorder/bmp.c46
11 files changed, 396 insertions, 11 deletions
diff --git a/apps/filetypes.c b/apps/filetypes.c
index e74edff5c2..49ae4afde2 100644
--- a/apps/filetypes.c
+++ b/apps/filetypes.c
@@ -109,9 +109,6 @@ static const struct filetype inbuilt_filetypes[] = {
109#ifdef HAVE_REMOTE_LCD 109#ifdef HAVE_REMOTE_LCD
110 { "rwps",FILE_ATTR_RWPS, Icon_Wps, VOICE_EXT_RWPS }, 110 { "rwps",FILE_ATTR_RWPS, Icon_Wps, VOICE_EXT_RWPS },
111#endif 111#endif
112#if LCD_DEPTH > 1
113 { "bmp", FILE_ATTR_BMP, Icon_Wps, VOICE_EXT_WPS },
114#endif
115#if CONFIG_TUNER 112#if CONFIG_TUNER
116 { "fmr", FILE_ATTR_FMR, Icon_Preset, LANG_FMR }, 113 { "fmr", FILE_ATTR_FMR, Icon_Preset, LANG_FMR },
117#endif 114#endif
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index 218055e311..4951f0db9c 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -3,6 +3,7 @@ autostart,apps
3battery_bench,apps 3battery_bench,apps
4bench_scaler,apps 4bench_scaler,apps
5blackjack,games 5blackjack,games
6bmp,viewers
6boomshine,games 7boomshine,games
7bounce,demos 8bounce,demos
8brickmania,games 9brickmania,games
diff --git a/apps/plugins/imageviewer/SUBDIRS b/apps/plugins/imageviewer/SUBDIRS
index 6785e47781..ca9665a022 100644
--- a/apps/plugins/imageviewer/SUBDIRS
+++ b/apps/plugins/imageviewer/SUBDIRS
@@ -1,3 +1,4 @@
1bmp
1jpeg 2jpeg
2#ifdef HAVE_LCD_COLOR 3#ifdef HAVE_LCD_COLOR
3png 4png
diff --git a/apps/plugins/imageviewer/bmp/SOURCES b/apps/plugins/imageviewer/bmp/SOURCES
new file mode 100644
index 0000000000..a50d245846
--- /dev/null
+++ b/apps/plugins/imageviewer/bmp/SOURCES
@@ -0,0 +1,2 @@
1bmp_ui.c
2bmp.c
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}
diff --git a/apps/plugins/imageviewer/bmp/bmp.make b/apps/plugins/imageviewer/bmp/bmp.make
new file mode 100644
index 0000000000..0582ba3eb3
--- /dev/null
+++ b/apps/plugins/imageviewer/bmp/bmp.make
@@ -0,0 +1,21 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10BMPSRCDIR := $(IMGVSRCDIR)/bmp
11BMPBUILDDIR := $(IMGVBUILDDIR)/bmp
12
13ROCKS += $(BMPBUILDDIR)/bmp.rock
14
15BMP_SRC := $(call preprocess, $(BMPSRCDIR)/SOURCES)
16BMP_OBJ := $(call c2obj, $(BMP_SRC))
17
18# add source files to OTHER_SRC to get automatic dependencies
19OTHER_SRC += $(BMP_SRC)
20
21$(BMPBUILDDIR)/bmp.rock: $(BMP_OBJ)
diff --git a/apps/plugins/imageviewer/bmp/bmp_ui.c b/apps/plugins/imageviewer/bmp/bmp_ui.c
new file mode 100644
index 0000000000..8ff3e0c880
--- /dev/null
+++ b/apps/plugins/imageviewer/bmp/bmp_ui.c
@@ -0,0 +1,5 @@
1#define BMP_VIEWER
2#define MENU_TITLE "BMP Menu"
3#define UNSCALED_IS_AVAILABLE 1
4
5#include "../imageviewer.c"
diff --git a/apps/plugins/imageviewer/jpeg/jpeg.c b/apps/plugins/imageviewer/jpeg/jpeg.c
index 91e0c1021f..b16ec1c4b1 100644
--- a/apps/plugins/imageviewer/jpeg/jpeg.c
+++ b/apps/plugins/imageviewer/jpeg/jpeg.c
@@ -136,7 +136,7 @@ int load_image(char *filename, struct image_info *info,
136 fd = rb->open(filename, O_RDONLY); 136 fd = rb->open(filename, O_RDONLY);
137 if (fd < 0) 137 if (fd < 0)
138 { 138 {
139 rb->splashf(HZ, "err opening %s:%d", filename, fd); 139 rb->splashf(HZ, "err opening %s: %d", filename, fd);
140 return PLUGIN_ERROR; 140 return PLUGIN_ERROR;
141 } 141 }
142 filesize = rb->filesize(fd); 142 filesize = rb->filesize(fd);
diff --git a/apps/plugins/imageviewer/png/png.c b/apps/plugins/imageviewer/png/png.c
index 958793b37d..4a7e0963d9 100644
--- a/apps/plugins/imageviewer/png/png.c
+++ b/apps/plugins/imageviewer/png/png.c
@@ -1338,7 +1338,7 @@ int load_image(char *filename, struct image_info *info,
1338 fd = rb->open(filename, O_RDONLY); 1338 fd = rb->open(filename, O_RDONLY);
1339 if (fd < 0) 1339 if (fd < 0)
1340 { 1340 {
1341 rb->splashf(HZ, "err opening %s:%d", filename, fd); 1341 rb->splashf(HZ, "err opening %s: %d", filename, fd);
1342 return PLUGIN_ERROR; 1342 return PLUGIN_ERROR;
1343 } 1343 }
1344 image_size = rb->filesize(fd); 1344 image_size = rb->filesize(fd);
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index 985115672d..1c70c2957f 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -2,6 +2,7 @@ ch8,viewers/chip8,0
2txt,viewers/viewer,1 2txt,viewers/viewer,1
3nfo,viewers/viewer,1 3nfo,viewers/viewer,1
4txt,apps/text_editor,2 4txt,apps/text_editor,2
5bmp,viewers/bmp,2
5jpg,viewers/jpeg,2 6jpg,viewers/jpeg,2
6jpe,viewers/jpeg,2 7jpe,viewers/jpeg,2
7jpeg,viewers/jpeg,2 8jpeg,viewers/jpeg,2
diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c
index 4e8cdd70c5..81ed8bc73b 100644
--- a/apps/recorder/bmp.c
+++ b/apps/recorder/bmp.c
@@ -621,6 +621,8 @@ int read_bmp_fd(int fd,
621 defined(HAVE_BMP_SCALING) || defined(PLUGIN) 621 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
622 if(resize) 622 if(resize)
623 totalsize += BM_SCALED_SIZE(bm->width, 0, 0, 0); 623 totalsize += BM_SCALED_SIZE(bm->width, 0, 0, 0);
624 else if (bm->width > BM_MAX_WIDTH)
625 totalsize += bm->width*4;
624#endif 626#endif
625 return totalsize; 627 return totalsize;
626 } 628 }
@@ -717,9 +719,7 @@ int read_bmp_fd(int fd,
717 719
718#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \ 720#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
719 defined(HAVE_BMP_SCALING) || defined(PLUGIN) 721 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
720#if LCD_DEPTH > 1 && defined(HAVE_BMP_SCALING)
721 if (resize) 722 if (resize)
722#endif
723 { 723 {
724 if (resize_on_load(bm, dither, &src_dim, &rset, 724 if (resize_on_load(bm, dither, &src_dim, &rset,
725 bitmap + totalsize, maxsize - totalsize, 725 bitmap + totalsize, maxsize - totalsize,
@@ -749,17 +749,51 @@ int read_bmp_fd(int fd,
749#endif 749#endif
750#endif 750#endif
751 751
752 unsigned char *buf = ba.buf;
753#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) || \
754 defined(PLUGIN)
755 if (bm->width > BM_MAX_WIDTH)
756 {
757#if defined(HAVE_BMP_SCALING) || defined(PLUGIN)
758 unsigned int len = maxsize - totalsize;
759 buf = bitmap + totalsize;
760 ALIGN_BUFFER(buf, len, sizeof(uint32_t));
761 if (bm->width*4 > (int)len)
762#endif
763 return -6;
764 }
765#endif
766
752 int row; 767 int row;
753 /* loop to read rows and put them to buffer */ 768 /* loop to read rows and put them to buffer */
754 for (row = rset.rowstart; row != rset.rowstop; row += rset.rowstep) { 769 for (row = rset.rowstart; row != rset.rowstop; row += rset.rowstep) {
770#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
771 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
772 if (bm->width > BM_MAX_WIDTH)
773 {
774#if defined(HAVE_LCD_COLOR)
775 struct uint8_rgb *p = (struct uint8_rgb *)buf;
776#else
777 uint8_t* p = buf;
778#endif
779 do {
780 int len = read_part_line(&ba);
781 if (!len)
782 return -9;
783 memcpy(p, ba.buf, len*sizeof(*p));
784 p += len;
785 } while (ba.cur_col);
786 }
787 else
788#endif
755 if (!read_part_line(&ba)) 789 if (!read_part_line(&ba))
756 return -9; 790 return -9;
757#ifndef PLUGIN 791#ifndef PLUGIN
758#if !defined(HAVE_LCD_COLOR) && \ 792#if !defined(HAVE_LCD_COLOR) && \
759 (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) 793 (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1))
760 uint8_t* qp = ba.buf; 794 uint8_t* qp = buf;
761#else 795#else
762 struct uint8_rgb *qp = (struct uint8_rgb *)ba.buf; 796 struct uint8_rgb *qp = (struct uint8_rgb *)buf;
763#endif 797#endif
764#endif 798#endif
765 /* Convert to destination format */ 799 /* Convert to destination format */
@@ -798,9 +832,9 @@ int read_bmp_fd(int fd,
798#if LCD_DEPTH > 1 || defined(PLUGIN) 832#if LCD_DEPTH > 1 || defined(PLUGIN)
799 { 833 {
800#if !defined(PLUGIN) && !defined(HAVE_JPEG) && !defined(HAVE_BMP_SCALING) 834#if !defined(PLUGIN) && !defined(HAVE_JPEG) && !defined(HAVE_BMP_SCALING)
801 output_row_8_native(row, ba.buf, &ctx); 835 output_row_8_native(row, buf, &ctx);
802#else 836#else
803 output_row_8(row, ba.buf, &ctx); 837 output_row_8(row, buf, &ctx);
804#endif 838#endif
805 } 839 }
806#endif 840#endif