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
57 typedef int jpeg_data_unit_t
[64];
62 struct grub_video_bitmap
**bitmap
;
67 grub_uint8_t
*huff_value
[4];
68 int huff_offset
[4][16];
69 int huff_maxval
[4][16];
71 grub_uint8_t quan_table
[2][64];
74 jpeg_data_unit_t ydu
[4];
75 jpeg_data_unit_t crdu
;
76 jpeg_data_unit_t cbdu
;
82 int bit_mask
, bit_save
;
86 grub_jpeg_get_byte (struct grub_jpeg_data
*data
)
91 grub_file_read (data
->file
, &r
, 1);
97 grub_jpeg_get_word (struct grub_jpeg_data
*data
)
102 grub_file_read (data
->file
, &r
, sizeof (grub_uint16_t
));
104 return grub_be_to_cpu16 (r
);
108 grub_jpeg_get_bit (struct grub_jpeg_data
*data
)
112 if (data
->bit_mask
== 0)
114 data
->bit_save
= grub_jpeg_get_byte (data
);
115 if (data
->bit_save
== JPEG_ESC_CHAR
)
117 if (grub_jpeg_get_byte (data
) != 0)
119 grub_error (GRUB_ERR_BAD_FILE_TYPE
,
120 "jpeg: invalid 0xFF in data stream");
124 data
->bit_mask
= 0x80;
127 ret
= ((data
->bit_save
& data
->bit_mask
) != 0);
128 data
->bit_mask
>>= 1;
133 grub_jpeg_get_number (struct grub_jpeg_data
*data
, int num
)
140 msb
= value
= grub_jpeg_get_bit (data
);
141 for (i
= 1; i
< num
; i
++)
142 value
= (value
<< 1) + (grub_jpeg_get_bit (data
) != 0);
144 value
+= 1 - (1 << num
);
150 grub_jpeg_get_huff_code (struct grub_jpeg_data
*data
, int id
)
155 for (i
= 0; i
< 16; i
++)
158 if (grub_jpeg_get_bit (data
))
160 if (code
< data
->huff_maxval
[id
][i
])
161 return data
->huff_value
[id
][code
+ data
->huff_offset
[id
][i
]];
163 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: huffman decode fails");
168 grub_jpeg_decode_huff_table (struct grub_jpeg_data
*data
)
170 int id
, ac
, i
, n
, base
, ofs
;
171 grub_uint32_t next_marker
;
172 grub_uint8_t count
[16];
174 next_marker
= data
->file
->offset
;
175 next_marker
+= grub_jpeg_get_word (data
);
177 id
= grub_jpeg_get_byte (data
);
181 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
182 "jpeg: too many huffman tables");
184 if (grub_file_read (data
->file
, &count
, sizeof (count
)) !=
189 for (i
= 0; i
< 16; i
++)
193 data
->huff_value
[id
] = grub_malloc (n
);
197 if (grub_file_read (data
->file
, data
->huff_value
[id
], n
) != n
)
202 for (i
= 0; i
< 16; i
++)
207 data
->huff_maxval
[id
][i
] = base
;
208 data
->huff_offset
[id
][i
] = ofs
- base
;
213 if (data
->file
->offset
!= next_marker
)
214 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: extra byte in huffman table");
220 grub_jpeg_decode_quan_table (struct grub_jpeg_data
*data
)
223 grub_uint32_t next_marker
;
225 next_marker
= data
->file
->offset
;
226 next_marker
+= grub_jpeg_get_word (data
);
228 id
= grub_jpeg_get_byte (data
);
229 if (id
>= 0x10) /* Upper 4-bit is precision. */
230 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
231 "jpeg: only 8-bit precision is supported");
234 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
235 "jpeg: too many quantization tables");
237 if (grub_file_read (data
->file
, &data
->quan_table
[id
], 64) != 64)
240 if (data
->file
->offset
!= next_marker
)
241 grub_error (GRUB_ERR_BAD_FILE_TYPE
,
242 "jpeg: extra byte in quantization table");
248 grub_jpeg_decode_sof (struct grub_jpeg_data
*data
)
251 grub_uint32_t next_marker
;
253 next_marker
= data
->file
->offset
;
254 next_marker
+= grub_jpeg_get_word (data
);
256 if (grub_jpeg_get_byte (data
) != 8)
257 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
258 "jpeg: only 8-bit precision is supported");
260 data
->image_height
= grub_jpeg_get_word (data
);
261 data
->image_width
= grub_jpeg_get_word (data
);
263 if ((!data
->image_height
) || (!data
->image_width
))
264 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid image size");
266 cc
= grub_jpeg_get_byte (data
);
268 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
269 "jpeg: component count must be 3");
271 for (i
= 0; i
< cc
; i
++)
275 id
= grub_jpeg_get_byte (data
) - 1;
276 if ((id
< 0) || (id
>= 3))
277 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid index");
279 ss
= grub_jpeg_get_byte (data
); /* Sampling factor. */
282 data
->vs
= ss
& 0xF; /* Vertical sampling. */
283 data
->hs
= ss
>> 4; /* Horizontal sampling. */
284 if ((data
->vs
> 2) || (data
->hs
> 2))
285 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
286 "jpeg: sampling method not supported");
288 else if (ss
!= JPEG_SAMPLING_1x1
)
289 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
290 "jpeg: sampling method not supported");
291 data
->comp_index
[id
][0] = grub_jpeg_get_byte (data
);
294 if (data
->file
->offset
!= next_marker
)
295 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: extra byte in sof");
301 grub_jpeg_idct_transform (jpeg_data_unit_t du
)
305 int t0
, t1
, t2
, t3
, t4
, t5
, t6
, t7
;
306 int v0
, v1
, v2
, v3
, v4
;
309 for (i
= 0; i
< JPEG_UNIT_SIZE
; i
++, pd
++)
311 if ((pd
[JPEG_UNIT_SIZE
* 1] | pd
[JPEG_UNIT_SIZE
* 2] |
312 pd
[JPEG_UNIT_SIZE
* 3] | pd
[JPEG_UNIT_SIZE
* 4] |
313 pd
[JPEG_UNIT_SIZE
* 5] | pd
[JPEG_UNIT_SIZE
* 6] |
314 pd
[JPEG_UNIT_SIZE
* 7]) == 0)
316 pd
[JPEG_UNIT_SIZE
* 0] <<= SHIFT_BITS
;
318 pd
[JPEG_UNIT_SIZE
* 1] = pd
[JPEG_UNIT_SIZE
* 2]
319 = pd
[JPEG_UNIT_SIZE
* 3] = pd
[JPEG_UNIT_SIZE
* 4]
320 = pd
[JPEG_UNIT_SIZE
* 5] = pd
[JPEG_UNIT_SIZE
* 6]
321 = pd
[JPEG_UNIT_SIZE
* 7] = pd
[JPEG_UNIT_SIZE
* 0];
326 t0
= pd
[JPEG_UNIT_SIZE
* 0];
327 t1
= pd
[JPEG_UNIT_SIZE
* 2];
328 t2
= pd
[JPEG_UNIT_SIZE
* 4];
329 t3
= pd
[JPEG_UNIT_SIZE
* 6];
331 v4
= (t1
+ t3
) * CONST (0.541196100);
333 v0
= ((t0
+ t2
) << SHIFT_BITS
);
334 v1
= ((t0
- t2
) << SHIFT_BITS
);
335 v2
= v4
- t3
* CONST (1.847759065);
336 v3
= v4
+ t1
* CONST (0.765366865);
343 t4
= pd
[JPEG_UNIT_SIZE
* 7];
344 t5
= pd
[JPEG_UNIT_SIZE
* 5];
345 t6
= pd
[JPEG_UNIT_SIZE
* 3];
346 t7
= pd
[JPEG_UNIT_SIZE
* 1];
353 v4
= (v2
+ v3
) * CONST (1.175875602);
355 v0
*= CONST (0.899976223);
356 v1
*= CONST (2.562915447);
357 v2
= v2
* CONST (1.961570560) - v4
;
358 v3
= v3
* CONST (0.390180644) - v4
;
360 t4
= t4
* CONST (0.298631336) - v0
- v2
;
361 t5
= t5
* CONST (2.053119869) - v1
- v3
;
362 t6
= t6
* CONST (3.072711026) - v1
- v2
;
363 t7
= t7
* CONST (1.501321110) - v0
- v3
;
365 pd
[JPEG_UNIT_SIZE
* 0] = t0
+ t7
;
366 pd
[JPEG_UNIT_SIZE
* 7] = t0
- t7
;
367 pd
[JPEG_UNIT_SIZE
* 1] = t1
+ t6
;
368 pd
[JPEG_UNIT_SIZE
* 6] = t1
- t6
;
369 pd
[JPEG_UNIT_SIZE
* 2] = t2
+ t5
;
370 pd
[JPEG_UNIT_SIZE
* 5] = t2
- t5
;
371 pd
[JPEG_UNIT_SIZE
* 3] = t3
+ t4
;
372 pd
[JPEG_UNIT_SIZE
* 4] = t3
- t4
;
376 for (i
= 0; i
< JPEG_UNIT_SIZE
; i
++, pd
+= JPEG_UNIT_SIZE
)
378 if ((pd
[1] | pd
[2] | pd
[3] | pd
[4] | pd
[5] | pd
[6] | pd
[7]) == 0)
380 pd
[0] >>= (SHIFT_BITS
+ 3);
381 pd
[1] = pd
[2] = pd
[3] = pd
[4] = pd
[5] = pd
[6] = pd
[7] = pd
[0];
385 v4
= (pd
[2] + pd
[6]) * CONST (0.541196100);
387 v0
= (pd
[0] + pd
[4]) << SHIFT_BITS
;
388 v1
= (pd
[0] - pd
[4]) << SHIFT_BITS
;
389 v2
= v4
- pd
[6] * CONST (1.847759065);
390 v3
= v4
+ pd
[2] * CONST (0.765366865);
407 v4
= (v2
+ v3
) * CONST (1.175875602);
409 v0
*= CONST (0.899976223);
410 v1
*= CONST (2.562915447);
411 v2
= v2
* CONST (1.961570560) - v4
;
412 v3
= v3
* CONST (0.390180644) - v4
;
414 t4
= t4
* CONST (0.298631336) - v0
- v2
;
415 t5
= t5
* CONST (2.053119869) - v1
- v3
;
416 t6
= t6
* CONST (3.072711026) - v1
- v2
;
417 t7
= t7
* CONST (1.501321110) - v0
- v3
;
419 pd
[0] = (t0
+ t7
) >> (SHIFT_BITS
* 2 + 3);
420 pd
[7] = (t0
- t7
) >> (SHIFT_BITS
* 2 + 3);
421 pd
[1] = (t1
+ t6
) >> (SHIFT_BITS
* 2 + 3);
422 pd
[6] = (t1
- t6
) >> (SHIFT_BITS
* 2 + 3);
423 pd
[2] = (t2
+ t5
) >> (SHIFT_BITS
* 2 + 3);
424 pd
[5] = (t2
- t5
) >> (SHIFT_BITS
* 2 + 3);
425 pd
[3] = (t3
+ t4
) >> (SHIFT_BITS
* 2 + 3);
426 pd
[4] = (t3
- t4
) >> (SHIFT_BITS
* 2 + 3);
429 for (i
= 0; i
< JPEG_UNIT_SIZE
* JPEG_UNIT_SIZE
; i
++)
441 grub_jpeg_decode_du (struct grub_jpeg_data
*data
, int id
, jpeg_data_unit_t du
)
445 grub_memset (du
, 0, sizeof (jpeg_data_unit_t
));
447 qt
= data
->comp_index
[id
][0];
448 h1
= data
->comp_index
[id
][1];
449 h2
= data
->comp_index
[id
][2];
451 data
->dc_value
[id
] +=
452 grub_jpeg_get_number (data
, grub_jpeg_get_huff_code (data
, h1
));
454 du
[0] = data
->dc_value
[id
] * (int) data
->quan_table
[qt
][0];
460 num
= grub_jpeg_get_huff_code (data
, h2
);
464 val
= grub_jpeg_get_number (data
, num
& 0xF);
467 du
[jpeg_zigzag_order
[pos
]] = val
* (int) data
->quan_table
[qt
][pos
];
471 grub_jpeg_idct_transform (du
);
475 grub_jpeg_ycrcb_to_rgb (int yy
, int cr
, int cb
, grub_uint8_t
* rgb
)
483 dd
= yy
+ ((cr
* CONST (1.402)) >> SHIFT_BITS
);
491 dd
= yy
- ((cb
* CONST (0.34414) + cr
* CONST (0.71414)) >> SHIFT_BITS
);
499 dd
= yy
+ ((cb
* CONST (1.772)) >> SHIFT_BITS
);
508 grub_jpeg_decode_sos (struct grub_jpeg_data
*data
)
510 int i
, cc
, r1
, c1
, nr1
, nc1
, vb
, hb
;
512 grub_uint32_t data_offset
;
514 data_offset
= data
->file
->offset
;
515 data_offset
+= grub_jpeg_get_word (data
);
517 cc
= grub_jpeg_get_byte (data
);
520 return grub_error (GRUB_ERR_BAD_FILE_TYPE
,
521 "jpeg: component count must be 3");
523 for (i
= 0; i
< cc
; i
++)
527 id
= grub_jpeg_get_byte (data
) - 1;
528 if ((id
< 0) || (id
>= 3))
529 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid index");
531 ht
= grub_jpeg_get_byte (data
);
532 data
->comp_index
[id
][1] = (ht
>> 4);
533 data
->comp_index
[id
][2] = (ht
& 0xF) + 2;
536 grub_jpeg_get_byte (data
); /* Skip 3 unused bytes. */
537 grub_jpeg_get_word (data
);
539 if (data
->file
->offset
!= data_offset
)
540 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: extra byte in sos");
542 if (grub_video_bitmap_create (data
->bitmap
, data
->image_width
,
544 GRUB_VIDEO_BLIT_FORMAT_RGB_888
))
547 data
->bit_mask
= 0x0;
551 nr1
= (data
->image_height
+ vb
- 1) / vb
;
552 nc1
= (data
->image_width
+ hb
- 1) / hb
;
554 ptr1
= (*data
->bitmap
)->data
;
555 for (r1
= 0; r1
< nr1
;
556 r1
++, ptr1
+= (vb
* data
->image_width
- hb
* nc1
) * 3)
557 for (c1
= 0; c1
< nc1
; c1
++, ptr1
+= hb
* 3)
559 int r2
, c2
, nr2
, nc2
;
562 for (r2
= 0; r2
< data
->vs
; r2
++)
563 for (c2
= 0; c2
< data
->hs
; c2
++)
564 grub_jpeg_decode_du (data
, 0, data
->ydu
[r2
* 2 + c2
]);
566 grub_jpeg_decode_du (data
, 1, data
->cbdu
);
567 grub_jpeg_decode_du (data
, 2, data
->crdu
);
572 nr2
= (r1
== nr1
- 1) ? (data
->image_height
- r1
* vb
) : vb
;
573 nc2
= (c1
== nc1
- 1) ? (data
->image_width
- c1
* hb
) : hb
;
576 for (r2
= 0; r2
< nr2
; r2
++, ptr2
+= (data
->image_width
- nc2
) * 3)
577 for (c2
= 0; c2
< nc2
; c2
++, ptr2
+= 3)
581 i0
= (r2
/ data
->vs
) * 8 + (c2
/ data
->hs
);
585 data
->ydu
[(r2
/ 8) * 2 + (c2
/ 8)][(r2
% 8) * 8 + (c2
% 8)];
587 grub_jpeg_ycrcb_to_rgb (yy
, cr
, cb
, ptr2
);
595 grub_jpeg_get_marker (struct grub_jpeg_data
*data
)
599 r
= grub_jpeg_get_byte (data
);
601 if (r
!= JPEG_ESC_CHAR
)
603 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid maker");
607 return grub_jpeg_get_byte (data
);
611 grub_jpeg_decode_jpeg (struct grub_jpeg_data
*data
)
613 if (grub_jpeg_get_marker (data
) != JPEG_MARKER_SOI
) /* Start Of Image. */
614 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "jpeg: invalid jpeg file");
616 while (grub_errno
== 0)
620 marker
= grub_jpeg_get_marker (data
);
625 grub_printf ("jpeg marker: %x\n", marker
);
630 case JPEG_MARKER_DHT
: /* Define Huffman Table. */
631 grub_jpeg_decode_huff_table (data
);
633 case JPEG_MARKER_DQT
: /* Define Quantization Table. */
634 grub_jpeg_decode_quan_table (data
);
636 case JPEG_MARKER_SOF0
: /* Start Of Frame 0. */
637 grub_jpeg_decode_sof (data
);
639 case JPEG_MARKER_SOS
: /* Start Of Scan. */
640 grub_jpeg_decode_sos (data
);
642 case JPEG_MARKER_EOI
: /* End Of Image. */
644 default: /* Skip unrecognized marker. */
648 sz
= grub_jpeg_get_word (data
);
651 grub_file_seek (data
->file
, data
->file
->offset
+ sz
- 2);
660 grub_video_reader_jpeg (struct grub_video_bitmap
**bitmap
,
661 const char *filename
)
664 struct grub_jpeg_data
*data
;
666 file
= grub_buffile_open (filename
, 0);
670 data
= grub_malloc (sizeof (*data
));
675 grub_memset (data
, 0, sizeof (*data
));
677 data
->bitmap
= bitmap
;
678 grub_jpeg_decode_jpeg (data
);
680 for (i
= 0; i
< 4; i
++)
681 if (data
->huff_value
[i
])
682 grub_free (data
->huff_value
[i
]);
687 if (grub_errno
!= GRUB_ERR_NONE
)
689 grub_video_bitmap_destroy (*bitmap
);
693 grub_file_close (file
);
697 #if defined(JPEG_DEBUG)
699 grub_cmd_jpegtest (struct grub_arg_list
*state
__attribute__ ((unused
)),
700 int argc
, char **args
)
702 struct grub_video_bitmap
*bitmap
= 0;
705 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "file name required");
707 grub_video_reader_jpeg (&bitmap
, args
[0]);
708 if (grub_errno
!= GRUB_ERR_NONE
)
711 grub_video_bitmap_destroy (bitmap
);
713 return GRUB_ERR_NONE
;
717 static struct grub_video_bitmap_reader jpg_reader
= {
719 .reader
= grub_video_reader_jpeg
,
723 static struct grub_video_bitmap_reader jpeg_reader
= {
724 .extension
= ".jpeg",
725 .reader
= grub_video_reader_jpeg
,
729 GRUB_MOD_INIT (video_reader_jpeg
)
731 grub_video_bitmap_reader_register (&jpg_reader
);
732 grub_video_bitmap_reader_register (&jpeg_reader
);
733 #if defined(JPEG_DEBUG)
734 grub_register_command ("jpegtest", grub_cmd_jpegtest
,
735 GRUB_COMMAND_FLAG_BOTH
, "jpegtest FILE",
736 "Tests loading of JPEG bitmap.", 0);
740 GRUB_MOD_FINI (video_reader_jpeg
)
742 #if defined(JPEG_DEBUG)
743 grub_unregister_command ("jpegtest");
745 grub_video_bitmap_reader_unregister (&jpeg_reader
);
746 grub_video_bitmap_reader_unregister (&jpg_reader
);