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>
24
#include <grub/misc.h>
25
#include <grub/bufio.h>
27
/* Uncomment following define to enable TGA debug. */
30
#if defined(TGA_DEBUG)
31
#define dump_int_field(x) grub_printf( #x " = %d (0x%04x)\n", x, x);
32
static grub_command_t cmd;
37
GRUB_TGA_IMAGE_TYPE_NONE = 0,
38
GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR = 1,
39
GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR = 2,
40
GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE = 3,
41
GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR = 9,
42
GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR = 10,
43
GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE = 11,
48
GRUB_TGA_COLOR_MAP_TYPE_NONE = 0,
49
GRUB_TGA_COLOR_MAP_TYPE_INCLUDED = 1
54
GRUB_TGA_IMAGE_ORIGIN_RIGHT = 0x10,
55
GRUB_TGA_IMAGE_ORIGIN_TOP = 0x20
58
struct grub_tga_header
60
grub_uint8_t id_length;
61
grub_uint8_t color_map_type;
62
grub_uint8_t image_type;
64
/* Color Map Specification. */
65
grub_uint16_t color_map_first_index;
66
grub_uint16_t color_map_length;
67
grub_uint8_t color_map_bpp;
69
/* Image Specification. */
70
grub_uint16_t image_x_origin;
71
grub_uint16_t image_y_origin;
72
grub_uint16_t image_width;
73
grub_uint16_t image_height;
74
grub_uint8_t image_bpp;
75
grub_uint8_t image_descriptor;
76
} __attribute__ ((packed));
79
tga_load_truecolor_rle_R8G8B8 (struct grub_video_bitmap *bitmap,
80
struct grub_tga_header *header,
87
grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */
88
grub_uint8_t bytes_per_pixel;
90
bytes_per_pixel = header->image_bpp / 8;
92
for (y = 0; y < header->image_height; y++)
95
if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
96
ptr += y * bitmap->mode_info.pitch;
98
ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
100
for (x = 0; x < header->image_width;)
102
if (grub_file_read (file, &type, sizeof (type)) != sizeof(type))
107
/* RLE-encoded packet. */
111
if (grub_file_read (file, &tmp[0], bytes_per_pixel)
117
if (x < header->image_width)
131
/* RAW-encoded packet. */
136
if (grub_file_read (file, &tmp[0], bytes_per_pixel)
140
if (x < header->image_width)
154
return GRUB_ERR_NONE;
158
tga_load_truecolor_rle_R8G8B8A8 (struct grub_video_bitmap *bitmap,
159
struct grub_tga_header *header,
166
grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */
167
grub_uint8_t bytes_per_pixel;
169
bytes_per_pixel = header->image_bpp / 8;
171
for (y = 0; y < header->image_height; y++)
174
if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
175
ptr += y * bitmap->mode_info.pitch;
177
ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
179
for (x = 0; x < header->image_width;)
181
if (grub_file_read (file, &type, sizeof (type)) != sizeof(type))
186
/* RLE-encoded packet. */
190
if (grub_file_read (file, &tmp[0], bytes_per_pixel)
196
if (x < header->image_width)
211
/* RAW-encoded packet. */
216
if (grub_file_read (file, &tmp[0], bytes_per_pixel)
220
if (x < header->image_width)
235
return GRUB_ERR_NONE;
239
tga_load_truecolor_R8G8B8 (struct grub_video_bitmap *bitmap,
240
struct grub_tga_header *header,
246
grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */
247
grub_uint8_t bytes_per_pixel;
249
bytes_per_pixel = header->image_bpp / 8;
251
for (y = 0; y < header->image_height; y++)
254
if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
255
ptr += y * bitmap->mode_info.pitch;
257
ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
259
for (x = 0; x < header->image_width; x++)
261
if (grub_file_read (file, &tmp[0], bytes_per_pixel)
272
return GRUB_ERR_NONE;
276
tga_load_truecolor_R8G8B8A8 (struct grub_video_bitmap *bitmap,
277
struct grub_tga_header *header,
283
grub_uint8_t tmp[4]; /* Size should be max_bpp / 8. */
284
grub_uint8_t bytes_per_pixel;
286
bytes_per_pixel = header->image_bpp / 8;
288
for (y = 0; y < header->image_height; y++)
291
if ((header->image_descriptor & GRUB_TGA_IMAGE_ORIGIN_TOP) != 0)
292
ptr += y * bitmap->mode_info.pitch;
294
ptr += (header->image_height - 1 - y) * bitmap->mode_info.pitch;
296
for (x = 0; x < header->image_width; x++)
298
if (grub_file_read (file, &tmp[0], bytes_per_pixel)
310
return GRUB_ERR_NONE;
314
grub_video_reader_tga (struct grub_video_bitmap **bitmap,
315
const char *filename)
319
struct grub_tga_header header;
322
file = grub_buffile_open (filename, 0);
326
/* TGA Specification states that we SHOULD start by reading
327
ID from end of file, but we really don't care about that as we are
328
not going to support developer area & extensions at this point. */
330
/* Read TGA header from beginning of file. */
331
if (grub_file_read (file, &header, sizeof (header))
334
grub_file_close (file);
339
pos = grub_file_tell (file);
340
pos += header.id_length;
341
grub_file_seek (file, pos);
342
if (grub_errno != GRUB_ERR_NONE)
344
grub_file_close (file);
348
#if defined(TGA_DEBUG)
349
grub_printf("tga: header\n");
350
dump_int_field(header.id_length);
351
dump_int_field(header.color_map_type);
352
dump_int_field(header.image_type);
353
dump_int_field(header.color_map_first_index);
354
dump_int_field(header.color_map_length);
355
dump_int_field(header.color_map_bpp);
356
dump_int_field(header.image_x_origin);
357
dump_int_field(header.image_y_origin);
358
dump_int_field(header.image_width);
359
dump_int_field(header.image_height);
360
dump_int_field(header.image_bpp);
361
dump_int_field(header.image_descriptor);
364
/* Check that bitmap encoding is supported. */
365
switch (header.image_type)
367
case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
368
case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
372
grub_file_close (file);
373
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
374
"unsupported bitmap format (unknown encoding)");
377
/* Check that bitmap depth is supported. */
378
switch (header.image_bpp)
389
grub_file_close (file);
390
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
391
"unsupported bitmap format (bpp=%d)",
395
/* Allocate bitmap. If there is alpha information store it too. */
398
grub_video_bitmap_create (bitmap, header.image_width,
400
GRUB_VIDEO_BLIT_FORMAT_RGBA_8888);
401
if (grub_errno != GRUB_ERR_NONE)
403
grub_file_close (file);
407
/* Load bitmap data. */
408
switch (header.image_type)
410
case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
411
tga_load_truecolor_R8G8B8A8 (*bitmap, &header, file);
414
case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
415
tga_load_truecolor_rle_R8G8B8A8 (*bitmap, &header, file);
421
grub_video_bitmap_create (bitmap, header.image_width,
423
GRUB_VIDEO_BLIT_FORMAT_RGB_888);
424
if (grub_errno != GRUB_ERR_NONE)
426
grub_file_close (file);
430
/* Load bitmap data. */
431
switch (header.image_type)
433
case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR:
434
tga_load_truecolor_R8G8B8 (*bitmap, &header, file);
437
case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR:
438
tga_load_truecolor_rle_R8G8B8 (*bitmap, &header, file);
443
/* If there was a loading problem, destroy bitmap. */
444
if (grub_errno != GRUB_ERR_NONE)
446
grub_video_bitmap_destroy (*bitmap);
450
grub_file_close (file);
454
#if defined(TGA_DEBUG)
456
grub_cmd_tgatest (grub_command_t cmd __attribute__ ((unused)),
457
int argc, char **args)
459
struct grub_video_bitmap *bitmap = 0;
462
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
464
grub_video_reader_tga (&bitmap, args[0]);
465
if (grub_errno != GRUB_ERR_NONE)
468
grub_video_bitmap_destroy (bitmap);
470
return GRUB_ERR_NONE;
474
static struct grub_video_bitmap_reader tga_reader = {
476
.reader = grub_video_reader_tga,
482
grub_video_bitmap_reader_register (&tga_reader);
483
#if defined(TGA_DEBUG)
484
cmd = grub_register_command ("tgatest", grub_cmd_tgatest,
485
"FILE", "Tests loading of TGA bitmap.");
491
#if defined(TGA_DEBUG)
492
grub_unregister_command (cmd);
494
grub_video_bitmap_reader_unregister (&tga_reader);