Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <memdraw.h>
5
#include <bio.h>
6
 
7
#define	MAXLINE	70
8
 
9
/* imported from libdraw/arith.c to permit an extern log2 function */
10
static int log2[] = {
11
	-1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4,
12
	-1, -1, -1, -1, -1, -1, -1, 4 /* BUG */, -1, -1, -1, -1, -1, -1, -1, 5
13
};
14
 
15
/*
16
 * Write data
17
 */
18
static
19
char*
20
writedata(Biobuf *fd, Image *image, Memimage *memimage)
21
{
22
	char *err;
23
	uchar *data;
24
	int i, x, y, ndata, depth, col, pix, xmask, pmask;
25
	ulong chan;
26
	Rectangle r;
27
 
28
	if(memimage != nil){
29
		r = memimage->r;
30
		depth = memimage->depth;
31
		chan = memimage->chan;
32
	}else{
33
		r = image->r;
34
		depth = image->depth;
35
		chan = image->chan;
36
	}
37
 
38
	/* 
39
	 * Read image data into memory
40
	 * potentially one extra byte on each end of each scan line
41
	 */
42
	ndata = Dy(r)*(2+Dx(r)*depth/8);
43
	data = malloc(ndata);
44
	if(data == nil)
45
		return "WritePPM: malloc failed";
46
	if(memimage != nil)
47
		ndata = unloadmemimage(memimage, r, data, ndata);
48
	else
49
		ndata = unloadimage(image, r, data, ndata);
50
	if(ndata < 0){
51
		err = malloc(ERRMAX);
52
		if(err == nil)
53
			return "WritePPM: malloc failed";
54
		snprint(err, ERRMAX, "WriteGIF: %r");
55
		free(data);
56
		return err;
57
	}
58
 
59
	/* Encode and emit the data */
60
	col = 0;
61
	switch(chan){
62
	case GREY1:
63
	case GREY2:
64
	case GREY4:
65
		pmask = (1<<depth)-1;
66
		xmask = 7>>log2[depth];
67
		for(y=r.min.y; y<r.max.y; y++){
68
			i = (y-r.min.y)*bytesperline(r, depth);
69
			for(x=r.min.x; x<r.max.x; x++){
70
				pix = (data[i]>>depth*((xmask-x)&xmask))&pmask;
71
				if(((x+1)&xmask) == 0)
72
					i++;
73
				col += Bprint(fd, "%d ", pix);
74
				if(col >= MAXLINE-(2+1)){
75
					Bprint(fd, "\n");
76
					col = 0;
77
				}else
78
					col += Bprint(fd, " ");
79
			}
80
		}
81
		break;
82
	case	GREY8:
83
		for(i=0; i<ndata; i++){
84
			col += Bprint(fd, "%d ", data[i]);
85
			if(col >= MAXLINE-(4+1)){
86
				Bprint(fd, "\n");
87
				col = 0;
88
			}else
89
				col += Bprint(fd, " ");
90
		}
91
		break;
92
	case RGB24:
93
		for(i=0; i<ndata; i+=3){
94
			col += Bprint(fd, "%d %d %d", data[i+2], data[i+1], data[i]);
95
			if(col >= MAXLINE-(4+4+4+1)){
96
				Bprint(fd, "\n");
97
				col = 0;
98
			}else
99
				col += Bprint(fd, " ");
100
		}
101
		break;
102
	default:
103
		return "WritePPM: can't handle channel type";
104
	}
105
 
106
	return nil;
107
}
108
 
109
static
110
char*
111
writeppm0(Biobuf *fd, Image *image, Memimage *memimage, Rectangle r, int chan, char *comment)
112
{
113
	char *err;
114
 
115
	switch(chan){
116
	case GREY1:
117
		Bprint(fd, "P1\n");
118
		break;
119
	case GREY2:
120
	case GREY4:
121
	case	GREY8:
122
		Bprint(fd, "P2\n");
123
		break;
124
	case RGB24:
125
		Bprint(fd, "P3\n");
126
		break;
127
	default:
128
		return "WritePPM: can't handle channel type";
129
	}
130
 
131
	if(comment!=nil && comment[0]!='\0'){
132
		Bprint(fd, "# %s", comment);
133
		if(comment[strlen(comment)-1] != '\n')
134
			Bprint(fd, "\n");
135
	}
136
	Bprint(fd, "%d %d\n", Dx(r), Dy(r));
137
 
138
	/* maximum pixel value */
139
	switch(chan){
140
	case GREY2:
141
		Bprint(fd, "%d\n", 3);
142
		break;
143
	case GREY4:
144
		Bprint(fd, "%d\n", 15);
145
		break;
146
	case	GREY8:
147
	case RGB24:
148
		Bprint(fd, "%d\n", 255);
149
		break;
150
	}
151
 
152
	err = writedata(fd, image, memimage);
153
 
154
	Bprint(fd, "\n");
155
	Bflush(fd);
156
	return err;
157
}
158
 
159
char*
160
writeppm(Biobuf *fd, Image *image, char *comment)
161
{
162
	return writeppm0(fd, image, nil, image->r, image->chan, comment);
163
}
164
 
165
char*
166
memwriteppm(Biobuf *fd, Memimage *memimage, char *comment)
167
{
168
	return writeppm0(fd, nil, memimage, memimage->r, memimage->chan, comment);
169
}