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"
7 a0d146ed 2005-07-12 devnull IDATSIZE = 20000,
8 a0d146ed 2005-07-12 devnull FilterNone = 0
11 a0d146ed 2005-07-12 devnull typedef struct ZlibR ZlibR;
12 a0d146ed 2005-07-12 devnull typedef struct ZlibW ZlibW;
14 a0d146ed 2005-07-12 devnull struct ZlibR
16 a0d146ed 2005-07-12 devnull uchar *data;
17 a0d146ed 2005-07-12 devnull int width;
22 a0d146ed 2005-07-12 devnull int pixwid;
25 a0d146ed 2005-07-12 devnull struct ZlibW
28 a0d146ed 2005-07-12 devnull uchar *buf;
29 a0d146ed 2005-07-12 devnull uchar *b;
30 a0d146ed 2005-07-12 devnull uchar *e;
33 a0d146ed 2005-07-12 devnull static ulong *crctab;
34 a0d146ed 2005-07-12 devnull static uchar PNGmagic[] = { 137, 'P', 'N', 'G', '\r', '\n', 26, '\n'};
36 a0d146ed 2005-07-12 devnull static void
37 a0d146ed 2005-07-12 devnull put4(uchar *a, ulong v)
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;
45 a0d146ed 2005-07-12 devnull static void
46 a0d146ed 2005-07-12 devnull chunk(Hio *io, char *type, uchar *d, int n)
48 a0d146ed 2005-07-12 devnull uchar buf[4];
49 a0d146ed 2005-07-12 devnull ulong crc = 0;
51 a0d146ed 2005-07-12 devnull if(strlen(type) != 4)
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);
63 a0d146ed 2005-07-12 devnull static int
64 a0d146ed 2005-07-12 devnull zread(void *va, void *buf, int n)
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;
71 a0d146ed 2005-07-12 devnull pixwid = z->pixwid;
74 a0d146ed 2005-07-12 devnull while(b+pixwid <= e){
75 a0d146ed 2005-07-12 devnull if(z->y >= z->dy)
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){
86 a0d146ed 2005-07-12 devnull * Convert to non-premultiplied alpha.
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;
103 a0d146ed 2005-07-12 devnull b += pixwid*pixels;
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;
111 a0d146ed 2005-07-12 devnull return b - (uchar*)buf;
114 a0d146ed 2005-07-12 devnull static void
115 a0d146ed 2005-07-12 devnull IDAT(ZlibW *z)
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;
121 a0d146ed 2005-07-12 devnull static int
122 a0d146ed 2005-07-12 devnull zwrite(void *va, void *buf, int n)
125 a0d146ed 2005-07-12 devnull uchar *b, *e;
126 a0d146ed 2005-07-12 devnull ZlibW *z;
129 a0d146ed 2005-07-12 devnull b = buf;
130 a0d146ed 2005-07-12 devnull e = b+n;
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;
139 a0d146ed 2005-07-12 devnull if(z->b >= z->e)
140 a0d146ed 2005-07-12 devnull IDAT(z);
142 a0d146ed 2005-07-12 devnull return n;
145 a0d146ed 2005-07-12 devnull static Memimage*
146 a0d146ed 2005-07-12 devnull memRGBA(Memimage *i)
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;
153 a0d146ed 2005-07-12 devnull * [A]BGR because we want R,G,B,[A] in big-endian order. Sigh.
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;
159 a0d146ed 2005-07-12 devnull dst = BGR24;
161 a0d146ed 2005-07-12 devnull if(i->chan == dst)
162 a0d146ed 2005-07-12 devnull return i;
164 a0d146ed 2005-07-12 devnull qlock(&memdrawlock);
165 a0d146ed 2005-07-12 devnull ni = allocmemimage(i->r, dst);
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;
173 a0d146ed 2005-07-12 devnull writepng(Hio *io, Memimage *m)
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;
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;
189 a0d146ed 2005-07-12 devnull qunlock(&lk);
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;
196 a0d146ed 2005-07-12 devnull hwrite(io, PNGmagic, sizeof PNGmagic);
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 */
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);
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 a0d146ed 2005-07-12 devnull zr.width = rgb->width * sizeof(ulong);
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;
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);
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);
238 a0d146ed 2005-07-12 devnull return 0;