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 GRUB_MOD_LICENSE ("GPLv3+");
29 /* Uncomment following define to enable 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
;
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,
50 GRUB_TGA_COLOR_MAP_TYPE_NONE
= 0,
51 GRUB_TGA_COLOR_MAP_TYPE_INCLUDED
= 1
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
));
81 tga_load_truecolor_rle_R8G8B8 (struct grub_video_bitmap
*bitmap
,
82 struct grub_tga_header
*header
,
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
++)
97 if ((header
->image_descriptor
& GRUB_TGA_IMAGE_ORIGIN_TOP
) != 0)
98 ptr
+= y
* bitmap
->mode_info
.pitch
;
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
))
109 /* RLE-encoded packet. */
113 if (grub_file_read (file
, &tmp
[0], bytes_per_pixel
)
119 if (x
< header
->image_width
)
133 /* RAW-encoded packet. */
138 if (grub_file_read (file
, &tmp
[0], bytes_per_pixel
)
142 if (x
< header
->image_width
)
156 return GRUB_ERR_NONE
;
160 tga_load_truecolor_rle_R8G8B8A8 (struct grub_video_bitmap
*bitmap
,
161 struct grub_tga_header
*header
,
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
++)
176 if ((header
->image_descriptor
& GRUB_TGA_IMAGE_ORIGIN_TOP
) != 0)
177 ptr
+= y
* bitmap
->mode_info
.pitch
;
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
))
188 /* RLE-encoded packet. */
192 if (grub_file_read (file
, &tmp
[0], bytes_per_pixel
)
198 if (x
< header
->image_width
)
213 /* RAW-encoded packet. */
218 if (grub_file_read (file
, &tmp
[0], bytes_per_pixel
)
222 if (x
< header
->image_width
)
237 return GRUB_ERR_NONE
;
241 tga_load_truecolor_R8G8B8 (struct grub_video_bitmap
*bitmap
,
242 struct grub_tga_header
*header
,
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
++)
256 if ((header
->image_descriptor
& GRUB_TGA_IMAGE_ORIGIN_TOP
) != 0)
257 ptr
+= y
* bitmap
->mode_info
.pitch
;
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
)
274 return GRUB_ERR_NONE
;
278 tga_load_truecolor_R8G8B8A8 (struct grub_video_bitmap
*bitmap
,
279 struct grub_tga_header
*header
,
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
++)
293 if ((header
->image_descriptor
& GRUB_TGA_IMAGE_ORIGIN_TOP
) != 0)
294 ptr
+= y
* bitmap
->mode_info
.pitch
;
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
)
312 return GRUB_ERR_NONE
;
316 grub_video_reader_tga (struct grub_video_bitmap
**bitmap
,
317 const char *filename
)
321 struct grub_tga_header header
;
324 file
= grub_buffile_open (filename
, 0);
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
))
336 grub_file_close (file
);
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
);
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
);
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
:
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
)
391 grub_file_close (file
);
392 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
393 "unsupported bitmap format (bpp=%d)",
397 /* Allocate bitmap. If there is alpha information store it too. */
400 grub_video_bitmap_create (bitmap
, header
.image_width
,
402 GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
);
403 if (grub_errno
!= GRUB_ERR_NONE
)
405 grub_file_close (file
);
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
);
416 case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR
:
417 tga_load_truecolor_rle_R8G8B8A8 (*bitmap
, &header
, file
);
423 grub_video_bitmap_create (bitmap
, header
.image_width
,
425 GRUB_VIDEO_BLIT_FORMAT_RGB_888
);
426 if (grub_errno
!= GRUB_ERR_NONE
)
428 grub_file_close (file
);
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
);
439 case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR
:
440 tga_load_truecolor_rle_R8G8B8 (*bitmap
, &header
, file
);
445 /* If there was a loading problem, destroy bitmap. */
446 if (grub_errno
!= GRUB_ERR_NONE
)
448 grub_video_bitmap_destroy (*bitmap
);
452 grub_file_close (file
);
456 #if defined(TGA_DEBUG)
458 grub_cmd_tgatest (grub_command_t cmd
__attribute__ ((unused
)),
459 int argc
, char **args
)
461 struct grub_video_bitmap
*bitmap
= 0;
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
)
470 grub_video_bitmap_destroy (bitmap
);
472 return GRUB_ERR_NONE
;
476 static struct grub_video_bitmap_reader tga_reader
= {
478 .reader
= grub_video_reader_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.");
493 #if defined(TGA_DEBUG)
494 grub_unregister_command (cmd
);
496 grub_video_bitmap_reader_unregister (&tga_reader
);