blob: e2e02a2a500447062556af7586feb25a7304188c [file] [log] [blame]
Mats Lidell8a700fe2002-08-16 14:02:48 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Mats Lidell8a700fe2002-08-16 14:02:48 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
Jens Arnoldc5e87ae2005-07-07 22:32:42 +000021/****************************************************************************
Mats Lidell8a700fe2002-08-16 14:02:48 +000022 *
23 * Converts BMP files to Rockbox bitmap format
24 *
25 * 1999-05-03 Linus Nielsen Feltzing
26 *
Jens Arnoldc5e87ae2005-07-07 22:32:42 +000027 * 2005-07-06 Jens Arnold
28 * added reading of 4, 16, 24 and 32 bit bmps
29 * added 2 new target formats (playergfx and iriver 4-grey)
30 *
31 ****************************************************************************/
Mats Lidell8a700fe2002-08-16 14:02:48 +000032
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <stdbool.h>
Daniel Stenbergafecfe42008-04-10 21:16:00 +000037#include <unistd.h>
Mats Lidell8a700fe2002-08-16 14:02:48 +000038
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42
43#define debugf printf
44
45#ifdef __GNUC__
46#define STRUCT_PACKED __attribute__((packed))
47#else
48#define STRUCT_PACKED
49#pragma pack (push, 2)
50#endif
51
52struct Fileheader
53{
Jens Arnoldc5e87ae2005-07-07 22:32:42 +000054 unsigned short Type; /* signature - 'BM' */
Jens Arnold41e1aa82006-02-16 20:03:07 +000055 unsigned int Size; /* file size in bytes */
Jens Arnoldc5e87ae2005-07-07 22:32:42 +000056 unsigned short Reserved1; /* 0 */
57 unsigned short Reserved2; /* 0 */
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +000058 unsigned int OffBits; /* offset to bitmap */
59 unsigned int StructSize; /* size of this struct (40) */
60 unsigned int Width; /* bmap width in pixels */
61 unsigned int Height; /* bmap height in pixels */
Jens Arnoldc5e87ae2005-07-07 22:32:42 +000062 unsigned short Planes; /* num planes - always 1 */
63 unsigned short BitCount; /* bits per pixel */
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +000064 unsigned int Compression; /* compression flag */
65 unsigned int SizeImage; /* image size in bytes */
66 int XPelsPerMeter; /* horz resolution */
67 int YPelsPerMeter; /* vert resolution */
68 unsigned int ClrUsed; /* 0 -> color table size */
69 unsigned int ClrImportant; /* important color count */
Mats Lidell8a700fe2002-08-16 14:02:48 +000070} STRUCT_PACKED;
71
72struct RGBQUAD
73{
Jens Arnoldc5e87ae2005-07-07 22:32:42 +000074 unsigned char rgbBlue;
75 unsigned char rgbGreen;
76 unsigned char rgbRed;
77 unsigned char rgbReserved;
Mats Lidell8a700fe2002-08-16 14:02:48 +000078} STRUCT_PACKED;
79
Daniel Stenberg2d81cf92003-05-21 06:31:44 +000080short readshort(void* value)
81{
82 unsigned char* bytes = (unsigned char*) value;
83 return bytes[0] | (bytes[1] << 8);
84}
85
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +000086int readint(void* value)
Daniel Stenberg2d81cf92003-05-21 06:31:44 +000087{
88 unsigned char* bytes = (unsigned char*) value;
89 return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
90}
Mats Lidell8a700fe2002-08-16 14:02:48 +000091
Jens Arnold6ae81042005-07-28 16:31:02 +000092unsigned char brightness(struct RGBQUAD color)
Jens Arnoldc5e87ae2005-07-07 22:32:42 +000093{
Jens Arnold6ae81042005-07-28 16:31:02 +000094 return (3 * (unsigned int)color.rgbRed + 6 * (unsigned int)color.rgbGreen
95 + (unsigned int)color.rgbBlue) / 10;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +000096}
97
Daniel Stenberg635b8302006-02-28 07:36:38 +000098#ifndef O_BINARY
99#define O_BINARY 0 /* systems that don't have O_BINARY won't make a difference
100 on text and binary files */
101#endif
102
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000103/****************************************************************************
Mats Lidell8a700fe2002-08-16 14:02:48 +0000104 * read_bmp_file()
105 *
Jens Arnold6ae81042005-07-28 16:31:02 +0000106 * Reads an uncompressed BMP file and puts the data in a 4-byte-per-pixel
107 * (RGBQUAD) array. Returns 0 on success.
Mats Lidell8a700fe2002-08-16 14:02:48 +0000108 *
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000109 ***************************************************************************/
110
Mats Lidell8a700fe2002-08-16 14:02:48 +0000111int read_bmp_file(char* filename,
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000112 int *get_width, /* in pixels */
113 int *get_height, /* in pixels */
Jens Arnold6ae81042005-07-28 16:31:02 +0000114 struct RGBQUAD **bitmap)
Mats Lidell8a700fe2002-08-16 14:02:48 +0000115{
Daniel Stenberg793ca182002-08-21 12:11:51 +0000116 struct Fileheader fh;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000117 struct RGBQUAD palette[256];
Mats Lidell8a700fe2002-08-16 14:02:48 +0000118
Daniel Stenberg635b8302006-02-28 07:36:38 +0000119 int fd = open(filename, O_RDONLY| O_BINARY);
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000120 unsigned short data;
Daniel Stenberg793ca182002-08-21 12:11:51 +0000121 unsigned char *bmp;
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000122 int width, height;
123 int padded_width;
124 int size;
125 int row, col, i;
126 int numcolors, compression;
Daniel Stenberg793ca182002-08-21 12:11:51 +0000127 int depth;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000128
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000129 if (fd == -1)
Daniel Stenberg793ca182002-08-21 12:11:51 +0000130 {
131 debugf("error - can't open '%s'\n", filename);
132 return 1;
133 }
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000134 if (read(fd, &fh, sizeof(struct Fileheader)) !=
Mats Lidell8a700fe2002-08-16 14:02:48 +0000135 sizeof(struct Fileheader))
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000136 {
137 debugf("error - can't Read Fileheader Stucture\n");
138 close(fd);
139 return 2;
140 }
Greg White1ab8f322007-01-17 19:54:35 +0000141
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000142 compression = readint(&fh.Compression);
Mats Lidell8a700fe2002-08-16 14:02:48 +0000143
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000144 if (compression != 0)
145 {
Daniel Stenbergafecfe42008-04-10 21:16:00 +0000146 debugf("error - Unsupported compression %d\n", compression);
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000147 close(fd);
148 return 3;
149 }
Mats Lidell8a700fe2002-08-16 14:02:48 +0000150
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000151 depth = readshort(&fh.BitCount);
Mats Lidell8a700fe2002-08-16 14:02:48 +0000152
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000153 if (depth <= 8)
154 {
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000155 numcolors = readint(&fh.ClrUsed);
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000156 if (numcolors == 0)
157 numcolors = 1 << depth;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000158
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000159 if (read(fd, &palette[0], numcolors * sizeof(struct RGBQUAD))
Daniel Stenbergafecfe42008-04-10 21:16:00 +0000160 != (int)(numcolors * sizeof(struct RGBQUAD)))
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000161 {
162 debugf("error - Can't read bitmap's color palette\n");
163 close(fd);
164 return 4;
165 }
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000166 }
Daniel Stenberg793ca182002-08-21 12:11:51 +0000167
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000168 width = readint(&fh.Width);
169 height = readint(&fh.Height);
Jens Arnold9b1c9db2006-02-27 21:59:48 +0000170 padded_width = ((width * depth + 31) / 8) & ~3; /* aligned 4-bytes boundaries */
Daniel Stenberg793ca182002-08-21 12:11:51 +0000171
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000172 size = padded_width * height; /* read this many bytes */
173 bmp = (unsigned char *)malloc(size);
Jens Arnold6ae81042005-07-28 16:31:02 +0000174 *bitmap = (struct RGBQUAD *)malloc(width * height * sizeof(struct RGBQUAD));
Daniel Stenberg463e3292004-12-20 09:09:49 +0000175
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000176 if ((bmp == NULL) || (*bitmap == NULL))
177 {
178 debugf("error - Out of memory\n");
179 close(fd);
180 return 5;
181 }
Daniel Stenberg463e3292004-12-20 09:09:49 +0000182
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000183 if (lseek(fd, (off_t)readint(&fh.OffBits), SEEK_SET) < 0)
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000184 {
185 debugf("error - Can't seek to start of image data\n");
186 close(fd);
187 return 6;
188 }
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000189 if (read(fd, (unsigned char*)bmp, (int)size) != size)
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000190 {
191 debugf("error - Can't read image\n");
192 close(fd);
193 return 7;
194 }
Mats Lidell8a700fe2002-08-16 14:02:48 +0000195
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000196 close(fd);
197 *get_width = width;
198 *get_height = height;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000199
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000200 switch (depth)
201 {
202 case 1:
203 for (row = 0; row < height; row++)
204 for (col = 0; col < width; col++)
205 {
Jens Arnold6ae81042005-07-28 16:31:02 +0000206 data = (bmp[(height - 1 - row) * padded_width + col / 8]
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000207 >> (~col & 7)) & 1;
Jens Arnold6ae81042005-07-28 16:31:02 +0000208 (*bitmap)[row * width + col] = palette[data];
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000209 }
210 break;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000211
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000212 case 4:
213 for (row = 0; row < height; row++)
214 for (col = 0; col < width; col++)
215 {
Greg White1ab8f322007-01-17 19:54:35 +0000216 data = (bmp[(height - 1 - row) * padded_width + col / 2]
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000217 >> (4 * (~col & 1))) & 0x0F;
Jens Arnold6ae81042005-07-28 16:31:02 +0000218 (*bitmap)[row * width + col] = palette[data];
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000219 }
220 break;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000221
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000222 case 8:
223 for (row = 0; row < height; row++)
224 for (col = 0; col < width; col++)
225 {
226 data = bmp[(height - 1 - row) * padded_width + col];
Jens Arnold6ae81042005-07-28 16:31:02 +0000227 (*bitmap)[row * width + col] = palette[data];
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000228 }
229 break;
Greg White1ab8f322007-01-17 19:54:35 +0000230
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000231 case 16:
232 for (row = 0; row < height; row++)
233 for (col = 0; col < width; col++)
234 {
235 data = readshort(&bmp[(height - 1 - row) * padded_width + 2 * col]);
Jens Arnold6ae81042005-07-28 16:31:02 +0000236 (*bitmap)[row * width + col].rgbRed =
237 ((data >> 7) & 0xF8) | ((data >> 12) & 0x07);
238 (*bitmap)[row * width + col].rgbGreen =
239 ((data >> 2) & 0xF8) | ((data >> 7) & 0x07);
240 (*bitmap)[row * width + col].rgbBlue =
241 ((data << 3) & 0xF8) | ((data >> 2) & 0x07);
242 (*bitmap)[row * width + col].rgbReserved = 0;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000243 }
244 break;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000245
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000246 case 24:
247 for (row = 0; row < height; row++)
248 for (col = 0; col < width; col++)
249 {
250 i = (height - 1 - row) * padded_width + 3 * col;
Jens Arnold6ae81042005-07-28 16:31:02 +0000251 (*bitmap)[row * width + col].rgbRed = bmp[i+2];
252 (*bitmap)[row * width + col].rgbGreen = bmp[i+1];
253 (*bitmap)[row * width + col].rgbBlue = bmp[i];
254 (*bitmap)[row * width + col].rgbReserved = 0;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000255 }
256 break;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000257
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000258 case 32:
259 for (row = 0; row < height; row++)
260 for (col = 0; col < width; col++)
Greg White1ab8f322007-01-17 19:54:35 +0000261 {
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000262 i = (height - 1 - row) * padded_width + 4 * col;
Jens Arnold6ae81042005-07-28 16:31:02 +0000263 (*bitmap)[row * width + col].rgbRed = bmp[i+2];
264 (*bitmap)[row * width + col].rgbGreen = bmp[i+1];
265 (*bitmap)[row * width + col].rgbBlue = bmp[i];
266 (*bitmap)[row * width + col].rgbReserved = 0;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000267 }
268 break;
269
270 default: /* should never happen */
271 debugf("error - Unsupported bitmap depth %d.\n", depth);
272 return 8;
273 }
274
275 free(bmp);
Greg White1ab8f322007-01-17 19:54:35 +0000276
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000277 return 0; /* success */
Mats Lidell8a700fe2002-08-16 14:02:48 +0000278}
279
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000280/****************************************************************************
281 * transform_bitmap()
282 *
Jens Arnold6ae81042005-07-28 16:31:02 +0000283 * Transform a 4-byte-per-pixel bitmap (RGBQUAD) into one of the supported
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000284 * destination formats
285 ****************************************************************************/
286
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000287int transform_bitmap(const struct RGBQUAD *src, int width, int height,
288 int format, unsigned short **dest, int *dst_width,
Jens Arnold41e1aa82006-02-16 20:03:07 +0000289 int *dst_height, int *dst_depth)
Mats Lidell8a700fe2002-08-16 14:02:48 +0000290{
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000291 int row, col;
Jens Arnold41e1aa82006-02-16 20:03:07 +0000292 int dst_w, dst_h, dst_d;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000293
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000294 switch (format)
295 {
Jens Arnold780f79e2006-11-10 20:26:01 +0000296 case 0: /* Archos recorders, Ondio, Iriver H1x0 monochrome */
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000297 dst_w = width;
298 dst_h = (height + 7) / 8;
Jens Arnold41e1aa82006-02-16 20:03:07 +0000299 dst_d = 8;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000300 break;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000301
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000302 case 1: /* Archos player graphics library */
303 dst_w = (width + 7) / 8;
304 dst_h = height;
Jens Arnold41e1aa82006-02-16 20:03:07 +0000305 dst_d = 8;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000306 break;
Daniel Stenberg8c789752002-08-19 08:04:48 +0000307
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000308 case 2: /* Iriver H1x0 4-grey */
309 dst_w = width;
310 dst_h = (height + 3) / 4;
Jens Arnold41e1aa82006-02-16 20:03:07 +0000311 dst_d = 8;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000312 break;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000313
Jens Arnold6ae81042005-07-28 16:31:02 +0000314 case 3: /* Canonical 8-bit grayscale */
315 dst_w = width;
316 dst_h = height;
Jens Arnold41e1aa82006-02-16 20:03:07 +0000317 dst_d = 8;
Jens Arnold6ae81042005-07-28 16:31:02 +0000318 break;
319
Linus Nielsen Feltzing057c8ec2005-11-14 14:47:23 +0000320 case 4: /* 16-bit packed RGB (5-6-5) */
Dave Chapman4202df02005-11-15 02:20:05 +0000321 case 5: /* 16-bit packed and byte-swapped RGB (5-6-5) */
322 dst_w = width;
323 dst_h = height;
Jens Arnold41e1aa82006-02-16 20:03:07 +0000324 dst_d = 16;
325 break;
326
327 case 6: /* greyscale iPods 4-grey */
328 dst_w = (width + 3) / 4;
329 dst_h = height;
330 dst_d = 8;
Dave Chapman4202df02005-11-15 02:20:05 +0000331 break;
Greg White1ab8f322007-01-17 19:54:35 +0000332
Jens Arnold05ddd9a2006-07-28 07:35:45 +0000333 case 7: /* greyscale X5 remote 4-grey */
334 dst_w = width;
335 dst_h = (height + 7) / 8;
336 dst_d = 16;
337 break;
Dave Chapman4202df02005-11-15 02:20:05 +0000338
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000339 default: /* unknown */
340 debugf("error - Undefined destination format\n");
341 return 1;
342 }
Greg White1ab8f322007-01-17 19:54:35 +0000343
Linus Nielsen Feltzing36cca232005-11-30 09:06:43 +0000344 *dest = (unsigned short *)malloc(dst_w * dst_h * sizeof(short));
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000345 if (*dest == NULL)
346 {
347 debugf("error - Out of memory.\n");
348 return 2;
349 }
Linus Nielsen Feltzing6e461562005-11-30 09:02:59 +0000350 memset(*dest, 0, dst_w * dst_h * sizeof(short));
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000351 *dst_width = dst_w;
352 *dst_height = dst_h;
Jens Arnold41e1aa82006-02-16 20:03:07 +0000353 *dst_depth = dst_d;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000354
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000355 switch (format)
356 {
Jens Arnold780f79e2006-11-10 20:26:01 +0000357 case 0: /* Archos recorders, Ondio, Iriver H1x0 b&w */
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000358 for (row = 0; row < height; row++)
359 for (col = 0; col < width; col++)
360 {
Greg White1ab8f322007-01-17 19:54:35 +0000361 (*dest)[(row/8) * dst_w + col] |=
Jens Arnold6ae81042005-07-28 16:31:02 +0000362 (~brightness(src[row * width + col]) & 0x80) >> (~row & 7);
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000363 }
364 break;
365
366 case 1: /* Archos player graphics library */
367 for (row = 0; row < height; row++)
368 for (col = 0; col < width; col++)
369 {
Greg White1ab8f322007-01-17 19:54:35 +0000370 (*dest)[row * dst_w + (col/8)] |=
Jens Arnold6ae81042005-07-28 16:31:02 +0000371 (~brightness(src[row * width + col]) & 0x80) >> (col & 7);
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000372 }
373 break;
374
375 case 2: /* Iriver H1x0 4-grey */
376 for (row = 0; row < height; row++)
377 for (col = 0; col < width; col++)
378 {
379 (*dest)[(row/4) * dst_w + col] |=
Jens Arnold6ae81042005-07-28 16:31:02 +0000380 (~brightness(src[row * width + col]) & 0xC0) >> (2 * (~row & 3));
381 }
382 break;
383
384 case 3: /* Canonical 8-bit grayscale */
385 for (row = 0; row < height; row++)
386 for (col = 0; col < width; col++)
387 {
388 (*dest)[row * dst_w + col] = brightness(src[row * width + col]);
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000389 }
390 break;
Linus Nielsen Feltzing057c8ec2005-11-14 14:47:23 +0000391
392 case 4: /* 16-bit packed RGB (5-6-5) */
Dave Chapman4202df02005-11-15 02:20:05 +0000393 case 5: /* 16-bit packed and byte-swapped RGB (5-6-5) */
Linus Nielsen Feltzing057c8ec2005-11-14 14:47:23 +0000394 for (row = 0; row < height; row++)
395 for (col = 0; col < width; col++)
396 {
397 unsigned short rgb =
398 (((src[row * width + col].rgbRed >> 3) << 11) |
399 ((src[row * width + col].rgbGreen >> 2) << 5) |
400 ((src[row * width + col].rgbBlue >> 3)));
401
Dave Chapman4202df02005-11-15 02:20:05 +0000402 if (format == 4)
403 (*dest)[row * dst_w + col] = rgb;
404 else
405 (*dest)[row * dst_w + col] = ((rgb&0xff00)>>8)|((rgb&0x00ff)<<8);
Linus Nielsen Feltzing057c8ec2005-11-14 14:47:23 +0000406 }
407 break;
Greg White1ab8f322007-01-17 19:54:35 +0000408
Jens Arnold41e1aa82006-02-16 20:03:07 +0000409 case 6: /* greyscale iPods 4-grey */
410 for (row = 0; row < height; row++)
411 for (col = 0; col < width; col++)
412 {
413 (*dest)[row * dst_w + (col/4)] |=
Jens Arnoldfcab6172006-04-04 00:55:16 +0000414 (~brightness(src[row * width + col]) & 0xC0) >> (2 * (col & 3));
Jens Arnold41e1aa82006-02-16 20:03:07 +0000415 }
416 break;
Greg White1ab8f322007-01-17 19:54:35 +0000417
Jens Arnold05ddd9a2006-07-28 07:35:45 +0000418 case 7: /* greyscale X5 remote 4-grey */
419 for (row = 0; row < height; row++)
420 for (col = 0; col < width; col++)
421 {
422 unsigned short data = (~brightness(src[row * width + col]) & 0xC0) >> 6;
Greg White1ab8f322007-01-17 19:54:35 +0000423
Jens Arnold05ddd9a2006-07-28 07:35:45 +0000424 data = (data | (data << 7)) & 0x0101;
425 (*dest)[(row/8) * dst_w + col] |= data << (row & 7);
426 }
427 break;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000428 }
Greg White1ab8f322007-01-17 19:54:35 +0000429
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000430 return 0;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000431}
432
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000433/****************************************************************************
434 * generate_c_source()
435 *
436 * Outputs a C source code with the bitmap in an array, accompanied by
437 * some #define's
438 ****************************************************************************/
Mats Lidell8a700fe2002-08-16 14:02:48 +0000439
Dave Chapman95538f62006-02-21 01:23:30 +0000440void generate_c_source(char *id, char* header_dir, int width, int height,
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000441 const unsigned short *t_bitmap, int t_width,
Jens Arnold41e1aa82006-02-16 20:03:07 +0000442 int t_height, int t_depth)
Mats Lidell8a700fe2002-08-16 14:02:48 +0000443{
444 FILE *f;
Dave Chapman95538f62006-02-21 01:23:30 +0000445 FILE *fh;
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000446 int i, a;
Dave Chapman95538f62006-02-21 01:23:30 +0000447 char header_name[1024];
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000448
449 if (!id || !id[0])
450 id = "bitmap";
451
Dave Chapman95538f62006-02-21 01:23:30 +0000452 f = stdout;
453
454 if (header_dir && header_dir[0])
455 {
456 snprintf(header_name,sizeof(header_name),"%s/%s.h",header_dir,id);
457 fh = fopen(header_name,"w+");
458
459 if (fh == NULL)
460 {
461 debugf("error - can't open '%s'\n", header_name);
462 return;
463 }
464 fprintf(fh,
Daniel Stenbergafecfe42008-04-10 21:16:00 +0000465 "#define BMPHEIGHT_%s %d\n"
466 "#define BMPWIDTH_%s %d\n",
Dave Chapman95538f62006-02-21 01:23:30 +0000467 id, height, id, width);
468 if (t_depth <= 8)
469 fprintf(fh, "extern const unsigned char %s[];\n", id);
470 else
471 fprintf(fh, "extern const unsigned short %s[];\n", id);
472
473 fclose(fh);
474 } else {
475 fprintf(f,
Daniel Stenbergafecfe42008-04-10 21:16:00 +0000476 "#define BMPHEIGHT_%s %d\n"
477 "#define BMPWIDTH_%s %d\n",
Dave Chapman95538f62006-02-21 01:23:30 +0000478 id, height, id, width);
479 }
480
Jens Arnold41e1aa82006-02-16 20:03:07 +0000481 if (t_depth <= 8)
Linus Nielsen Feltzing057c8ec2005-11-14 14:47:23 +0000482 fprintf(f, "const unsigned char %s[] = {\n", id);
483 else
484 fprintf(f, "const unsigned short %s[] = {\n", id);
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000485
486 for (i = 0; i < t_height; i++)
487 {
488 for (a = 0; a < t_width; a++)
Linus Nielsen Feltzing057c8ec2005-11-14 14:47:23 +0000489 {
Jens Arnold41e1aa82006-02-16 20:03:07 +0000490 if (t_depth <= 8)
Linus Nielsen Feltzing057c8ec2005-11-14 14:47:23 +0000491 fprintf(f, "0x%02x,%c", t_bitmap[i * t_width + a],
492 (a + 1) % 13 ? ' ' : '\n');
493 else
494 fprintf(f, "0x%04x,%c", t_bitmap[i * t_width + a],
495 (a + 1) % 10 ? ' ' : '\n');
496 }
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000497 fprintf(f, "\n");
498 }
499
500 fprintf(f, "\n};\n");
501}
502
Daniel Stenbergafecfe42008-04-10 21:16:00 +0000503void generate_raw_file(const unsigned short *t_bitmap,
Dave Chapman024537d2007-01-18 09:30:25 +0000504 int t_width, int t_height, int t_depth)
Greg Whiteb3c66f52007-01-17 18:30:04 +0000505{
506 FILE *f;
507 int i, a;
Dave Chapman024537d2007-01-18 09:30:25 +0000508 unsigned char lo,hi;
Greg Whiteb3c66f52007-01-17 18:30:04 +0000509
510 f = stdout;
511
512 for (i = 0; i < t_height; i++)
513 {
514 for (a = 0; a < t_width; a++)
515 {
516 if (t_depth <= 8)
Dave Chapman024537d2007-01-18 09:30:25 +0000517 {
518 lo = (t_bitmap[i * t_width + a] & 0x00ff);
519 fwrite(&lo, 1, 1, f);
520 }
521 else
522 {
523 lo = (t_bitmap[i * t_width + a] & 0x00ff);
524 hi = (t_bitmap[i * t_width + a] & 0xff00) >> 8;
525 fwrite(&lo, 1, 1, f);
526 fwrite(&hi, 1, 1, f);
527 }
Greg Whiteb3c66f52007-01-17 18:30:04 +0000528 }
529 }
530}
531
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000532/****************************************************************************
533 * generate_ascii()
534 *
535 * Outputs an ascii picture of the bitmap
536 ****************************************************************************/
537
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000538void generate_ascii(int width, int height, struct RGBQUAD *bitmap)
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000539{
540 FILE *f;
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000541 int x, y;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000542
543 f = stdout;
544
545 /* for screen output debugging */
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000546 for (y = 0; y < height; y++)
547 {
548 for (x = 0; x < width; x++)
549 {
Jens Arnold6ae81042005-07-28 16:31:02 +0000550 fprintf(f, (brightness(bitmap[y * width + x]) & 0x80) ? " " : "*");
Mats Lidell8a700fe2002-08-16 14:02:48 +0000551 }
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000552 fprintf(f, "\n");
Mats Lidell8a700fe2002-08-16 14:02:48 +0000553 }
554}
555
556void print_usage(void)
557{
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000558 printf("Usage: %s [-i <id>] [-a] <bitmap file>\n"
559 "\t-i <id> Bitmap name (default is filename without extension)\n"
Dave Chapman95538f62006-02-21 01:23:30 +0000560 "\t-h <dir> Create header file in <dir>/<id>.h\n"
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000561 "\t-a Show ascii picture of bitmap\n"
Dave Chapman024537d2007-01-18 09:30:25 +0000562 "\t-r Generate RAW file (little-endian)\n"
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000563 "\t-f <n> Generate destination format n, default = 0\n"
Jens Arnold780f79e2006-11-10 20:26:01 +0000564 "\t 0 Archos recorder, Ondio, Iriver H1x0 mono\n"
Daniel Stenbergafecfe42008-04-10 21:16:00 +0000565 , APPLICATION_NAME);
566 printf("\t 1 Archos player graphics library\n"
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000567 "\t 2 Iriver H1x0 4-grey\n"
Jens Arnold05ddd9a2006-07-28 07:35:45 +0000568 "\t 3 Canonical 8-bit greyscale\n"
Linus Nielsen Feltzing057c8ec2005-11-14 14:47:23 +0000569 "\t 4 16-bit packed 5-6-5 RGB (iriver H300)\n"
Dave Chapman4202df02005-11-15 02:20:05 +0000570 "\t 5 16-bit packed and byte-swapped 5-6-5 RGB (iPod)\n"
Jens Arnold05ddd9a2006-07-28 07:35:45 +0000571 "\t 6 Greyscale iPod 4-grey\n"
Daniel Stenbergafecfe42008-04-10 21:16:00 +0000572 "\t 7 Greyscale X5 remote 4-grey\n");
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000573 printf("build date: " __DATE__ "\n\n");
Mats Lidell8a700fe2002-08-16 14:02:48 +0000574}
575
576int main(int argc, char **argv)
577{
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000578 char *bmp_filename = NULL;
579 char *id = NULL;
Dave Chapman95538f62006-02-21 01:23:30 +0000580 char* header_dir = NULL;
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000581 int i;
582 int ascii = false;
583 int format = 0;
Jens Arnold6ae81042005-07-28 16:31:02 +0000584 struct RGBQUAD *bitmap = NULL;
Linus Nielsen Feltzing057c8ec2005-11-14 14:47:23 +0000585 unsigned short *t_bitmap = NULL;
Daniel Stenbergdcc9a8a2006-02-08 13:05:37 +0000586 int width, height;
Jens Arnold41e1aa82006-02-16 20:03:07 +0000587 int t_width, t_height, t_depth;
Greg Whiteb3c66f52007-01-17 18:30:04 +0000588 bool raw = false;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000589
Mats Lidell8a700fe2002-08-16 14:02:48 +0000590
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000591 for (i = 1;i < argc;i++)
592 {
593 if (argv[i][0] == '-')
594 {
595 switch (argv[i][1])
596 {
Dave Chapman95538f62006-02-21 01:23:30 +0000597 case 'h': /* .h filename */
598 if (argv[i][2])
599 {
600 header_dir = &argv[i][2];
601 }
602 else if (argc > i+1)
603 {
604 header_dir = argv[i+1];
605 i++;
606 }
607 else
608 {
609 print_usage();
610 exit(1);
611 }
612 break;
613
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000614 case 'i': /* ID */
615 if (argv[i][2])
616 {
617 id = &argv[i][2];
618 }
619 else if (argc > i+1)
620 {
621 id = argv[i+1];
622 i++;
623 }
624 else
625 {
626 print_usage();
627 exit(1);
628 }
629 break;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000630
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000631 case 'a': /* Ascii art */
632 ascii = true;
633 break;
Greg White1ab8f322007-01-17 19:54:35 +0000634
635 case 'r': /* Raw File */
Greg Whiteb3c66f52007-01-17 18:30:04 +0000636 raw = true;
637 break;
Greg White1ab8f322007-01-17 19:54:35 +0000638
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000639 case 'f':
640 if (argv[i][2])
641 {
642 format = atoi(&argv[i][2]);
643 }
644 else if (argc > i+1)
645 {
646 format = atoi(argv[i+1]);
647 i++;
648 }
649 else
650 {
651 print_usage();
652 exit(1);
653 }
654 break;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000655
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000656 default:
657 print_usage();
658 exit(1);
659 break;
660 }
661 }
662 else
663 {
664 if (!bmp_filename)
665 {
666 bmp_filename = argv[i];
667 }
668 else
669 {
670 print_usage();
671 exit(1);
672 }
673 }
674 }
Mats Lidell8a700fe2002-08-16 14:02:48 +0000675
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000676 if (!bmp_filename)
677 {
678 print_usage();
679 exit(1);
680 }
681
682 if (!id)
683 {
684 char *ptr=strrchr(bmp_filename, '/');
685 if (ptr)
686 ptr++;
687 else
688 ptr = bmp_filename;
689 id = strdup(ptr);
690 for (i = 0; id[i]; i++)
691 if (id[i] == '.')
692 id[i] = '\0';
693 }
694
695 if (read_bmp_file(bmp_filename, &width, &height, &bitmap))
696 exit(1);
Greg White1ab8f322007-01-17 19:54:35 +0000697
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000698
699 if (ascii)
700 {
701 generate_ascii(width, height, bitmap);
702 }
703 else
704 {
Dave Chapman024537d2007-01-18 09:30:25 +0000705 if (transform_bitmap(bitmap, width, height, format, &t_bitmap,
706 &t_width, &t_height, &t_depth))
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000707 exit(1);
Greg Whiteb3c66f52007-01-17 18:30:04 +0000708 if(raw)
Daniel Stenbergafecfe42008-04-10 21:16:00 +0000709 generate_raw_file(t_bitmap, t_width, t_height, t_depth);
Greg Whiteb3c66f52007-01-17 18:30:04 +0000710 else
Dave Chapman024537d2007-01-18 09:30:25 +0000711 generate_c_source(id, header_dir, width, height, t_bitmap,
712 t_width, t_height, t_depth);
Jens Arnoldc5e87ae2005-07-07 22:32:42 +0000713 }
714
715 return 0;
Mats Lidell8a700fe2002-08-16 14:02:48 +0000716}