Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / common / boot / grub2 / video / readers / png.c
blob3364d56c068eb4f3edd50419867ce3bef974c835
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/arg.h>
26 #include <grub/bufio.h>
28 /* Uncomment following define to enable PNG debug. */
29 //#define PNG_DEBUG
31 #define PNG_COLOR_MASK_PALETTE 1
32 #define PNG_COLOR_MASK_COLOR 2
33 #define PNG_COLOR_MASK_ALPHA 4
35 #define PNG_COLOR_TYPE_GRAY 0
36 #define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
37 #define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
38 #define PNG_COLOR_TYPE_RGBA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
39 #define PNG_COLOR_TYPE_GRAYA (PNG_COLOR_MASK_ALPHA)
41 #define PNG_COMPRESSION_BASE 0
43 #define PNG_INTERLACE_NONE 0
44 #define PNG_INTERLACE_ADAM7 1
46 #define PNG_FILTER_TYPE_BASE 0
48 #define PNG_FILTER_VALUE_NONE 0
49 #define PNG_FILTER_VALUE_SUB 1
50 #define PNG_FILTER_VALUE_UP 2
51 #define PNG_FILTER_VALUE_AVG 3
52 #define PNG_FILTER_VALUE_PAETH 4
53 #define PNG_FILTER_VALUE_LAST 5
55 #define PNG_CHUNK_IHDR 0x49484452
56 #define PNG_CHUNK_IDAT 0x49444154
57 #define PNG_CHUNK_IEND 0x49454e44
59 #define Z_DEFLATED 8
60 #define Z_FLAG_DICT 32
62 #define INFLATE_STORED 0
63 #define INFLATE_FIXED 1
64 #define INFLATE_DYNAMIC 2
66 #define WSIZE 0x8000
68 #define DEFLATE_HCLEN_BASE 4
69 #define DEFLATE_HCLEN_MAX 19
70 #define DEFLATE_HLIT_BASE 257
71 #define DEFLATE_HLIT_MAX 288
72 #define DEFLATE_HDIST_BASE 1
73 #define DEFLATE_HDIST_MAX 30
75 #define DEFLATE_HUFF_LEN 16
77 struct huff_table
79 int *values, *maxval, *offset;
80 int num_values, max_length;
83 struct grub_png_data
85 grub_file_t file;
86 struct grub_video_bitmap **bitmap;
88 int bit_count, bit_save;
90 grub_uint32_t next_offset;
92 int image_width, image_height, bpp, is_16bit, raw_bytes;
93 grub_uint8_t *image_data;
95 int inside_idat, idat_remain;
97 int code_values[DEFLATE_HLIT_MAX];
98 int code_maxval[DEFLATE_HUFF_LEN];
99 int code_offset[DEFLATE_HUFF_LEN];
101 int dist_values[DEFLATE_HDIST_MAX];
102 int dist_maxval[DEFLATE_HUFF_LEN];
103 int dist_offset[DEFLATE_HUFF_LEN];
105 struct huff_table code_table;
106 struct huff_table dist_table;
108 grub_uint8_t slide[WSIZE];
109 int wp;
111 grub_uint8_t *cur_rgb;
113 int cur_colume, cur_filter, first_line;
116 static grub_uint32_t
117 grub_png_get_dword (struct grub_png_data *data)
119 grub_uint32_t r;
121 r = 0;
122 grub_file_read (data->file, (char *) &r, sizeof (grub_uint32_t));
124 return grub_be_to_cpu32 (r);
127 static grub_uint8_t
128 grub_png_get_byte (struct grub_png_data *data)
130 grub_uint8_t r;
132 if ((data->inside_idat) && (data->idat_remain == 0))
134 grub_uint32_t len, type;
138 /* Skip crc checksum. */
139 grub_png_get_dword (data);
141 if (data->file->offset != data->next_offset)
143 grub_error (GRUB_ERR_BAD_FILE_TYPE,
144 "png: chunk size error");
145 return 0;
148 len = grub_png_get_dword (data);
149 type = grub_png_get_dword (data);
150 if (type != PNG_CHUNK_IDAT)
152 grub_error (GRUB_ERR_BAD_FILE_TYPE,
153 "png: unexpected end of data");
154 return 0;
157 data->next_offset = data->file->offset + len + 4;
159 while (len == 0);
160 data->idat_remain = len;
163 r = 0;
164 grub_file_read (data->file, (char *) &r, 1);
166 if (data->inside_idat)
167 data->idat_remain--;
169 return r;
172 static int
173 grub_png_get_bits (struct grub_png_data *data, int num)
175 int code, shift;
177 if (data->bit_count == 0)
179 data->bit_save = grub_png_get_byte (data);
180 data->bit_count = 8;
183 code = 0;
184 shift = 0;
185 while (grub_errno == 0)
187 int n;
189 n = data->bit_count;
190 if (n > num)
191 n = num;
193 code += (int) (data->bit_save & ((1 << n) - 1)) << shift;
194 num -= n;
195 if (!num)
197 data->bit_count -= n;
198 data->bit_save >>= n;
199 break;
202 shift += n;
204 data->bit_save = grub_png_get_byte (data);
205 data->bit_count = 8;
208 return code;
211 static grub_err_t
212 grub_png_decode_image_header (struct grub_png_data *data)
214 int color_type;
215 int color_bits;
217 data->image_width = grub_png_get_dword (data);
218 data->image_height = grub_png_get_dword (data);
220 if ((!data->image_height) || (!data->image_width))
221 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size");
223 color_bits = grub_png_get_byte (data);
224 if ((color_bits != 8) && (color_bits != 16))
225 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
226 "png: bit depth must be 8 or 16");
227 data->is_16bit = (color_bits == 16);
229 color_type = grub_png_get_byte (data);
230 if (color_type == PNG_COLOR_TYPE_RGB)
232 if (grub_video_bitmap_create (data->bitmap, data->image_width,
233 data->image_height,
234 GRUB_VIDEO_BLIT_FORMAT_RGB_888))
235 return grub_errno;
236 data->bpp = 3;
238 else if (color_type == PNG_COLOR_TYPE_RGBA)
240 if (grub_video_bitmap_create (data->bitmap, data->image_width,
241 data->image_height,
242 GRUB_VIDEO_BLIT_FORMAT_RGBA_8888))
243 return grub_errno;
244 data->bpp = 4;
246 else
247 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
248 "png: color type not supported");
250 if (data->is_16bit)
252 data->bpp <<= 1;
254 data->image_data = grub_malloc (data->image_height *
255 data->image_width * data->bpp);
256 if (grub_errno)
257 return grub_errno;
259 data->cur_rgb = data->image_data;
261 else
263 data->image_data = 0;
264 data->cur_rgb = (*data->bitmap)->data;
267 data->raw_bytes = data->image_height * (data->image_width + 1) * data->bpp;
269 data->cur_colume = 0;
270 data->first_line = 1;
272 if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE)
273 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
274 "png: compression method not supported");
276 if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE)
277 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
278 "png: filter method not supported");
280 if (grub_png_get_byte (data) != PNG_INTERLACE_NONE)
281 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
282 "png: interlace method not supported");
284 /* Skip crc checksum. */
285 grub_png_get_dword (data);
287 return grub_errno;
290 /* Order of the bit length code lengths. */
291 static const grub_uint8_t bitorder[] = {
292 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
295 /* Copy lengths for literal codes 257..285. */
296 static const int cplens[] = {
297 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
298 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
301 /* Extra bits for literal codes 257..285. */
302 static const grub_uint8_t cplext[] = {
303 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
304 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
305 }; /* 99==invalid */
307 /* Copy offsets for distance codes 0..29. */
308 static const int cpdist[] = {
309 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
310 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
311 8193, 12289, 16385, 24577
314 /* Extra bits for distance codes. */
315 static const grub_uint8_t cpdext[] = {
316 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
317 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
318 12, 12, 13, 13
321 static void
322 grub_png_init_huff_table (struct huff_table *ht, int cur_maxlen,
323 int *cur_values, int *cur_maxval, int *cur_offset)
325 ht->values = cur_values;
326 ht->maxval = cur_maxval;
327 ht->offset = cur_offset;
328 ht->num_values = 0;
329 ht->max_length = cur_maxlen;
330 grub_memset (cur_maxval, 0, sizeof (int) * cur_maxlen);
333 static void
334 grub_png_insert_huff_item (struct huff_table *ht, int code, int len)
336 int i, n;
338 if (len == 0)
339 return;
341 if (len > ht->max_length)
343 grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid code length");
344 return;
347 n = 0;
348 for (i = len; i < ht->max_length; i++)
349 n += ht->maxval[i];
351 for (i = 0; i < n; i++)
352 ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1];
354 ht->values[ht->num_values - n] = code;
355 ht->num_values++;
356 ht->maxval[len - 1]++;
359 static void
360 grub_png_build_huff_table (struct huff_table *ht)
362 int base, ofs, i;
364 base = 0;
365 ofs = 0;
366 for (i = 0; i < ht->max_length; i++)
368 base += ht->maxval[i];
369 ofs += ht->maxval[i];
371 ht->maxval[i] = base;
372 ht->offset[i] = ofs - base;
374 base <<= 1;
378 static int
379 grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht)
381 int code, i;
383 code = 0;
384 for (i = 0; i < ht->max_length; i++)
386 code = (code << 1) + grub_png_get_bits (data, 1);
387 if (code < ht->maxval[i])
388 return ht->values[code + ht->offset[i]];
390 return 0;
393 static grub_err_t
394 grub_png_init_fixed_block (struct grub_png_data *data)
396 int i;
398 grub_png_init_huff_table (&data->code_table, DEFLATE_HUFF_LEN,
399 data->code_values, data->code_maxval,
400 data->code_offset);
402 for (i = 0; i < 144; i++)
403 grub_png_insert_huff_item (&data->code_table, i, 8);
405 for (; i < 256; i++)
406 grub_png_insert_huff_item (&data->code_table, i, 9);
408 for (; i < 280; i++)
409 grub_png_insert_huff_item (&data->code_table, i, 7);
411 for (; i < DEFLATE_HLIT_MAX; i++)
412 grub_png_insert_huff_item (&data->code_table, i, 8);
414 grub_png_build_huff_table (&data->code_table);
416 grub_png_init_huff_table (&data->dist_table, DEFLATE_HUFF_LEN,
417 data->dist_values, data->dist_maxval,
418 data->dist_offset);
420 for (i = 0; i < DEFLATE_HDIST_MAX; i++)
421 grub_png_insert_huff_item (&data->dist_table, i, 5);
423 grub_png_build_huff_table (&data->dist_table);
425 return grub_errno;
428 static grub_err_t
429 grub_png_init_dynamic_block (struct grub_png_data *data)
431 int nl, nd, nb, i, prev;
432 struct huff_table cl;
433 int cl_values[sizeof (bitorder)];
434 int cl_maxval[8];
435 int cl_offset[8];
436 grub_uint8_t lens[DEFLATE_HCLEN_MAX];
438 nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5);
439 nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5);
440 nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4);
442 if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) ||
443 (nb > DEFLATE_HCLEN_MAX))
444 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: too much data");
446 grub_png_init_huff_table (&cl, 8, cl_values, cl_maxval, cl_offset);
448 for (i = 0; i < nb; i++)
449 lens[bitorder[i]] = grub_png_get_bits (data, 3);
451 for (; i < DEFLATE_HCLEN_MAX; i++)
452 lens[bitorder[i]] = 0;
454 for (i = 0; i < DEFLATE_HCLEN_MAX; i++)
455 grub_png_insert_huff_item (&cl, i, lens[i]);
457 grub_png_build_huff_table (&cl);
459 grub_png_init_huff_table (&data->code_table, DEFLATE_HUFF_LEN,
460 data->code_values, data->code_maxval,
461 data->code_offset);
463 grub_png_init_huff_table (&data->dist_table, DEFLATE_HUFF_LEN,
464 data->dist_values, data->dist_maxval,
465 data->dist_offset);
467 prev = 0;
468 for (i = 0; i < nl + nd; i++)
470 int n, code;
471 struct huff_table *ht;
473 if (grub_errno)
474 return grub_errno;
476 if (i < nl)
478 ht = &data->code_table;
479 code = i;
481 else
483 ht = &data->dist_table;
484 code = i - nl;
487 n = grub_png_get_huff_code (data, &cl);
488 if (n < 16)
490 grub_png_insert_huff_item (ht, code, n);
491 prev = n;
493 else if (n == 16)
495 int c;
497 c = 3 + grub_png_get_bits (data, 2);
498 while (c > 0)
500 grub_png_insert_huff_item (ht, code++, prev);
501 i++;
502 c--;
504 i--;
506 else if (n == 17)
507 i += 3 + grub_png_get_bits (data, 3) - 1;
508 else
509 i += 11 + grub_png_get_bits (data, 7) - 1;
512 grub_png_build_huff_table (&data->code_table);
513 grub_png_build_huff_table (&data->dist_table);
515 return grub_errno;
518 static grub_err_t
519 grub_png_output_byte (struct grub_png_data *data, grub_uint8_t n)
521 int row_bytes;
523 if (--data->raw_bytes < 0)
524 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "image size overflown");
526 if (data->cur_colume == 0)
528 if (n >= PNG_FILTER_VALUE_LAST)
529 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid filter value");
531 data->cur_filter = n;
533 else
534 *(data->cur_rgb++) = n;
536 data->cur_colume++;
537 row_bytes = data->image_width * data->bpp;
538 if (data->cur_colume == row_bytes + 1)
540 grub_uint8_t *blank_line = NULL;
541 grub_uint8_t *cur = data->cur_rgb - row_bytes;
542 grub_uint8_t *left = cur;
543 grub_uint8_t *up;
545 if (data->first_line)
547 blank_line = grub_malloc (row_bytes);
548 if (blank_line == NULL)
549 return grub_errno;
551 grub_memset (blank_line, 0, row_bytes);
552 up = blank_line;
554 else
555 up = cur - row_bytes;
557 switch (data->cur_filter)
559 case PNG_FILTER_VALUE_SUB:
561 int i;
563 cur += data->bpp;
564 for (i = data->bpp; i < row_bytes; i++, cur++, left++)
565 *cur += *left;
567 break;
569 case PNG_FILTER_VALUE_UP:
571 int i;
573 for (i = 0; i < row_bytes; i++, cur++, up++)
574 *cur += *up;
576 break;
578 case PNG_FILTER_VALUE_AVG:
580 int i;
582 for (i = 0; i < data->bpp; i++, cur++, up++)
583 *cur += *up >> 1;
585 for (; i < row_bytes; i++, cur++, up++, left++)
586 *cur += ((int) *up + (int) *left) >> 1;
588 break;
590 case PNG_FILTER_VALUE_PAETH:
592 int i;
593 grub_uint8_t *upper_left = up;
595 for (i = 0; i < data->bpp; i++, cur++, up++)
596 *cur += *up;
598 for (; i < row_bytes; i++, cur++, up++, left++, upper_left++)
600 int a, b, c, pa, pb, pc;
602 a = *left;
603 b = *up;
604 c = *upper_left;
606 pa = b - c;
607 pb = a - c;
608 pc = pa + pb;
610 if (pa < 0)
611 pa = -pa;
613 if (pb < 0)
614 pb = -pb;
616 if (pc < 0)
617 pc = -pc;
619 *cur += ((pa <= pb) && (pa <= pc)) ? a : (pb <= pc) ? b : c;
624 if (blank_line)
625 grub_free (blank_line);
627 data->cur_colume = 0;
628 data->first_line = 0;
631 return grub_errno;
634 static grub_err_t
635 grub_png_read_dynamic_block (struct grub_png_data *data)
637 while (grub_errno == 0)
639 int n;
641 n = grub_png_get_huff_code (data, &data->code_table);
642 if (n < 256)
644 data->slide[data->wp] = n;
645 grub_png_output_byte (data, n);
647 data->wp++;
648 if (data->wp >= WSIZE)
649 data->wp = 0;
651 else if (n == 256)
652 break;
653 else
655 int len, dist, pos;
657 n -= 257;
658 len = cplens[n];
659 if (cplext[n])
660 len += grub_png_get_bits (data, cplext[n]);
662 n = grub_png_get_huff_code (data, &data->dist_table);
663 dist = cpdist[n];
664 if (cpdext[n])
665 dist += grub_png_get_bits (data, cpdext[n]);
667 pos = data->wp - dist;
668 if (pos < 0)
669 pos += WSIZE;
671 while (len > 0)
673 data->slide[data->wp] = data->slide[pos];
674 grub_png_output_byte (data, data->slide[data->wp]);
676 data->wp++;
677 if (data->wp >= WSIZE)
678 data->wp = 0;
680 pos++;
681 if (pos >= WSIZE)
682 pos = 0;
684 len--;
689 return grub_errno;
692 static grub_err_t
693 grub_png_decode_image_data (struct grub_png_data *data)
695 grub_uint8_t cmf, flg;
696 int final;
698 cmf = grub_png_get_byte (data);
699 flg = grub_png_get_byte (data);
701 if ((cmf & 0xF) != Z_DEFLATED)
702 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
703 "png: only support deflate compression method");
705 if (flg & Z_FLAG_DICT)
706 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
707 "png: dictionary not supported");
711 int block_type;
713 final = grub_png_get_bits (data, 1);
714 block_type = grub_png_get_bits (data, 2);
716 switch (block_type)
718 case INFLATE_STORED:
720 grub_uint16_t i, len;
722 data->bit_count = 0;
723 len = grub_png_get_byte (data);
724 len += ((grub_uint16_t) grub_png_get_byte (data)) << 8;
726 /* Skip NLEN field. */
727 grub_png_get_byte (data);
728 grub_png_get_byte (data);
730 for (i = 0; i < len; i++)
731 grub_png_output_byte (data, grub_png_get_byte (data));
733 break;
736 case INFLATE_FIXED:
737 grub_png_init_fixed_block (data);
738 grub_png_read_dynamic_block (data);
739 break;
741 case INFLATE_DYNAMIC:
742 grub_png_init_dynamic_block (data);
743 grub_png_read_dynamic_block (data);
744 break;
746 default:
747 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
748 "png: unknown block type");
751 while ((!final) && (grub_errno == 0));
753 /* Skip adler checksum. */
754 grub_png_get_dword (data);
756 /* Skip crc checksum. */
757 grub_png_get_dword (data);
759 return grub_errno;
762 static const grub_uint8_t png_magic[8] =
763 { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0x0a };
765 static void
766 grub_png_convert_image (struct grub_png_data *data)
768 int i;
769 grub_uint8_t *d1, *d2;
771 d1 = (*data->bitmap)->data;
772 d2 = data->image_data + 1;
774 /* Only copy the upper 8 bit. */
775 for (i = 0; i < (data->image_width * data->image_height * data->bpp >> 1);
776 i++, d1++, d2+=2)
777 *d1 = *d2;
780 static grub_err_t
781 grub_png_decode_png (struct grub_png_data *data)
783 grub_uint8_t magic[8];
785 if (grub_file_read (data->file, (char *) &magic[0], 8) != 8)
786 return grub_errno;
788 if (grub_memcmp (magic, png_magic, sizeof (png_magic)))
789 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: not a png file");
791 while (1)
793 grub_uint32_t len, type;
795 len = grub_png_get_dword (data);
796 type = grub_png_get_dword (data);
797 data->next_offset = data->file->offset + len + 4;
799 switch (type)
801 case PNG_CHUNK_IHDR:
802 grub_png_decode_image_header (data);
803 break;
805 case PNG_CHUNK_IDAT:
806 data->inside_idat = 1;
807 data->idat_remain = len;
808 data->bit_count = 0;
810 grub_png_decode_image_data (data);
812 data->inside_idat = 0;
813 break;
815 case PNG_CHUNK_IEND:
816 if (data->is_16bit)
817 grub_png_convert_image (data);
819 return grub_errno;
821 default:
822 grub_file_seek (data->file, data->file->offset + len + 4);
825 if (grub_errno)
826 break;
828 if (data->file->offset != data->next_offset)
829 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
830 "png: chunk size error");
833 return grub_errno;
836 static grub_err_t
837 grub_video_reader_png (struct grub_video_bitmap **bitmap,
838 const char *filename)
840 grub_file_t file;
841 struct grub_png_data *data;
843 file = grub_buffile_open (filename, 0);
844 if (!file)
845 return grub_errno;
847 data = grub_malloc (sizeof (*data));
848 if (data != NULL)
850 grub_memset (data, 0, sizeof (*data));
851 data->file = file;
852 data->bitmap = bitmap;
854 grub_png_decode_png (data);
856 grub_free (data->image_data);
857 grub_free (data);
860 if (grub_errno != GRUB_ERR_NONE)
862 grub_video_bitmap_destroy (*bitmap);
863 *bitmap = 0;
866 grub_file_close (file);
867 return grub_errno;
870 #if defined(PNG_DEBUG)
871 static grub_err_t
872 grub_cmd_pngtest (struct grub_arg_list *state __attribute__ ((unused)),
873 int argc, char **args)
875 struct grub_video_bitmap *bitmap = 0;
877 if (argc != 1)
878 return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
880 grub_video_reader_png (&bitmap, args[0]);
881 if (grub_errno != GRUB_ERR_NONE)
882 return grub_errno;
884 grub_video_bitmap_destroy (bitmap);
886 return GRUB_ERR_NONE;
888 #endif
890 static struct grub_video_bitmap_reader png_reader = {
891 .extension = ".png",
892 .reader = grub_video_reader_png,
893 .next = 0
896 GRUB_MOD_INIT (video_reader_png)
898 grub_video_bitmap_reader_register (&png_reader);
899 #if defined(PNG_DEBUG)
900 grub_register_command ("pngtest", grub_cmd_pngtest,
901 GRUB_COMMAND_FLAG_BOTH, "pngtest FILE",
902 "Tests loading of PNG bitmap.", 0);
903 #endif
906 GRUB_MOD_FINI (video_reader_png)
908 #if defined(PNG_DEBUG)
909 grub_unregister_command ("pngtest");
910 #endif
911 grub_video_bitmap_reader_unregister (&png_reader);