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>
26 #include <grub/file.h>
28 /* Uncomment following define to enable TGA debug. */
31 #if defined(TGA_DEBUG)
32 #define dump_int_field(x) grub_printf( #x " = %d (0x%04x)\n", x, x);
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
, (char *)&type
, sizeof (type
)) != sizeof(type
))
107 /* RLE-encoded packet. */
111 if (grub_file_read (file
, (char *)&tmp
[0], bytes_per_pixel
)
117 if (x
< header
->image_width
)
131 /* RAW-encoded packet. */
136 if (grub_file_read (file
, (char *)&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
, (char *)&type
, sizeof (type
)) != sizeof(type
))
186 /* RLE-encoded packet. */
190 if (grub_file_read (file
, (char *)&tmp
[0], bytes_per_pixel
)
196 if (x
< header
->image_width
)
211 /* RAW-encoded packet. */
216 if (grub_file_read (file
, (char *)&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
, (char *)&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
, (char *)&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_file_open (filename
);
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
, (char*)&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_R8G8B8A8
);
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_R8G8B8
);
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 (struct grub_arg_list
*state
__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
,
480 GRUB_MOD_INIT(video_reader_tga
)
482 grub_video_bitmap_reader_register (&tga_reader
);
483 #if defined(TGA_DEBUG)
484 grub_register_command ("tgatest", grub_cmd_tgatest
, GRUB_COMMAND_FLAG_BOTH
,
485 "tgatest FILE", "Tests loading of TGA bitmap.", 0);
489 GRUB_MOD_FINI(video_reader_tga
)
491 #if defined(TGA_DEBUG)
492 grub_unregister_command ("tgatest");
494 grub_video_bitmap_reader_unregister (&tga_reader
);