Blame


1 a0d146ed 2005-07-12 devnull #include "stdinc.h"
2 a0d146ed 2005-07-12 devnull #include "dat.h"
3 a0d146ed 2005-07-12 devnull #include "fns.h"
4 a0d146ed 2005-07-12 devnull
5 a0d146ed 2005-07-12 devnull enum
6 a0d146ed 2005-07-12 devnull {
7 a0d146ed 2005-07-12 devnull IDATSIZE = 20000,
8 a0d146ed 2005-07-12 devnull FilterNone = 0
9 a0d146ed 2005-07-12 devnull };
10 a0d146ed 2005-07-12 devnull
11 a0d146ed 2005-07-12 devnull typedef struct ZlibR ZlibR;
12 a0d146ed 2005-07-12 devnull typedef struct ZlibW ZlibW;
13 a0d146ed 2005-07-12 devnull
14 a0d146ed 2005-07-12 devnull struct ZlibR
15 a0d146ed 2005-07-12 devnull {
16 a0d146ed 2005-07-12 devnull uchar *data;
17 a0d146ed 2005-07-12 devnull int width;
18 a0d146ed 2005-07-12 devnull int dx;
19 a0d146ed 2005-07-12 devnull int dy;
20 a0d146ed 2005-07-12 devnull int x;
21 a0d146ed 2005-07-12 devnull int y;
22 a0d146ed 2005-07-12 devnull int pixwid;
23 a0d146ed 2005-07-12 devnull };
24 a0d146ed 2005-07-12 devnull
25 a0d146ed 2005-07-12 devnull struct ZlibW
26 a0d146ed 2005-07-12 devnull {
27 a0d146ed 2005-07-12 devnull Hio *io;
28 a0d146ed 2005-07-12 devnull uchar *buf;
29 a0d146ed 2005-07-12 devnull uchar *b;
30 a0d146ed 2005-07-12 devnull uchar *e;
31 a0d146ed 2005-07-12 devnull };
32 a0d146ed 2005-07-12 devnull
33 8425b514 2010-02-23 rsc static u32int *crctab;
34 a0d146ed 2005-07-12 devnull static uchar PNGmagic[] = { 137, 'P', 'N', 'G', '\r', '\n', 26, '\n'};
35 a0d146ed 2005-07-12 devnull
36 a0d146ed 2005-07-12 devnull static void
37 a0d146ed 2005-07-12 devnull put4(uchar *a, ulong v)
38 a0d146ed 2005-07-12 devnull {
39 a0d146ed 2005-07-12 devnull a[0] = v>>24;
40 a0d146ed 2005-07-12 devnull a[1] = v>>16;
41 a0d146ed 2005-07-12 devnull a[2] = v>>8;
42 a0d146ed 2005-07-12 devnull a[3] = v;
43 a0d146ed 2005-07-12 devnull }
44 a0d146ed 2005-07-12 devnull
45 a0d146ed 2005-07-12 devnull static void
46 a0d146ed 2005-07-12 devnull chunk(Hio *io, char *type, uchar *d, int n)
47 a0d146ed 2005-07-12 devnull {
48 a0d146ed 2005-07-12 devnull uchar buf[4];
49 a0d146ed 2005-07-12 devnull ulong crc = 0;
50 a0d146ed 2005-07-12 devnull
51 a0d146ed 2005-07-12 devnull if(strlen(type) != 4)
52 a0d146ed 2005-07-12 devnull return;
53 a0d146ed 2005-07-12 devnull put4(buf, n);
54 a0d146ed 2005-07-12 devnull hwrite(io, buf, 4);
55 a0d146ed 2005-07-12 devnull hwrite(io, type, 4);
56 a0d146ed 2005-07-12 devnull hwrite(io, d, n);
57 a0d146ed 2005-07-12 devnull crc = blockcrc(crctab, crc, type, 4);
58 a0d146ed 2005-07-12 devnull crc = blockcrc(crctab, crc, d, n);
59 a0d146ed 2005-07-12 devnull put4(buf, crc);
60 a0d146ed 2005-07-12 devnull hwrite(io, buf, 4);
61 a0d146ed 2005-07-12 devnull }
62 a0d146ed 2005-07-12 devnull
63 a0d146ed 2005-07-12 devnull static int
64 a0d146ed 2005-07-12 devnull zread(void *va, void *buf, int n)
65 a0d146ed 2005-07-12 devnull {
66 a0d146ed 2005-07-12 devnull int a, i, pixels, pixwid;
67 a0d146ed 2005-07-12 devnull uchar *b, *e, *img;
68 a0d146ed 2005-07-12 devnull ZlibR *z;
69 a0d146ed 2005-07-12 devnull
70 a0d146ed 2005-07-12 devnull z = va;
71 a0d146ed 2005-07-12 devnull pixwid = z->pixwid;
72 a0d146ed 2005-07-12 devnull b = buf;
73 a0d146ed 2005-07-12 devnull e = b+n;
74 a0d146ed 2005-07-12 devnull while(b+pixwid <= e){
75 a0d146ed 2005-07-12 devnull if(z->y >= z->dy)
76 a0d146ed 2005-07-12 devnull break;
77 a0d146ed 2005-07-12 devnull if(z->x == 0)
78 a0d146ed 2005-07-12 devnull *b++ = FilterNone;
79 a0d146ed 2005-07-12 devnull pixels = (e-b)/pixwid;
80 a0d146ed 2005-07-12 devnull if(pixels > z->dx - z->x)
81 a0d146ed 2005-07-12 devnull pixels = z->dx - z->x;
82 a0d146ed 2005-07-12 devnull img = z->data + z->width*z->y + pixwid*z->x;
83 a0d146ed 2005-07-12 devnull memmove(b, img, pixwid*pixels);
84 a0d146ed 2005-07-12 devnull if(pixwid == 4){
85 a0d146ed 2005-07-12 devnull /*
86 a0d146ed 2005-07-12 devnull * Convert to non-premultiplied alpha.
87 a0d146ed 2005-07-12 devnull */
88 a0d146ed 2005-07-12 devnull for(i=0; i<pixels; i++, b+=4){
89 a0d146ed 2005-07-12 devnull a = b[3];
90 a9ecda2d 2005-10-29 devnull if(a != 0 && a != 255){
91 a0d146ed 2005-07-12 devnull if(b[0] >= a)
92 a0d146ed 2005-07-12 devnull b[0] = a;
93 a0d146ed 2005-07-12 devnull b[0] = (b[0]*255)/a;
94 a0d146ed 2005-07-12 devnull if(b[1] >= a)
95 a0d146ed 2005-07-12 devnull b[1] = a;
96 a0d146ed 2005-07-12 devnull b[1] = (b[1]*255)/a;
97 a0d146ed 2005-07-12 devnull if(b[2] >= a)
98 a0d146ed 2005-07-12 devnull b[2] = a;
99 a0d146ed 2005-07-12 devnull b[2] = (b[2]*255)/a;
100 a0d146ed 2005-07-12 devnull }
101 a0d146ed 2005-07-12 devnull }
102 fa325e9b 2020-01-10 cross }else
103 a0d146ed 2005-07-12 devnull b += pixwid*pixels;
104 a0d146ed 2005-07-12 devnull
105 a0d146ed 2005-07-12 devnull z->x += pixels;
106 a0d146ed 2005-07-12 devnull if(z->x >= z->dx){
107 a0d146ed 2005-07-12 devnull z->x = 0;
108 a0d146ed 2005-07-12 devnull z->y++;
109 a0d146ed 2005-07-12 devnull }
110 a0d146ed 2005-07-12 devnull }
111 a0d146ed 2005-07-12 devnull return b - (uchar*)buf;
112 a0d146ed 2005-07-12 devnull }
113 a0d146ed 2005-07-12 devnull
114 a0d146ed 2005-07-12 devnull static void
115 a0d146ed 2005-07-12 devnull IDAT(ZlibW *z)
116 a0d146ed 2005-07-12 devnull {
117 a0d146ed 2005-07-12 devnull chunk(z->io, "IDAT", z->buf, z->b - z->buf);
118 a0d146ed 2005-07-12 devnull z->b = z->buf;
119 a0d146ed 2005-07-12 devnull }
120 a0d146ed 2005-07-12 devnull
121 a0d146ed 2005-07-12 devnull static int
122 a0d146ed 2005-07-12 devnull zwrite(void *va, void *buf, int n)
123 a0d146ed 2005-07-12 devnull {
124 a0d146ed 2005-07-12 devnull int m;
125 a0d146ed 2005-07-12 devnull uchar *b, *e;
126 a0d146ed 2005-07-12 devnull ZlibW *z;
127 a0d146ed 2005-07-12 devnull
128 a0d146ed 2005-07-12 devnull z = va;
129 a0d146ed 2005-07-12 devnull b = buf;
130 a0d146ed 2005-07-12 devnull e = b+n;
131 a0d146ed 2005-07-12 devnull
132 a0d146ed 2005-07-12 devnull while(b < e){
133 a0d146ed 2005-07-12 devnull m = z->e - z->b;
134 a0d146ed 2005-07-12 devnull if(m > e - b)
135 a0d146ed 2005-07-12 devnull m = e - b;
136 a0d146ed 2005-07-12 devnull memmove(z->b, b, m);
137 a0d146ed 2005-07-12 devnull z->b += m;
138 a0d146ed 2005-07-12 devnull b += m;
139 a0d146ed 2005-07-12 devnull if(z->b >= z->e)
140 a0d146ed 2005-07-12 devnull IDAT(z);
141 a0d146ed 2005-07-12 devnull }
142 a0d146ed 2005-07-12 devnull return n;
143 a0d146ed 2005-07-12 devnull }
144 a0d146ed 2005-07-12 devnull
145 a0d146ed 2005-07-12 devnull static Memimage*
146 a0d146ed 2005-07-12 devnull memRGBA(Memimage *i)
147 a0d146ed 2005-07-12 devnull {
148 a0d146ed 2005-07-12 devnull Memimage *ni;
149 a0d146ed 2005-07-12 devnull char buf[32];
150 a0d146ed 2005-07-12 devnull ulong dst;
151 fa325e9b 2020-01-10 cross
152 a0d146ed 2005-07-12 devnull /*
153 a0d146ed 2005-07-12 devnull * [A]BGR because we want R,G,B,[A] in big-endian order. Sigh.
154 a0d146ed 2005-07-12 devnull */
155 a0d146ed 2005-07-12 devnull chantostr(buf, i->chan);
156 a0d146ed 2005-07-12 devnull if(strchr(buf, 'a'))
157 a0d146ed 2005-07-12 devnull dst = ABGR32;
158 a0d146ed 2005-07-12 devnull else
159 a0d146ed 2005-07-12 devnull dst = BGR24;
160 fa325e9b 2020-01-10 cross
161 a0d146ed 2005-07-12 devnull if(i->chan == dst)
162 a0d146ed 2005-07-12 devnull return i;
163 a0d146ed 2005-07-12 devnull
164 a0d146ed 2005-07-12 devnull qlock(&memdrawlock);
165 a0d146ed 2005-07-12 devnull ni = allocmemimage(i->r, dst);
166 a0d146ed 2005-07-12 devnull if(ni)
167 a0d146ed 2005-07-12 devnull memimagedraw(ni, ni->r, i, i->r.min, nil, i->r.min, S);
168 a0d146ed 2005-07-12 devnull qunlock(&memdrawlock);
169 a0d146ed 2005-07-12 devnull return ni;
170 a0d146ed 2005-07-12 devnull }
171 a0d146ed 2005-07-12 devnull
172 a0d146ed 2005-07-12 devnull int
173 a0d146ed 2005-07-12 devnull writepng(Hio *io, Memimage *m)
174 a0d146ed 2005-07-12 devnull {
175 a0d146ed 2005-07-12 devnull static int first = 1;
176 a0d146ed 2005-07-12 devnull static QLock lk;
177 a0d146ed 2005-07-12 devnull uchar buf[200], *h;
178 a0d146ed 2005-07-12 devnull Memimage *rgb;
179 a0d146ed 2005-07-12 devnull ZlibR zr;
180 a0d146ed 2005-07-12 devnull ZlibW zw;
181 a0d146ed 2005-07-12 devnull
182 a0d146ed 2005-07-12 devnull if(first){
183 a0d146ed 2005-07-12 devnull qlock(&lk);
184 a0d146ed 2005-07-12 devnull if(first){
185 a0d146ed 2005-07-12 devnull deflateinit();
186 a0d146ed 2005-07-12 devnull crctab = mkcrctab(0xedb88320);
187 a0d146ed 2005-07-12 devnull first = 0;
188 a0d146ed 2005-07-12 devnull }
189 a0d146ed 2005-07-12 devnull qunlock(&lk);
190 a0d146ed 2005-07-12 devnull }
191 a0d146ed 2005-07-12 devnull
192 a0d146ed 2005-07-12 devnull rgb = memRGBA(m);
193 a0d146ed 2005-07-12 devnull if(rgb == nil)
194 a0d146ed 2005-07-12 devnull return -1;
195 a0d146ed 2005-07-12 devnull
196 a0d146ed 2005-07-12 devnull hwrite(io, PNGmagic, sizeof PNGmagic);
197 fa325e9b 2020-01-10 cross
198 a0d146ed 2005-07-12 devnull /* IHDR chunk */
199 a0d146ed 2005-07-12 devnull h = buf;
200 a0d146ed 2005-07-12 devnull put4(h, Dx(m->r)); h += 4;
201 a0d146ed 2005-07-12 devnull put4(h, Dy(m->r)); h += 4;
202 a0d146ed 2005-07-12 devnull *h++ = 8; /* 8 bits per channel */
203 a0d146ed 2005-07-12 devnull if(rgb->chan == BGR24)
204 a0d146ed 2005-07-12 devnull *h++ = 2; /* RGB */
205 a0d146ed 2005-07-12 devnull else
206 a0d146ed 2005-07-12 devnull *h++ = 6; /* RGBA */
207 a0d146ed 2005-07-12 devnull *h++ = 0; /* compression - deflate */
208 a0d146ed 2005-07-12 devnull *h++ = 0; /* filter - none */
209 a0d146ed 2005-07-12 devnull *h++ = 0; /* interlace - none */
210 a0d146ed 2005-07-12 devnull chunk(io, "IHDR", buf, h-buf);
211 a0d146ed 2005-07-12 devnull
212 a0d146ed 2005-07-12 devnull /* image data */
213 a0d146ed 2005-07-12 devnull zr.dx = Dx(m->r);
214 a0d146ed 2005-07-12 devnull zr.dy = Dy(m->r);
215 4a8c0c75 2017-07-23 0intro zr.width = rgb->width * sizeof(u32int);
216 a0d146ed 2005-07-12 devnull zr.data = rgb->data->bdata;
217 a0d146ed 2005-07-12 devnull zr.x = 0;
218 a0d146ed 2005-07-12 devnull zr.y = 0;
219 a0d146ed 2005-07-12 devnull zr.pixwid = chantodepth(rgb->chan)/8;
220 a0d146ed 2005-07-12 devnull zw.io = io;
221 a0d146ed 2005-07-12 devnull zw.buf = vtmalloc(IDATSIZE);
222 a0d146ed 2005-07-12 devnull zw.b = zw.buf;
223 a0d146ed 2005-07-12 devnull zw.e = zw.b + IDATSIZE;
224 a0d146ed 2005-07-12 devnull if(deflatezlib(&zw, zwrite, &zr, zread, 6, 0) < 0){
225 a0d146ed 2005-07-12 devnull free(zw.buf);
226 a0d146ed 2005-07-12 devnull return -1;
227 a0d146ed 2005-07-12 devnull }
228 a0d146ed 2005-07-12 devnull if(zw.b > zw.buf)
229 a0d146ed 2005-07-12 devnull IDAT(&zw);
230 a0d146ed 2005-07-12 devnull free(zw.buf);
231 a0d146ed 2005-07-12 devnull chunk(io, "IEND", nil, 0);
232 a0d146ed 2005-07-12 devnull
233 a0d146ed 2005-07-12 devnull if(m != rgb){
234 a0d146ed 2005-07-12 devnull qlock(&memdrawlock);
235 a0d146ed 2005-07-12 devnull freememimage(rgb);
236 a0d146ed 2005-07-12 devnull qunlock(&memdrawlock);
237 a0d146ed 2005-07-12 devnull }
238 a0d146ed 2005-07-12 devnull return 0;
239 a0d146ed 2005-07-12 devnull }