/[james]/archive/pngrender/pngrender.c
ViewVC logotype

Annotation of /archive/pngrender/pngrender.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 17 - (hide annotations) (download) (as text)
Tue Feb 11 09:59:30 2003 UTC (21 years, 4 months ago) by james
File MIME type: text/x-csrc
File size: 18740 byte(s)
Initial import.

1 james 17 /*
2     * pngrender.c
3     */
4    
5     /*
6     ________________________________________________________________________________
7    
8     Copyright (c) 2001 James Bursa
9    
10     All rights reserved.
11    
12     Permission is hereby granted, free of charge, to any person obtaining a
13     copy of this software and associated documentation files (the
14     "Software"), to deal in the Software without restriction, including
15     without limitation the rights to use, copy, modify, merge, publish,
16     distribute, and/or sell copies of the Software, and to permit persons
17     to whom the Software is furnished to do so, provided that the above
18     copyright notice(s) and this permission notice appear in all copies of
19     the Software and that both the above copyright notice(s) and this
20     permission notice appear in supporting documentation.
21    
22     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
25     OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26     HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
27     INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
28     FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
29     NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
30     WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31    
32     Except as contained in this notice, the name of a copyright holder
33     shall not be used in advertising or otherwise to promote the sale, use
34     or other dealings in this Software without prior written authorization
35     of the copyright holder.
36    
37     ________________________________________________________________________________
38    
39     james.bursa@strcprstskrzkrk.co.uk
40     http://www.strcprstskrzkrk.co.uk/
41    
42     ________________________________________________________________________________
43     */
44    
45     #include <stdio.h>
46     #include <stdlib.h>
47    
48     #include <png.h>
49    
50     #include <colourtrans.h>
51     #include <os.h>
52    
53     /********************************************************************************/
54    
55     int render_png_file(const char *path, signed int x, signed int y);
56     int load_png_file(png_struct *png, png_info *info, const char *path);
57     int render_png_to_screen(png_struct *png, png_info *info, signed int value_list[],
58     signed int x, signed int y);
59     void png_render_32(png_byte *prows[], unsigned char *srow, signed int x0,
60     signed int y0, signed int x1, signed int y1, signed int sx,
61     unsigned int sline_length, unsigned int pchannels);
62     void png_render_16(png_byte *prows[], unsigned char *srow, signed int x0,
63     signed int y0, signed int x1, signed int y1, signed int sx,
64     unsigned int sline_length, unsigned int pchannels);
65     int png_render_8(png_byte *prows[], unsigned char *srow, signed int x0,
66     signed int y0, signed int x1, signed int y1, signed int sx,
67     unsigned int sline_length, unsigned int pchannels);
68     int png_render_4(png_byte *prows[], unsigned char *srow, signed int x0,
69     signed int y0, signed int x1, signed int y1, signed int sx,
70     unsigned int sline_length, unsigned int pchannels);
71     os_palette *read_palette();
72    
73     /********************************************************************************/
74    
75     float alpha_table[] = {
76     0.0, 1.0/255, 2.0/255, 3.0/255, 4.0/255, 5.0/255,
77     6.0/255, 7.0/255, 8.0/255, 9.0/255, 10.0/255, 11.0/255,
78     12.0/255, 13.0/255, 14.0/255, 15.0/255, 16.0/255, 17.0/255,
79     18.0/255, 19.0/255, 20.0/255, 21.0/255, 22.0/255, 23.0/255,
80     24.0/255, 25.0/255, 26.0/255, 27.0/255, 28.0/255, 29.0/255,
81     30.0/255, 31.0/255, 32.0/255, 33.0/255, 34.0/255, 35.0/255,
82     36.0/255, 37.0/255, 38.0/255, 39.0/255, 40.0/255, 41.0/255,
83     42.0/255, 43.0/255, 44.0/255, 45.0/255, 46.0/255, 47.0/255,
84     48.0/255, 49.0/255, 50.0/255, 51.0/255, 52.0/255, 53.0/255,
85     54.0/255, 55.0/255, 56.0/255, 57.0/255, 58.0/255, 59.0/255,
86     60.0/255, 61.0/255, 62.0/255, 63.0/255, 64.0/255, 65.0/255,
87     66.0/255, 67.0/255, 68.0/255, 69.0/255, 70.0/255, 71.0/255,
88     72.0/255, 73.0/255, 74.0/255, 75.0/255, 76.0/255, 77.0/255,
89     78.0/255, 79.0/255, 80.0/255, 81.0/255, 82.0/255, 83.0/255,
90     84.0/255, 85.0/255, 86.0/255, 87.0/255, 88.0/255, 89.0/255,
91     90.0/255, 91.0/255, 92.0/255, 93.0/255, 94.0/255, 95.0/255,
92     96.0/255, 97.0/255, 98.0/255, 99.0/255, 100.0/255, 101.0/255,
93     102.0/255, 103.0/255, 104.0/255, 105.0/255, 106.0/255, 107.0/255,
94     108.0/255, 109.0/255, 110.0/255, 111.0/255, 112.0/255, 113.0/255,
95     114.0/255, 115.0/255, 116.0/255, 117.0/255, 118.0/255, 119.0/255,
96     120.0/255, 121.0/255, 122.0/255, 123.0/255, 124.0/255, 125.0/255,
97     126.0/255, 127.0/255, 128.0/255, 129.0/255, 130.0/255, 131.0/255,
98     132.0/255, 133.0/255, 134.0/255, 135.0/255, 136.0/255, 137.0/255,
99     138.0/255, 139.0/255, 140.0/255, 141.0/255, 142.0/255, 143.0/255,
100     144.0/255, 145.0/255, 146.0/255, 147.0/255, 148.0/255, 149.0/255,
101     150.0/255, 151.0/255, 152.0/255, 153.0/255, 154.0/255, 155.0/255,
102     156.0/255, 157.0/255, 158.0/255, 159.0/255, 160.0/255, 161.0/255,
103     162.0/255, 163.0/255, 164.0/255, 165.0/255, 166.0/255, 167.0/255,
104     168.0/255, 169.0/255, 170.0/255, 171.0/255, 172.0/255, 173.0/255,
105     174.0/255, 175.0/255, 176.0/255, 177.0/255, 178.0/255, 179.0/255,
106     180.0/255, 181.0/255, 182.0/255, 183.0/255, 184.0/255, 185.0/255,
107     186.0/255, 187.0/255, 188.0/255, 189.0/255, 190.0/255, 191.0/255,
108     192.0/255, 193.0/255, 194.0/255, 195.0/255, 196.0/255, 197.0/255,
109     198.0/255, 199.0/255, 200.0/255, 201.0/255, 202.0/255, 203.0/255,
110     204.0/255, 205.0/255, 206.0/255, 207.0/255, 208.0/255, 209.0/255,
111     210.0/255, 211.0/255, 212.0/255, 213.0/255, 214.0/255, 215.0/255,
112     216.0/255, 217.0/255, 218.0/255, 219.0/255, 220.0/255, 221.0/255,
113     222.0/255, 223.0/255, 224.0/255, 225.0/255, 226.0/255, 227.0/255,
114     228.0/255, 229.0/255, 230.0/255, 231.0/255, 232.0/255, 233.0/255,
115     234.0/255, 235.0/255, 236.0/255, 237.0/255, 238.0/255, 239.0/255,
116     240.0/255, 241.0/255, 242.0/255, 243.0/255, 244.0/255, 245.0/255,
117     246.0/255, 247.0/255, 248.0/255, 249.0/255, 250.0/255, 251.0/255,
118     252.0/255, 253.0/255, 254.0/255, 1.0 };
119    
120     /********************************************************************************/
121    
122     int main(int argc, char *argv[])
123     {
124     char *end;
125    
126     if (argc != 4)
127     {
128     fprintf(stderr, "Usage: pngrender file x y\n");
129     exit(1);
130     }
131    
132     return render_png_file(argv[1], strtol(argv[2], &end, 10), strtol(argv[3], &end, 10));
133     }
134    
135     /********************************************************************************
136     * render a png file to the screen
137     * => path -- filename of png file to render
138     * x, y -- position of bottom-left corner in os units from screen bottom-left
139     * <= return code:
140     * 0 - OK
141     * -1 - file failed to open
142     * -2 - couldn't read header
143     * -3 - not a png
144     * -4 - bpp of png not understood
145     * -5 - malloc or colourtrans failed
146     * other - os error number from OS_ReadVduVariables
147     */
148    
149     int render_png_file(const char *path, signed int x, signed int y)
150     {
151     unsigned int status;
152     signed int value_list[20];
153     png_struct *png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
154     png_info *info = png_create_info_struct(png);
155     const os_vdu_var var_list[] = {os_MODEVAR_LINE_LENGTH, os_MODEVAR_LOG2_BPP,
156     os_MODEVAR_XEIG_FACTOR, os_MODEVAR_YEIG_FACTOR,
157     os_VDUVAR_GWL_COL, os_VDUVAR_GWB_ROW, os_VDUVAR_GWR_COL, os_VDUVAR_GWT_ROW,
158     os_VDUVAR_ORGX, os_VDUVAR_ORGY, os_VDUVAR_SCREEN_START,
159     os_MODEVAR_YWIND_LIMIT, -1};
160     os_error const *error;
161    
162     status = load_png_file(png, info, path);
163     if (status)
164     {
165     png_destroy_read_struct(&png, &info, (png_info **) NULL);
166     return status;
167     }
168    
169     error = xos_read_vdu_variables((os_vdu_var_list *) &var_list, value_list);
170     if (error)
171     {
172     png_destroy_read_struct(&png, &info, (png_info **) NULL);
173     return error->errnum;
174     }
175    
176     status = render_png_to_screen(png, info, value_list, x, y);
177     png_destroy_read_struct(&png, &info, (png_info **) NULL);
178     return status;
179     }
180    
181     /********************************************************************************/
182    
183     int load_png_file(png_struct *png, png_info *info, const char *path)
184     {
185     unsigned char buf[10];
186     FILE *file;
187    
188     if (!(file = fopen(path, "rb"))) return -1;
189     if (fread(buf, 1, 8, file) < 8) return -2;
190     if (png_sig_cmp(buf, 0, 8) != 0) return -3;
191    
192     rewind(file);
193    
194     png_init_io(png, file);
195     png_read_png(png, info,
196     PNG_TRANSFORM_STRIP_16 // Strip 16-bit samples to 8 bits
197     | PNG_TRANSFORM_PACKING // Expand 1, 2 and 4-bit samples to bytes
198     | PNG_TRANSFORM_EXPAND // Perform set_expand()
199     , NULL);
200    
201     fclose(file);
202    
203     return 0;
204     }
205    
206     /********************************************************************************/
207    
208     int render_png_to_screen(png_struct *png, png_info *info, signed int value_list[],
209     signed int sx, signed int sy)
210     {
211     unsigned char *srow;
212     unsigned int pwidth, pheight, pchannels, sbpp, sline_length, ox, oy;
213     signed int x0, y0, x1, y1;
214     png_byte **prows;
215    
216     pchannels = png_get_channels(png, info); /* png channels, including alpha */
217     pwidth = png_get_image_width(png, info); /* png width / pixels */
218     pheight = png_get_image_height(png, info); /* png height / pixels */
219     prows = png_get_rows(png, info); /* array of png rows data */
220    
221     sline_length = value_list[0]; /* screen line length / bytes */
222     sbpp = 1 << value_list[1]; /* screen depth */
223    
224     ox = value_list[8] >> value_list[2]; /* graphics origin / pixels */
225     oy = value_list[9] >> value_list[2];
226     sx = (sx >> value_list[2]) + ox; /* x / pixels */
227     sy = (sy >> value_list[3]) + oy; /* y / pixels */
228    
229     x0 = value_list[4] - sx; /* graphics window relative to */
230     y0 = value_list[5] - sy; /* image origin / pixels */
231     x1 = value_list[6] - sx;
232     y1 = value_list[7] - sy;
233    
234     if (x0 < 0) x0 = 0; /* region of image to render */
235     if (y0 < 0) y0 = 0;
236     if (x1 >= pwidth) x1 = pwidth - 1;
237     if (y1 >= pheight) y1 = pheight - 1;
238    
239     if (x0 >= pwidth) return 0; /* outside graphics window */
240     if (y0 >= pheight) return 0;
241     if (x1 < 0) return 0;
242     if (y1 < 0) return 0;
243    
244     srow = (unsigned char *) (value_list[10] +
245     (value_list[11] - sy - pheight + 1) * sline_length);
246    
247     switch (sbpp)
248     {
249     case 32:
250     png_render_32(prows, srow, x0, pheight - 1 - y1, x1, pheight - 1 - y0,
251     sx, sline_length, pchannels);
252     break;
253    
254     case 16:
255     png_render_16(prows, srow, x0, pheight - 1 - y1, x1, pheight - 1 - y0,
256     sx, sline_length, pchannels);
257     break;
258    
259     case 8:
260     return png_render_8(prows, srow, x0, pheight - 1 - y1, x1, pheight - 1 - y0,
261     sx, sline_length, pchannels);
262    
263     case 4:
264     return png_render_4(prows, srow, x0, pheight - 1 - y1, x1, pheight - 1 - y0,
265     sx, sline_length, pchannels);
266     }
267    
268     return 0;
269     }
270    
271     /********************************************************************************/
272    
273     void png_render_32(png_byte *prows[], unsigned char *srow, signed int x0,
274     signed int y0, signed int x1, signed int y1, signed int sx,
275     unsigned int sline_length, unsigned int pchannels)
276     {
277     unsigned char pr, pg, pb, sr, sb, sg, *pbyte, *sbyte;
278     unsigned int prow, pcol, palpha;
279     float alphaf, ialphaf;
280    
281     for (prow = y0; prow <= y1; prow++)
282     {
283     pbyte = prows[prow] + (x0 * pchannels);
284     sbyte = srow + sline_length * prow + (sx + x0) * 4;
285    
286     for (pcol = x0; pcol <= x1; pcol++)
287     {
288     pr = *pbyte++;
289     if (pchannels == 1 || pchannels == 2) pg = pb = pr; /* greyscale */
290     else { pg = *pbyte++; pb = *pbyte++; } /* colour */
291    
292     palpha = (pchannels == 4 || pchannels == 2 ? *pbyte++ : 255);
293    
294     if (palpha == 0) { sbyte += 4; continue; } /* fully transparent */
295    
296     if (palpha != 255) /* partially transparent */
297     {
298     alphaf = alpha_table[palpha];
299     ialphaf = alpha_table[255 - palpha];
300    
301     sr = *sbyte; sg = *(sbyte + 1); sb = *(sbyte + 2);
302    
303     pr = alphaf * pr + ialphaf * sr;
304     pg = alphaf * pg + ialphaf * sg;
305     pb = alphaf * pb + ialphaf * sb;
306     }
307    
308     *sbyte++ = pr; *sbyte++ = pg; *sbyte++ = pb; sbyte++;
309     }
310     }
311     }
312    
313     /********************************************************************************/
314    
315     void png_render_16(png_byte *prows[], unsigned char *srow, signed int x0,
316     signed int y0, signed int x1, signed int y1, signed int sx,
317     unsigned int sline_length, unsigned int pchannels)
318     {
319     unsigned char pr, pg, pb, sr, sb, sg, *pbyte, *sbyte;
320     unsigned int prow, pcol, palpha;
321     float alphaf, ialphaf;
322    
323     for (prow = y0; prow <= y1; prow++)
324     {
325     pbyte = prows[prow] + (x0 * pchannels);
326     sbyte = srow + sline_length * prow + (sx + x0) * 2;
327    
328     for (pcol = x0; pcol <= x1; pcol++)
329     {
330     pr = *pbyte++ >> 3;
331     if (pchannels == 1 || pchannels == 2) pg = pb = pr;
332     else { pg = *pbyte++ >> 3; pb = *pbyte++ >> 3; }
333    
334     palpha = (pchannels == 4 || pchannels == 2 ? *pbyte++ : 255);
335    
336     if (palpha == 0) { sbyte += 2; continue; }
337    
338     if (palpha != 255)
339     {
340     alphaf = alpha_table[palpha];
341     ialphaf = alpha_table[255 - palpha];
342    
343     sr = *sbyte & 0x1f;
344     sg = (*sbyte >> 5) | ((*(sbyte + 1) & 0x3) << 3);
345     sb = (*(sbyte + 1) >> 2) & 0x1f;
346    
347     pr = alphaf * pr + ialphaf * sr;
348     pg = alphaf * pg + ialphaf * sg;
349     pb = alphaf * pb + ialphaf * sb;
350     }
351    
352     *sbyte++ = (pg << 5) | pr;
353     *sbyte++ = (pb << 2) | (pg >> 3);
354     }
355     }
356     }
357    
358     /********************************************************************************/
359    
360     int png_render_8(png_byte *prows[], unsigned char *srow, signed int x0,
361     signed int y0, signed int x1, signed int y1, signed int sx,
362     unsigned int sline_length, unsigned int pchannels)
363     {
364     unsigned char pr, pg, pb, sr, sb, sg, *pbyte, *sbyte, map[0x1000];
365     unsigned int prow, pcol, palpha, colour;
366     float alphaf, ialphaf;
367     os_palette *palette;
368     os_colour scolour;
369    
370     palette = read_palette();
371     if (!palette) return -5;
372    
373     for (colour = 0; colour < 0x1000; colour++)
374     {
375     map[colour] = colourtrans_return_colour_number(
376     ((colour & 0xf) << 8) | /* red */
377     ((colour & 0xf) << 12) |
378     (((colour >> 4) & 0xf) << 16) | /* green */
379     (((colour >> 4) & 0xf) << 20) |
380     (((colour >> 8) & 0xf) << 24) | /* blue */
381     (((colour >> 8) & 0xf) << 28));
382     }
383    
384     /* render image */
385     for (prow = y0; prow <= y1; prow++)
386     {
387     pbyte = prows[prow] + (x0 * pchannels);
388     sbyte = srow + sline_length * prow + sx + x0;
389    
390     for (pcol = x0; pcol <= x1; pcol++)
391     {
392     pr = *pbyte++;
393     if (pchannels == 1 || pchannels == 2) pg = pb = pr;
394     else { pg = *pbyte++; pb = *pbyte++; }
395    
396     palpha = (pchannels == 4 || pchannels == 2 ? *pbyte++ : 255);
397    
398     if (palpha == 0) { sbyte++; continue; }
399    
400     if (palpha != 255)
401     {
402     alphaf = alpha_table[palpha];
403     ialphaf = alpha_table[255 - palpha];
404    
405     scolour = palette->entries[*sbyte];
406     sr = (scolour >> 8) & 0xff;
407     sg = (scolour >> 16) & 0xff;
408     sb = (scolour >> 24) & 0xff;
409    
410     pr = alphaf * pr + ialphaf * sr;
411     pg = alphaf * pg + ialphaf * sg;
412     pb = alphaf * pb + ialphaf * sb;
413     }
414    
415     *sbyte++ = map[(pr >> 4) | (pg & 0xf0) | ((pb << 4) & 0xf00)];
416     }
417     }
418    
419     free(palette);
420    
421     return 0;
422     }
423    
424     /********************************************************************************/
425    
426     int png_render_4(png_byte *prows[], unsigned char *srow, signed int x0,
427     signed int y0, signed int x1, signed int y1, signed int sx,
428     unsigned int sline_length, unsigned int pchannels)
429     {
430     unsigned char pr, pg, pb, sr, sb, sg, *pbyte, *sbyte, map[0x1000];
431     unsigned int prow, pcol, palpha, spix, colour;
432     float alphaf, ialphaf;
433     os_palette *palette;
434     os_colour scolour;
435    
436     palette = read_palette();
437     if (!palette) return -5;
438    
439     for (colour = 0; colour < 0x1000; colour++)
440     {
441     map[colour] = colourtrans_return_colour_number(
442     ((colour & 0xf) << 8) | /* red */
443     ((colour & 0xf) << 12) |
444     (((colour >> 4) & 0xf) << 16) | /* green */
445     (((colour >> 4) & 0xf) << 20) |
446     (((colour >> 8) & 0xf) << 24) | /* blue */
447     (((colour >> 8) & 0xf) << 28));
448     }
449    
450     /* render image */
451     for (prow = y0; prow <= y1; prow++)
452     {
453     pbyte = prows[prow] + (x0 * pchannels);
454     sbyte = srow + sline_length * prow + (sx + x0) / 2;
455     spix = (sx + x0) & 1;
456    
457     for (pcol = x0; pcol <= x1; pcol++)
458     {
459     pr = *pbyte++;
460     if (pchannels == 1 || pchannels == 2) pg = pb = pr;
461     else { pg = *pbyte++; pb = *pbyte++; }
462    
463     palpha = (pchannels == 4 || pchannels == 2 ? *pbyte++ : 255);
464    
465     if (palpha == 0)
466     {
467     spix = 1 - spix;
468     if (spix == 0) sbyte++;
469     continue;
470     }
471    
472     if (palpha != 255)
473     {
474     alphaf = alpha_table[palpha];
475     ialphaf = alpha_table[255 - palpha];
476    
477     scolour = (spix ? palette->entries[(*sbyte >> 4) & 0xf]
478     : palette->entries[*sbyte & 0xf]);
479     sr = (scolour >> 8) & 0xff;
480     sg = (scolour >> 16) & 0xff;
481     sb = (scolour >> 24) & 0xff;
482    
483     pr = alphaf * pr + ialphaf * sr;
484     pg = alphaf * pg + ialphaf * sg;
485     pb = alphaf * pb + ialphaf * sb;
486     }
487    
488     *sbyte = (spix ?
489     (map[(pr >> 4) | (pg & 0xf0) | ((pb << 4) & 0xf00)] << 4) | (*sbyte & 0xf) :
490     map[(pr >> 4) | (pg & 0xf0) | ((pb << 4) & 0xf00)] | (*sbyte & 0xf0));
491    
492     spix = 1 - spix;
493     if (spix == 0) sbyte++;
494     }
495     }
496    
497     free(palette);
498    
499     return 0;
500     }
501    
502     /********************************************************************************
503     * read screen palette
504     */
505    
506     os_palette *read_palette()
507     {
508     unsigned int size;
509     os_palette *palette;
510     os_error const *error;
511    
512     error = xcolourtrans_read_palette((osspriteop_area const *) -1, (osspriteop_id) -1,
513     (os_palette *) 0, 0, 0, &size);
514     if (error) return 0;
515    
516     palette = malloc(size);
517     if (!palette) return 0;
518    
519     error = xcolourtrans_read_palette((osspriteop_area const *) -1, (osspriteop_id) -1,
520     palette, size, 0, NULL);
521     if (error) return 0;
522    
523     return palette;
524     }
525    
526     /********************************************************************************/

  ViewVC Help
Powered by ViewVC 1.1.26