1 /*****************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ /
5 * Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) (
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 Alexander Papst
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
23 #if defined(HAVE_LCD_COLOR)
27 /* Magic constants. */
28 #define PPM_MAGIC1 'P'
29 #define PPM_MAGIC2 '3'
30 #define RPPM_MAGIC2 '6'
31 #define PPM_FORMAT (PPM_MAGIC1 * 256 + PPM_MAGIC2)
32 #define RPPM_FORMAT (PPM_MAGIC1 * 256 + RPPM_MAGIC2)
34 #define PPM_OVERALLMAXVAL 65535
35 #define PPM_MAXSIZE (300*1024)/sizeof(fb_data)
37 #define ppm_error(...) rb->splash(HZ*2, __VA_ARGS__ )
39 static fb_data buffer
[PPM_MAXSIZE
];
40 static fb_data lcd_buf
[LCD_WIDTH
* LCD_HEIGHT
];
42 static const struct plugin_api
* rb
; /* global api struct pointer */
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 int read_ppm_row(int fd
,
206 for (col
= 0; col
< cols
; ++col
) {
211 if (r
== PLUGIN_ERROR
|| g
== PLUGIN_ERROR
||
216 buffer
[(cols
* row
) + col
] = LCD_RGBPACK(
224 for (col
= 0; col
< cols
; ++col
) {
225 r
= ppm_getrawsample(fd
, maxval
);
226 g
= ppm_getrawsample(fd
, maxval
);
227 b
= ppm_getrawsample(fd
, maxval
);
229 if (r
== PLUGIN_ERROR
|| g
== PLUGIN_ERROR
||
234 buffer
[(cols
* row
) + col
] = LCD_RGBPACK(
256 read_ppm_init(fd
, cols
, rows
, maxval
, &format
);
258 if(format
== PLUGIN_ERROR
) {
262 for (row
= 0; row
< *rows
; ++row
) {
263 if( read_ppm_row(fd
, row
, *cols
, *maxval
, format
) == PLUGIN_ERROR
) {
270 /* this is the plugin entry point */
271 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
273 static char filename
[MAX_PATH
];
282 struct bitmap small_bitmap
, orig_bitmap
;
284 if(!parameter
) return PLUGIN_ERROR
;
288 rb
->strcpy(filename
, parameter
);
290 fd
= rb
->open(filename
, O_RDONLY
);
293 ppm_error("Couldnt open file: %s, %d", filename
, fd
);
297 result
= read_ppm(fd
, &cols
, &rows
, &maxval
);
300 if(result
== PLUGIN_ERROR
) return PLUGIN_ERROR
;
302 orig_bitmap
.width
= cols
;
303 orig_bitmap
.height
= rows
;
304 orig_bitmap
.data
= (char*)buffer
;
306 if (cols
> LCD_WIDTH
|| rows
> LCD_HEIGHT
)
308 if (cols
> LCD_WIDTH
) {
309 small_bitmap
.width
= LCD_WIDTH
;
310 small_bitmap
.height
=
311 (int)(((float)LCD_WIDTH
/ (float)cols
) * (float)rows
);
313 } else { /* rows > LCD_HEIGHT */
316 (int)(((float)LCD_HEIGHT
/ (float)rows
) * (float)cols
);
317 small_bitmap
.height
= LCD_HEIGHT
;
319 small_bitmap
.data
= (char*)lcd_buf
;
321 smooth_resize_bitmap( &orig_bitmap
, &small_bitmap
);
323 rb
->lcd_bitmap((fb_data
*)small_bitmap
.data
, 0, 0,
324 small_bitmap
.width
, small_bitmap
.height
);
326 rb
->lcd_bitmap((fb_data
*)orig_bitmap
.data
, 0, 0, cols
, rows
);
329 rb
->button_get(true);