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
#include "imagefile.h"
7
 
8
/* Convert image to a single channel, one byte per pixel */
9
 
10
static
11
int
12
notrans(ulong chan)
13
{
14
	switch(chan){
15
	case GREY1:
16
	case GREY2:
17
	case GREY4:
18
	case	CMAP8:
19
	case GREY8:
20
		return 1;
21
	}
22
	return 0;
23
}
24
 
25
static
26
int
27
easycase(ulong chan)
28
{
29
	switch(chan){
30
	case RGB16:
31
	case RGB24:
32
	case RGBA32:
33
	case ARGB32:
34
		return 1;
35
	}
36
	return 0;
37
}
38
 
39
/*
40
 * Convert to one byte per pixel, RGBV or grey, depending
41
 */
42
 
43
static
44
uchar*
45
load(Image *image, Memimage *memimage)
46
{
47
	uchar *data, *p, *q0, *q1, *q2;
48
	uchar *rgbv;
49
	int depth, ndata, dx, dy, i, v;
50
	ulong chan, pixel;
51
	Rectangle r;
52
	Rawimage ri, *nri;
53
 
54
	if(memimage == nil){
55
		r = image->r;
56
		depth = image->depth;
57
		chan = image->chan;
58
	}else{
59
		r = memimage->r;
60
		depth = memimage->depth;
61
		chan = memimage->chan;
62
	}
63
	dx = Dx(r);
64
	dy = Dy(r);
65
 
66
	/* 
67
	 * Read image data into memory
68
	 * potentially one extra byte on each end of each scan line.
69
	 */
70
	ndata = dy*(2+bytesperline(r, depth));
71
	data = malloc(ndata);
72
	if(data == nil)
73
		return nil;
74
	if(memimage != nil)
75
		ndata = unloadmemimage(memimage, r, data, ndata);
76
	else
77
		ndata = unloadimage(image, r, data, ndata);
78
	if(ndata < 0){
79
		werrstr("onechan: %r");
80
		free(data);
81
		return nil;
82
	}
83
 
84
	/*
85
	 * Repack
86
	 */
87
	memset(&ri, 0, sizeof(ri));
88
	ri.r = r;
89
	ri.cmap = nil;
90
	ri.cmaplen = 0;
91
	ri.nchans = 3;
92
	ri.chanlen = dx*dy;
93
	ri.chans[0] = malloc(ri.chanlen);
94
	ri.chans[1] = malloc(ri.chanlen);
95
	ri.chans[2] = malloc(ri.chanlen);
96
	if(ri.chans[0]==nil || ri.chans[1]==nil || ri.chans[2]==nil){
97
    Err:
98
		free(ri.chans[0]);
99
		free(ri.chans[1]);
100
		free(ri.chans[2]);
101
		free(data);
102
		return nil;
103
	}
104
	ri.chandesc = CRGB;
105
 
106
	p = data;
107
	q0 = ri.chans[0];
108
	q1 = ri.chans[1];
109
	q2 = ri.chans[2];
110
 
111
	switch(chan){
112
	default:
113
		werrstr("can't handle image type 0x%lux", chan);
114
		goto Err;
115
	case RGB16:
116
		for(i=0; i<ri.chanlen; i++, p+=2){
117
			pixel = (p[1]<<8)|p[0];	/* rrrrrggg gggbbbbb */
118
			v = (pixel & 0xF800) >> 8;
119
			*q0++ = v | (v>>5);
120
			v = (pixel & 0x07E0) >> 3;
121
			*q1++ = v | (v>>6);
122
			v = (pixel & 0x001F) << 3;
123
			*q2++ = v | (v>>5);
124
		}
125
		break;
126
	case RGB24:
127
		for(i=0; i<ri.chanlen; i++){
128
			*q2++ = *p++;
129
			*q1++ = *p++;
130
			*q0++ = *p++;
131
		}
132
		break;
133
	case RGBA32:
134
		for(i=0; i<ri.chanlen; i++){
135
			*q2++ = *p++;
136
			*q1++ = *p++;
137
			*q0++ = *p++;
138
			p++;
139
		}
140
		break;
141
	case ARGB32:
142
		for(i=0; i<ri.chanlen; i++){
143
			p++;
144
			*q2++ = *p++;
145
			*q1++ = *p++;
146
			*q0++ = *p++;
147
		}
148
		break;
149
	}
150
 
151
	rgbv = nil;
152
	nri = torgbv(&ri, 1);
153
	if(nri != nil){
154
		rgbv = nri->chans[0];
155
		free(nri);
156
	}
157
 
158
	free(ri.chans[0]);
159
	free(ri.chans[1]);
160
	free(ri.chans[2]);
161
	free(data);
162
	return rgbv;
163
}
164
 
165
Image*
166
onechan(Image *i)
167
{
168
	uchar *data;
169
	Image *ni;
170
 
171
	if(notrans(i->chan))
172
		return i;
173
 
174
	if(easycase(i->chan))
175
		data = load(i, nil);
176
	else{
177
		ni = allocimage(display, i->r, RGB24, 0, DNofill);
178
		if(ni == nil)
179
			return ni;
180
		draw(ni, ni->r, i, nil, i->r.min);
181
		data = load(ni, nil);
182
		freeimage(ni);
183
	}
184
 
185
	if(data == nil)
186
		return nil;
187
 
188
	ni = allocimage(display, i->r, CMAP8, 0, DNofill);
189
	if(ni != nil)
190
		if(loadimage(ni, ni->r, data, Dx(ni->r)*Dy(ni->r)) < 0){
191
			freeimage(ni);
192
			ni = nil;
193
		}
194
	free(data);
195
	return ni;
196
}
197
 
198
Memimage*
199
memonechan(Memimage *i)
200
{
201
	uchar *data;
202
	Memimage *ni;
203
 
204
	if(notrans(i->chan))
205
		return i;
206
 
207
	if(easycase(i->chan))
208
		data = load(nil, i);
209
	else{
210
		ni = allocmemimage(i->r, RGB24);
211
		if(ni == nil)
212
			return ni;
213
		memimagedraw(ni, ni->r, i, i->r.min, nil, ZP, S);
214
		data = load(nil, ni);
215
		freememimage(ni);
216
	}
217
 
218
	if(data == nil)
219
		return nil;
220
 
221
	ni = allocmemimage(i->r, CMAP8);
222
	if(ni != nil)
223
		if(loadmemimage(ni, ni->r, data, Dx(ni->r)*Dy(ni->r)) < 0){
224
			freememimage(ni);
225
			ni = nil;
226
		}
227
	free(data);
228
	return ni;
229
}