Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/venti/srv/png.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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