2009-08-04 Robert Millan <rmh.grub@aybabtu.com>
[grub2/phcoder/solaris.git] / video / readers / jpeg.c
blob460a52872b8aaa9704cd6bcc7290e53a8c6ca9c3
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 typedef int jpeg_data_unit_t[64];
59 struct grub_jpeg_data
61 grub_file_t file;
62 struct grub_video_bitmap **bitmap;
64 int image_width;
65 int image_height;
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];
72 int comp_index[3][3];
74 jpeg_data_unit_t ydu[4];
75 jpeg_data_unit_t crdu;
76 jpeg_data_unit_t cbdu;
78 int vs, hs;
80 int dc_value[3];
82 int bit_mask, bit_save;
85 static grub_uint8_t
86 grub_jpeg_get_byte (struct grub_jpeg_data *data)
88 grub_uint8_t r;
90 r = 0;
91 grub_file_read (data->file, &r, 1);
93 return r;
96 static grub_uint16_t
97 grub_jpeg_get_word (struct grub_jpeg_data *data)
99 grub_uint16_t r;
101 r = 0;
102 grub_file_read (data->file, &r, sizeof (grub_uint16_t));
104 return grub_be_to_cpu16 (r);
107 static int
108 grub_jpeg_get_bit (struct grub_jpeg_data *data)
110 int ret;
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");
121 return 0;
124 data->bit_mask = 0x80;
127 ret = ((data->bit_save & data->bit_mask) != 0);
128 data->bit_mask >>= 1;
129 return ret;
132 static int
133 grub_jpeg_get_number (struct grub_jpeg_data *data, int num)
135 int value, i, msb;
137 if (num == 0)
138 return 0;
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);
143 if (!msb)
144 value += 1 - (1 << num);
146 return value;
149 static int
150 grub_jpeg_get_huff_code (struct grub_jpeg_data *data, int id)
152 int code, i;
154 code = 0;
155 for (i = 0; i < 16; i++)
157 code <<= 1;
158 if (grub_jpeg_get_bit (data))
159 code++;
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");
164 return 0;
167 static grub_err_t
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);
178 ac = (id >> 4);
179 id &= 0xF;
180 if (id > 1)
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)) !=
185 sizeof (count))
186 return grub_errno;
188 n = 0;
189 for (i = 0; i < 16; i++)
190 n += count[i];
192 id += ac * 2;
193 data->huff_value[id] = grub_malloc (n);
194 if (grub_errno)
195 return grub_errno;
197 if (grub_file_read (data->file, data->huff_value[id], n) != n)
198 return grub_errno;
200 base = 0;
201 ofs = 0;
202 for (i = 0; i < 16; i++)
204 base += count[i];
205 ofs += count[i];
207 data->huff_maxval[id][i] = base;
208 data->huff_offset[id][i] = ofs - base;
210 base <<= 1;
213 if (data->file->offset != next_marker)
214 grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in huffman table");
216 return grub_errno;
219 static grub_err_t
220 grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
222 int id;
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");
233 if (id > 1)
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)
238 return grub_errno;
240 if (data->file->offset != next_marker)
241 grub_error (GRUB_ERR_BAD_FILE_TYPE,
242 "jpeg: extra byte in quantization table");
244 return grub_errno;
247 static grub_err_t
248 grub_jpeg_decode_sof (struct grub_jpeg_data *data)
250 int i, cc;
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);
267 if (cc != 3)
268 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
269 "jpeg: component count must be 3");
271 for (i = 0; i < cc; i++)
273 int id, ss;
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. */
280 if (!id)
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");
297 return grub_errno;
300 static void
301 grub_jpeg_idct_transform (jpeg_data_unit_t du)
303 int *pd;
304 int i;
305 int t0, t1, t2, t3, t4, t5, t6, t7;
306 int v0, v1, v2, v3, v4;
308 pd = du;
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];
323 continue;
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);
338 t0 = v0 + v3;
339 t3 = v0 - v3;
340 t1 = v1 + v2;
341 t2 = v1 - v2;
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];
348 v0 = t4 + t7;
349 v1 = t5 + t6;
350 v2 = t4 + t6;
351 v3 = t5 + t7;
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;
375 pd = du;
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];
382 continue;
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);
392 t0 = v0 + v3;
393 t3 = v0 - v3;
394 t1 = v1 + v2;
395 t2 = v1 - v2;
397 t4 = pd[7];
398 t5 = pd[5];
399 t6 = pd[3];
400 t7 = pd[1];
402 v0 = t4 + t7;
403 v1 = t5 + t6;
404 v2 = t4 + t6;
405 v3 = t5 + t7;
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++)
431 du[i] += 128;
433 if (du[i] < 0)
434 du[i] = 0;
435 if (du[i] > 255)
436 du[i] = 255;
440 static void
441 grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
443 int pos, h1, h2, qt;
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];
455 pos = 1;
456 while (pos < 64)
458 int num, val;
460 num = grub_jpeg_get_huff_code (data, h2);
461 if (!num)
462 break;
464 val = grub_jpeg_get_number (data, num & 0xF);
465 num >>= 4;
466 pos += num;
467 du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
468 pos++;
471 grub_jpeg_idct_transform (du);
474 static void
475 grub_jpeg_ycrcb_to_rgb (int yy, int cr, int cb, grub_uint8_t * rgb)
477 int dd;
479 cr -= 128;
480 cb -= 128;
482 /* Red */
483 dd = yy + ((cr * CONST (1.402)) >> SHIFT_BITS);
484 if (dd < 0)
485 dd = 0;
486 if (dd > 255)
487 dd = 255;
488 *(rgb++) = dd;
490 /* Green */
491 dd = yy - ((cb * CONST (0.34414) + cr * CONST (0.71414)) >> SHIFT_BITS);
492 if (dd < 0)
493 dd = 0;
494 if (dd > 255)
495 dd = 255;
496 *(rgb++) = dd;
498 /* Blue */
499 dd = yy + ((cb * CONST (1.772)) >> SHIFT_BITS);
500 if (dd < 0)
501 dd = 0;
502 if (dd > 255)
503 dd = 255;
504 *(rgb++) = dd;
507 static grub_err_t
508 grub_jpeg_decode_sos (struct grub_jpeg_data *data)
510 int i, cc, r1, c1, nr1, nc1, vb, hb;
511 grub_uint8_t *ptr1;
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);
519 if (cc != 3)
520 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
521 "jpeg: component count must be 3");
523 for (i = 0; i < cc; i++)
525 int id, ht;
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,
543 data->image_height,
544 GRUB_VIDEO_BLIT_FORMAT_RGB_888))
545 return grub_errno;
547 data->bit_mask = 0x0;
549 vb = data->vs * 8;
550 hb = data->hs * 8;
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;
560 grub_uint8_t *ptr2;
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);
569 if (grub_errno)
570 return grub_errno;
572 nr2 = (r1 == nr1 - 1) ? (data->image_height - r1 * vb) : vb;
573 nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
575 ptr2 = ptr1;
576 for (r2 = 0; r2 < nr2; r2++, ptr2 += (data->image_width - nc2) * 3)
577 for (c2 = 0; c2 < nc2; c2++, ptr2 += 3)
579 int i0, yy, cr, cb;
581 i0 = (r2 / data->vs) * 8 + (c2 / data->hs);
582 cr = data->crdu[i0];
583 cb = data->cbdu[i0];
584 yy =
585 data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)];
587 grub_jpeg_ycrcb_to_rgb (yy, cr, cb, ptr2);
591 return grub_errno;
594 static grub_uint8_t
595 grub_jpeg_get_marker (struct grub_jpeg_data *data)
597 grub_uint8_t r;
599 r = grub_jpeg_get_byte (data);
601 if (r != JPEG_ESC_CHAR)
603 grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid maker");
604 return 0;
607 return grub_jpeg_get_byte (data);
610 static grub_err_t
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)
618 grub_uint8_t marker;
620 marker = grub_jpeg_get_marker (data);
621 if (grub_errno)
622 break;
624 #ifdef JPEG_DEBUG
625 grub_printf ("jpeg marker: %x\n", marker);
626 #endif
628 switch (marker)
630 case JPEG_MARKER_DHT: /* Define Huffman Table. */
631 grub_jpeg_decode_huff_table (data);
632 break;
633 case JPEG_MARKER_DQT: /* Define Quantization Table. */
634 grub_jpeg_decode_quan_table (data);
635 break;
636 case JPEG_MARKER_SOF0: /* Start Of Frame 0. */
637 grub_jpeg_decode_sof (data);
638 break;
639 case JPEG_MARKER_SOS: /* Start Of Scan. */
640 grub_jpeg_decode_sos (data);
641 break;
642 case JPEG_MARKER_EOI: /* End Of Image. */
643 return grub_errno;
644 default: /* Skip unrecognized marker. */
646 grub_uint16_t sz;
648 sz = grub_jpeg_get_word (data);
649 if (grub_errno)
650 return (grub_errno);
651 grub_file_seek (data->file, data->file->offset + sz - 2);
656 return grub_errno;
659 static grub_err_t
660 grub_video_reader_jpeg (struct grub_video_bitmap **bitmap,
661 const char *filename)
663 grub_file_t file;
664 struct grub_jpeg_data *data;
666 file = grub_buffile_open (filename, 0);
667 if (!file)
668 return grub_errno;
670 data = grub_zalloc (sizeof (*data));
671 if (data != NULL)
673 int i;
675 data->file = file;
676 data->bitmap = bitmap;
677 grub_jpeg_decode_jpeg (data);
679 for (i = 0; i < 4; i++)
680 if (data->huff_value[i])
681 grub_free (data->huff_value[i]);
683 grub_free (data);
686 if (grub_errno != GRUB_ERR_NONE)
688 grub_video_bitmap_destroy (*bitmap);
689 *bitmap = 0;
692 grub_file_close (file);
693 return grub_errno;
696 #if defined(JPEG_DEBUG)
697 static grub_err_t
698 grub_cmd_jpegtest (struct grub_arg_list *state __attribute__ ((unused)),
699 int argc, char **args)
701 struct grub_video_bitmap *bitmap = 0;
703 if (argc != 1)
704 return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
706 grub_video_reader_jpeg (&bitmap, args[0]);
707 if (grub_errno != GRUB_ERR_NONE)
708 return grub_errno;
710 grub_video_bitmap_destroy (bitmap);
712 return GRUB_ERR_NONE;
714 #endif
716 static struct grub_video_bitmap_reader jpg_reader = {
717 .extension = ".jpg",
718 .reader = grub_video_reader_jpeg,
719 .next = 0
722 static struct grub_video_bitmap_reader jpeg_reader = {
723 .extension = ".jpeg",
724 .reader = grub_video_reader_jpeg,
725 .next = 0
728 GRUB_MOD_INIT (video_reader_jpeg)
730 grub_video_bitmap_reader_register (&jpg_reader);
731 grub_video_bitmap_reader_register (&jpeg_reader);
732 #if defined(JPEG_DEBUG)
733 grub_register_command ("jpegtest", grub_cmd_jpegtest,
734 GRUB_COMMAND_FLAG_BOTH, "jpegtest FILE",
735 "Tests loading of JPEG bitmap.", 0);
736 #endif
739 GRUB_MOD_FINI (video_reader_jpeg)
741 #if defined(JPEG_DEBUG)
742 grub_unregister_command ("jpegtest");
743 #endif
744 grub_video_bitmap_reader_unregister (&jpeg_reader);
745 grub_video_bitmap_reader_unregister (&jpg_reader);