Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / video / readers / tga.c
blob84be68a0a4b9f691c40d5eb7c9a76fefd30b30ad
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2006,2007 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/bitmap.h>
20 #include <grub/types.h>
21 #include <grub/normal.h>
22 #include <grub/dl.h>
23 #include <grub/mm.h>
24 #include <grub/misc.h>
25 #include <grub/bufio.h>
27 GRUB_MOD_LICENSE ("GPLv3+");
29 /* Uncomment following define to enable TGA debug. */
30 //#define TGA_DEBUG
32 #if defined(TGA_DEBUG)
33 #define dump_int_field(x) grub_printf( #x " = %d (0x%04x)\n", x, x);
34 static grub_command_t cmd;
35 #endif
37 enum
39 GRUB_TGA_IMAGE_TYPE_NONE = 0,
40 GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR = 1,
41 GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR = 2,
42 GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE = 3,
43 GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR = 9,
44 GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR = 10,
45 GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE = 11,
48 enum
50 GRUB_TGA_COLOR_MAP_TYPE_NONE = 0,
51 GRUB_TGA_COLOR_MAP_TYPE_INCLUDED = 1
54 enum
56 GRUB_TGA_IMAGE_ORIGIN_RIGHT = 0x10,
57 GRUB_TGA_IMAGE_ORIGIN_TOP = 0x20
60 struct grub_tga_header
62 grub_uint8_t id_length;
63 grub_uint8_t color_map_type;
64 grub_uint8_t image_type;
66 /* Color Map Specification. */
67 grub_uint16_t color_map_first_index;
68 grub_uint16_t color_map_length;
69 grub_uint8_t color_map_bpp;
71 /* Image Specification. */
72 grub_uint16_t image_x_origin;
73 grub_uint16_t image_y_origin;
74 grub_uint16_t image_width;
75 grub_uint16_t image_height;
76 grub_uint8_t image_bpp;
77 grub_uint8_t image_descriptor;
78 } __attribute__ ((packed));
80 static grub_err_t
81 tga_load_truecolor_rle_R8G8B8 (struct grub_video_bitmap *bitmap,
82 struct grub_tga_header *header,
83 grub_file_t file)
85 unsigned int x;
86 unsigned int y;
87 grub_uint8_t type;
88 grub_uint8_t *ptr;
89 grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */
90 grub_uint8_t bytes_per_pixel;
92 bytes_per_pixel = header->image_bpp / 8;
94 for (y = 0; y < header->image_height; y++)
96 ptr = bitmap->data;
97 if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
98 ptr += y * bitmap->mode_info.pitch;
99 else
100 ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
102 for (x = 0; x < header->image_width;)
104 if (grub_file_read (file, &type, sizeof (type)) != sizeof(type))
105 return grub_errno;
107 if (type & 0x80)
109 /* RLE-encoded packet. */
110 type &= 0x7f;
111 type++;
113 if (grub_file_read (file, &tmp[0], bytes_per_pixel)
114 != bytes_per_pixel)
115 return grub_errno;
117 while (type)
119 if (x < header->image_width)
121 ptr[0] = tmp[2];
122 ptr[1] = tmp[1];
123 ptr[2] = tmp[0];
124 ptr += 3;
127 type--;
128 x++;
131 else
133 /* RAW-encoded packet. */
134 type++;
136 while (type)
138 if (grub_file_read (file, &tmp[0], bytes_per_pixel)
139 != bytes_per_pixel)
140 return grub_errno;
142 if (x < header->image_width)
144 ptr[0] = tmp[2];
145 ptr[1] = tmp[1];
146 ptr[2] = tmp[0];
147 ptr += 3;
150 type--;
151 x++;
156 return GRUB_ERR_NONE;
159 static grub_err_t
160 tga_load_truecolor_rle_R8G8B8A8 (struct grub_video_bitmap *bitmap,
161 struct grub_tga_header *header,
162 grub_file_t file)
164 unsigned int x;
165 unsigned int y;
166 grub_uint8_t type;
167 grub_uint8_t *ptr;
168 grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */
169 grub_uint8_t bytes_per_pixel;
171 bytes_per_pixel = header->image_bpp / 8;
173 for (y = 0; y < header->image_height; y++)
175 ptr = bitmap->data;
176 if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
177 ptr += y * bitmap->mode_info.pitch;
178 else
179 ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
181 for (x = 0; x < header->image_width;)
183 if (grub_file_read (file, &type, sizeof (type)) != sizeof(type))
184 return grub_errno;
186 if (type & 0x80)
188 /* RLE-encoded packet. */
189 type &= 0x7f;
190 type++;
192 if (grub_file_read (file, &tmp[0], bytes_per_pixel)
193 != bytes_per_pixel)
194 return grub_errno;
196 while (type)
198 if (x < header->image_width)
200 ptr[0] = tmp[2];
201 ptr[1] = tmp[1];
202 ptr[2] = tmp[0];
203 ptr[3] = tmp[3];
204 ptr += 4;
207 type--;
208 x++;
211 else
213 /* RAW-encoded packet. */
214 type++;
216 while (type)
218 if (grub_file_read (file, &tmp[0], bytes_per_pixel)
219 != bytes_per_pixel)
220 return grub_errno;
222 if (x < header->image_width)
224 ptr[0] = tmp[2];
225 ptr[1] = tmp[1];
226 ptr[2] = tmp[0];
227 ptr[3] = tmp[3];
228 ptr += 4;
231 type--;
232 x++;
237 return GRUB_ERR_NONE;
240 static grub_err_t
241 tga_load_truecolor_R8G8B8 (struct grub_video_bitmap *bitmap,
242 struct grub_tga_header *header,
243 grub_file_t file)
245 unsigned int x;
246 unsigned int y;
247 grub_uint8_t *ptr;
248 grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */
249 grub_uint8_t bytes_per_pixel;
251 bytes_per_pixel = header->image_bpp / 8;
253 for (y = 0; y < header->image_height; y++)
255 ptr = bitmap->data;
256 if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
257 ptr += y * bitmap->mode_info.pitch;
258 else
259 ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
261 for (x = 0; x < header->image_width; x++)
263 if (grub_file_read (file, &tmp[0], bytes_per_pixel)
264 != bytes_per_pixel)
265 return grub_errno;
267 ptr[0] = tmp[2];
268 ptr[1] = tmp[1];
269 ptr[2] = tmp[0];
271 ptr += 3;
274 return GRUB_ERR_NONE;
277 static grub_err_t
278 tga_load_truecolor_R8G8B8A8 (struct grub_video_bitmap *bitmap,
279 struct grub_tga_header *header,
280 grub_file_t file)
282 unsigned int x;
283 unsigned int y;
284 grub_uint8_t *ptr;
285 grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */
286 grub_uint8_t bytes_per_pixel;
288 bytes_per_pixel = header->image_bpp / 8;
290 for (y = 0; y < header->image_height; y++)
292 ptr = bitmap->data;
293 if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
294 ptr += y * bitmap->mode_info.pitch;
295 else
296 ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
298 for (x = 0; x < header->image_width; x++)
300 if (grub_file_read (file, &tmp[0], bytes_per_pixel)
301 != bytes_per_pixel)
302 return grub_errno;
304 ptr[0] = tmp[2];
305 ptr[1] = tmp[1];
306 ptr[2] = tmp[0];
307 ptr[3] = tmp[3];
309 ptr += 4;
312 return GRUB_ERR_NONE;
315 static grub_err_t
316 grub_video_reader_tga (struct grub_video_bitmap **bitmap,
317 const char *filename)
319 grub_file_t file;
320 grub_ssize_t pos;
321 struct grub_tga_header header;
322 int has_alpha;
324 file = grub_buffile_open (filename, 0);
325 if (! file)
326 return grub_errno;
328 /* TGA Specification states that we SHOULD start by reading
329 ID from end of file, but we really don't care about that as we are
330 not going to support developer area & extensions at this point. */
332 /* Read TGA header from beginning of file. */
333 if (grub_file_read (file, &header, sizeof (header))
334 != sizeof (header))
336 grub_file_close (file);
337 return grub_errno;
340 /* Skip ID field. */
341 pos = grub_file_tell (file);
342 pos += header.id_length;
343 grub_file_seek (file, pos);
344 if (grub_errno != GRUB_ERR_NONE)
346 grub_file_close (file);
347 return grub_errno;
350 #if defined(TGA_DEBUG)
351 grub_printf("tga: header\n");
352 dump_int_field(header.id_length);
353 dump_int_field(header.color_map_type);
354 dump_int_field(header.image_type);
355 dump_int_field(header.color_map_first_index);
356 dump_int_field(header.color_map_length);
357 dump_int_field(header.color_map_bpp);
358 dump_int_field(header.image_x_origin);
359 dump_int_field(header.image_y_origin);
360 dump_int_field(header.image_width);
361 dump_int_field(header.image_height);
362 dump_int_field(header.image_bpp);
363 dump_int_field(header.image_descriptor);
364 #endif
366 /* Check that bitmap encoding is supported. */
367 switch (header.image_type)
369 case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
370 case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
371 break;
373 default:
374 grub_file_close (file);
375 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
376 "unsupported bitmap format (unknown encoding)");
379 /* Check that bitmap depth is supported. */
380 switch (header.image_bpp)
382 case 24:
383 has_alpha = 0;
384 break;
386 case 32:
387 has_alpha = 1;
388 break;
390 default:
391 grub_file_close (file);
392 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
393 "unsupported bitmap format (bpp=%d)",
394 header.image_bpp);
397 /* Allocate bitmap. If there is alpha information store it too. */
398 if (has_alpha)
400 grub_video_bitmap_create (bitmap, header.image_width,
401 header.image_height,
402 GRUB_VIDEO_BLIT_FORMAT_RGBA_8888);
403 if (grub_errno != GRUB_ERR_NONE)
405 grub_file_close (file);
406 return grub_errno;
409 /* Load bitmap data. */
410 switch (header.image_type)
412 case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
413 tga_load_truecolor_R8G8B8A8 (*bitmap, &header, file);
414 break;
416 case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
417 tga_load_truecolor_rle_R8G8B8A8 (*bitmap, &header, file);
418 break;
421 else
423 grub_video_bitmap_create (bitmap, header.image_width,
424 header.image_height,
425 GRUB_VIDEO_BLIT_FORMAT_RGB_888);
426 if (grub_errno != GRUB_ERR_NONE)
428 grub_file_close (file);
429 return grub_errno;
432 /* Load bitmap data. */
433 switch (header.image_type)
435 case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
436 tga_load_truecolor_R8G8B8 (*bitmap, &header, file);
437 break;
439 case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
440 tga_load_truecolor_rle_R8G8B8 (*bitmap, &header, file);
441 break;
445 /* If there was a loading problem, destroy bitmap. */
446 if (grub_errno != GRUB_ERR_NONE)
448 grub_video_bitmap_destroy (*bitmap);
449 *bitmap = 0;
452 grub_file_close (file);
453 return grub_errno;
456 #if defined(TGA_DEBUG)
457 static grub_err_t
458 grub_cmd_tgatest (grub_command_t cmd __attribute__ ((unused)),
459 int argc, char **args)
461 struct grub_video_bitmap *bitmap = 0;
463 if (argc != 1)
464 return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
466 grub_video_reader_tga (&bitmap, args[0]);
467 if (grub_errno != GRUB_ERR_NONE)
468 return grub_errno;
470 grub_video_bitmap_destroy (bitmap);
472 return GRUB_ERR_NONE;
474 #endif
476 static struct grub_video_bitmap_reader tga_reader = {
477 .extension = ".tga",
478 .reader = grub_video_reader_tga,
479 .next = 0
482 GRUB_MOD_INIT(tga)
484 grub_video_bitmap_reader_register (&tga_reader);
485 #if defined(TGA_DEBUG)
486 cmd = grub_register_command ("tgatest", grub_cmd_tgatest,
487 "FILE", "Tests loading of TGA bitmap.");
488 #endif
491 GRUB_MOD_FINI(tga)
493 #if defined(TGA_DEBUG)
494 grub_unregister_command (cmd);
495 #endif
496 grub_video_bitmap_reader_unregister (&tga_reader);