1 /* -*- mode: C; mode: fold; -*- */
2 /*
3 Copyright (C) 2005-2017,2018 John E. Davis
4
5 This file is part of the S-Lang Library.
6
7 The S-Lang Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The S-Lang Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 USA.
21 */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <slang.h>
29
30 #include <png.h>
31
32 SLANG_MODULE(png);
33
34 static SLFUTURE_CONST char *Module_Version_String = "0.2.0";
35 #define MODULE_VERSION_NUMBER (0*10000 + 2*100 + 0)
36
37 /*{{{ Byte-swapping routines */
38
39 static int Is_Little_Endian;
40
byte_swap32(unsigned char * p,unsigned char * t,SLuindex_Type n)41 static void byte_swap32 (unsigned char *p, unsigned char *t, SLuindex_Type n)
42 {
43 unsigned char *pmax;
44
45 /* t and p could point to the same buffer */
46 pmax = p + 4 * n;
47 while (p < pmax)
48 {
49 unsigned char ch = *p;
50 *t = *(p + 3);
51 *(t + 3) = ch;
52
53 ch = *(p + 1);
54 *(t + 1) = *(p + 2);
55 *(t + 2) = ch;
56 p += 4;
57 t += 4;
58 }
59 }
60
byte_swap16(unsigned char * p,unsigned char * t,SLuindex_Type n)61 static void byte_swap16 (unsigned char *p, unsigned char *t, SLuindex_Type n)
62 {
63 unsigned char *pmax;
64
65 pmax = p + 2 * n;
66 while (p < pmax)
67 {
68 unsigned char ch = *p;
69 *t = *(p + 1);
70 *(t + 1) = ch;
71 p += 2;
72 t += 2;
73 }
74 }
75
76 /*}}}*/
77
78 /*{{{ Png_Type */
79
80 typedef struct
81 {
82 FILE *fp;
83 int mode; /* 'r' or 'w' */
84 png_struct *png;
85 png_info *info;
86 }
87 Png_Type;
88
free_png_type(Png_Type * p)89 static void free_png_type (Png_Type *p)
90 {
91 if (p == NULL)
92 return;
93 if (p->png != NULL)
94 {
95 if (p->mode == 'r')
96 {
97 if (p->info != NULL)
98 png_destroy_read_struct (&p->png, &p->info, NULL);
99 else
100 png_destroy_read_struct (&p->png, NULL, NULL);
101 }
102 else
103 {
104 if (p->info != NULL)
105 png_destroy_write_struct (&p->png, &p->info);
106 else
107 png_destroy_write_struct (&p->png, NULL);
108 }
109 }
110
111 if (p->fp != NULL)
112 fclose (p->fp);
113
114 SLfree ((char *) p);
115 }
116
alloc_png_type(int mode)117 static Png_Type *alloc_png_type (int mode)
118 {
119 Png_Type *p;
120
121 if (NULL != (p = (Png_Type *)SLmalloc (sizeof (Png_Type))))
122 {
123 memset ((char *) p, 0, sizeof (Png_Type));
124 p->mode = mode;
125 }
126 return p;
127 }
128
129 /*}}}*/
130
allocate_image_pointers(png_uint_32 height,png_byte * data,png_uint_32 rowbytes,int flip)131 static png_byte **allocate_image_pointers (png_uint_32 height, png_byte *data, png_uint_32 rowbytes, int flip)
132 {
133 png_byte **image_pointers;
134 png_uint_32 i;
135
136 if (NULL == (image_pointers = (png_byte **) SLmalloc (height * sizeof (png_byte *))))
137 return NULL;
138
139 if (flip)
140 {
141 i = height;
142 while (i != 0)
143 {
144 i--;
145 image_pointers[i] = data;
146 data += rowbytes;
147 }
148 return image_pointers;
149 }
150 for (i = 0; i < height; i++)
151 {
152 image_pointers[i] = data;
153 data += rowbytes;
154 }
155 return image_pointers;
156 }
157
free_image_pointers(png_byte ** image_pointers)158 static void free_image_pointers (png_byte **image_pointers)
159 {
160 if (image_pointers == NULL)
161 return;
162
163 SLfree ((char *) image_pointers);
164 }
165
166 /*{{{ png read functions */
167
open_png_file(char * file)168 static Png_Type *open_png_file (char *file)
169 {
170 png_byte header[8];
171 Png_Type *p;
172
173 if (NULL == (p = alloc_png_type ('r')))
174 return NULL;
175
176 if ((NULL == (p->fp = fopen (file, "rb")))
177 || (8 != fread (header, 1, 8, p->fp))
178 || (0 != png_sig_cmp(header, 0, 8)))
179 {
180 SLang_verror (SL_Open_Error, "Unable to open %s as a png file", file);
181 free_png_type (p);
182 return NULL;
183 }
184
185 if (NULL == (p->png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
186 {
187 SLang_verror (SL_Open_Error, "Unable to read png structure from %s", file);
188 free_png_type (p);
189 return NULL;
190 }
191
192 if (NULL == (p->info = png_create_info_struct (p->png)))
193 {
194 SLang_verror (SL_Read_Error, "Unable to create info struct for %s", file);
195 free_png_type (p);
196 return NULL;
197 }
198
199 return p;
200 }
201
fixup_array_rgb(SLang_Array_Type * at)202 static void fixup_array_rgb (SLang_Array_Type *at)
203 {
204 SLindex_Type num_rows, num_cols, row;
205 unsigned char *data;
206
207 num_rows = at->dims[0];
208 num_cols = at->dims[1];
209 data = (unsigned char *) at->data;
210
211 /* Convert RGBRGBRGB.... to 0RGB0RGB0RGB ... */
212 for (row = 0; row < num_rows; row++)
213 {
214 unsigned char *p = data + 3*num_cols;
215 unsigned char *q = p + num_cols;
216 while (p != data)
217 {
218 *(--q) = *(--p);
219 *(--q) = *(--p);
220 *(--q) = *(--p);
221 *(--q) = 0; /* or 0xFF */
222 }
223 data += 4*num_cols;
224 }
225
226 if (Is_Little_Endian)
227 byte_swap32 ((unsigned char *)at->data, (unsigned char *)at->data, at->num_elements);
228 }
229
fixup_array_rgba(SLang_Array_Type * at)230 static void fixup_array_rgba (SLang_Array_Type *at)
231 {
232 unsigned char *data, *data_max;
233
234 data = (unsigned char *) at->data;
235 data_max = data + 4*at->num_elements;
236
237 /* RGBARGBA -> ARGBARGB */
238 while (data < data_max)
239 {
240 unsigned char a = data[3];
241 data[3] = data[2];
242 data[2] = data[1];
243 data[1] = data[0];
244 data[0] = a;
245 data += 4;
246 }
247 if (Is_Little_Endian)
248 byte_swap32 ((unsigned char *)at->data, (unsigned char *)at->data, at->num_elements);
249 }
250
fixup_array_ga(SLang_Array_Type * at)251 static void fixup_array_ga (SLang_Array_Type *at)
252 {
253 if (Is_Little_Endian)
254 byte_swap16 ((unsigned char *)at->data, (unsigned char *) at->data, at->num_elements);
255 }
256
257 /* For little endian systems, ARGB is equivalent to the int32 BGRA.
258 * So, to read the image as RGB
259 */
read_image_internal(char * file,int flip,int * color_typep)260 static SLang_Array_Type *read_image_internal (char *file, int flip, int *color_typep)
261 {
262 Png_Type *p;
263 png_uint_32 width, height, rowbytes;
264 png_struct *png;
265 png_info *info;
266 int bit_depth;
267 /* int interlace_type; */
268 int color_type;
269 unsigned int sizeof_type;
270 SLindex_Type dims[2];
271 SLtype data_type;
272 png_byte **image_pointers = NULL;
273 png_byte *data = NULL;
274 SLang_Array_Type *at;
275 void (*fixup_array_fun) (SLang_Array_Type *);
276
277 if (NULL == (p = open_png_file (file)))
278 return NULL;
279
280 png = p->png;
281 if (setjmp (png_jmpbuf (png)))
282 {
283 free_png_type (p);
284 if (data != NULL) SLfree ((char *) data);
285 free_image_pointers (image_pointers);
286 SLang_verror (SL_Read_Error, "Error encountered during I/O to %s", file);
287 return NULL;
288 }
289
290 png_init_io (png, p->fp);
291 png_set_sig_bytes (png, 8);
292 info = p->info;
293 png_read_info(png, info);
294
295 width = png_get_image_width (png, info);
296 height = png_get_image_height (png, info);
297 /* interlace_type = png_get_interlace_type (png, info); */
298 bit_depth = png_get_bit_depth (png, info);
299
300 if (bit_depth == 16)
301 png_set_strip_16 (png);
302
303 switch (png_get_color_type (png, info))
304 {
305 case PNG_COLOR_TYPE_GRAY:
306 #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10209)
307 if (bit_depth < 8) png_set_expand_gray_1_2_4_to_8 (png);
308 #else /* deprecated */
309 if (bit_depth < 8) png_set_gray_1_2_4_to_8 (png);
310 #endif
311 break;
312 case PNG_COLOR_TYPE_GRAY_ALPHA:
313 /* png_set_gray_to_rgb (png); */
314 break;
315
316 case PNG_COLOR_TYPE_PALETTE:
317 png_set_palette_to_rgb (png);
318 break;
319 }
320
321 if (png_get_valid(png, info, PNG_INFO_tRNS))
322 png_set_tRNS_to_alpha(png);
323
324 png_read_update_info (png, info);
325
326 color_type = png_get_color_type (png, info);
327 switch (color_type)
328 {
329 case PNG_COLOR_TYPE_RGBA:
330 sizeof_type = 4;
331 fixup_array_fun = fixup_array_rgba;
332 data_type = SLang_get_int_type (32);
333 break;
334
335 case PNG_COLOR_TYPE_RGB:
336 sizeof_type = 4;
337 fixup_array_fun = fixup_array_rgb;
338 data_type = SLang_get_int_type (32);
339 break;
340
341 case PNG_COLOR_TYPE_GRAY_ALPHA:
342 sizeof_type = 2;
343 fixup_array_fun = fixup_array_ga;
344 data_type = SLang_get_int_type (16);
345 break;
346
347 case PNG_COLOR_TYPE_GRAY:
348 sizeof_type = 1;
349 fixup_array_fun = NULL;
350 data_type = SLANG_UCHAR_TYPE;
351 break;
352
353 default:
354 SLang_verror (SL_Read_Error, "Unsupported PNG color-type");
355 free_png_type (p);
356 return NULL;
357 }
358 *color_typep = color_type;
359
360 /* Use the high-level interface */
361 rowbytes = png_get_rowbytes (png, info);
362 if (rowbytes > width * sizeof_type)
363 {
364 SLang_verror (SL_INTERNAL_ERROR, "Unexpected value returned from png_get_rowbytes");
365 free_png_type (p);
366 return NULL;
367 }
368
369 if (NULL == (data = (png_byte *) SLmalloc (height * width * sizeof_type)))
370 {
371 free_png_type (p);
372 return NULL;
373 }
374
375 if (NULL == (image_pointers = allocate_image_pointers (height, data, width * sizeof_type, flip)))
376 {
377 SLfree ((char *) data);
378 free_png_type (p);
379 return NULL;
380 }
381 png_read_image(png, image_pointers);
382
383 dims[0] = height;
384 dims[1] = width;
385
386 if (NULL == (at = SLang_create_array (data_type, 0, (VOID_STAR) data, dims, 2)))
387 {
388 SLfree ((char *) data);
389 free_image_pointers (image_pointers);
390 free_png_type (p);
391 return NULL;
392 }
393 free_png_type (p);
394 free_image_pointers (image_pointers);
395 if (fixup_array_fun != NULL)
396 (*fixup_array_fun) (at);
397 return at;
398 }
399
read_image(int flipped)400 static void read_image (int flipped)
401 {
402 int color_type;
403 char *file;
404 SLang_Ref_Type *ref = NULL;
405 SLang_Array_Type *at;
406
407 if ((SLang_Num_Function_Args == 2)
408 && (-1 == SLang_pop_ref (&ref)))
409 return;
410
411 if (-1 == SLang_pop_slstring (&file))
412 {
413 file = NULL;
414 goto free_return;
415 }
416
417 if (NULL == (at = read_image_internal (file, flipped, &color_type)))
418 goto free_return;
419
420 if ((ref != NULL)
421 && (-1 == SLang_assign_to_ref (ref, SLANG_INT_TYPE, &color_type)))
422 {
423 SLang_free_array (at);
424 goto free_return;
425 }
426
427 (void) SLang_push_array (at, 1);
428
429 free_return:
430 SLang_free_slstring (file);
431 if (ref != NULL)
432 SLang_free_ref (ref);
433 }
434
435 /*}}}*/
436
write_gray_to_gray(png_struct * png,png_byte * data,SLindex_Type num_cols,png_byte * tmpbuf)437 static void write_gray_to_gray (png_struct *png, png_byte *data, SLindex_Type num_cols, png_byte *tmpbuf)
438 {
439 (void) num_cols;
440 (void) tmpbuf;
441 png_write_row (png, data);
442 }
443
write_gray_to_gray_alpha(png_struct * png,png_byte * data,SLindex_Type num_cols,png_byte * tmpbuf)444 static void write_gray_to_gray_alpha (png_struct *png, png_byte *data, SLindex_Type num_cols, png_byte *tmpbuf)
445 {
446 SLindex_Type i, j;
447
448 j = 0;
449 for (i = 0; i < num_cols; i++)
450 {
451 tmpbuf[j] = data[i];
452 tmpbuf[j+1] = 0xFF;
453 j += 2;
454 }
455 png_write_row (png, tmpbuf);
456 }
457
write_gray_alpha_to_gray(png_struct * png,png_byte * data,SLindex_Type num_cols,png_byte * tmpbuf)458 static void write_gray_alpha_to_gray (png_struct *png, png_byte *data, SLindex_Type num_cols, png_byte *tmpbuf)
459 {
460 SLindex_Type i;
461
462 if (Is_Little_Endian == 0)
463 data++; /* AGAGAG... -> GAGAGA... */
464
465 for (i = 0; i < num_cols; i++)
466 {
467 tmpbuf[i] = *data;
468 data += 2;
469 }
470 png_write_row (png, tmpbuf);
471 }
472
write_gray_alpha_to_gray_alpha(png_struct * png,png_byte * data,SLindex_Type num_cols,png_byte * tmpbuf)473 static void write_gray_alpha_to_gray_alpha (png_struct *png, png_byte *data, SLindex_Type num_cols, png_byte *tmpbuf)
474 {
475 if (Is_Little_Endian == 0)
476 {
477 png_write_row (png, data);
478 return;
479 }
480
481 byte_swap16 ((unsigned char *) data, (unsigned char *) tmpbuf, num_cols);
482 png_write_row (png, tmpbuf);
483 }
484
write_rgb_alpha_to_rgb_alpha(png_struct * png,png_byte * data,SLindex_Type num_cols,png_byte * tmpbuf)485 static void write_rgb_alpha_to_rgb_alpha (png_struct *png, png_byte *data, SLindex_Type num_cols, png_byte *tmpbuf)
486 {
487 unsigned char *data_max;
488 unsigned char *p;
489
490 if (Is_Little_Endian)
491 {
492 byte_swap32 ((unsigned char *) data, (unsigned char *) tmpbuf, num_cols);
493 data = tmpbuf;
494 }
495 data_max = data + 4 * num_cols;
496 p = tmpbuf;
497 /* Change ARGBARGB... to RGBARGBA... */
498 while (data < data_max)
499 {
500 unsigned char a = data[0];
501 p[0] = data[1];
502 p[1] = data[2];
503 p[2] = data[3];
504 p[3] = a;
505 data += 4;
506 p += 4;
507 }
508 png_write_row (png, tmpbuf);
509 }
510
write_rgb_to_rgb(png_struct * png,png_byte * data,SLindex_Type num_cols,png_byte * tmpbuf)511 static void write_rgb_to_rgb (png_struct *png, png_byte *data, SLindex_Type num_cols, png_byte *tmpbuf)
512 {
513 SLindex_Type i;
514 png_byte *p, *q;
515
516 if (Is_Little_Endian)
517 {
518 byte_swap32 ((unsigned char *) data, (unsigned char *) tmpbuf, num_cols);
519 p = tmpbuf;
520 }
521 else p = data;
522
523 /* ARGBARGB... -> RGBRGBRGB */
524 q = tmpbuf;
525 for (i = 0; i < num_cols; i++)
526 {
527 p++;
528 *q++ = *p++;
529 *q++ = *p++;
530 *q++ = *p++;
531 }
532 png_write_row (png, tmpbuf);
533 }
534
write_array(png_struct * png,png_byte ** image_pointers,SLindex_Type num_rows,SLindex_Type num_cols,void (* write_row_func)(png_struct *,png_byte *,SLindex_Type,png_byte *),png_byte * tmpbuf)535 static int write_array (png_struct *png, png_byte **image_pointers, SLindex_Type num_rows, SLindex_Type num_cols,
536 void (*write_row_func) (png_struct *, png_byte *, SLindex_Type, png_byte *),
537 png_byte *tmpbuf)
538 {
539 int num_pass;
540 SLindex_Type i;
541
542 num_pass = png_set_interlace_handling(png);
543 while (num_pass > 0)
544 {
545 num_pass--;
546 for (i = 0; i < num_rows; i++)
547 (*write_row_func) (png, image_pointers[i], num_cols, tmpbuf);
548 }
549 return 0;
550 }
551
write_image_internal(char * file,SLang_Array_Type * at,int color_type,void (* write_fun)(png_struct *,png_byte * p,SLindex_Type,png_byte *),int flip,int compress_level)552 static int write_image_internal (char *file, SLang_Array_Type *at,
553 int color_type,
554 void (*write_fun)(png_struct *, png_byte *p, SLindex_Type, png_byte *),
555 int flip, int compress_level)
556 {
557 FILE *fp;
558 Png_Type *p = NULL;
559 png_struct *png;
560 png_info *info;
561 SLindex_Type width, height;
562 png_byte **image_pointers;
563 int bit_depth;
564 int status = -1;
565 png_byte *tmpbuf;
566
567 bit_depth = 8;
568
569 height = at->dims[0];
570 width = at->dims[1];
571
572 if (NULL == (image_pointers = allocate_image_pointers (height, (png_byte *)at->data, width * at->sizeof_type, flip)))
573 return -1;
574
575 if (NULL == (tmpbuf = (png_byte *)SLmalloc (4*width)))
576 {
577 free_image_pointers (image_pointers);
578 return -1;
579 }
580
581 if (NULL == (fp = fopen (file, "wb")))
582 {
583 (void)SLerrno_set_errno (errno);
584 SLang_verror (SL_Open_Error, "Unable to open %s", file);
585 goto return_error;
586 }
587
588 if (NULL == (p = alloc_png_type ('w')))
589 goto return_error;
590
591 p->fp = fp;
592
593 if (NULL == (p->png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
594 {
595 SLang_verror (SL_Open_Error, "png_create_write_struct failed");
596 goto return_error;
597 }
598 png = p->png;
599 if (NULL == (p->info = png_create_info_struct (png)))
600 {
601 SLang_verror (SL_Open_Error, "png_create_info_struct failed");
602 goto return_error;
603 }
604 info = p->info;
605 if (setjmp(png_jmpbuf(png)))
606 {
607 SLang_verror (SL_Write_Error, "PNG I/O error");
608 goto return_error;
609 }
610 png_init_io(png, fp);
611
612 if ((compress_level >= 0) && (compress_level <= 9))
613 png_set_compression_level (png, compress_level);
614
615 png_set_IHDR (png, info, width, height,
616 bit_depth, color_type, PNG_INTERLACE_NONE,
617 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
618 png_write_info(png, info);
619
620 if (-1 == write_array (png, image_pointers, height, width, write_fun, tmpbuf))
621 goto return_error;
622
623 png_write_end(png, NULL);
624 if (EOF == fclose (p->fp))
625 {
626 SLang_verror (SL_Write_Error, "Error closing %s", file);
627 SLerrno_set_errno (errno);
628 }
629 else status = 0;
630
631 p->fp = NULL;
632 /* drop */
633 return_error:
634 if (tmpbuf != NULL)
635 SLfree ((char *) tmpbuf);
636 free_image_pointers (image_pointers);
637 if (p != NULL)
638 free_png_type (p);
639
640 return status;
641 }
642
write_image(int flip)643 static void write_image (int flip)
644 {
645 char *file;
646 SLang_Array_Type *at;
647 int with_alpha = 0;
648 int has_with_alpha = 0;
649 int compress_level;
650 int color_type;
651 void (*write_fun) (png_struct *, png_byte *, SLindex_Type, png_byte *);
652
653 if (SLang_Num_Function_Args == 3)
654 {
655 if (-1 == SLang_pop_int (&with_alpha))
656 return;
657 has_with_alpha = 1;
658 }
659
660 if (-1 == SLang_get_int_qualifier ("compress", &compress_level, -1))
661 return;
662
663 if (-1 == SLang_pop_array (&at, 0))
664 return;
665
666 if (at->num_dims != 2)
667 {
668 SLang_verror (SL_InvalidParm_Error, "Expecting a 2-d array");
669 SLang_free_array (at);
670 return;
671 }
672
673 switch (SLang_get_int_size (at->data_type))
674 {
675 case -8:
676 case 8:
677 if (with_alpha)
678 {
679 write_fun = write_gray_to_gray_alpha;
680 color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
681 }
682 else
683 {
684 write_fun = write_gray_to_gray;
685 color_type = PNG_COLOR_TYPE_GRAY;
686 }
687 break;
688 case -16:
689 case 16:
690 if (has_with_alpha && (with_alpha == 0))
691 {
692 write_fun = write_gray_alpha_to_gray;
693 color_type = PNG_COLOR_TYPE_GRAY;
694 }
695 else
696 {
697 write_fun = write_gray_alpha_to_gray_alpha;
698 color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
699 }
700 break;
701 case -32:
702 case 32:
703 if (with_alpha)
704 {
705 write_fun = write_rgb_alpha_to_rgb_alpha;
706 color_type = PNG_COLOR_TYPE_RGBA;
707 }
708 else
709 {
710 write_fun = write_rgb_to_rgb;
711 color_type = PNG_COLOR_TYPE_RGB;
712 }
713 break;
714 default:
715 SLang_verror (SL_InvalidParm_Error, "Expecting an 8, 16, or 32 bit integer array");
716 SLang_free_array (at);
717 return;
718 }
719
720 if (-1 == SLang_pop_slstring (&file))
721 {
722 SLang_free_array (at);
723 return;
724 }
725 (void) write_image_internal (file, at, color_type, write_fun, flip, compress_level);
726 SLang_free_slstring (file);
727 SLang_free_array (at);
728 }
729
read_intrin(void)730 static void read_intrin (void)
731 {
732 read_image (0);
733 }
read_flipped_intrin(void)734 static void read_flipped_intrin (void)
735 {
736 read_image (1);
737 }
738
write_intrin(void)739 static void write_intrin (void)
740 {
741 write_image (0);
742 }
write_flipped_intrin(void)743 static void write_flipped_intrin (void)
744 {
745 write_image (1);
746 }
747
748 static SLang_Intrin_Fun_Type Module_Intrinsics [] =
749 {
750 MAKE_INTRINSIC_0("png_read", read_intrin, SLANG_VOID_TYPE),
751 MAKE_INTRINSIC_0("png_read_flipped", read_flipped_intrin, SLANG_VOID_TYPE),
752 MAKE_INTRINSIC_0("png_write", write_intrin, SLANG_VOID_TYPE),
753 MAKE_INTRINSIC_0("png_write_flipped", write_flipped_intrin, SLANG_VOID_TYPE),
754 SLANG_END_INTRIN_FUN_TABLE
755 };
756
757 static SLang_Intrin_Var_Type Module_Variables [] =
758 {
759 MAKE_VARIABLE("_png_module_version_string", &Module_Version_String, SLANG_STRING_TYPE, 1),
760 SLANG_END_INTRIN_VAR_TABLE
761 };
762
763 static SLang_IConstant_Type Module_IConstants [] =
764 {
765 MAKE_ICONSTANT("PNG_COLOR_TYPE_GRAY", PNG_COLOR_TYPE_GRAY),
766 MAKE_ICONSTANT("PNG_COLOR_TYPE_GRAY_ALPHA", PNG_COLOR_TYPE_GRAY_ALPHA),
767 MAKE_ICONSTANT("PNG_COLOR_TYPE_RGB", PNG_COLOR_TYPE_RGB),
768 MAKE_ICONSTANT("PNG_COLOR_TYPE_RGBA", PNG_COLOR_TYPE_RGBA),
769
770 MAKE_ICONSTANT("_png_module_version", MODULE_VERSION_NUMBER),
771 SLANG_END_ICONST_TABLE
772 };
773
init_png_module_ns(char * ns_name)774 int init_png_module_ns (char *ns_name)
775 {
776 unsigned short x;
777
778 SLang_NameSpace_Type *ns = SLns_create_namespace (ns_name);
779 if (ns == NULL)
780 return -1;
781
782 x = 0xFF;
783 Is_Little_Endian = (*(unsigned char *)&x == 0xFF);
784
785 if (
786 (-1 == SLns_add_intrin_var_table (ns, Module_Variables, NULL))
787 || (-1 == SLns_add_intrin_fun_table (ns, Module_Intrinsics, NULL))
788 || (-1 == SLns_add_iconstant_table (ns, Module_IConstants, NULL))
789 )
790 return -1;
791
792 return 0;
793 }
794
795 /* This function is optional */
deinit_png_module(void)796 void deinit_png_module (void)
797 {
798 }
799