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 |
|
|
/********************************************************************************/ |