2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2008 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 JPEG debug. */
30 #define JPEG_ESC_CHAR 0xFF
32 #define JPEG_SAMPLING_1x1 0x11
34 #define JPEG_MARKER_SOI 0xd8
35 #define JPEG_MARKER_EOI 0xd9
36 #define JPEG_MARKER_DHT 0xc4
37 #define JPEG_MARKER_DQT 0xdb
38 #define JPEG_MARKER_SOF0 0xc0
39 #define JPEG_MARKER_SOS 0xda
42 #define CONST(x) ((int) ((x) * (1L << SHIFT_BITS) + 0.5))
44 #define JPEG_UNIT_SIZE 8
46 static const grub_uint8_t jpeg_zigzag_order
[64] = {
47 0, 1, 8, 16, 9, 2, 3, 10,
48 17, 24, 32, 25, 18, 11, 4, 5,
49 12, 19, 26, 33, 40, 48, 41, 34,
50 27, 20, 13, 6, 7, 14, 21, 28,
51 35, 42, 49, 56, 57, 50, 43, 36,
52 29, 22, 15, 23, 30, 37, 44, 51,
53 58, 59, 52, 45, 38, 31, 39, 46,
54 53, 60, 61, 54, 47, 55, 62, 63
58 static grub_command_t cmd
;
61 typedef int jpeg_data_unit_t
[64];
66 struct grub_video_bitmap
**bitmap
;
71 grub_uint8_t
*huff_value
[4];
72 int huff_offset
[4][16];
73 int huff_maxval
[4][16];
75 grub_uint8_t quan_table
[2][64];
78 jpeg_data_unit_t ydu
[4];
79 jpeg_data_unit_t crdu
;
80 jpeg_data_unit_t cbdu
;
86 int bit_mask
, bit_save
;
90 grub_jpeg_get_byte (struct grub_jpeg_data
*data
)
95 grub_file_read (data
->file
, &r
, 1);
101 grub_jpeg_get_word (struct grub_jpeg_data
*data
)
106 grub_file_read (data
->file
, &r
, sizeof (grub_uint16_t
));
108 return grub_be_to_cpu16 (r
);
112 grub_jpeg_get_bit (struct grub_jpeg_data
*data
)
116 if (data
->bit_mask
== 0)
118 data
->bit_save
= grub_jpeg_get_byte (data
);
119 if (data
->bit_save
== JPEG_ESC_CHAR
)
121 if (grub_jpeg_get_byte (data
) != 0)
123 grub_error (GRUB_ERR_BAD_FILE_TYPE
,
124 "jpeg: invalid 0xFF in data stream");
128 data
->bit_mask
= 0x80;
131 ret
= ((data
->bit_save
& data
->bit_mask
) != 0);
132 data
->bit_mask
>>= 1;
137 grub_jpeg_get_number (struct grub_jpeg_data
*data
, int num
)
144 msb
= value
= grub_jpeg_get_bit (data
);
145 for (i
= 1; i
< num
; i
++)
146 value
= (value
<< 1) + (grub_jpeg_get_bit (data
) != 0);
148 value
+= 1 - (1 << num
);
154 grub_jpeg_get_huff_code (struct grub_jpeg_data
*data
, int id
)
159 for (i
= 0; i
< 16; i
++)
162 if (grub_jpeg_get_bit (data
))
164 if (code
< data
->huff_maxval
[id
][i
])
165 return data
->huff_value
[id
][code
+ data
->huff_offset
[id
][i
]];
167 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: huffman decode fails");
172 grub_jpeg_decode_huff_table (struct grub_jpeg_data
*data
)
174 int id
, ac
, i
, n
, base
, ofs
;
175 grub_uint32_t next_marker
;
176 grub_uint8_t count
[16];
178 next_marker
= data
->file
->offset
;
179 next_marker
+= grub_jpeg_get_word (data
);
181 id
= grub_jpeg_get_byte (data
);
185 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
186 "jpeg: too many huffman tables");
188 if (grub_file_read (data
->file
, &count
, sizeof (count
)) !=
193 for (i
= 0; i
< 16; i
++)
197 data
->huff_value
[id
] = grub_malloc (n
);
201 if (grub_file_read (data
->file
, data
->huff_value
[id
], n
) != n
)
206 for (i
= 0; i
< 16; i
++)
211 data
->huff_maxval
[id
][i
] = base
;
212 data
->huff_offset
[id
][i
] = ofs
- base
;
217 if (data
->file
->offset
!= next_marker
)
218 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: extra byte in huffman table");
224 grub_jpeg_decode_quan_table (struct grub_jpeg_data
*data
)
227 grub_uint32_t next_marker
;
229 next_marker
= data
->file
->offset
;
230 next_marker
+= grub_jpeg_get_word (data
);
232 id
= grub_jpeg_get_byte (data
);
233 if (id
>= 0x10) /* Upper 4-bit is precision. */
234 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
235 "jpeg: only 8-bit precision is supported");
238 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
239 "jpeg: too many quantization tables");
241 if (grub_file_read (data
->file
, &data
->quan_table
[id
], 64) != 64)
244 if (data
->file
->offset
!= next_marker
)
245 grub_error (GRUB_ERR_BAD_FILE_TYPE
,
246 "jpeg: extra byte in quantization table");
252 grub_jpeg_decode_sof (struct grub_jpeg_data
*data
)
255 grub_uint32_t next_marker
;
257 next_marker
= data
->file
->offset
;
258 next_marker
+= grub_jpeg_get_word (data
);
260 if (grub_jpeg_get_byte (data
) != 8)
261 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
262 "jpeg: only 8-bit precision is supported");
264 data
->image_height
= grub_jpeg_get_word (data
);
265 data
->image_width
= grub_jpeg_get_word (data
);
267 if ((!data
->image_height
) || (!data
->image_width
))
268 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid image size");
270 cc
= grub_jpeg_get_byte (data
);
272 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
273 "jpeg: component count must be 3");
275 for (i
= 0; i
< cc
; i
++)
279 id
= grub_jpeg_get_byte (data
) - 1;
280 if ((id
< 0) || (id
>= 3))
281 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid index");
283 ss
= grub_jpeg_get_byte (data
); /* Sampling factor. */
286 data
->vs
= ss
& 0xF; /* Vertical sampling. */
287 data
->hs
= ss
>> 4; /* Horizontal sampling. */
288 if ((data
->vs
> 2) || (data
->hs
> 2))
289 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
290 "jpeg: sampling method not supported");
292 else if (ss
!= JPEG_SAMPLING_1x1
)
293 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
294 "jpeg: sampling method not supported");
295 data
->comp_index
[id
][0] = grub_jpeg_get_byte (data
);
298 if (data
->file
->offset
!= next_marker
)
299 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: extra byte in sof");
305 grub_jpeg_idct_transform (jpeg_data_unit_t du
)
309 int t0
, t1
, t2
, t3
, t4
, t5
, t6
, t7
;
310 int v0
, v1
, v2
, v3
, v4
;
313 for (i
= 0; i
< JPEG_UNIT_SIZE
; i
++, pd
++)
315 if ((pd
[JPEG_UNIT_SIZE
* 1] | pd
[JPEG_UNIT_SIZE
* 2] |
316 pd
[JPEG_UNIT_SIZE
* 3] | pd
[JPEG_UNIT_SIZE
* 4] |
317 pd
[JPEG_UNIT_SIZE
* 5] | pd
[JPEG_UNIT_SIZE
* 6] |
318 pd
[JPEG_UNIT_SIZE
* 7]) == 0)
320 pd
[JPEG_UNIT_SIZE
* 0] <<= SHIFT_BITS
;
322 pd
[JPEG_UNIT_SIZE
* 1] = pd
[JPEG_UNIT_SIZE
* 2]
323 = pd
[JPEG_UNIT_SIZE
* 3] = pd
[JPEG_UNIT_SIZE
* 4]
324 = pd
[JPEG_UNIT_SIZE
* 5] = pd
[JPEG_UNIT_SIZE
* 6]
325 = pd
[JPEG_UNIT_SIZE
* 7] = pd
[JPEG_UNIT_SIZE
* 0];
330 t0
= pd
[JPEG_UNIT_SIZE
* 0];
331 t1
= pd
[JPEG_UNIT_SIZE
* 2];
332 t2
= pd
[JPEG_UNIT_SIZE
* 4];
333 t3
= pd
[JPEG_UNIT_SIZE
* 6];
335 v4
= (t1
+ t3
) * CONST (0.541196100);
337 v0
= ((t0
+ t2
) << SHIFT_BITS
);
338 v1
= ((t0
- t2
) << SHIFT_BITS
);
339 v2
= v4
- t3
* CONST (1.847759065);
340 v3
= v4
+ t1
* CONST (0.765366865);
347 t4
= pd
[JPEG_UNIT_SIZE
* 7];
348 t5
= pd
[JPEG_UNIT_SIZE
* 5];
349 t6
= pd
[JPEG_UNIT_SIZE
* 3];
350 t7
= pd
[JPEG_UNIT_SIZE
* 1];
357 v4
= (v2
+ v3
) * CONST (1.175875602);
359 v0
*= CONST (0.899976223);
360 v1
*= CONST (2.562915447);
361 v2
= v2
* CONST (1.961570560) - v4
;
362 v3
= v3
* CONST (0.390180644) - v4
;
364 t4
= t4
* CONST (0.298631336) - v0
- v2
;
365 t5
= t5
* CONST (2.053119869) - v1
- v3
;
366 t6
= t6
* CONST (3.072711026) - v1
- v2
;
367 t7
= t7
* CONST (1.501321110) - v0
- v3
;
369 pd
[JPEG_UNIT_SIZE
* 0] = t0
+ t7
;
370 pd
[JPEG_UNIT_SIZE
* 7] = t0
- t7
;
371 pd
[JPEG_UNIT_SIZE
* 1] = t1
+ t6
;
372 pd
[JPEG_UNIT_SIZE
* 6] = t1
- t6
;
373 pd
[JPEG_UNIT_SIZE
* 2] = t2
+ t5
;
374 pd
[JPEG_UNIT_SIZE
* 5] = t2
- t5
;
375 pd
[JPEG_UNIT_SIZE
* 3] = t3
+ t4
;
376 pd
[JPEG_UNIT_SIZE
* 4] = t3
- t4
;
380 for (i
= 0; i
< JPEG_UNIT_SIZE
; i
++, pd
+= JPEG_UNIT_SIZE
)
382 if ((pd
[1] | pd
[2] | pd
[3] | pd
[4] | pd
[5] | pd
[6] | pd
[7]) == 0)
384 pd
[0] >>= (SHIFT_BITS
+ 3);
385 pd
[1] = pd
[2] = pd
[3] = pd
[4] = pd
[5] = pd
[6] = pd
[7] = pd
[0];
389 v4
= (pd
[2] + pd
[6]) * CONST (0.541196100);
391 v0
= (pd
[0] + pd
[4]) << SHIFT_BITS
;
392 v1
= (pd
[0] - pd
[4]) << SHIFT_BITS
;
393 v2
= v4
- pd
[6] * CONST (1.847759065);
394 v3
= v4
+ pd
[2] * CONST (0.765366865);
411 v4
= (v2
+ v3
) * CONST (1.175875602);
413 v0
*= CONST (0.899976223);
414 v1
*= CONST (2.562915447);
415 v2
= v2
* CONST (1.961570560) - v4
;
416 v3
= v3
* CONST (0.390180644) - v4
;
418 t4
= t4
* CONST (0.298631336) - v0
- v2
;
419 t5
= t5
* CONST (2.053119869) - v1
- v3
;
420 t6
= t6
* CONST (3.072711026) - v1
- v2
;
421 t7
= t7
* CONST (1.501321110) - v0
- v3
;
423 pd
[0] = (t0
+ t7
) >> (SHIFT_BITS
* 2 + 3);
424 pd
[7] = (t0
- t7
) >> (SHIFT_BITS
* 2 + 3);
425 pd
[1] = (t1
+ t6
) >> (SHIFT_BITS
* 2 + 3);
426 pd
[6] = (t1
- t6
) >> (SHIFT_BITS
* 2 + 3);
427 pd
[2] = (t2
+ t5
) >> (SHIFT_BITS
* 2 + 3);
428 pd
[5] = (t2
- t5
) >> (SHIFT_BITS
* 2 + 3);
429 pd
[3] = (t3
+ t4
) >> (SHIFT_BITS
* 2 + 3);
430 pd
[4] = (t3
- t4
) >> (SHIFT_BITS
* 2 + 3);
433 for (i
= 0; i
< JPEG_UNIT_SIZE
* JPEG_UNIT_SIZE
; i
++)
445 grub_jpeg_decode_du (struct grub_jpeg_data
*data
, int id
, jpeg_data_unit_t du
)
449 grub_memset (du
, 0, sizeof (jpeg_data_unit_t
));
451 qt
= data
->comp_index
[id
][0];
452 h1
= data
->comp_index
[id
][1];
453 h2
= data
->comp_index
[id
][2];
455 data
->dc_value
[id
] +=
456 grub_jpeg_get_number (data
, grub_jpeg_get_huff_code (data
, h1
));
458 du
[0] = data
->dc_value
[id
] * (int) data
->quan_table
[qt
][0];
464 num
= grub_jpeg_get_huff_code (data
, h2
);
468 val
= grub_jpeg_get_number (data
, num
& 0xF);
471 du
[jpeg_zigzag_order
[pos
]] = val
* (int) data
->quan_table
[qt
][pos
];
475 grub_jpeg_idct_transform (du
);
479 grub_jpeg_ycrcb_to_rgb (int yy
, int cr
, int cb
, grub_uint8_t
* rgb
)
487 dd
= yy
+ ((cr
* CONST (1.402)) >> SHIFT_BITS
);
495 dd
= yy
- ((cb
* CONST (0.34414) + cr
* CONST (0.71414)) >> SHIFT_BITS
);
503 dd
= yy
+ ((cb
* CONST (1.772)) >> SHIFT_BITS
);
512 grub_jpeg_decode_sos (struct grub_jpeg_data
*data
)
514 int i
, cc
, r1
, c1
, nr1
, nc1
, vb
, hb
;
516 grub_uint32_t data_offset
;
518 data_offset
= data
->file
->offset
;
519 data_offset
+= grub_jpeg_get_word (data
);
521 cc
= grub_jpeg_get_byte (data
);
524 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
525 "jpeg: component count must be 3");
527 for (i
= 0; i
< cc
; i
++)
531 id
= grub_jpeg_get_byte (data
) - 1;
532 if ((id
< 0) || (id
>= 3))
533 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid index");
535 ht
= grub_jpeg_get_byte (data
);
536 data
->comp_index
[id
][1] = (ht
>> 4);
537 data
->comp_index
[id
][2] = (ht
& 0xF) + 2;
540 grub_jpeg_get_byte (data
); /* Skip 3 unused bytes. */
541 grub_jpeg_get_word (data
);
543 if (data
->file
->offset
!= data_offset
)
544 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: extra byte in sos");
546 if (grub_video_bitmap_create (data
->bitmap
, data
->image_width
,
548 GRUB_VIDEO_BLIT_FORMAT_RGB_888
))
551 data
->bit_mask
= 0x0;
555 nr1
= (data
->image_height
+ vb
- 1) / vb
;
556 nc1
= (data
->image_width
+ hb
- 1) / hb
;
558 ptr1
= (*data
->bitmap
)->data
;
559 for (r1
= 0; r1
< nr1
;
560 r1
++, ptr1
+= (vb
* data
->image_width
- hb
* nc1
) * 3)
561 for (c1
= 0; c1
< nc1
; c1
++, ptr1
+= hb
* 3)
563 int r2
, c2
, nr2
, nc2
;
566 for (r2
= 0; r2
< data
->vs
; r2
++)
567 for (c2
= 0; c2
< data
->hs
; c2
++)
568 grub_jpeg_decode_du (data
, 0, data
->ydu
[r2
* 2 + c2
]);
570 grub_jpeg_decode_du (data
, 1, data
->cbdu
);
571 grub_jpeg_decode_du (data
, 2, data
->crdu
);
576 nr2
= (r1
== nr1
- 1) ? (data
->image_height
- r1
* vb
) : vb
;
577 nc2
= (c1
== nc1
- 1) ? (data
->image_width
- c1
* hb
) : hb
;
580 for (r2
= 0; r2
< nr2
; r2
++, ptr2
+= (data
->image_width
- nc2
) * 3)
581 for (c2
= 0; c2
< nc2
; c2
++, ptr2
+= 3)
585 i0
= (r2
/ data
->vs
) * 8 + (c2
/ data
->hs
);
589 data
->ydu
[(r2
/ 8) * 2 + (c2
/ 8)][(r2
% 8) * 8 + (c2
% 8)];
591 grub_jpeg_ycrcb_to_rgb (yy
, cr
, cb
, ptr2
);
599 grub_jpeg_get_marker (struct grub_jpeg_data
*data
)
603 r
= grub_jpeg_get_byte (data
);
605 if (r
!= JPEG_ESC_CHAR
)
607 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid maker");
611 return grub_jpeg_get_byte (data
);
615 grub_jpeg_decode_jpeg (struct grub_jpeg_data
*data
)
617 if (grub_jpeg_get_marker (data
) != JPEG_MARKER_SOI
) /* Start Of Image. */
618 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid jpeg file");
620 while (grub_errno
== 0)
624 marker
= grub_jpeg_get_marker (data
);
629 grub_printf ("jpeg marker: %x\n", marker
);
634 case JPEG_MARKER_DHT
: /* Define Huffman Table. */
635 grub_jpeg_decode_huff_table (data
);
637 case JPEG_MARKER_DQT
: /* Define Quantization Table. */
638 grub_jpeg_decode_quan_table (data
);
640 case JPEG_MARKER_SOF0
: /* Start Of Frame 0. */
641 grub_jpeg_decode_sof (data
);
643 case JPEG_MARKER_SOS
: /* Start Of Scan. */
644 grub_jpeg_decode_sos (data
);
646 case JPEG_MARKER_EOI
: /* End Of Image. */
648 default: /* Skip unrecognized marker. */
652 sz
= grub_jpeg_get_word (data
);
655 grub_file_seek (data
->file
, data
->file
->offset
+ sz
- 2);
664 grub_video_reader_jpeg (struct grub_video_bitmap
**bitmap
,
665 const char *filename
)
668 struct grub_jpeg_data
*data
;
670 file
= grub_buffile_open (filename
, 0);
674 data
= grub_zalloc (sizeof (*data
));
680 data
->bitmap
= bitmap
;
681 grub_jpeg_decode_jpeg (data
);
683 for (i
= 0; i
< 4; i
++)
684 if (data
->huff_value
[i
])
685 grub_free (data
->huff_value
[i
]);
690 if (grub_errno
!= GRUB_ERR_NONE
)
692 grub_video_bitmap_destroy (*bitmap
);
696 grub_file_close (file
);
700 #if defined(JPEG_DEBUG)
702 grub_cmd_jpegtest (grub_command_t cmd
__attribute__ ((unused
)),
703 int argc
, char **args
)
705 struct grub_video_bitmap
*bitmap
= 0;
708 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "file name required");
710 grub_video_reader_jpeg (&bitmap
, args
[0]);
711 if (grub_errno
!= GRUB_ERR_NONE
)
714 grub_video_bitmap_destroy (bitmap
);
716 return GRUB_ERR_NONE
;
720 static struct grub_video_bitmap_reader jpg_reader
= {
722 .reader
= grub_video_reader_jpeg
,
726 static struct grub_video_bitmap_reader jpeg_reader
= {
727 .extension
= ".jpeg",
728 .reader
= grub_video_reader_jpeg
,
732 GRUB_MOD_INIT (video_reader_jpeg
)
734 grub_video_bitmap_reader_register (&jpg_reader
);
735 grub_video_bitmap_reader_register (&jpeg_reader
);
736 #if defined(JPEG_DEBUG)
737 cmd
= grub_register_command ("jpegtest", grub_cmd_jpegtest
,
739 "Tests loading of JPEG bitmap.");
743 GRUB_MOD_FINI (video_reader_jpeg
)
745 #if defined(JPEG_DEBUG)
746 grub_unregister_command (cmd
);
748 grub_video_bitmap_reader_unregister (&jpeg_reader
);
749 grub_video_bitmap_reader_unregister (&jpg_reader
);