1 /*****************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ /
5 * Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) (
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 Alexander Papst
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 ****************************************************************************/
23 #include "lib/pluginlib_bmp.h"
25 #if defined(HAVE_LCD_COLOR)
29 /* Magic constants. */
30 #define PPM_MAGIC1 'P'
31 #define PPM_MAGIC2 '3'
32 #define RPPM_MAGIC2 '6'
33 #define PPM_FORMAT (PPM_MAGIC1 * 256 + PPM_MAGIC2)
34 #define RPPM_FORMAT (PPM_MAGIC1 * 256 + RPPM_MAGIC2)
36 #define PPM_OVERALLMAXVAL 65535
37 #define PPM_MAXSIZE (300*1024)/sizeof(fb_data)
39 #define ppm_error(...) rb->splashf(HZ*2, __VA_ARGS__ )
41 static fb_data buffer
[PPM_MAXSIZE
];
42 static fb_data lcd_buf
[LCD_WIDTH
* LCD_HEIGHT
];
44 int ppm_read_magic_number(int fd
)
47 if(!rb
->read(fd
, &i1
, 1) || !rb
->read(fd
, &i2
, 1))
49 ppm_error( "Error reading magic number from ppm image stream. "\
50 "Most often, this means your input file is empty." );
60 if (!rb
->read(fd
, &ch
, 1)) {
61 ppm_error("EOF. Read error reading a byte");
67 if (!rb
->read(fd
, &ch
, 1)) {
68 ppm_error("EOF. Read error reading a byte");
71 } while (ch
!= '\n' && ch
!= '\r');
76 int ppm_getuint(int fd
)
84 } while (ch
== ' ' || ch
== '\t' || ch
== '\n' || ch
== '\r');
86 if (ch
< '0' || ch
> '9') {
87 ppm_error("Junk (%c) in file where an integer should be.", ch
);
96 if (i
> INT_MAX
/10 - digitVal
) {
97 ppm_error("ASCII decimal integer in file is "\
98 "too large to be processed.");
102 i
= i
* 10 + digitVal
;
105 } while (ch
>= '0' && ch
<= '9');
110 int ppm_getrawbyte(int fd
)
114 if (!rb
->read(fd
, &by
, 1)) {
115 ppm_error("EOF. Read error while reading a one-byte sample.");
122 int ppm_getrawsample(int fd
, int const maxval
)
125 /* The sample is just one byte. Read it. */
126 return(ppm_getrawbyte(fd
));
128 /* The sample is two bytes. Read both. */
129 unsigned char byte_pair
[2];
131 if (!rb
->read(fd
, byte_pair
, 2)) {
132 ppm_error("EOF. Read error while reading a long sample.");
135 return((byte_pair
[0]<<8) | byte_pair
[1]);
139 int read_ppm_init_rest(int fd
,
145 *cols
= ppm_getuint(fd
);
146 *rows
= ppm_getuint(fd
);
148 if ((long unsigned int)(*cols
* *rows
) > PPM_MAXSIZE
) {
149 ppm_error("Imagesize (%ld pixels) is too large. "\
150 "The maximum allowed is %ld.",
151 (long unsigned int)(*cols
* *rows
),
152 (long unsigned int)PPM_MAXSIZE
);
157 *maxval
= ppm_getuint(fd
);
159 if (*maxval
> PPM_OVERALLMAXVAL
) {
160 ppm_error("maxval of input image (%u) is too large. "\
161 "The maximum allowed by the PPM is %u.",
162 *maxval
, PPM_OVERALLMAXVAL
);
166 ppm_error("maxval of input image is zero.");
172 void read_ppm_init(int fd
,
178 /* Check magic number. */
179 *format
= ppm_read_magic_number( fd
);
181 if (*format
== PLUGIN_ERROR
) return;
185 if(read_ppm_init_rest(fd
, cols
, rows
, maxval
) == PLUGIN_ERROR
) {
186 *format
= PLUGIN_ERROR
;
191 ppm_error( "Bad magic number - not a ppm or rppm file." );
192 *format
= PLUGIN_ERROR
;
196 #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
197 #define BUFADDR(x, y, width, height) ( buffer + height*(x) + (y))
199 #define BUFADDR(x, y, width, height) ( buffer + width*(y) + (x))
202 int read_ppm_row(int fd
,
209 #if !(defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE)
217 for (col
= 0; col
< cols
; ++col
) {
222 if (r
== PLUGIN_ERROR
|| g
== PLUGIN_ERROR
||
227 *BUFADDR(col
, row
, cols
, rows
) = LCD_RGBPACK(
235 for (col
= 0; col
< cols
; ++col
) {
236 r
= ppm_getrawsample(fd
, maxval
);
237 g
= ppm_getrawsample(fd
, maxval
);
238 b
= ppm_getrawsample(fd
, maxval
);
240 if (r
== PLUGIN_ERROR
|| g
== PLUGIN_ERROR
||
245 *BUFADDR(col
, row
, cols
, rows
) = LCD_RGBPACK(
267 read_ppm_init(fd
, cols
, rows
, maxval
, &format
);
269 if(format
== PLUGIN_ERROR
) {
273 for (row
= 0; row
< *rows
; ++row
) {
274 if( read_ppm_row(fd
, row
, *cols
, *rows
, *maxval
, format
) == PLUGIN_ERROR
) {
281 /* this is the plugin entry point */
282 enum plugin_status
plugin_start(const void* parameter
)
284 static char filename
[MAX_PATH
];
293 struct bitmap small_bitmap
, orig_bitmap
;
295 if(!parameter
) return PLUGIN_ERROR
;
297 rb
->strcpy(filename
, parameter
);
299 fd
= rb
->open(filename
, O_RDONLY
);
302 ppm_error("Couldnt open file: %s, %d", filename
, fd
);
306 result
= read_ppm(fd
, &cols
, &rows
, &maxval
);
309 if(result
== PLUGIN_ERROR
) return PLUGIN_ERROR
;
311 orig_bitmap
.width
= cols
;
312 orig_bitmap
.height
= rows
;
313 orig_bitmap
.data
= (char*)buffer
;
315 if (cols
> LCD_WIDTH
|| rows
> LCD_HEIGHT
)
317 if (cols
> LCD_WIDTH
) {
318 small_bitmap
.width
= LCD_WIDTH
;
319 small_bitmap
.height
=
320 (int)(((float)LCD_WIDTH
/ (float)cols
) * (float)rows
);
322 } else { /* rows > LCD_HEIGHT */
325 (int)(((float)LCD_HEIGHT
/ (float)rows
) * (float)cols
);
326 small_bitmap
.height
= LCD_HEIGHT
;
328 small_bitmap
.data
= (char*)lcd_buf
;
330 smooth_resize_bitmap( &orig_bitmap
, &small_bitmap
);
332 rb
->lcd_bitmap((fb_data
*)small_bitmap
.data
, 0, 0,
333 small_bitmap
.width
, small_bitmap
.height
);
335 rb
->lcd_bitmap((fb_data
*)orig_bitmap
.data
, 0, 0, cols
, rows
);
338 rb
->button_get(true);