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>
26 #include <grub/file.h>
28 /* Uncomment following define to enable JPEG debug. */
31 #define JPEG_ESC_CHAR 0xFF
33 #define JPEG_SAMPLING_1x1 0x11
35 #define JPEG_MARKER_SOI 0xd8
36 #define JPEG_MARKER_EOI 0xd9
37 #define JPEG_MARKER_DHT 0xc4
38 #define JPEG_MARKER_DQT 0xdb
39 #define JPEG_MARKER_SOF0 0xc0
40 #define JPEG_MARKER_SOS 0xda
43 #define CONST(x) ((int) ((x) * (1L << SHIFT_BITS) + 0.5))
45 #define JPEG_UNIT_SIZE 8
47 static const grub_uint8_t jpeg_zigzag_order
[64] = {
48 0, 1, 8, 16, 9, 2, 3, 10,
49 17, 24, 32, 25, 18, 11, 4, 5,
50 12, 19, 26, 33, 40, 48, 41, 34,
51 27, 20, 13, 6, 7, 14, 21, 28,
52 35, 42, 49, 56, 57, 50, 43, 36,
53 29, 22, 15, 23, 30, 37, 44, 51,
54 58, 59, 52, 45, 38, 31, 39, 46,
55 53, 60, 61, 54, 47, 55, 62, 63
58 typedef int jpeg_data_unit_t
[64];
63 struct grub_video_bitmap
**bitmap
;
68 grub_uint8_t
*huff_value
[4];
69 int huff_offset
[4][16];
70 int huff_maxval
[4][16];
72 grub_uint8_t quan_table
[2][64];
75 jpeg_data_unit_t ydu
[4];
76 jpeg_data_unit_t crdu
;
77 jpeg_data_unit_t cbdu
;
83 int bit_mask
, bit_save
;
87 grub_jpeg_get_byte (struct grub_jpeg_data
*data
)
92 grub_file_read (data
->file
, (char *) &r
, 1);
98 grub_jpeg_get_word (struct grub_jpeg_data
*data
)
103 grub_file_read (data
->file
, (char *) &r
, sizeof (grub_uint16_t
));
105 return grub_be_to_cpu16 (r
);
109 grub_jpeg_get_bit (struct grub_jpeg_data
*data
)
113 if (data
->bit_mask
== 0)
115 data
->bit_save
= grub_jpeg_get_byte (data
);
116 if (data
->bit_save
== JPEG_ESC_CHAR
)
118 if (grub_jpeg_get_byte (data
) != 0)
120 grub_error (GRUB_ERR_BAD_FILE_TYPE
,
121 "jpeg: invalid 0xFF in data stream");
125 data
->bit_mask
= 0x80;
128 ret
= ((data
->bit_save
& data
->bit_mask
) != 0);
129 data
->bit_mask
>>= 1;
134 grub_jpeg_get_number (struct grub_jpeg_data
*data
, int num
)
141 msb
= value
= grub_jpeg_get_bit (data
);
142 for (i
= 1; i
< num
; i
++)
143 value
= (value
<< 1) + (grub_jpeg_get_bit (data
) != 0);
145 value
+= 1 - (1 << num
);
151 grub_jpeg_get_huff_code (struct grub_jpeg_data
*data
, int id
)
156 for (i
= 0; i
< 16; i
++)
159 if (grub_jpeg_get_bit (data
))
161 if (code
< data
->huff_maxval
[id
][i
])
162 return data
->huff_value
[id
][code
+ data
->huff_offset
[id
][i
]];
164 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: huffman decode fails");
169 grub_jpeg_decode_huff_table (struct grub_jpeg_data
*data
)
171 int id
, ac
, i
, n
, base
, ofs
;
172 grub_uint32_t next_marker
;
173 grub_uint8_t count
[16];
175 next_marker
= data
->file
->offset
;
176 next_marker
+= grub_jpeg_get_word (data
);
178 id
= grub_jpeg_get_byte (data
);
182 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
183 "jpeg: too many huffman tables");
185 if (grub_file_read (data
->file
, (char *) &count
, sizeof (count
)) !=
190 for (i
= 0; i
< 16; i
++)
194 data
->huff_value
[id
] = grub_malloc (n
);
198 if (grub_file_read (data
->file
, (char *) data
->huff_value
[id
], n
) != n
)
203 for (i
= 0; i
< 16; i
++)
208 data
->huff_maxval
[id
][i
] = base
;
209 data
->huff_offset
[id
][i
] = ofs
- base
;
214 if (data
->file
->offset
!= next_marker
)
215 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: extra byte in huffman table");
221 grub_jpeg_decode_quan_table (struct grub_jpeg_data
*data
)
224 grub_uint32_t next_marker
;
226 next_marker
= data
->file
->offset
;
227 next_marker
+= grub_jpeg_get_word (data
);
229 id
= grub_jpeg_get_byte (data
);
230 if (id
>= 0x10) /* Upper 4-bit is precision. */
231 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
232 "jpeg: only 8-bit precision is supported");
235 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
236 "jpeg: too many quantization tables");
238 if (grub_file_read (data
->file
, (char *) &data
->quan_table
[id
], 64) != 64)
241 if (data
->file
->offset
!= next_marker
)
242 grub_error (GRUB_ERR_BAD_FILE_TYPE
,
243 "jpeg: extra byte in quantization table");
249 grub_jpeg_decode_sof (struct grub_jpeg_data
*data
)
252 grub_uint32_t next_marker
;
254 next_marker
= data
->file
->offset
;
255 next_marker
+= grub_jpeg_get_word (data
);
257 if (grub_jpeg_get_byte (data
) != 8)
258 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
259 "jpeg: only 8-bit precision is supported");
261 data
->image_height
= grub_jpeg_get_word (data
);
262 data
->image_width
= grub_jpeg_get_word (data
);
264 if ((!data
->image_height
) || (!data
->image_width
))
265 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid image size");
267 cc
= grub_jpeg_get_byte (data
);
269 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
270 "jpeg: component count must be 3");
272 for (i
= 0; i
< cc
; i
++)
276 id
= grub_jpeg_get_byte (data
) - 1;
277 if ((id
< 0) || (id
>= 3))
278 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid index");
280 ss
= grub_jpeg_get_byte (data
); /* Sampling factor. */
283 data
->vs
= ss
& 0xF; /* Vertical sampling. */
284 data
->hs
= ss
>> 4; /* Horizontal sampling. */
285 if ((data
->vs
> 2) || (data
->hs
> 2))
286 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
287 "jpeg: sampling method not supported");
289 else if (ss
!= JPEG_SAMPLING_1x1
)
290 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
291 "jpeg: sampling method not supported");
292 data
->comp_index
[id
][0] = grub_jpeg_get_byte (data
);
295 if (data
->file
->offset
!= next_marker
)
296 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: extra byte in sof");
302 grub_jpeg_idct_transform (jpeg_data_unit_t du
)
306 int t0
, t1
, t2
, t3
, t4
, t5
, t6
, t7
;
307 int v0
, v1
, v2
, v3
, v4
;
310 for (i
= 0; i
< JPEG_UNIT_SIZE
; i
++, pd
++)
312 if ((pd
[JPEG_UNIT_SIZE
* 1] | pd
[JPEG_UNIT_SIZE
* 2] |
313 pd
[JPEG_UNIT_SIZE
* 3] | pd
[JPEG_UNIT_SIZE
* 4] |
314 pd
[JPEG_UNIT_SIZE
* 5] | pd
[JPEG_UNIT_SIZE
* 6] |
315 pd
[JPEG_UNIT_SIZE
* 7]) == 0)
317 pd
[JPEG_UNIT_SIZE
* 0] <<= SHIFT_BITS
;
319 pd
[JPEG_UNIT_SIZE
* 1] = pd
[JPEG_UNIT_SIZE
* 2]
320 = pd
[JPEG_UNIT_SIZE
* 3] = pd
[JPEG_UNIT_SIZE
* 4]
321 = pd
[JPEG_UNIT_SIZE
* 5] = pd
[JPEG_UNIT_SIZE
* 6]
322 = pd
[JPEG_UNIT_SIZE
* 7] = pd
[JPEG_UNIT_SIZE
* 0];
327 t0
= pd
[JPEG_UNIT_SIZE
* 0];
328 t1
= pd
[JPEG_UNIT_SIZE
* 2];
329 t2
= pd
[JPEG_UNIT_SIZE
* 4];
330 t3
= pd
[JPEG_UNIT_SIZE
* 6];
332 v4
= (t1
+ t3
) * CONST (0.541196100);
334 v0
= ((t0
+ t2
) << SHIFT_BITS
);
335 v1
= ((t0
- t2
) << SHIFT_BITS
);
336 v2
= v4
- t3
* CONST (1.847759065);
337 v3
= v4
+ t1
* CONST (0.765366865);
344 t4
= pd
[JPEG_UNIT_SIZE
* 7];
345 t5
= pd
[JPEG_UNIT_SIZE
* 5];
346 t6
= pd
[JPEG_UNIT_SIZE
* 3];
347 t7
= pd
[JPEG_UNIT_SIZE
* 1];
354 v4
= (v2
+ v3
) * CONST (1.175875602);
356 v0
*= CONST (0.899976223);
357 v1
*= CONST (2.562915447);
358 v2
= v2
* CONST (1.961570560) - v4
;
359 v3
= v3
* CONST (0.390180644) - v4
;
361 t4
= t4
* CONST (0.298631336) - v0
- v2
;
362 t5
= t5
* CONST (2.053119869) - v1
- v3
;
363 t6
= t6
* CONST (3.072711026) - v1
- v2
;
364 t7
= t7
* CONST (1.501321110) - v0
- v3
;
366 pd
[JPEG_UNIT_SIZE
* 0] = t0
+ t7
;
367 pd
[JPEG_UNIT_SIZE
* 7] = t0
- t7
;
368 pd
[JPEG_UNIT_SIZE
* 1] = t1
+ t6
;
369 pd
[JPEG_UNIT_SIZE
* 6] = t1
- t6
;
370 pd
[JPEG_UNIT_SIZE
* 2] = t2
+ t5
;
371 pd
[JPEG_UNIT_SIZE
* 5] = t2
- t5
;
372 pd
[JPEG_UNIT_SIZE
* 3] = t3
+ t4
;
373 pd
[JPEG_UNIT_SIZE
* 4] = t3
- t4
;
377 for (i
= 0; i
< JPEG_UNIT_SIZE
; i
++, pd
+= JPEG_UNIT_SIZE
)
379 if ((pd
[1] | pd
[2] | pd
[3] | pd
[4] | pd
[5] | pd
[6] | pd
[7]) == 0)
381 pd
[0] >>= (SHIFT_BITS
+ 3);
382 pd
[1] = pd
[2] = pd
[3] = pd
[4] = pd
[5] = pd
[6] = pd
[7] = pd
[0];
386 v4
= (pd
[2] + pd
[6]) * CONST (0.541196100);
388 v0
= (pd
[0] + pd
[4]) << SHIFT_BITS
;
389 v1
= (pd
[0] - pd
[4]) << SHIFT_BITS
;
390 v2
= v4
- pd
[6] * CONST (1.847759065);
391 v3
= v4
+ pd
[2] * CONST (0.765366865);
408 v4
= (v2
+ v3
) * CONST (1.175875602);
410 v0
*= CONST (0.899976223);
411 v1
*= CONST (2.562915447);
412 v2
= v2
* CONST (1.961570560) - v4
;
413 v3
= v3
* CONST (0.390180644) - v4
;
415 t4
= t4
* CONST (0.298631336) - v0
- v2
;
416 t5
= t5
* CONST (2.053119869) - v1
- v3
;
417 t6
= t6
* CONST (3.072711026) - v1
- v2
;
418 t7
= t7
* CONST (1.501321110) - v0
- v3
;
420 pd
[0] = (t0
+ t7
) >> (SHIFT_BITS
* 2 + 3);
421 pd
[7] = (t0
- t7
) >> (SHIFT_BITS
* 2 + 3);
422 pd
[1] = (t1
+ t6
) >> (SHIFT_BITS
* 2 + 3);
423 pd
[6] = (t1
- t6
) >> (SHIFT_BITS
* 2 + 3);
424 pd
[2] = (t2
+ t5
) >> (SHIFT_BITS
* 2 + 3);
425 pd
[5] = (t2
- t5
) >> (SHIFT_BITS
* 2 + 3);
426 pd
[3] = (t3
+ t4
) >> (SHIFT_BITS
* 2 + 3);
427 pd
[4] = (t3
- t4
) >> (SHIFT_BITS
* 2 + 3);
430 for (i
= 0; i
< JPEG_UNIT_SIZE
* JPEG_UNIT_SIZE
; i
++)
442 grub_jpeg_decode_du (struct grub_jpeg_data
*data
, int id
, jpeg_data_unit_t du
)
446 grub_memset (du
, 0, sizeof (jpeg_data_unit_t
));
448 qt
= data
->comp_index
[id
][0];
449 h1
= data
->comp_index
[id
][1];
450 h2
= data
->comp_index
[id
][2];
452 data
->dc_value
[id
] +=
453 grub_jpeg_get_number (data
, grub_jpeg_get_huff_code (data
, h1
));
455 du
[0] = data
->dc_value
[id
] * (int) data
->quan_table
[qt
][0];
461 num
= grub_jpeg_get_huff_code (data
, h2
);
465 val
= grub_jpeg_get_number (data
, num
& 0xF);
468 du
[jpeg_zigzag_order
[pos
]] = val
* (int) data
->quan_table
[qt
][pos
];
472 grub_jpeg_idct_transform (du
);
476 grub_jpeg_ycrcb_to_rgb (int yy
, int cr
, int cb
, grub_uint8_t
* rgb
)
484 dd
= yy
+ ((cr
* CONST (1.402)) >> SHIFT_BITS
);
492 dd
= yy
- ((cb
* CONST (0.34414) + cr
* CONST (0.71414)) >> SHIFT_BITS
);
500 dd
= yy
+ ((cb
* CONST (1.772)) >> SHIFT_BITS
);
509 grub_jpeg_decode_sos (struct grub_jpeg_data
*data
)
511 int i
, cc
, r1
, c1
, nr1
, nc1
, vb
, hb
;
513 grub_uint32_t data_offset
;
515 data_offset
= data
->file
->offset
;
516 data_offset
+= grub_jpeg_get_word (data
);
518 cc
= grub_jpeg_get_byte (data
);
521 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
522 "jpeg: component count must be 3");
524 for (i
= 0; i
< cc
; i
++)
528 id
= grub_jpeg_get_byte (data
) - 1;
529 if ((id
< 0) || (id
>= 3))
530 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid index");
532 ht
= grub_jpeg_get_byte (data
);
533 data
->comp_index
[id
][1] = (ht
>> 4);
534 data
->comp_index
[id
][2] = (ht
& 0xF) + 2;
537 grub_jpeg_get_byte (data
); /* Skip 3 unused bytes. */
538 grub_jpeg_get_word (data
);
540 if (data
->file
->offset
!= data_offset
)
541 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: extra byte in sos");
543 if (grub_video_bitmap_create (data
->bitmap
, data
->image_width
,
545 GRUB_VIDEO_BLIT_FORMAT_R8G8B8
))
548 data
->bit_mask
= 0x0;
552 nr1
= (data
->image_height
+ vb
- 1) / vb
;
553 nc1
= (data
->image_width
+ hb
- 1) / hb
;
555 ptr1
= (*data
->bitmap
)->data
;
556 for (r1
= 0; r1
< nr1
;
557 r1
++, ptr1
+= (vb
* data
->image_width
- hb
* nc1
) * 3)
558 for (c1
= 0; c1
< nc1
; c1
++, ptr1
+= hb
* 3)
560 int r2
, c2
, nr2
, nc2
;
563 for (r2
= 0; r2
< data
->vs
; r2
++)
564 for (c2
= 0; c2
< data
->hs
; c2
++)
565 grub_jpeg_decode_du (data
, 0, data
->ydu
[r2
* 2 + c2
]);
567 grub_jpeg_decode_du (data
, 1, data
->cbdu
);
568 grub_jpeg_decode_du (data
, 2, data
->crdu
);
573 nr2
= (r1
== nr1
- 1) ? (data
->image_height
- r1
* vb
) : vb
;
574 nc2
= (c1
== nc1
- 1) ? (data
->image_width
- c1
* hb
) : hb
;
577 for (r2
= 0; r2
< nr2
; r2
++, ptr2
+= (data
->image_width
- nc2
) * 3)
578 for (c2
= 0; c2
< nc2
; c2
++, ptr2
+= 3)
582 i0
= (r2
/ data
->vs
) * 8 + (c2
/ data
->hs
);
586 data
->ydu
[(r2
/ 8) * 2 + (c2
/ 8)][(r2
% 8) * 8 + (c2
% 8)];
588 grub_jpeg_ycrcb_to_rgb (yy
, cr
, cb
, ptr2
);
596 grub_jpeg_get_marker (struct grub_jpeg_data
*data
)
600 r
= grub_jpeg_get_byte (data
);
602 if (r
!= JPEG_ESC_CHAR
)
604 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid maker");
608 return grub_jpeg_get_byte (data
);
612 grub_jpeg_decode_jpeg (struct grub_jpeg_data
*data
)
614 if (grub_jpeg_get_marker (data
) != JPEG_MARKER_SOI
) /* Start Of Image. */
615 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid jpeg file");
617 while (grub_errno
== 0)
621 marker
= grub_jpeg_get_marker (data
);
626 grub_printf ("jpeg marker: %x\n", marker
);
631 case JPEG_MARKER_DHT
: /* Define Huffman Table. */
632 grub_jpeg_decode_huff_table (data
);
634 case JPEG_MARKER_DQT
: /* Define Quantization Table. */
635 grub_jpeg_decode_quan_table (data
);
637 case JPEG_MARKER_SOF0
: /* Start Of Frame 0. */
638 grub_jpeg_decode_sof (data
);
640 case JPEG_MARKER_SOS
: /* Start Of Scan. */
641 grub_jpeg_decode_sos (data
);
643 case JPEG_MARKER_EOI
: /* End Of Image. */
645 default: /* Skip unrecognized marker. */
649 sz
= grub_jpeg_get_word (data
);
652 grub_file_seek (data
->file
, data
->file
->offset
+ sz
- 2);
661 grub_video_reader_jpeg (struct grub_video_bitmap
**bitmap
,
662 const char *filename
)
665 struct grub_jpeg_data
*data
;
667 file
= grub_file_open (filename
);
671 data
= grub_malloc (sizeof (*data
));
676 grub_memset (data
, 0, sizeof (*data
));
678 data
->bitmap
= bitmap
;
679 grub_jpeg_decode_jpeg (data
);
681 for (i
= 0; i
< 4; i
++)
682 if (data
->huff_value
[i
])
683 grub_free (data
->huff_value
[i
]);
688 if (grub_errno
!= GRUB_ERR_NONE
)
690 grub_video_bitmap_destroy (*bitmap
);
694 grub_file_close (file
);
698 #if defined(JPEG_DEBUG)
700 grub_cmd_jpegtest (struct grub_arg_list
*state
__attribute__ ((unused
)),
701 int argc
, char **args
)
703 struct grub_video_bitmap
*bitmap
= 0;
706 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "file name required");
708 grub_video_reader_jpeg (&bitmap
, args
[0]);
709 if (grub_errno
!= GRUB_ERR_NONE
)
712 grub_video_bitmap_destroy (bitmap
);
714 return GRUB_ERR_NONE
;
718 static struct grub_video_bitmap_reader jpg_reader
= {
720 .reader
= grub_video_reader_jpeg
,
724 static struct grub_video_bitmap_reader jpeg_reader
= {
725 .extension
= ".jpeg",
726 .reader
= grub_video_reader_jpeg
,
730 GRUB_MOD_INIT (video_reader_jpeg
)
732 grub_video_bitmap_reader_register (&jpg_reader
);
733 grub_video_bitmap_reader_register (&jpeg_reader
);
734 #if defined(JPEG_DEBUG)
735 grub_register_command ("jpegtest", grub_cmd_jpegtest
,
736 GRUB_COMMAND_FLAG_BOTH
, "jpegtest FILE",
737 "Tests loading of JPEG bitmap.", 0);
741 GRUB_MOD_FINI (video_reader_jpeg
)
743 #if defined(JPEG_DEBUG)
744 grub_unregister_command ("jpegtest");
746 grub_video_bitmap_reader_unregister (&jpeg_reader
);
747 grub_video_bitmap_reader_unregister (&jpg_reader
);