GRUB-1.98 changes
[grub2/jjazz.git] / video / readers / jpeg.c
blob3c3ac33bbe24ea30aa3f16c147875fca20f24b06
1 /*
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>
22 #include <grub/dl.h>
23 #include <grub/mm.h>
24 #include <grub/misc.h>
25 #include <grub/bufio.h>
27 /* Uncomment following define to enable JPEG debug. */
28 //#define 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
41 #define SHIFT_BITS 8
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 #ifdef JPEG_DEBUG
58 static grub_command_t cmd;
59 #endif
61 typedef int jpeg_data_unit_t[64];
63 struct grub_jpeg_data
65 grub_file_t file;
66 struct grub_video_bitmap **bitmap;
68 int image_width;
69 int image_height;
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];
76 int comp_index[3][3];
78 jpeg_data_unit_t ydu[4];
79 jpeg_data_unit_t crdu;
80 jpeg_data_unit_t cbdu;
82 int vs, hs;
84 int dc_value[3];
86 int bit_mask, bit_save;
89 static grub_uint8_t
90 grub_jpeg_get_byte (struct grub_jpeg_data *data)
92 grub_uint8_t r;
94 r = 0;
95 grub_file_read (data->file, &r, 1);
97 return r;
100 static grub_uint16_t
101 grub_jpeg_get_word (struct grub_jpeg_data *data)
103 grub_uint16_t r;
105 r = 0;
106 grub_file_read (data->file, &r, sizeof (grub_uint16_t));
108 return grub_be_to_cpu16 (r);
111 static int
112 grub_jpeg_get_bit (struct grub_jpeg_data *data)
114 int ret;
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");
125 return 0;
128 data->bit_mask = 0x80;
131 ret = ((data->bit_save & data->bit_mask) != 0);
132 data->bit_mask >>= 1;
133 return ret;
136 static int
137 grub_jpeg_get_number (struct grub_jpeg_data *data, int num)
139 int value, i, msb;
141 if (num == 0)
142 return 0;
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);
147 if (!msb)
148 value += 1 - (1 << num);
150 return value;
153 static int
154 grub_jpeg_get_huff_code (struct grub_jpeg_data *data, int id)
156 int code, i;
158 code = 0;
159 for (i = 0; i < 16; i++)
161 code <<= 1;
162 if (grub_jpeg_get_bit (data))
163 code++;
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");
168 return 0;
171 static grub_err_t
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);
182 ac = (id >> 4);
183 id &= 0xF;
184 if (id > 1)
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)) !=
189 sizeof (count))
190 return grub_errno;
192 n = 0;
193 for (i = 0; i < 16; i++)
194 n += count[i];
196 id += ac * 2;
197 data->huff_value[id] = grub_malloc (n);
198 if (grub_errno)
199 return grub_errno;
201 if (grub_file_read (data->file, data->huff_value[id], n) != n)
202 return grub_errno;
204 base = 0;
205 ofs = 0;
206 for (i = 0; i < 16; i++)
208 base += count[i];
209 ofs += count[i];
211 data->huff_maxval[id][i] = base;
212 data->huff_offset[id][i] = ofs - base;
214 base <<= 1;
217 if (data->file->offset != next_marker)
218 grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in huffman table");
220 return grub_errno;
223 static grub_err_t
224 grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
226 int id;
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");
237 if (id > 1)
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)
242 return grub_errno;
244 if (data->file->offset != next_marker)
245 grub_error (GRUB_ERR_BAD_FILE_TYPE,
246 "jpeg: extra byte in quantization table");
248 return grub_errno;
251 static grub_err_t
252 grub_jpeg_decode_sof (struct grub_jpeg_data *data)
254 int i, cc;
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);
271 if (cc != 3)
272 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
273 "jpeg: component count must be 3");
275 for (i = 0; i < cc; i++)
277 int id, ss;
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. */
284 if (!id)
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");
301 return grub_errno;
304 static void
305 grub_jpeg_idct_transform (jpeg_data_unit_t du)
307 int *pd;
308 int i;
309 int t0, t1, t2, t3, t4, t5, t6, t7;
310 int v0, v1, v2, v3, v4;
312 pd = du;
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];
327 continue;
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);
342 t0 = v0 + v3;
343 t3 = v0 - v3;
344 t1 = v1 + v2;
345 t2 = v1 - v2;
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];
352 v0 = t4 + t7;
353 v1 = t5 + t6;
354 v2 = t4 + t6;
355 v3 = t5 + t7;
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;
379 pd = du;
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];
386 continue;
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);
396 t0 = v0 + v3;
397 t3 = v0 - v3;
398 t1 = v1 + v2;
399 t2 = v1 - v2;
401 t4 = pd[7];
402 t5 = pd[5];
403 t6 = pd[3];
404 t7 = pd[1];
406 v0 = t4 + t7;
407 v1 = t5 + t6;
408 v2 = t4 + t6;
409 v3 = t5 + t7;
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++)
435 du[i] += 128;
437 if (du[i] < 0)
438 du[i] = 0;
439 if (du[i] > 255)
440 du[i] = 255;
444 static void
445 grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
447 int pos, h1, h2, qt;
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];
459 pos = 1;
460 while (pos < 64)
462 int num, val;
464 num = grub_jpeg_get_huff_code (data, h2);
465 if (!num)
466 break;
468 val = grub_jpeg_get_number (data, num & 0xF);
469 num >>= 4;
470 pos += num;
471 du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
472 pos++;
475 grub_jpeg_idct_transform (du);
478 static void
479 grub_jpeg_ycrcb_to_rgb (int yy, int cr, int cb, grub_uint8_t * rgb)
481 int dd;
483 cr -= 128;
484 cb -= 128;
486 /* Red */
487 dd = yy + ((cr * CONST (1.402)) >> SHIFT_BITS);
488 if (dd < 0)
489 dd = 0;
490 if (dd > 255)
491 dd = 255;
492 *(rgb++) = dd;
494 /* Green */
495 dd = yy - ((cb * CONST (0.34414) + cr * CONST (0.71414)) >> SHIFT_BITS);
496 if (dd < 0)
497 dd = 0;
498 if (dd > 255)
499 dd = 255;
500 *(rgb++) = dd;
502 /* Blue */
503 dd = yy + ((cb * CONST (1.772)) >> SHIFT_BITS);
504 if (dd < 0)
505 dd = 0;
506 if (dd > 255)
507 dd = 255;
508 *(rgb++) = dd;
511 static grub_err_t
512 grub_jpeg_decode_sos (struct grub_jpeg_data *data)
514 int i, cc, r1, c1, nr1, nc1, vb, hb;
515 grub_uint8_t *ptr1;
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);
523 if (cc != 3)
524 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
525 "jpeg: component count must be 3");
527 for (i = 0; i < cc; i++)
529 int id, ht;
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,
547 data->image_height,
548 GRUB_VIDEO_BLIT_FORMAT_RGB_888))
549 return grub_errno;
551 data->bit_mask = 0x0;
553 vb = data->vs * 8;
554 hb = data->hs * 8;
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;
564 grub_uint8_t *ptr2;
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);
573 if (grub_errno)
574 return grub_errno;
576 nr2 = (r1 == nr1 - 1) ? (data->image_height - r1 * vb) : vb;
577 nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
579 ptr2 = ptr1;
580 for (r2 = 0; r2 < nr2; r2++, ptr2 += (data->image_width - nc2) * 3)
581 for (c2 = 0; c2 < nc2; c2++, ptr2 += 3)
583 int i0, yy, cr, cb;
585 i0 = (r2 / data->vs) * 8 + (c2 / data->hs);
586 cr = data->crdu[i0];
587 cb = data->cbdu[i0];
588 yy =
589 data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)];
591 grub_jpeg_ycrcb_to_rgb (yy, cr, cb, ptr2);
595 return grub_errno;
598 static grub_uint8_t
599 grub_jpeg_get_marker (struct grub_jpeg_data *data)
601 grub_uint8_t r;
603 r = grub_jpeg_get_byte (data);
605 if (r != JPEG_ESC_CHAR)
607 grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid maker");
608 return 0;
611 return grub_jpeg_get_byte (data);
614 static grub_err_t
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)
622 grub_uint8_t marker;
624 marker = grub_jpeg_get_marker (data);
625 if (grub_errno)
626 break;
628 #ifdef JPEG_DEBUG
629 grub_printf ("jpeg marker: %x\n", marker);
630 #endif
632 switch (marker)
634 case JPEG_MARKER_DHT: /* Define Huffman Table. */
635 grub_jpeg_decode_huff_table (data);
636 break;
637 case JPEG_MARKER_DQT: /* Define Quantization Table. */
638 grub_jpeg_decode_quan_table (data);
639 break;
640 case JPEG_MARKER_SOF0: /* Start Of Frame 0. */
641 grub_jpeg_decode_sof (data);
642 break;
643 case JPEG_MARKER_SOS: /* Start Of Scan. */
644 grub_jpeg_decode_sos (data);
645 break;
646 case JPEG_MARKER_EOI: /* End Of Image. */
647 return grub_errno;
648 default: /* Skip unrecognized marker. */
650 grub_uint16_t sz;
652 sz = grub_jpeg_get_word (data);
653 if (grub_errno)
654 return (grub_errno);
655 grub_file_seek (data->file, data->file->offset + sz - 2);
660 return grub_errno;
663 static grub_err_t
664 grub_video_reader_jpeg (struct grub_video_bitmap **bitmap,
665 const char *filename)
667 grub_file_t file;
668 struct grub_jpeg_data *data;
670 file = grub_buffile_open (filename, 0);
671 if (!file)
672 return grub_errno;
674 data = grub_zalloc (sizeof (*data));
675 if (data != NULL)
677 int i;
679 data->file = file;
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]);
687 grub_free (data);
690 if (grub_errno != GRUB_ERR_NONE)
692 grub_video_bitmap_destroy (*bitmap);
693 *bitmap = 0;
696 grub_file_close (file);
697 return grub_errno;
700 #if defined(JPEG_DEBUG)
701 static grub_err_t
702 grub_cmd_jpegtest (grub_command_t cmd __attribute__ ((unused)),
703 int argc, char **args)
705 struct grub_video_bitmap *bitmap = 0;
707 if (argc != 1)
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)
712 return grub_errno;
714 grub_video_bitmap_destroy (bitmap);
716 return GRUB_ERR_NONE;
718 #endif
720 static struct grub_video_bitmap_reader jpg_reader = {
721 .extension = ".jpg",
722 .reader = grub_video_reader_jpeg,
723 .next = 0
726 static struct grub_video_bitmap_reader jpeg_reader = {
727 .extension = ".jpeg",
728 .reader = grub_video_reader_jpeg,
729 .next = 0
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,
738 "FILE",
739 "Tests loading of JPEG bitmap.");
740 #endif
743 GRUB_MOD_FINI (video_reader_jpeg)
745 #if defined(JPEG_DEBUG)
746 grub_unregister_command (cmd);
747 #endif
748 grub_video_bitmap_reader_unregister (&jpeg_reader);
749 grub_video_bitmap_reader_unregister (&jpg_reader);