revert personal change accidentally included in r29110
[kugel-rb.git] / apps / plugins / imageviewer / image_decoder.c
blob416bda9e4240037fdb96945901a4426889de9ac2
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * load image decoder.
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 "imageviewer.h"
24 #include "image_decoder.h"
26 static const char *decoder_names[MAX_IMAGE_TYPES] = {
27 "bmp",
28 "jpeg",
29 "png",
30 #ifdef HAVE_LCD_COLOR
31 "ppm"
32 #endif
35 /* Check file type by magic number or file extension
37 * If the file contains magic number, use it to determine image type.
38 * Otherwise use file extension to determine image type.
39 * If the file contains magic number and file extension is not correct,
40 * informs user that something is wrong.
42 enum image_type get_image_type(const char *name, bool quiet)
44 static const struct {
45 char *ext;
46 enum image_type type;
47 } ext_list[] = {
48 { ".bmp", IMAGE_BMP },
49 { ".jpg", IMAGE_JPEG },
50 { ".jpe", IMAGE_JPEG },
51 { ".jpeg", IMAGE_JPEG },
52 { ".png", IMAGE_PNG },
53 #ifdef HAVE_LCD_COLOR
54 { ".ppm", IMAGE_PPM },
55 #endif
57 static const struct {
58 char *magic; /* magic number */
59 int length; /* length of the magic number */
60 enum image_type type;
61 } magic_list[] = {
62 { "BM", 2, IMAGE_BMP },
63 { "\xff\xd8\xff\xe0", 4, IMAGE_JPEG },
64 { "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8, IMAGE_PNG },
65 #ifdef HAVE_LCD_COLOR
66 { "P3", 2, IMAGE_PPM },
67 { "P6", 2, IMAGE_PPM },
68 #endif
71 enum image_type type = IMAGE_UNKNOWN;
72 const char *ext = rb->strrchr(name, '.');
73 int i, fd;
74 char buf[12];
76 /* check file extention */
77 if (ext)
79 for (i = 0; i < (int)ARRAYLEN(ext_list); i++)
81 if (!rb->strcasecmp(ext, ext_list[i].ext))
83 type = ext_list[i].type;
84 break;
89 /* check magic value in the file */
90 fd = rb->open(name, O_RDONLY);
91 if (fd >= 0)
93 rb->memset(buf, 0, sizeof buf);
94 rb->read(fd, buf, sizeof buf);
95 rb->close(fd);
96 for (i = 0; i < (int)ARRAYLEN(magic_list); i++)
98 if (!rb->memcmp(buf, magic_list[i].magic, magic_list[i].length))
100 if (!quiet && type != magic_list[i].type)
102 /* file extension is wrong. */
103 rb->splashf(HZ*1, "Note: File extension is not correct");
105 type = magic_list[i].type;
106 break;
110 return type;
113 static void *decoder_handle = NULL;
114 const struct image_decoder *load_decoder(struct loader_info *loader_info)
116 const char *name;
117 char filename[MAX_PATH];
118 struct imgdec_header *hdr;
119 struct lc_header *lc_hdr;
121 if (loader_info->type < 0 || loader_info->type >= MAX_IMAGE_TYPES)
123 rb->splashf(2*HZ, "Unknown type: %d", loader_info->type);
124 goto error;
127 release_decoder();
129 name = decoder_names[loader_info->type];
130 rb->snprintf(filename, MAX_PATH, VIEWERS_DIR "/%s.ovl", name);
132 /* load decoder to the buffer. */
133 decoder_handle = rb->lc_open(filename, loader_info->buffer, loader_info->size);
134 if (!decoder_handle)
136 rb->splashf(2*HZ, "Can't open %s", filename);
137 goto error;
140 hdr = rb->lc_get_header(decoder_handle);
141 if (!hdr)
143 rb->splash(2*HZ, "Can't get header");
144 goto error_close;
146 lc_hdr = &hdr->lc_hdr;
148 if (lc_hdr->magic != PLUGIN_MAGIC || lc_hdr->target_id != TARGET_ID)
150 rb->splashf(2*HZ, "%s decoder: Incompatible model.", name);
151 goto error_close;
154 if (lc_hdr->api_version != IMGDEC_API_VERSION)
156 rb->splashf(2*HZ, "%s decoder: Incompatible version.", name);
157 goto error_close;
160 *(hdr->api) = rb;
161 *(hdr->img_api) = loader_info->iv;
163 /* set remaining buffer size to loader_info. decoder will
164 * be loaded to the end of the buffer, so fix size only. */
165 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
166 loader_info->size = lc_hdr->load_addr - loader_info->buffer;
167 #endif
169 return hdr->decoder;
171 error_close:
172 release_decoder();
173 error:
174 return NULL;
177 void release_decoder(void)
179 if (decoder_handle != NULL)
181 rb->lc_close(decoder_handle);
182 decoder_handle = NULL;