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 ****************************************************************************/
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 static const struct plugin_api
* rb
; /* global api struct pointer */
46 int ppm_read_magic_number(int fd
)
49 if(!rb
->read(fd
, &i1
, 1) || !rb
->read(fd
, &i2
, 1))
51 ppm_error( "Error reading magic number from ppm image stream. "\
52 "Most often, this means your input file is empty." );
62 if (!rb
->read(fd
, &ch
, 1)) {
63 ppm_error("EOF. Read error reading a byte");
69 if (!rb
->read(fd
, &ch
, 1)) {
70 ppm_error("EOF. Read error reading a byte");
73 } while (ch
!= '\n' && ch
!= '\r');
78 int ppm_getuint(int fd
)
86 } while (ch
== ' ' || ch
== '\t' || ch
== '\n' || ch
== '\r');
88 if (ch
< '0' || ch
> '9') {
89 ppm_error("Junk (%c) in file where an integer should be.", ch
);
98 if (i
> INT_MAX
/10 - digitVal
) {
99 ppm_error("ASCII decimal integer in file is "\
100 "too large to be processed.");
104 i
= i
* 10 + digitVal
;
107 } while (ch
>= '0' && ch
<= '9');
112 int ppm_getrawbyte(int fd
)
116 if (!rb
->read(fd
, &by
, 1)) {
117 ppm_error("EOF. Read error while reading a one-byte sample.");
124 int ppm_getrawsample(int fd
, int const maxval
)
127 /* The sample is just one byte. Read it. */
128 return(ppm_getrawbyte(fd
));
130 /* The sample is two bytes. Read both. */
131 unsigned char byte_pair
[2];
133 if (!rb
->read(fd
, byte_pair
, 2)) {
134 ppm_error("EOF. Read error while reading a long sample.");
137 return((byte_pair
[0]<<8) | byte_pair
[1]);
141 int read_ppm_init_rest(int fd
,
147 *cols
= ppm_getuint(fd
);
148 *rows
= ppm_getuint(fd
);
150 if ((long unsigned int)(*cols
* *rows
) > PPM_MAXSIZE
) {
151 ppm_error("Imagesize (%ld pixels) is too large. "\
152 "The maximum allowed is %ld.",
153 (long unsigned int)(*cols
* *rows
),
154 (long unsigned int)PPM_MAXSIZE
);
159 *maxval
= ppm_getuint(fd
);
161 if (*maxval
> PPM_OVERALLMAXVAL
) {
162 ppm_error("maxval of input image (%u) is too large. "\
163 "The maximum allowed by the PPM is %u.",
164 *maxval
, PPM_OVERALLMAXVAL
);
168 ppm_error("maxval of input image is zero.");
174 void read_ppm_init(int fd
,
180 /* Check magic number. */
181 *format
= ppm_read_magic_number( fd
);
183 if (*format
== PLUGIN_ERROR
) return;
187 if(read_ppm_init_rest(fd
, cols
, rows
, maxval
) == PLUGIN_ERROR
) {
188 *format
= PLUGIN_ERROR
;
193 ppm_error( "Bad magic number - not a ppm or rppm file." );
194 *format
= PLUGIN_ERROR
;
198 int read_ppm_row(int fd
,
208 for (col
= 0; col
< cols
; ++col
) {
213 if (r
== PLUGIN_ERROR
|| g
== PLUGIN_ERROR
||
218 buffer
[(cols
* row
) + col
] = LCD_RGBPACK(
226 for (col
= 0; col
< cols
; ++col
) {
227 r
= ppm_getrawsample(fd
, maxval
);
228 g
= ppm_getrawsample(fd
, maxval
);
229 b
= ppm_getrawsample(fd
, maxval
);
231 if (r
== PLUGIN_ERROR
|| g
== PLUGIN_ERROR
||
236 buffer
[(cols
* row
) + col
] = LCD_RGBPACK(
258 read_ppm_init(fd
, cols
, rows
, maxval
, &format
);
260 if(format
== PLUGIN_ERROR
) {
264 for (row
= 0; row
< *rows
; ++row
) {
265 if( read_ppm_row(fd
, row
, *cols
, *maxval
, format
) == PLUGIN_ERROR
) {
272 /* this is the plugin entry point */
273 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
275 static char filename
[MAX_PATH
];
284 struct bitmap small_bitmap
, orig_bitmap
;
286 if(!parameter
) return PLUGIN_ERROR
;
290 rb
->strcpy(filename
, parameter
);
292 fd
= rb
->open(filename
, O_RDONLY
);
295 ppm_error("Couldnt open file: %s, %d", filename
, fd
);
299 result
= read_ppm(fd
, &cols
, &rows
, &maxval
);
302 if(result
== PLUGIN_ERROR
) return PLUGIN_ERROR
;
304 orig_bitmap
.width
= cols
;
305 orig_bitmap
.height
= rows
;
306 orig_bitmap
.data
= (char*)buffer
;
308 if (cols
> LCD_WIDTH
|| rows
> LCD_HEIGHT
)
310 if (cols
> LCD_WIDTH
) {
311 small_bitmap
.width
= LCD_WIDTH
;
312 small_bitmap
.height
=
313 (int)(((float)LCD_WIDTH
/ (float)cols
) * (float)rows
);
315 } else { /* rows > LCD_HEIGHT */
318 (int)(((float)LCD_HEIGHT
/ (float)rows
) * (float)cols
);
319 small_bitmap
.height
= LCD_HEIGHT
;
321 small_bitmap
.data
= (char*)lcd_buf
;
323 smooth_resize_bitmap( &orig_bitmap
, &small_bitmap
);
325 rb
->lcd_bitmap((fb_data
*)small_bitmap
.data
, 0, 0,
326 small_bitmap
.width
, small_bitmap
.height
);
328 rb
->lcd_bitmap((fb_data
*)orig_bitmap
.data
, 0, 0, cols
, rows
);
331 rb
->button_get(true);