summaryrefslogtreecommitdiff
path: root/rbutil/ibassoboot/jni
diff options
context:
space:
mode:
authorSimon Rothen <rothen@gmx.net>2014-08-30 13:15:53 +0200
committerMichael Giacomelli <giac2000@hotmail.com>2014-09-18 18:19:01 +0200
commit0b5ad60c26f30dc5363c21e436b73292c09ac567 (patch)
tree2d7cee2b2133218d59e0f462c9dbdbec8e88b2e2 /rbutil/ibassoboot/jni
parent1f0fa0546647a191c52784a4a225982ffbd1af11 (diff)
downloadrockbox-0b5ad60c26f30dc5363c21e436b73292c09ac567.tar.gz
rockbox-0b5ad60c26f30dc5363c21e436b73292c09ac567.zip
Introducing Targets iBasso DX50 & iBasso DX90
The port to for this two targets has been entirely developped by Ilia Sergachev (alias Il or xzcc). His source can be found at https://bitbucket.org/isergachev/rockbox . The few necesary modifications for the DX90 port was done by headwhacker form head-fi.org. Unfortunately i could not try out the final state of the DX90 port. The port is hosted on android (without java) as standalone app. The official Firmware is required to run this port. Ilia did modify the source files for the "android" target in the rockbox source to make the DX port work. The work I did was to separate the code for DX50 (&DX90) from the android target. On this Target Ilia used source from tinyalsa from AOSP. I did not touch that part of the code because I do not understand it. What else I changed from Ilias sources besides the separation from the target "android": * removed a dirty hack to keep backlight off * changed value battery meter to voltage battery meter * made all plugins compile (named target as "standalone") and added keymaps * i added the graphics for the manual but did not do anything else for the manual yet * minor optimizations known bugs: * timers are slowed donw when playback is active (tinyalsa related?) * some minor bugs Things to do: * The main prolem will be how to install the app correctly. A guy called DOC2008 added a CWM (by androtab.info) to the official firmware and Ilia made a CWM installation script and a dualboot selector (rbutils/ibassoboot, build with ndk-build). We will have to find a way to install rockbox in a proper way without breaking any copyrights. Maybe ADB is an option but it is not enable with OF by default. Patching the OF is probably the way to go. * All the wiki and manual to build: needed: android ndk installed, android sdk installed with additional build-tools 19.1.0 installed ./tools/configure select iBasso DX50 or iBasso DX90 make -j apk the content of rockbox.zip/.rockbox needs to be copied to /system/rockbox/app_rockbox/rockbox/ (rockbox app not needed) the content of libs/armeabi to /system/rockbox/lib/ (rockbox app needed) The boot selector is needed as /system/bin/MangoPlayer and the iBasso app as /system/bin/MangoPlayer_original. There is also the "vold" file. The one from OF does not work with DX50 rockbox (DX90 works!?), the one from Ilia is necessary. Until we have found a proper way to install it, it can only be installed following the instructions of Ilia on his bitbucket page, using the CWM-OF and his installation script package. Change-Id: Ic4faaf84824c162aabcc08e492cee6e0068719d0 Reviewed-on: http://gerrit.rockbox.org/941 Tested: Chiwen Chang <rock1104.tw@yahoo.com.tw> Reviewed-by: Michael Giacomelli <giac2000@hotmail.com>
Diffstat (limited to 'rbutil/ibassoboot/jni')
-rw-r--r--rbutil/ibassoboot/jni/Android.mk6
-rw-r--r--rbutil/ibassoboot/jni/chooser.bmpbin0 -> 230454 bytes
-rw-r--r--rbutil/ibassoboot/jni/ibassodualboot.c439
-rw-r--r--rbutil/ibassoboot/jni/qdbmp.c798
-rw-r--r--rbutil/ibassoboot/jni/qdbmp.h133
5 files changed, 1376 insertions, 0 deletions
diff --git a/rbutil/ibassoboot/jni/Android.mk b/rbutil/ibassoboot/jni/Android.mk
new file mode 100644
index 0000000000..1d1566d8c0
--- /dev/null
+++ b/rbutil/ibassoboot/jni/Android.mk
@@ -0,0 +1,6 @@
1LOCAL_PATH := $(call my-dir)
2include $(CLEAR_VARS)
3
4LOCAL_MODULE := MangoPlayer
5LOCAL_SRC_FILES := ibassodualboot.c qdbmp.c
6include $(BUILD_EXECUTABLE)
diff --git a/rbutil/ibassoboot/jni/chooser.bmp b/rbutil/ibassoboot/jni/chooser.bmp
new file mode 100644
index 0000000000..3e6742d600
--- /dev/null
+++ b/rbutil/ibassoboot/jni/chooser.bmp
Binary files differ
diff --git a/rbutil/ibassoboot/jni/ibassodualboot.c b/rbutil/ibassoboot/jni/ibassodualboot.c
new file mode 100644
index 0000000000..3f20bbeecf
--- /dev/null
+++ b/rbutil/ibassoboot/jni/ibassodualboot.c
@@ -0,0 +1,439 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 by Ilia Sergachev
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <dirent.h>
23#include <errno.h>
24#include <fcntl.h>
25
26#include <linux/fb.h>
27#include <linux/input.h>
28#include <linux/reboot.h>
29
30#include <stdbool.h>
31#include <string.h>
32#include <stdint.h>
33#include <stdio.h>
34#include <stdlib.h>
35
36#include <time.h>
37
38#include <sys/limits.h>
39#include <sys/mman.h>
40#include <sys/inotify.h>
41#include <sys/ioctl.h>
42#include <sys/poll.h>
43#include <sys/stat.h>
44#include <sys/time.h>
45#include <sys/types.h>
46
47#include <unistd.h>
48
49#include "qdbmp.h"
50
51
52#define MIN_TIME 1395606821
53#define TIME_FILE "/data/time_store"
54#define TIME_CHECK_PERIOD 60 /* seconds */
55#define VOLD_LINK "/data/vold"
56#define PLAYER_FILE "/data/chosen_player"
57#define NOASK_FLAG "/data/no_ask_once"
58#define POLL_MS 10
59
60
61#define KEYCODE_HEADPHONES 114
62#define KEYCODE_HOLD 115
63#define KEYCODE_PWR 116
64#define KEYCODE_PWR_LONG 117
65#define KEYCODE_SD 143
66#define KEYCODE_VOLPLUS 158
67#define KEYCODE_VOLMINUS 159
68#define KEYCODE_PREV 160
69#define KEYCODE_NEXT 162
70#define KEYCODE_PLAY 161
71
72#define KEY_HOLD_OFF 16
73
74void checktime()
75{
76 time_t t_stored=0, t_current=time(NULL);
77
78 FILE *f = fopen(TIME_FILE, "r");
79 if(f!=NULL)
80 {
81 fscanf(f, "%ld", &t_stored);
82 fclose(f);
83 }
84
85 printf("stored time: %ld, current time: %ld\n", t_stored, t_current);
86
87 if(t_stored<MIN_TIME)
88 t_stored=MIN_TIME;
89
90 if(t_stored<t_current)
91 {
92 f = fopen(TIME_FILE, "w");
93 fprintf(f, "%ld", t_current);
94 fclose(f);
95 }
96 else
97 {
98 t_stored += TIME_CHECK_PERIOD;
99 struct tm *t = localtime(&t_stored);
100 struct timeval tv = {mktime(t), 0};
101 settimeofday(&tv, 0);
102 }
103}
104
105
106static struct pollfd *ufds;
107static char **device_names;
108static int nfds;
109
110
111
112static int open_device(const char *device, int print_flags)
113{
114 int fd;
115 struct pollfd *new_ufds;
116 char **new_device_names;
117
118 fd = open(device, O_RDWR);
119 if(fd < 0)
120 {
121 fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));
122 return -1;
123 }
124
125 new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1));
126 if(new_ufds == NULL)
127 {
128 fprintf(stderr, "out of memory\n");
129 return -1;
130 }
131 ufds = new_ufds;
132 new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1));
133 if(new_device_names == NULL)
134 {
135 fprintf(stderr, "out of memory\n");
136 return -1;
137 }
138 device_names = new_device_names;
139
140 ufds[nfds].fd = fd;
141 ufds[nfds].events = POLLIN;
142 device_names[nfds] = strdup(device);
143 nfds++;
144
145 return 0;
146}
147
148
149
150static int scan_dir(const char *dirname, int print_flags)
151{
152 char devname[PATH_MAX];
153 char *filename;
154 DIR *dir;
155 struct dirent *de;
156 dir = opendir(dirname);
157 if(dir == NULL)
158 return -1;
159 strcpy(devname, dirname);
160 filename = devname + strlen(devname);
161 *filename++ = '/';
162 while((de = readdir(dir)))
163 {
164 if(de->d_name[0] == '.' &&
165 (de->d_name[1] == '\0' ||
166 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
167 continue;
168 strcpy(filename, de->d_name);
169 open_device(devname, print_flags);
170 }
171 closedir(dir);
172 return 0;
173}
174
175
176
177void button_init_device(void)
178{
179 int res;
180 int print_flags = 0;
181 const char *device = NULL;
182 const char *device_path = "/dev/input";
183
184 nfds = 1;
185 ufds = calloc(1, sizeof(ufds[0]));
186 ufds[0].fd = inotify_init();
187 ufds[0].events = POLLIN;
188 if(device)
189 {
190 res = open_device(device, print_flags);
191 if(res < 0) {
192 fprintf(stderr, "open device failed\n");
193 }
194 }
195 else
196 {
197 res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE);
198 if(res < 0)
199 {
200 fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno));
201 }
202 res = scan_dir(device_path, print_flags);
203 if(res < 0)
204 {
205 fprintf(stderr, "scan dir failed for %s\n", device_path);
206 }
207 }
208}
209
210
211int draw()
212{
213 int fbfd = 0;
214 struct fb_var_screeninfo vinfo;
215 struct fb_fix_screeninfo finfo;
216 long int screensize = 0;
217 char *fbp = 0;
218 int x = 0, y = 0;
219 long int location = 0;
220
221 /* Open the file for reading and writing */
222 fbfd = open("/dev/graphics/fb0", O_RDWR);
223 if (fbfd == -1)
224 {
225 perror("Error: cannot open framebuffer device");
226 exit(1);
227 }
228 /* Get fixed screen information */
229 if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1)
230 {
231 perror("Error reading fixed information");
232 exit(2);
233 }
234
235 /* Get variable screen information */
236 if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1)
237 {
238 perror("Error reading variable information");
239 exit(3);
240 }
241
242 /* Figure out the size of the screen in bytes */
243 screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
244
245 vinfo.xres = vinfo.xres_virtual = vinfo.width = 320;
246 vinfo.yres = vinfo.yres_virtual = vinfo.height = 240;
247 vinfo.xoffset = vinfo.yoffset = vinfo.sync = vinfo.vmode = 0;
248 vinfo.pixclock = 104377;
249 vinfo.left_margin = 20;
250 vinfo.right_margin = 50;
251 vinfo.upper_margin = 2;
252 vinfo.lower_margin = 4;
253 vinfo.hsync_len = 10;
254 vinfo.vsync_len = 2;
255 vinfo.red.offset = 11;
256 vinfo.red.length = 5;
257 vinfo.red.msb_right = 0;
258 vinfo.green.offset = 5;
259 vinfo.green.length = 6;
260 vinfo.green.msb_right = 0;
261 vinfo.blue.offset = 0;
262 vinfo.blue.length = 5;
263 vinfo.blue.msb_right = 0;
264 vinfo.transp.offset = vinfo.transp.length = vinfo.transp.msb_right = 0;
265 vinfo.nonstd = 4;
266
267 if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo))
268 {
269 perror("fbset(ioctl)");
270 exit(4);
271 }
272
273
274 /* Map the device to memory */
275 fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
276 fbfd, 0);
277 if ((int)fbp == -1)
278 {
279 perror("Error: failed to map framebuffer device to memory");
280 exit(4);
281 }
282
283 BMP* bmp = BMP_ReadFile("/system/rockbox/chooser.bmp");
284 BMP_CHECK_ERROR( stderr, -1 );
285
286 UCHAR r, g, b;
287 unsigned short int t;
288
289 for (y = 0; y < 240; y++)
290 for (x = 0; x < 320; x++)
291 {
292 location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
293 (y+vinfo.yoffset) * finfo.line_length;
294
295 BMP_GetPixelRGB(bmp, x, y, &r, &g, &b);
296 t = (r>>3)<<11 | (g>>2) << 5 | (b>>3);
297 *((unsigned short int*)(fbp + location)) = t;
298 }
299
300 BMP_Free( bmp );
301
302 munmap(fbp, screensize);
303 close(fbfd);
304 return 0;
305}
306
307
308int choose_player()
309{
310 int i;
311 int res;
312 struct input_event event;
313
314 while(true)
315 {
316 poll(ufds, nfds, POLL_MS);
317 for(i = 1; i < nfds; i++)
318 {
319 if(ufds[i].revents & POLLIN)
320 {
321 res = read(ufds[i].fd, &event, sizeof(event));
322 if(res < (int)sizeof(event))
323 {
324 fprintf(stderr, "could not get event\n");
325 }
326 if(event.type==1)
327 {
328 if(event.code==KEYCODE_NEXT)
329 {
330 puts("rockbox!");
331 return 1;
332 }
333 else if(event.code==KEYCODE_PREV)
334 {
335 puts("mango!");
336 return 0;
337 }
338 else if(event.code==KEYCODE_PWR || event.code==KEYCODE_PWR_LONG)
339 {
340 reboot(LINUX_REBOOT_CMD_POWER_OFF);
341 }
342 }
343 else if(event.type==3)
344 {
345 if(event.code==53) //x coord
346 {
347 if(event.value<160)
348 {
349 puts("mango!");
350 return 0;
351 }
352 else
353 {
354 puts("rockbox!");
355 return 1;
356 }
357 }
358 }
359 }
360 }
361 }
362 return true;
363}
364
365bool check_for_hold()
366{
367 FILE *f = fopen("/sys/class/axppower/holdkey", "r");
368 char x;
369 fscanf(f, "%c", &x);
370 fclose(f);
371
372 if(x & KEY_HOLD_OFF)
373 return false;
374 else
375 return true;
376}
377
378int main(int argc, char **argv)
379{
380 FILE *f;
381 int last_chosen_player = -1;
382
383 f = fopen(PLAYER_FILE, "r");
384 if(f!=NULL)
385 {
386 fscanf(f, "%d", &last_chosen_player);
387 fclose(f);
388 }
389 bool ask = (access(VOLD_LINK, F_OK) == -1) || ((access(NOASK_FLAG, F_OK) == -1) && check_for_hold()) || (last_chosen_player==-1);
390
391 if(ask)
392 {
393 draw();
394 button_init_device();
395 int player_chosen_now = choose_player();
396
397 if(last_chosen_player!=player_chosen_now)
398 {
399 f = fopen(PLAYER_FILE, "w");
400 fprintf(f, "%d", player_chosen_now);
401 fclose(f);
402 }
403
404 if(last_chosen_player!=player_chosen_now || (access(VOLD_LINK, F_OK) == -1))
405 {
406 system("rm "VOLD_LINK);
407
408 if(player_chosen_now)
409 system("ln -s /system/bin/vold_rockbox "VOLD_LINK);
410 else
411 system("ln -s /system/bin/vold_original "VOLD_LINK);
412
413 system("touch "NOASK_FLAG);
414 system("reboot");
415 }
416 last_chosen_player = player_chosen_now;
417 }
418
419 system("rm "NOASK_FLAG);
420
421 while(1)
422 {
423 if(last_chosen_player)
424 {
425// system("/system/bin/openadb");
426 system("/system/rockbox/lib/rockbox");
427 }
428 else
429// system("/system/bin/closeadb");
430 system("/system/bin/MangoPlayer_original");
431
432 sleep(1);
433 }
434
435 return 0;
436}
437
438
439
diff --git a/rbutil/ibassoboot/jni/qdbmp.c b/rbutil/ibassoboot/jni/qdbmp.c
new file mode 100644
index 0000000000..fd1337277d
--- /dev/null
+++ b/rbutil/ibassoboot/jni/qdbmp.c
@@ -0,0 +1,798 @@
1#include "qdbmp.h"
2#include <stdlib.h>
3#include <string.h>
4
5
6/* Bitmap header */
7typedef struct _BMP_Header
8{
9 USHORT Magic; /* Magic identifier: "BM" */
10 UINT FileSize; /* Size of the BMP file in bytes */
11 USHORT Reserved1; /* Reserved */
12 USHORT Reserved2; /* Reserved */
13 UINT DataOffset; /* Offset of image data relative to the file's start */
14 UINT HeaderSize; /* Size of the header in bytes */
15 UINT Width; /* Bitmap's width */
16 UINT Height; /* Bitmap's height */
17 USHORT Planes; /* Number of color planes in the bitmap */
18 USHORT BitsPerPixel; /* Number of bits per pixel */
19 UINT CompressionType; /* Compression type */
20 UINT ImageDataSize; /* Size of uncompressed image's data */
21 UINT HPixelsPerMeter; /* Horizontal resolution (pixels per meter) */
22 UINT VPixelsPerMeter; /* Vertical resolution (pixels per meter) */
23 UINT ColorsUsed; /* Number of color indexes in the color table that are actually used by the bitmap */
24 UINT ColorsRequired; /* Number of color indexes that are required for displaying the bitmap */
25} BMP_Header;
26
27
28/* Private data structure */
29struct _BMP
30{
31 BMP_Header Header;
32 UCHAR* Palette;
33 UCHAR* Data;
34};
35
36
37/* Holds the last error code */
38static BMP_STATUS BMP_LAST_ERROR_CODE = 0;
39
40
41/* Error description strings */
42static const char* BMP_ERROR_STRING[] =
43{
44 "",
45 "General error",
46 "Could not allocate enough memory to complete the operation",
47 "File input/output error",
48 "File not found",
49 "File is not a supported BMP variant (must be uncompressed 8, 24 or 32 BPP)",
50 "File is not a valid BMP image",
51 "An argument is invalid or out of range",
52 "The requested action is not compatible with the BMP's type"
53};
54
55
56/* Size of the palette data for 8 BPP bitmaps */
57#define BMP_PALETTE_SIZE ( 256 * 4 )
58
59
60
61/*********************************** Forward declarations **********************************/
62int ReadHeader ( BMP* bmp, FILE* f );
63int WriteHeader ( BMP* bmp, FILE* f );
64
65int ReadUINT ( UINT* x, FILE* f );
66int ReadUSHORT ( USHORT *x, FILE* f );
67
68int WriteUINT ( UINT x, FILE* f );
69int WriteUSHORT ( USHORT x, FILE* f );
70
71
72
73
74
75
76/*********************************** Public methods **********************************/
77
78
79/**************************************************************
80 Creates a blank BMP image with the specified dimensions
81 and bit depth.
82**************************************************************/
83BMP* BMP_Create( UINT width, UINT height, USHORT depth )
84{
85 BMP* bmp;
86 int bytes_per_pixel = depth >> 3;
87 UINT bytes_per_row;
88
89 if ( height <= 0 || width <= 0 )
90 {
91 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
92 return NULL;
93 }
94
95 if ( depth != 8 && depth != 24 && depth != 32 )
96 {
97 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
98 return NULL;
99 }
100
101
102 /* Allocate the bitmap data structure */
103 bmp = calloc( 1, sizeof( BMP ) );
104 if ( bmp == NULL )
105 {
106 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
107 return NULL;
108 }
109
110
111 /* Set header' default values */
112 bmp->Header.Magic = 0x4D42;
113 bmp->Header.Reserved1 = 0;
114 bmp->Header.Reserved2 = 0;
115 bmp->Header.HeaderSize = 40;
116 bmp->Header.Planes = 1;
117 bmp->Header.CompressionType = 0;
118 bmp->Header.HPixelsPerMeter = 0;
119 bmp->Header.VPixelsPerMeter = 0;
120 bmp->Header.ColorsUsed = 0;
121 bmp->Header.ColorsRequired = 0;
122
123
124 /* Calculate the number of bytes used to store a single image row. This is always
125 rounded up to the next multiple of 4. */
126 bytes_per_row = width * bytes_per_pixel;
127 bytes_per_row += ( bytes_per_row % 4 ? 4 - bytes_per_row % 4 : 0 );
128
129
130 /* Set header's image specific values */
131 bmp->Header.Width = width;
132 bmp->Header.Height = height;
133 bmp->Header.BitsPerPixel = depth;
134 bmp->Header.ImageDataSize = bytes_per_row * height;
135 bmp->Header.FileSize = bmp->Header.ImageDataSize + 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
136 bmp->Header.DataOffset = 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
137
138
139 /* Allocate palette */
140 if ( bmp->Header.BitsPerPixel == 8 )
141 {
142 bmp->Palette = (UCHAR*) calloc( BMP_PALETTE_SIZE, sizeof( UCHAR ) );
143 if ( bmp->Palette == NULL )
144 {
145 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
146 free( bmp );
147 return NULL;
148 }
149 }
150 else
151 {
152 bmp->Palette = NULL;
153 }
154
155
156 /* Allocate pixels */
157 bmp->Data = (UCHAR*) calloc( bmp->Header.ImageDataSize, sizeof( UCHAR ) );
158 if ( bmp->Data == NULL )
159 {
160 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
161 free( bmp->Palette );
162 free( bmp );
163 return NULL;
164 }
165
166
167 BMP_LAST_ERROR_CODE = BMP_OK;
168
169 return bmp;
170}
171
172
173/**************************************************************
174 Frees all the memory used by the specified BMP image.
175**************************************************************/
176void BMP_Free( BMP* bmp )
177{
178 if ( bmp == NULL )
179 {
180 return;
181 }
182
183 if ( bmp->Palette != NULL )
184 {
185 free( bmp->Palette );
186 }
187
188 if ( bmp->Data != NULL )
189 {
190 free( bmp->Data );
191 }
192
193 free( bmp );
194
195 BMP_LAST_ERROR_CODE = BMP_OK;
196}
197
198
199/**************************************************************
200 Reads the specified BMP image file.
201**************************************************************/
202BMP* BMP_ReadFile( const char* filename )
203{
204 BMP* bmp;
205 FILE* f;
206
207 if ( filename == NULL )
208 {
209 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
210 return NULL;
211 }
212
213
214 /* Allocate */
215 bmp = calloc( 1, sizeof( BMP ) );
216 if ( bmp == NULL )
217 {
218 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
219 return NULL;
220 }
221
222
223 /* Open file */
224 f = fopen( filename, "rb" );
225 if ( f == NULL )
226 {
227 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
228 free( bmp );
229 return NULL;
230 }
231
232
233 /* Read header */
234 if ( ReadHeader( bmp, f ) != BMP_OK || bmp->Header.Magic != 0x4D42 )
235 {
236 BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
237 fclose( f );
238 free( bmp );
239 return NULL;
240 }
241
242
243 /* Verify that the bitmap variant is supported */
244 if ( ( bmp->Header.BitsPerPixel != 32 && bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 8 )
245 || bmp->Header.CompressionType != 0 || bmp->Header.HeaderSize != 40 )
246 {
247 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
248 fclose( f );
249 free( bmp );
250 return NULL;
251 }
252
253
254 /* Allocate and read palette */
255 if ( bmp->Header.BitsPerPixel == 8 )
256 {
257 bmp->Palette = (UCHAR*) malloc( BMP_PALETTE_SIZE * sizeof( UCHAR ) );
258 if ( bmp->Palette == NULL )
259 {
260 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
261 fclose( f );
262 free( bmp );
263 return NULL;
264 }
265
266 if ( fread( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
267 {
268 BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
269 fclose( f );
270 free( bmp->Palette );
271 free( bmp );
272 return NULL;
273 }
274 }
275 else /* Not an indexed image */
276 {
277 bmp->Palette = NULL;
278 }
279
280
281 /* Allocate memory for image data */
282 bmp->Data = (UCHAR*) malloc( bmp->Header.ImageDataSize );
283 if ( bmp->Data == NULL )
284 {
285 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
286 fclose( f );
287 free( bmp->Palette );
288 free( bmp );
289 return NULL;
290 }
291
292
293 /* Read image data */
294 if ( fread( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
295 {
296 BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
297 fclose( f );
298 free( bmp->Data );
299 free( bmp->Palette );
300 free( bmp );
301 return NULL;
302 }
303
304
305 fclose( f );
306
307 BMP_LAST_ERROR_CODE = BMP_OK;
308
309 return bmp;
310}
311
312
313/**************************************************************
314 Writes the BMP image to the specified file.
315**************************************************************/
316void BMP_WriteFile( BMP* bmp, const char* filename )
317{
318 FILE* f;
319
320 if ( filename == NULL )
321 {
322 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
323 return;
324 }
325
326
327 /* Open file */
328 f = fopen( filename, "wb" );
329 if ( f == NULL )
330 {
331 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
332 return;
333 }
334
335
336 /* Write header */
337 if ( WriteHeader( bmp, f ) != BMP_OK )
338 {
339 BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
340 fclose( f );
341 return;
342 }
343
344
345 /* Write palette */
346 if ( bmp->Palette )
347 {
348 if ( fwrite( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
349 {
350 BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
351 fclose( f );
352 return;
353 }
354 }
355
356
357 /* Write data */
358 if ( fwrite( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
359 {
360 BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
361 fclose( f );
362 return;
363 }
364
365
366 BMP_LAST_ERROR_CODE = BMP_OK;
367 fclose( f );
368}
369
370
371/**************************************************************
372 Returns the image's width.
373**************************************************************/
374UINT BMP_GetWidth( BMP* bmp )
375{
376 if ( bmp == NULL )
377 {
378 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
379 return -1;
380 }
381
382 BMP_LAST_ERROR_CODE = BMP_OK;
383
384 return ( bmp->Header.Width );
385}
386
387
388/**************************************************************
389 Returns the image's height.
390**************************************************************/
391UINT BMP_GetHeight( BMP* bmp )
392{
393 if ( bmp == NULL )
394 {
395 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
396 return -1;
397 }
398
399 BMP_LAST_ERROR_CODE = BMP_OK;
400
401 return ( bmp->Header.Height );
402}
403
404
405/**************************************************************
406 Returns the image's color depth (bits per pixel).
407**************************************************************/
408USHORT BMP_GetDepth( BMP* bmp )
409{
410 if ( bmp == NULL )
411 {
412 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
413 return -1;
414 }
415
416 BMP_LAST_ERROR_CODE = BMP_OK;
417
418 return ( bmp->Header.BitsPerPixel );
419}
420
421
422/**************************************************************
423 Populates the arguments with the specified pixel's RGB
424 values.
425**************************************************************/
426void BMP_GetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b )
427{
428 UCHAR* pixel;
429 UINT bytes_per_row;
430 UCHAR bytes_per_pixel;
431
432 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
433 {
434 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
435 }
436 else
437 {
438 BMP_LAST_ERROR_CODE = BMP_OK;
439
440 bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
441
442 /* Row's size is rounded up to the next multiple of 4 bytes */
443 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
444
445 /* Calculate the location of the relevant pixel (rows are flipped) */
446 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
447
448
449 /* In indexed color mode the pixel's value is an index within the palette */
450 if ( bmp->Header.BitsPerPixel == 8 )
451 {
452 pixel = bmp->Palette + *pixel * 4;
453 }
454
455 /* Note: colors are stored in BGR order */
456 if ( r ) *r = *( pixel + 2 );
457 if ( g ) *g = *( pixel + 1 );
458 if ( b ) *b = *( pixel + 0 );
459 }
460}
461
462
463/**************************************************************
464 Sets the specified pixel's RGB values.
465**************************************************************/
466void BMP_SetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b )
467{
468 UCHAR* pixel;
469 UINT bytes_per_row;
470 UCHAR bytes_per_pixel;
471
472 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
473 {
474 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
475 }
476
477 else if ( bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 32 )
478 {
479 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
480 }
481
482 else
483 {
484 BMP_LAST_ERROR_CODE = BMP_OK;
485
486 bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
487
488 /* Row's size is rounded up to the next multiple of 4 bytes */
489 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
490
491 /* Calculate the location of the relevant pixel (rows are flipped) */
492 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
493
494 /* Note: colors are stored in BGR order */
495 *( pixel + 2 ) = r;
496 *( pixel + 1 ) = g;
497 *( pixel + 0 ) = b;
498 }
499}
500
501
502/**************************************************************
503 Gets the specified pixel's color index.
504**************************************************************/
505void BMP_GetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR* val )
506{
507 UCHAR* pixel;
508 UINT bytes_per_row;
509
510 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
511 {
512 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
513 }
514
515 else if ( bmp->Header.BitsPerPixel != 8 )
516 {
517 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
518 }
519
520 else
521 {
522 BMP_LAST_ERROR_CODE = BMP_OK;
523
524 /* Row's size is rounded up to the next multiple of 4 bytes */
525 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
526
527 /* Calculate the location of the relevant pixel */
528 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
529
530
531 if ( val ) *val = *pixel;
532 }
533}
534
535
536/**************************************************************
537 Sets the specified pixel's color index.
538**************************************************************/
539void BMP_SetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR val )
540{
541 UCHAR* pixel;
542 UINT bytes_per_row;
543
544 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
545 {
546 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
547 }
548
549 else if ( bmp->Header.BitsPerPixel != 8 )
550 {
551 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
552 }
553
554 else
555 {
556 BMP_LAST_ERROR_CODE = BMP_OK;
557
558 /* Row's size is rounded up to the next multiple of 4 bytes */
559 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
560
561 /* Calculate the location of the relevant pixel */
562 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
563
564 *pixel = val;
565 }
566}
567
568
569/**************************************************************
570 Gets the color value for the specified palette index.
571**************************************************************/
572void BMP_GetPaletteColor( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b )
573{
574 if ( bmp == NULL )
575 {
576 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
577 }
578
579 else if ( bmp->Header.BitsPerPixel != 8 )
580 {
581 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
582 }
583
584 else
585 {
586 if ( r ) *r = *( bmp->Palette + index * 4 + 2 );
587 if ( g ) *g = *( bmp->Palette + index * 4 + 1 );
588 if ( b ) *b = *( bmp->Palette + index * 4 + 0 );
589
590 BMP_LAST_ERROR_CODE = BMP_OK;
591 }
592}
593
594
595/**************************************************************
596 Sets the color value for the specified palette index.
597**************************************************************/
598void BMP_SetPaletteColor( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b )
599{
600 if ( bmp == NULL )
601 {
602 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
603 }
604
605 else if ( bmp->Header.BitsPerPixel != 8 )
606 {
607 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
608 }
609
610 else
611 {
612 *( bmp->Palette + index * 4 + 2 ) = r;
613 *( bmp->Palette + index * 4 + 1 ) = g;
614 *( bmp->Palette + index * 4 + 0 ) = b;
615
616 BMP_LAST_ERROR_CODE = BMP_OK;
617 }
618}
619
620
621/**************************************************************
622 Returns the last error code.
623**************************************************************/
624BMP_STATUS BMP_GetError()
625{
626 return BMP_LAST_ERROR_CODE;
627}
628
629
630/**************************************************************
631 Returns a description of the last error code.
632**************************************************************/
633const char* BMP_GetErrorDescription()
634{
635 if ( BMP_LAST_ERROR_CODE > 0 && BMP_LAST_ERROR_CODE < BMP_ERROR_NUM )
636 {
637 return BMP_ERROR_STRING[ BMP_LAST_ERROR_CODE ];
638 }
639 else
640 {
641 return NULL;
642 }
643}
644
645
646
647
648
649/*********************************** Private methods **********************************/
650
651
652/**************************************************************
653 Reads the BMP file's header into the data structure.
654 Returns BMP_OK on success.
655**************************************************************/
656int ReadHeader( BMP* bmp, FILE* f )
657{
658 if ( bmp == NULL || f == NULL )
659 {
660 return BMP_INVALID_ARGUMENT;
661 }
662
663 /* The header's fields are read one by one, and converted from the format's
664 little endian to the system's native representation. */
665 if ( !ReadUSHORT( &( bmp->Header.Magic ), f ) ) return BMP_IO_ERROR;
666 if ( !ReadUINT( &( bmp->Header.FileSize ), f ) ) return BMP_IO_ERROR;
667 if ( !ReadUSHORT( &( bmp->Header.Reserved1 ), f ) ) return BMP_IO_ERROR;
668 if ( !ReadUSHORT( &( bmp->Header.Reserved2 ), f ) ) return BMP_IO_ERROR;
669 if ( !ReadUINT( &( bmp->Header.DataOffset ), f ) ) return BMP_IO_ERROR;
670 if ( !ReadUINT( &( bmp->Header.HeaderSize ), f ) ) return BMP_IO_ERROR;
671 if ( !ReadUINT( &( bmp->Header.Width ), f ) ) return BMP_IO_ERROR;
672 if ( !ReadUINT( &( bmp->Header.Height ), f ) ) return BMP_IO_ERROR;
673 if ( !ReadUSHORT( &( bmp->Header.Planes ), f ) ) return BMP_IO_ERROR;
674 if ( !ReadUSHORT( &( bmp->Header.BitsPerPixel ), f ) ) return BMP_IO_ERROR;
675 if ( !ReadUINT( &( bmp->Header.CompressionType ), f ) ) return BMP_IO_ERROR;
676 if ( !ReadUINT( &( bmp->Header.ImageDataSize ), f ) ) return BMP_IO_ERROR;
677 if ( !ReadUINT( &( bmp->Header.HPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
678 if ( !ReadUINT( &( bmp->Header.VPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
679 if ( !ReadUINT( &( bmp->Header.ColorsUsed ), f ) ) return BMP_IO_ERROR;
680 if ( !ReadUINT( &( bmp->Header.ColorsRequired ), f ) ) return BMP_IO_ERROR;
681
682 return BMP_OK;
683}
684
685
686/**************************************************************
687 Writes the BMP file's header into the data structure.
688 Returns BMP_OK on success.
689**************************************************************/
690int WriteHeader( BMP* bmp, FILE* f )
691{
692 if ( bmp == NULL || f == NULL )
693 {
694 return BMP_INVALID_ARGUMENT;
695 }
696
697 /* The header's fields are written one by one, and converted to the format's
698 little endian representation. */
699 if ( !WriteUSHORT( bmp->Header.Magic, f ) ) return BMP_IO_ERROR;
700 if ( !WriteUINT( bmp->Header.FileSize, f ) ) return BMP_IO_ERROR;
701 if ( !WriteUSHORT( bmp->Header.Reserved1, f ) ) return BMP_IO_ERROR;
702 if ( !WriteUSHORT( bmp->Header.Reserved2, f ) ) return BMP_IO_ERROR;
703 if ( !WriteUINT( bmp->Header.DataOffset, f ) ) return BMP_IO_ERROR;
704 if ( !WriteUINT( bmp->Header.HeaderSize, f ) ) return BMP_IO_ERROR;
705 if ( !WriteUINT( bmp->Header.Width, f ) ) return BMP_IO_ERROR;
706 if ( !WriteUINT( bmp->Header.Height, f ) ) return BMP_IO_ERROR;
707 if ( !WriteUSHORT( bmp->Header.Planes, f ) ) return BMP_IO_ERROR;
708 if ( !WriteUSHORT( bmp->Header.BitsPerPixel, f ) ) return BMP_IO_ERROR;
709 if ( !WriteUINT( bmp->Header.CompressionType, f ) ) return BMP_IO_ERROR;
710 if ( !WriteUINT( bmp->Header.ImageDataSize, f ) ) return BMP_IO_ERROR;
711 if ( !WriteUINT( bmp->Header.HPixelsPerMeter, f ) ) return BMP_IO_ERROR;
712 if ( !WriteUINT( bmp->Header.VPixelsPerMeter, f ) ) return BMP_IO_ERROR;
713 if ( !WriteUINT( bmp->Header.ColorsUsed, f ) ) return BMP_IO_ERROR;
714 if ( !WriteUINT( bmp->Header.ColorsRequired, f ) ) return BMP_IO_ERROR;
715
716 return BMP_OK;
717}
718
719
720/**************************************************************
721 Reads a little-endian unsigned int from the file.
722 Returns non-zero on success.
723**************************************************************/
724int ReadUINT( UINT* x, FILE* f )
725{
726 UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
727
728 if ( x == NULL || f == NULL )
729 {
730 return 0;
731 }
732
733 if ( fread( little, 4, 1, f ) != 1 )
734 {
735 return 0;
736 }
737
738 *x = ( little[ 3 ] << 24 | little[ 2 ] << 16 | little[ 1 ] << 8 | little[ 0 ] );
739
740 return 1;
741}
742
743
744/**************************************************************
745 Reads a little-endian unsigned short int from the file.
746 Returns non-zero on success.
747**************************************************************/
748int ReadUSHORT( USHORT *x, FILE* f )
749{
750 UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
751
752 if ( x == NULL || f == NULL )
753 {
754 return 0;
755 }
756
757 if ( fread( little, 2, 1, f ) != 1 )
758 {
759 return 0;
760 }
761
762 *x = ( little[ 1 ] << 8 | little[ 0 ] );
763
764 return 1;
765}
766
767
768/**************************************************************
769 Writes a little-endian unsigned int to the file.
770 Returns non-zero on success.
771**************************************************************/
772int WriteUINT( UINT x, FILE* f )
773{
774 UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
775
776 little[ 3 ] = (UCHAR)( ( x & 0xff000000 ) >> 24 );
777 little[ 2 ] = (UCHAR)( ( x & 0x00ff0000 ) >> 16 );
778 little[ 1 ] = (UCHAR)( ( x & 0x0000ff00 ) >> 8 );
779 little[ 0 ] = (UCHAR)( ( x & 0x000000ff ) >> 0 );
780
781 return ( f && fwrite( little, 4, 1, f ) == 1 );
782}
783
784
785/**************************************************************
786 Writes a little-endian unsigned short int to the file.
787 Returns non-zero on success.
788**************************************************************/
789int WriteUSHORT( USHORT x, FILE* f )
790{
791 UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
792
793 little[ 1 ] = (UCHAR)( ( x & 0xff00 ) >> 8 );
794 little[ 0 ] = (UCHAR)( ( x & 0x00ff ) >> 0 );
795
796 return ( f && fwrite( little, 2, 1, f ) == 1 );
797}
798
diff --git a/rbutil/ibassoboot/jni/qdbmp.h b/rbutil/ibassoboot/jni/qdbmp.h
new file mode 100644
index 0000000000..d6c0e6c452
--- /dev/null
+++ b/rbutil/ibassoboot/jni/qdbmp.h
@@ -0,0 +1,133 @@
1#ifndef _BMP_H_
2#define _BMP_H_
3
4
5/**************************************************************
6
7 QDBMP - Quick n' Dirty BMP
8
9 v1.0.0 - 2007-04-07
10 http://qdbmp.sourceforge.net
11
12
13 The library supports the following BMP variants:
14 1. Uncompressed 32 BPP (alpha values are ignored)
15 2. Uncompressed 24 BPP
16 3. Uncompressed 8 BPP (indexed color)
17
18 QDBMP is free and open source software, distributed
19 under the MIT licence.
20
21 Copyright (c) 2007 Chai Braudo (braudo@users.sourceforge.net)
22
23 Permission is hereby granted, free of charge, to any person obtaining a copy
24 of this software and associated documentation files (the "Software"), to deal
25 in the Software without restriction, including without limitation the rights
26 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 copies of the Software, and to permit persons to whom the Software is
28 furnished to do so, subject to the following conditions:
29
30 The above copyright notice and this permission notice shall be included in
31 all copies or substantial portions of the Software.
32
33 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 THE SOFTWARE.
40
41**************************************************************/
42
43#include <stdio.h>
44
45
46
47/* Type definitions */
48#ifndef UINT
49 #define UINT unsigned long int
50#endif
51
52#ifndef USHORT
53 #define USHORT unsigned short
54#endif
55
56#ifndef UCHAR
57 #define UCHAR unsigned char
58#endif
59
60
61/* Version */
62#define QDBMP_VERSION_MAJOR 1
63#define QDBMP_VERSION_MINOR 0
64#define QDBMP_VERSION_PATCH 1
65
66
67/* Error codes */
68typedef enum
69{
70 BMP_OK = 0, /* No error */
71 BMP_ERROR, /* General error */
72 BMP_OUT_OF_MEMORY, /* Could not allocate enough memory to complete the operation */
73 BMP_IO_ERROR, /* General input/output error */
74 BMP_FILE_NOT_FOUND, /* File not found */
75 BMP_FILE_NOT_SUPPORTED, /* File is not a supported BMP variant */
76 BMP_FILE_INVALID, /* File is not a BMP image or is an invalid BMP */
77 BMP_INVALID_ARGUMENT, /* An argument is invalid or out of range */
78 BMP_TYPE_MISMATCH, /* The requested action is not compatible with the BMP's type */
79 BMP_ERROR_NUM
80} BMP_STATUS;
81
82
83/* Bitmap image */
84typedef struct _BMP BMP;
85
86
87
88
89/*********************************** Public methods **********************************/
90
91
92/* Construction/destruction */
93BMP* BMP_Create ( UINT width, UINT height, USHORT depth );
94void BMP_Free ( BMP* bmp );
95
96
97/* I/O */
98BMP* BMP_ReadFile ( const char* filename );
99void BMP_WriteFile ( BMP* bmp, const char* filename );
100
101
102/* Meta info */
103UINT BMP_GetWidth ( BMP* bmp );
104UINT BMP_GetHeight ( BMP* bmp );
105USHORT BMP_GetDepth ( BMP* bmp );
106
107
108/* Pixel access */
109void BMP_GetPixelRGB ( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b );
110void BMP_SetPixelRGB ( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b );
111void BMP_GetPixelIndex ( BMP* bmp, UINT x, UINT y, UCHAR* val );
112void BMP_SetPixelIndex ( BMP* bmp, UINT x, UINT y, UCHAR val );
113
114
115/* Palette handling */
116void BMP_GetPaletteColor ( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b );
117void BMP_SetPaletteColor ( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b );
118
119
120/* Error handling */
121BMP_STATUS BMP_GetError ();
122const char* BMP_GetErrorDescription ();
123
124
125/* Useful macro that may be used after each BMP operation to check for an error */
126#define BMP_CHECK_ERROR( output_file, return_value ) \
127 if ( BMP_GetError() != BMP_OK ) \
128 { \
129 fprintf( ( output_file ), "BMP error: %s\n", BMP_GetErrorDescription() ); \
130 return( return_value ); \
131 } \
132
133#endif