Don't objcopy simulator plugins.
[kugel-rb.git] / apps / plugins / ppmviewer.c
blob97f085ad6f1d330ae9842fec8c4dc0c1cc742f83
1 /*****************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ /
5 * Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) (
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include "plugin.h"
23 #include "lib/bmp.h"
25 #if defined(HAVE_LCD_COLOR)
27 PLUGIN_HEADER
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)
48 char i1, i2;
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." );
53 return PLUGIN_ERROR;
55 return i1 * 256 + i2;
58 char ppm_getc(int fd)
60 char ch;
62 if (!rb->read(fd, &ch, 1)) {
63 ppm_error("EOF. Read error reading a byte");
64 return PLUGIN_ERROR;
67 if (ch == '#') {
68 do {
69 if (!rb->read(fd, &ch, 1)) {
70 ppm_error("EOF. Read error reading a byte");
71 return PLUGIN_ERROR;
73 } while (ch != '\n' && ch != '\r');
75 return ch;
78 int ppm_getuint(int fd)
80 char ch;
81 int i;
82 int digitVal;
84 do {
85 ch = ppm_getc(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);
90 return PLUGIN_ERROR;
93 i = 0;
95 do {
96 digitVal = ch - '0';
98 if (i > INT_MAX/10 - digitVal) {
99 ppm_error("ASCII decimal integer in file is "\
100 "too large to be processed.");
101 return PLUGIN_ERROR;
104 i = i * 10 + digitVal;
105 ch = ppm_getc(fd);
107 } while (ch >= '0' && ch <= '9');
109 return i;
112 int ppm_getrawbyte(int fd)
114 unsigned char by;
116 if (!rb->read(fd, &by, 1)) {
117 ppm_error("EOF. Read error while reading a one-byte sample.");
118 return PLUGIN_ERROR;
121 return (int)by;
124 int ppm_getrawsample(int fd, int const maxval)
126 if (maxval < 256) {
127 /* The sample is just one byte. Read it. */
128 return(ppm_getrawbyte(fd));
129 } else {
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.");
135 return PLUGIN_ERROR;
137 return((byte_pair[0]<<8) | byte_pair[1]);
141 int read_ppm_init_rest(int fd,
142 int * const cols,
143 int * const rows,
144 int * const maxval)
146 /* Read size. */
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);
155 return PLUGIN_ERROR;
158 /* Read maxval. */
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);
165 return PLUGIN_ERROR;
167 if (*maxval == 0) {
168 ppm_error("maxval of input image is zero.");
169 return PLUGIN_ERROR;
171 return 1;
174 void read_ppm_init(int fd,
175 int * const cols,
176 int * const rows,
177 int * const maxval,
178 int * const format)
180 /* Check magic number. */
181 *format = ppm_read_magic_number( fd );
183 if (*format == PLUGIN_ERROR) return;
184 switch (*format) {
185 case PPM_FORMAT:
186 case RPPM_FORMAT:
187 if(read_ppm_init_rest(fd, cols, rows, maxval) == PLUGIN_ERROR) {
188 *format = PLUGIN_ERROR;
190 break;
192 default:
193 ppm_error( "Bad magic number - not a ppm or rppm file." );
194 *format = PLUGIN_ERROR;
198 int read_ppm_row(int fd,
199 int const row,
200 int const cols,
201 int const maxval,
202 int const format)
204 int col;
205 int r, g, b;
206 switch (format) {
207 case PPM_FORMAT:
208 for (col = 0; col < cols; ++col) {
209 r = ppm_getuint(fd);
210 g = ppm_getuint(fd);
211 b = ppm_getuint(fd);
213 if (r == PLUGIN_ERROR || g == PLUGIN_ERROR ||
214 b == PLUGIN_ERROR)
216 return PLUGIN_ERROR;
218 buffer[(cols * row) + col] = LCD_RGBPACK(
219 (255 / maxval) * r,
220 (255 / maxval) * g,
221 (255 / maxval) * b);
223 break;
225 case RPPM_FORMAT:
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 ||
232 b == PLUGIN_ERROR)
234 return PLUGIN_ERROR;
236 buffer[(cols * row) + col] = LCD_RGBPACK(
237 (255 / maxval) * r,
238 (255 / maxval) * g,
239 (255 / maxval) * b);
241 break;
243 default:
244 ppm_error("What?!");
245 return PLUGIN_ERROR;
247 return 1;
250 int read_ppm(int fd,
251 int * const cols,
252 int * const rows,
253 int * const maxval)
255 int row;
256 int format;
258 read_ppm_init(fd, cols, rows, maxval, &format);
260 if(format == PLUGIN_ERROR) {
261 return PLUGIN_ERROR;
264 for (row = 0; row < *rows; ++row) {
265 if( read_ppm_row(fd, row, *cols, *maxval, format) == PLUGIN_ERROR) {
266 return PLUGIN_ERROR;
269 return 1;
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];
276 int fd;
278 int cols;
279 int rows;
280 int maxval;
282 int result;
284 struct bitmap small_bitmap, orig_bitmap;
286 if(!parameter) return PLUGIN_ERROR;
288 rb = api;
290 rb->strcpy(filename, parameter);
292 fd = rb->open(filename, O_RDONLY);
293 if (fd < 0)
295 ppm_error("Couldnt open file: %s, %d", filename, fd);
296 return PLUGIN_ERROR;
299 result = read_ppm(fd, &cols, &rows, &maxval);
301 rb->close(fd);
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 */
317 small_bitmap.width =
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);
327 } else {
328 rb->lcd_bitmap((fb_data*)orig_bitmap.data, 0, 0, cols, rows);
330 rb->lcd_update();
331 rb->button_get(true);
333 return PLUGIN_OK;
336 #endif