Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / video / readers / png.c
blob7ef7e3b4c1cceef82c66fd10898031434a2f61e5
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2008,2009 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 GRUB_MOD_LICENSE ("GPLv3+");
29 /* Uncomment following define to enable PNG debug. */
30 //#define PNG_DEBUG
32 #define PNG_COLOR_MASK_PALETTE 1
33 #define PNG_COLOR_MASK_COLOR 2
34 #define PNG_COLOR_MASK_ALPHA 4
36 #define PNG_COLOR_TYPE_GRAY 0
37 #define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
38 #define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
39 #define PNG_COLOR_TYPE_RGBA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
40 #define PNG_COLOR_TYPE_GRAYA (PNG_COLOR_MASK_ALPHA)
42 #define PNG_COMPRESSION_BASE 0
44 #define PNG_INTERLACE_NONE 0
45 #define PNG_INTERLACE_ADAM7 1
47 #define PNG_FILTER_TYPE_BASE 0
49 #define PNG_FILTER_VALUE_NONE 0
50 #define PNG_FILTER_VALUE_SUB 1
51 #define PNG_FILTER_VALUE_UP 2
52 #define PNG_FILTER_VALUE_AVG 3
53 #define PNG_FILTER_VALUE_PAETH 4
54 #define PNG_FILTER_VALUE_LAST 5
56 #define PNG_CHUNK_IHDR 0x49484452
57 #define PNG_CHUNK_IDAT 0x49444154
58 #define PNG_CHUNK_IEND 0x49454e44
60 #define Z_DEFLATED 8
61 #define Z_FLAG_DICT 32
63 #define INFLATE_STORED 0
64 #define INFLATE_FIXED 1
65 #define INFLATE_DYNAMIC 2
67 #define WSIZE 0x8000
69 #define DEFLATE_HCLEN_BASE 4
70 #define DEFLATE_HCLEN_MAX 19
71 #define DEFLATE_HLIT_BASE 257
72 #define DEFLATE_HLIT_MAX 288
73 #define DEFLATE_HDIST_BASE 1
74 #define DEFLATE_HDIST_MAX 30
76 #define DEFLATE_HUFF_LEN 16
78 #ifdef PNG_DEBUG
79 static grub_command_t cmd;
80 #endif
82 struct huff_table
84 int *values, *maxval, *offset;
85 int num_values, max_length;
88 struct grub_png_data
90 grub_file_t file;
91 struct grub_video_bitmap **bitmap;
93 int bit_count, bit_save;
95 grub_uint32_t next_offset;
97 int image_width, image_height, bpp, is_16bit, raw_bytes;
98 grub_uint8_t *image_data;
100 int inside_idat, idat_remain;
102 int code_values[DEFLATE_HLIT_MAX];
103 int code_maxval[DEFLATE_HUFF_LEN];
104 int code_offset[DEFLATE_HUFF_LEN];
106 int dist_values[DEFLATE_HDIST_MAX];
107 int dist_maxval[DEFLATE_HUFF_LEN];
108 int dist_offset[DEFLATE_HUFF_LEN];
110 struct huff_table code_table;
111 struct huff_table dist_table;
113 grub_uint8_t slide[WSIZE];
114 int wp;
116 grub_uint8_t *cur_rgb;
118 int cur_column, cur_filter, first_line;
121 static grub_uint32_t
122 grub_png_get_dword (struct grub_png_data *data)
124 grub_uint32_t r;
126 r = 0;
127 grub_file_read (data->file, &r, sizeof (grub_uint32_t));
129 return grub_be_to_cpu32 (r);
132 static grub_uint8_t
133 grub_png_get_byte (struct grub_png_data *data)
135 grub_uint8_t r;
137 if ((data->inside_idat) && (data->idat_remain == 0))
139 grub_uint32_t len, type;
143 /* Skip crc checksum. */
144 grub_png_get_dword (data);
146 if (data->file->offset != data->next_offset)
148 grub_error (GRUB_ERR_BAD_FILE_TYPE,
149 "png: chunk size error");
150 return 0;
153 len = grub_png_get_dword (data);
154 type = grub_png_get_dword (data);
155 if (type != PNG_CHUNK_IDAT)
157 grub_error (GRUB_ERR_BAD_FILE_TYPE,
158 "png: unexpected end of data");
159 return 0;
162 data->next_offset = data->file->offset + len + 4;
164 while (len == 0);
165 data->idat_remain = len;
168 r = 0;
169 grub_file_read (data->file, &r, 1);
171 if (data->inside_idat)
172 data->idat_remain--;
174 return r;
177 static int
178 grub_png_get_bits (struct grub_png_data *data, int num)
180 int code, shift;
182 if (data->bit_count == 0)
184 data->bit_save = grub_png_get_byte (data);
185 data->bit_count = 8;
188 code = 0;
189 shift = 0;
190 while (grub_errno == 0)
192 int n;
194 n = data->bit_count;
195 if (n > num)
196 n = num;
198 code += (int) (data->bit_save & ((1 << n) - 1)) << shift;
199 num -= n;
200 if (!num)
202 data->bit_count -= n;
203 data->bit_save >>= n;
204 break;
207 shift += n;
209 data->bit_save = grub_png_get_byte (data);
210 data->bit_count = 8;
213 return code;
216 static grub_err_t
217 grub_png_decode_image_header (struct grub_png_data *data)
219 int color_type;
220 int color_bits;
222 data->image_width = grub_png_get_dword (data);
223 data->image_height = grub_png_get_dword (data);
225 if ((!data->image_height) || (!data->image_width))
226 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size");
228 color_bits = grub_png_get_byte (data);
229 if ((color_bits != 8) && (color_bits != 16))
230 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
231 "png: bit depth must be 8 or 16");
232 data->is_16bit = (color_bits == 16);
234 color_type = grub_png_get_byte (data);
235 if (color_type == PNG_COLOR_TYPE_RGB)
237 if (grub_video_bitmap_create (data->bitmap, data->image_width,
238 data->image_height,
239 GRUB_VIDEO_BLIT_FORMAT_RGB_888))
240 return grub_errno;
241 data->bpp = 3;
243 else if (color_type == PNG_COLOR_TYPE_RGBA)
245 if (grub_video_bitmap_create (data->bitmap, data->image_width,
246 data->image_height,
247 GRUB_VIDEO_BLIT_FORMAT_RGBA_8888))
248 return grub_errno;
249 data->bpp = 4;
251 else
252 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
253 "png: color type not supported");
255 if (data->is_16bit)
257 data->bpp <<= 1;
259 data->image_data = grub_malloc (data->image_height *
260 data->image_width * data->bpp);
261 if (grub_errno)
262 return grub_errno;
264 data->cur_rgb = data->image_data;
266 else
268 data->image_data = 0;
269 data->cur_rgb = (*data->bitmap)->data;
272 data->raw_bytes = data->image_height * (data->image_width + 1) * data->bpp;
274 data->cur_column = 0;
275 data->first_line = 1;
277 if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE)
278 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
279 "png: compression method not supported");
281 if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE)
282 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
283 "png: filter method not supported");
285 if (grub_png_get_byte (data) != PNG_INTERLACE_NONE)
286 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
287 "png: interlace method not supported");
289 /* Skip crc checksum. */
290 grub_png_get_dword (data);
292 return grub_errno;
295 /* Order of the bit length code lengths. */
296 static const grub_uint8_t bitorder[] = {
297 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
300 /* Copy lengths for literal codes 257..285. */
301 static const int cplens[] = {
302 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
303 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
306 /* Extra bits for literal codes 257..285. */
307 static const grub_uint8_t cplext[] = {
308 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
309 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
310 }; /* 99==invalid */
312 /* Copy offsets for distance codes 0..29. */
313 static const int cpdist[] = {
314 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
315 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
316 8193, 12289, 16385, 24577
319 /* Extra bits for distance codes. */
320 static const grub_uint8_t cpdext[] = {
321 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
322 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
323 12, 12, 13, 13
326 static void
327 grub_png_init_huff_table (struct huff_table *ht, int cur_maxlen,
328 int *cur_values, int *cur_maxval, int *cur_offset)
330 ht->values = cur_values;
331 ht->maxval = cur_maxval;
332 ht->offset = cur_offset;
333 ht->num_values = 0;
334 ht->max_length = cur_maxlen;
335 grub_memset (cur_maxval, 0, sizeof (int) * cur_maxlen);
338 static void
339 grub_png_insert_huff_item (struct huff_table *ht, int code, int len)
341 int i, n;
343 if (len == 0)
344 return;
346 if (len > ht->max_length)
348 grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid code length");
349 return;
352 n = 0;
353 for (i = len; i < ht->max_length; i++)
354 n += ht->maxval[i];
356 for (i = 0; i < n; i++)
357 ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1];
359 ht->values[ht->num_values - n] = code;
360 ht->num_values++;
361 ht->maxval[len - 1]++;
364 static void
365 grub_png_build_huff_table (struct huff_table *ht)
367 int base, ofs, i;
369 base = 0;
370 ofs = 0;
371 for (i = 0; i < ht->max_length; i++)
373 base += ht->maxval[i];
374 ofs += ht->maxval[i];
376 ht->maxval[i] = base;
377 ht->offset[i] = ofs - base;
379 base <<= 1;
383 static int
384 grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht)
386 int code, i;
388 code = 0;
389 for (i = 0; i < ht->max_length; i++)
391 code = (code << 1) + grub_png_get_bits (data, 1);
392 if (code < ht->maxval[i])
393 return ht->values[code + ht->offset[i]];
395 return 0;
398 static grub_err_t
399 grub_png_init_fixed_block (struct grub_png_data *data)
401 int i;
403 grub_png_init_huff_table (&data->code_table, DEFLATE_HUFF_LEN,
404 data->code_values, data->code_maxval,
405 data->code_offset);
407 for (i = 0; i < 144; i++)
408 grub_png_insert_huff_item (&data->code_table, i, 8);
410 for (; i < 256; i++)
411 grub_png_insert_huff_item (&data->code_table, i, 9);
413 for (; i < 280; i++)
414 grub_png_insert_huff_item (&data->code_table, i, 7);
416 for (; i < DEFLATE_HLIT_MAX; i++)
417 grub_png_insert_huff_item (&data->code_table, i, 8);
419 grub_png_build_huff_table (&data->code_table);
421 grub_png_init_huff_table (&data->dist_table, DEFLATE_HUFF_LEN,
422 data->dist_values, data->dist_maxval,
423 data->dist_offset);
425 for (i = 0; i < DEFLATE_HDIST_MAX; i++)
426 grub_png_insert_huff_item (&data->dist_table, i, 5);
428 grub_png_build_huff_table (&data->dist_table);
430 return grub_errno;
433 static grub_err_t
434 grub_png_init_dynamic_block (struct grub_png_data *data)
436 int nl, nd, nb, i, prev;
437 struct huff_table cl;
438 int cl_values[sizeof (bitorder)];
439 int cl_maxval[8];
440 int cl_offset[8];
441 grub_uint8_t lens[DEFLATE_HCLEN_MAX];
443 nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5);
444 nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5);
445 nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4);
447 if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) ||
448 (nb > DEFLATE_HCLEN_MAX))
449 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: too much data");
451 grub_png_init_huff_table (&cl, 8, cl_values, cl_maxval, cl_offset);
453 for (i = 0; i < nb; i++)
454 lens[bitorder[i]] = grub_png_get_bits (data, 3);
456 for (; i < DEFLATE_HCLEN_MAX; i++)
457 lens[bitorder[i]] = 0;
459 for (i = 0; i < DEFLATE_HCLEN_MAX; i++)
460 grub_png_insert_huff_item (&cl, i, lens[i]);
462 grub_png_build_huff_table (&cl);
464 grub_png_init_huff_table (&data->code_table, DEFLATE_HUFF_LEN,
465 data->code_values, data->code_maxval,
466 data->code_offset);
468 grub_png_init_huff_table (&data->dist_table, DEFLATE_HUFF_LEN,
469 data->dist_values, data->dist_maxval,
470 data->dist_offset);
472 prev = 0;
473 for (i = 0; i < nl + nd; i++)
475 int n, code;
476 struct huff_table *ht;
478 if (grub_errno)
479 return grub_errno;
481 if (i < nl)
483 ht = &data->code_table;
484 code = i;
486 else
488 ht = &data->dist_table;
489 code = i - nl;
492 n = grub_png_get_huff_code (data, &cl);
493 if (n < 16)
495 grub_png_insert_huff_item (ht, code, n);
496 prev = n;
498 else if (n == 16)
500 int c;
502 c = 3 + grub_png_get_bits (data, 2);
503 while (c > 0)
505 grub_png_insert_huff_item (ht, code++, prev);
506 i++;
507 c--;
509 i--;
511 else if (n == 17)
512 i += 3 + grub_png_get_bits (data, 3) - 1;
513 else
514 i += 11 + grub_png_get_bits (data, 7) - 1;
517 grub_png_build_huff_table (&data->code_table);
518 grub_png_build_huff_table (&data->dist_table);
520 return grub_errno;
523 static grub_err_t
524 grub_png_output_byte (struct grub_png_data *data, grub_uint8_t n)
526 int row_bytes;
528 if (--data->raw_bytes < 0)
529 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "image size overflown");
531 if (data->cur_column == 0)
533 if (n >= PNG_FILTER_VALUE_LAST)
534 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid filter value");
536 data->cur_filter = n;
538 else
539 *(data->cur_rgb++) = n;
541 data->cur_column++;
542 row_bytes = data->image_width * data->bpp;
543 if (data->cur_column == row_bytes + 1)
545 grub_uint8_t *blank_line = NULL;
546 grub_uint8_t *cur = data->cur_rgb - row_bytes;
547 grub_uint8_t *left = cur;
548 grub_uint8_t *up;
550 if (data->first_line)
552 blank_line = grub_zalloc (row_bytes);
553 if (blank_line == NULL)
554 return grub_errno;
556 up = blank_line;
558 else
559 up = cur - row_bytes;
561 switch (data->cur_filter)
563 case PNG_FILTER_VALUE_SUB:
565 int i;
567 cur += data->bpp;
568 for (i = data->bpp; i < row_bytes; i++, cur++, left++)
569 *cur += *left;
571 break;
573 case PNG_FILTER_VALUE_UP:
575 int i;
577 for (i = 0; i < row_bytes; i++, cur++, up++)
578 *cur += *up;
580 break;
582 case PNG_FILTER_VALUE_AVG:
584 int i;
586 for (i = 0; i < data->bpp; i++, cur++, up++)
587 *cur += *up >> 1;
589 for (; i < row_bytes; i++, cur++, up++, left++)
590 *cur += ((int) *up + (int) *left) >> 1;
592 break;
594 case PNG_FILTER_VALUE_PAETH:
596 int i;
597 grub_uint8_t *upper_left = up;
599 for (i = 0; i < data->bpp; i++, cur++, up++)
600 *cur += *up;
602 for (; i < row_bytes; i++, cur++, up++, left++, upper_left++)
604 int a, b, c, pa, pb, pc;
606 a = *left;
607 b = *up;
608 c = *upper_left;
610 pa = b - c;
611 pb = a - c;
612 pc = pa + pb;
614 if (pa < 0)
615 pa = -pa;
617 if (pb < 0)
618 pb = -pb;
620 if (pc < 0)
621 pc = -pc;
623 *cur += ((pa <= pb) && (pa <= pc)) ? a : (pb <= pc) ? b : c;
628 grub_free (blank_line);
630 data->cur_column = 0;
631 data->first_line = 0;
634 return grub_errno;
637 static grub_err_t
638 grub_png_read_dynamic_block (struct grub_png_data *data)
640 while (grub_errno == 0)
642 int n;
644 n = grub_png_get_huff_code (data, &data->code_table);
645 if (n < 256)
647 data->slide[data->wp] = n;
648 grub_png_output_byte (data, n);
650 data->wp++;
651 if (data->wp >= WSIZE)
652 data->wp = 0;
654 else if (n == 256)
655 break;
656 else
658 int len, dist, pos;
660 n -= 257;
661 len = cplens[n];
662 if (cplext[n])
663 len += grub_png_get_bits (data, cplext[n]);
665 n = grub_png_get_huff_code (data, &data->dist_table);
666 dist = cpdist[n];
667 if (cpdext[n])
668 dist += grub_png_get_bits (data, cpdext[n]);
670 pos = data->wp - dist;
671 if (pos < 0)
672 pos += WSIZE;
674 while (len > 0)
676 data->slide[data->wp] = data->slide[pos];
677 grub_png_output_byte (data, data->slide[data->wp]);
679 data->wp++;
680 if (data->wp >= WSIZE)
681 data->wp = 0;
683 pos++;
684 if (pos >= WSIZE)
685 pos = 0;
687 len--;
692 return grub_errno;
695 static grub_err_t
696 grub_png_decode_image_data (struct grub_png_data *data)
698 grub_uint8_t cmf, flg;
699 int final;
701 cmf = grub_png_get_byte (data);
702 flg = grub_png_get_byte (data);
704 if ((cmf & 0xF) != Z_DEFLATED)
705 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
706 "png: only support deflate compression method");
708 if (flg & Z_FLAG_DICT)
709 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
710 "png: dictionary not supported");
714 int block_type;
716 final = grub_png_get_bits (data, 1);
717 block_type = grub_png_get_bits (data, 2);
719 switch (block_type)
721 case INFLATE_STORED:
723 grub_uint16_t i, len;
725 data->bit_count = 0;
726 len = grub_png_get_byte (data);
727 len += ((grub_uint16_t) grub_png_get_byte (data)) << 8;
729 /* Skip NLEN field. */
730 grub_png_get_byte (data);
731 grub_png_get_byte (data);
733 for (i = 0; i < len; i++)
734 grub_png_output_byte (data, grub_png_get_byte (data));
736 break;
739 case INFLATE_FIXED:
740 grub_png_init_fixed_block (data);
741 grub_png_read_dynamic_block (data);
742 break;
744 case INFLATE_DYNAMIC:
745 grub_png_init_dynamic_block (data);
746 grub_png_read_dynamic_block (data);
747 break;
749 default:
750 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
751 "png: unknown block type");
754 while ((!final) && (grub_errno == 0));
756 /* Skip adler checksum. */
757 grub_png_get_dword (data);
759 /* Skip crc checksum. */
760 grub_png_get_dword (data);
762 return grub_errno;
765 static const grub_uint8_t png_magic[8] =
766 { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0x0a };
768 static void
769 grub_png_convert_image (struct grub_png_data *data)
771 int i;
772 grub_uint8_t *d1, *d2;
774 d1 = (*data->bitmap)->data;
775 d2 = data->image_data + 1;
777 /* Only copy the upper 8 bit. */
778 for (i = 0; i < (data->image_width * data->image_height * data->bpp >> 1);
779 i++, d1++, d2+=2)
780 *d1 = *d2;
783 static grub_err_t
784 grub_png_decode_png (struct grub_png_data *data)
786 grub_uint8_t magic[8];
788 if (grub_file_read (data->file, &magic[0], 8) != 8)
789 return grub_errno;
791 if (grub_memcmp (magic, png_magic, sizeof (png_magic)))
792 return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: not a png file");
794 while (1)
796 grub_uint32_t len, type;
798 len = grub_png_get_dword (data);
799 type = grub_png_get_dword (data);
800 data->next_offset = data->file->offset + len + 4;
802 switch (type)
804 case PNG_CHUNK_IHDR:
805 grub_png_decode_image_header (data);
806 break;
808 case PNG_CHUNK_IDAT:
809 data->inside_idat = 1;
810 data->idat_remain = len;
811 data->bit_count = 0;
813 grub_png_decode_image_data (data);
815 data->inside_idat = 0;
816 break;
818 case PNG_CHUNK_IEND:
819 if (data->is_16bit)
820 grub_png_convert_image (data);
822 return grub_errno;
824 default:
825 grub_file_seek (data->file, data->file->offset + len + 4);
828 if (grub_errno)
829 break;
831 if (data->file->offset != data->next_offset)
832 return grub_error (GRUB_ERR_BAD_FILE_TYPE,
833 "png: chunk size error");
836 return grub_errno;
839 static grub_err_t
840 grub_video_reader_png (struct grub_video_bitmap **bitmap,
841 const char *filename)
843 grub_file_t file;
844 struct grub_png_data *data;
846 file = grub_buffile_open (filename, 0);
847 if (!file)
848 return grub_errno;
850 data = grub_zalloc (sizeof (*data));
851 if (data != NULL)
853 data->file = file;
854 data->bitmap = bitmap;
856 grub_png_decode_png (data);
858 grub_free (data->image_data);
859 grub_free (data);
862 if (grub_errno != GRUB_ERR_NONE)
864 grub_video_bitmap_destroy (*bitmap);
865 *bitmap = 0;
868 grub_file_close (file);
869 return grub_errno;
872 #if defined(PNG_DEBUG)
873 static grub_err_t
874 grub_cmd_pngtest (grub_command_t cmd __attribute__ ((unused)),
875 int argc, char **args)
877 struct grub_video_bitmap *bitmap = 0;
879 if (argc != 1)
880 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
882 grub_video_reader_png (&bitmap, args[0]);
883 if (grub_errno != GRUB_ERR_NONE)
884 return grub_errno;
886 grub_video_bitmap_destroy (bitmap);
888 return GRUB_ERR_NONE;
890 #endif
892 static struct grub_video_bitmap_reader png_reader = {
893 .extension = ".png",
894 .reader = grub_video_reader_png,
895 .next = 0
898 GRUB_MOD_INIT (png)
900 grub_video_bitmap_reader_register (&png_reader);
901 #if defined(PNG_DEBUG)
902 cmd = grub_register_command ("pngtest", grub_cmd_pngtest,
903 "FILE",
904 "Tests loading of PNG bitmap.");
905 #endif
908 GRUB_MOD_FINI (png)
910 #if defined(PNG_DEBUG)
911 grub_unregister_command (cmd);
912 #endif
913 grub_video_bitmap_reader_unregister (&png_reader);