Blame


1 28994509 2004-04-21 devnull #include <u.h>
2 28994509 2004-04-21 devnull #include <libc.h>
3 28994509 2004-04-21 devnull #include <bio.h>
4 28994509 2004-04-21 devnull #include <draw.h>
5 28994509 2004-04-21 devnull
6 28994509 2004-04-21 devnull enum
7 28994509 2004-04-21 devnull {
8 28994509 2004-04-21 devnull FileHdrLen= 6,
9 28994509 2004-04-21 devnull IconDescrLen= 16,
10 cbeb0b26 2006-04-01 devnull IconHdrLen= 40
11 28994509 2004-04-21 devnull };
12 28994509 2004-04-21 devnull
13 28994509 2004-04-21 devnull typedef struct Icon Icon;
14 28994509 2004-04-21 devnull struct Icon
15 28994509 2004-04-21 devnull {
16 28994509 2004-04-21 devnull Icon *next;
17 28994509 2004-04-21 devnull char *file;
18 28994509 2004-04-21 devnull
19 28994509 2004-04-21 devnull uchar w; /* icon width */
20 28994509 2004-04-21 devnull uchar h; /* icon height */
21 28994509 2004-04-21 devnull ushort ncolor; /* number of colors */
22 28994509 2004-04-21 devnull ushort nplane; /* number of bit planes */
23 28994509 2004-04-21 devnull ushort bits; /* bits per pixel */
24 28994509 2004-04-21 devnull ulong len; /* length of data */
25 28994509 2004-04-21 devnull ulong offset; /* file offset to data */
26 28994509 2004-04-21 devnull uchar map[4*256]; /* color map */
27 28994509 2004-04-21 devnull
28 28994509 2004-04-21 devnull Image *img;
29 28994509 2004-04-21 devnull
30 28994509 2004-04-21 devnull uchar *xor;
31 28994509 2004-04-21 devnull int xorlen;
32 28994509 2004-04-21 devnull uchar *and;
33 28994509 2004-04-21 devnull int andlen;
34 28994509 2004-04-21 devnull };
35 28994509 2004-04-21 devnull
36 28994509 2004-04-21 devnull typedef struct Header Header;
37 28994509 2004-04-21 devnull struct Header
38 28994509 2004-04-21 devnull {
39 28994509 2004-04-21 devnull uint n;
40 28994509 2004-04-21 devnull Icon *first;
41 28994509 2004-04-21 devnull Icon *last;
42 28994509 2004-04-21 devnull };
43 28994509 2004-04-21 devnull
44 28994509 2004-04-21 devnull void
45 28994509 2004-04-21 devnull Bputs(Biobuf *b, ushort x)
46 28994509 2004-04-21 devnull {
47 28994509 2004-04-21 devnull Bputc(b, x&0xff);
48 28994509 2004-04-21 devnull Bputc(b, x>>8);
49 28994509 2004-04-21 devnull }
50 28994509 2004-04-21 devnull
51 28994509 2004-04-21 devnull void
52 28994509 2004-04-21 devnull Bputl(Biobuf *b, ulong x)
53 28994509 2004-04-21 devnull {
54 28994509 2004-04-21 devnull Bputs(b, x&0xffff);
55 28994509 2004-04-21 devnull Bputs(b, x>>16);
56 28994509 2004-04-21 devnull }
57 28994509 2004-04-21 devnull
58 28994509 2004-04-21 devnull Header h;
59 28994509 2004-04-21 devnull
60 28994509 2004-04-21 devnull void* emalloc(int);
61 28994509 2004-04-21 devnull void mk8bit(Icon*, int);
62 28994509 2004-04-21 devnull void mkxorand(Icon*, int);
63 28994509 2004-04-21 devnull void readicon(char*);
64 28994509 2004-04-21 devnull
65 28994509 2004-04-21 devnull void
66 28994509 2004-04-21 devnull main(int argc, char **argv)
67 28994509 2004-04-21 devnull {
68 28994509 2004-04-21 devnull int i;
69 28994509 2004-04-21 devnull Biobuf *b, out;
70 28994509 2004-04-21 devnull Icon *icon;
71 28994509 2004-04-21 devnull ulong offset;
72 28994509 2004-04-21 devnull ulong len;
73 28994509 2004-04-21 devnull
74 28994509 2004-04-21 devnull ARGBEGIN{
75 28994509 2004-04-21 devnull }ARGEND;
76 28994509 2004-04-21 devnull
77 28994509 2004-04-21 devnull /* read in all the images */
78 a8763864 2004-07-09 devnull initdraw(0, nil, nil);
79 28994509 2004-04-21 devnull if(argc < 1){
80 d159da84 2005-11-12 devnull readicon("/dev/stdin");
81 28994509 2004-04-21 devnull } else {
82 28994509 2004-04-21 devnull for(i = 0; i < argc; i++)
83 28994509 2004-04-21 devnull readicon(argv[i]);
84 28994509 2004-04-21 devnull }
85 28994509 2004-04-21 devnull
86 28994509 2004-04-21 devnull /* create the .ico file */
87 28994509 2004-04-21 devnull b = &out;
88 28994509 2004-04-21 devnull Binit(b, 1, OWRITE);
89 28994509 2004-04-21 devnull
90 28994509 2004-04-21 devnull /* offset to first icon */
91 28994509 2004-04-21 devnull offset = FileHdrLen + h.n*IconDescrLen;
92 28994509 2004-04-21 devnull
93 28994509 2004-04-21 devnull /* file header is */
94 28994509 2004-04-21 devnull Bputs(b, 0);
95 28994509 2004-04-21 devnull Bputs(b, 1);
96 28994509 2004-04-21 devnull Bputs(b, h.n);
97 28994509 2004-04-21 devnull
98 28994509 2004-04-21 devnull /* icon description */
99 28994509 2004-04-21 devnull for(icon = h.first; icon != nil; icon = icon->next){
100 28994509 2004-04-21 devnull Bputc(b, icon->w);
101 28994509 2004-04-21 devnull Bputc(b, icon->h);
102 28994509 2004-04-21 devnull Bputc(b, icon->ncolor);
103 28994509 2004-04-21 devnull Bputc(b, 0);
104 28994509 2004-04-21 devnull Bputs(b, icon->nplane);
105 28994509 2004-04-21 devnull Bputs(b, icon->bits);
106 28994509 2004-04-21 devnull len = IconHdrLen + icon->ncolor*4 + icon->xorlen + icon->andlen;
107 28994509 2004-04-21 devnull Bputl(b, len);
108 28994509 2004-04-21 devnull Bputl(b, offset);
109 28994509 2004-04-21 devnull offset += len;
110 28994509 2004-04-21 devnull }
111 28994509 2004-04-21 devnull
112 28994509 2004-04-21 devnull /* icons */
113 28994509 2004-04-21 devnull for(icon = h.first; icon != nil; icon = icon->next){
114 28994509 2004-04-21 devnull /* icon header (BMP like) */
115 28994509 2004-04-21 devnull Bputl(b, IconHdrLen);
116 28994509 2004-04-21 devnull Bputl(b, icon->w);
117 28994509 2004-04-21 devnull Bputl(b, 2*icon->h);
118 28994509 2004-04-21 devnull Bputs(b, icon->nplane);
119 28994509 2004-04-21 devnull Bputs(b, icon->bits);
120 28994509 2004-04-21 devnull Bputl(b, 0); /* compression info */
121 28994509 2004-04-21 devnull Bputl(b, 0);
122 28994509 2004-04-21 devnull Bputl(b, 0);
123 28994509 2004-04-21 devnull Bputl(b, 0);
124 28994509 2004-04-21 devnull Bputl(b, 0);
125 28994509 2004-04-21 devnull Bputl(b, 0);
126 28994509 2004-04-21 devnull
127 28994509 2004-04-21 devnull /* color map */
128 28994509 2004-04-21 devnull if(Bwrite(b, icon->map, 4*icon->ncolor) < 0)
129 28994509 2004-04-21 devnull sysfatal("writing color map: %r");
130 28994509 2004-04-21 devnull
131 28994509 2004-04-21 devnull /* xor bits */
132 28994509 2004-04-21 devnull if(Bwrite(b, icon->xor, icon->xorlen) < 0)
133 28994509 2004-04-21 devnull sysfatal("writing xor bits: %r");
134 28994509 2004-04-21 devnull
135 28994509 2004-04-21 devnull /* and bits */
136 28994509 2004-04-21 devnull if(Bwrite(b, icon->and, icon->andlen) < 0)
137 28994509 2004-04-21 devnull sysfatal("writing and bits: %r");
138 28994509 2004-04-21 devnull }
139 28994509 2004-04-21 devnull
140 28994509 2004-04-21 devnull Bterm(b);
141 28994509 2004-04-21 devnull exits(0);
142 28994509 2004-04-21 devnull }
143 28994509 2004-04-21 devnull
144 28994509 2004-04-21 devnull void
145 28994509 2004-04-21 devnull readicon(char *file)
146 28994509 2004-04-21 devnull {
147 28994509 2004-04-21 devnull int fd;
148 28994509 2004-04-21 devnull Icon *icon;
149 28994509 2004-04-21 devnull
150 28994509 2004-04-21 devnull fd = open(file, OREAD);
151 28994509 2004-04-21 devnull if(fd < 0)
152 28994509 2004-04-21 devnull sysfatal("opening %s: %r", file);
153 28994509 2004-04-21 devnull icon = emalloc(sizeof(Icon));
154 28994509 2004-04-21 devnull icon->img = readimage(display, fd, 0);
155 28994509 2004-04-21 devnull if(icon->img == nil)
156 28994509 2004-04-21 devnull sysfatal("reading image %s: %r", file);
157 28994509 2004-04-21 devnull close(fd);
158 28994509 2004-04-21 devnull
159 28994509 2004-04-21 devnull if(h.first)
160 28994509 2004-04-21 devnull h.last->next = icon;
161 28994509 2004-04-21 devnull else
162 28994509 2004-04-21 devnull h.first = icon;
163 28994509 2004-04-21 devnull h.last = icon;
164 28994509 2004-04-21 devnull h.n++;
165 28994509 2004-04-21 devnull
166 28994509 2004-04-21 devnull icon->h = Dy(icon->img->r);
167 28994509 2004-04-21 devnull icon->w = Dx(icon->img->r);
168 28994509 2004-04-21 devnull icon->bits = 1<<icon->img->depth;
169 28994509 2004-04-21 devnull icon->nplane = 1;
170 28994509 2004-04-21 devnull
171 28994509 2004-04-21 devnull /* convert to 8 bits per pixel */
172 28994509 2004-04-21 devnull switch(icon->img->chan){
173 28994509 2004-04-21 devnull case GREY8:
174 28994509 2004-04-21 devnull case CMAP8:
175 28994509 2004-04-21 devnull break;
176 28994509 2004-04-21 devnull case GREY1:
177 28994509 2004-04-21 devnull case GREY2:
178 28994509 2004-04-21 devnull case GREY4:
179 28994509 2004-04-21 devnull mk8bit(icon, 1);
180 28994509 2004-04-21 devnull break;
181 28994509 2004-04-21 devnull default:
182 28994509 2004-04-21 devnull mk8bit(icon, 0);
183 28994509 2004-04-21 devnull break;
184 28994509 2004-04-21 devnull }
185 28994509 2004-04-21 devnull icon->bits = 8;
186 28994509 2004-04-21 devnull icon->file = file;
187 28994509 2004-04-21 devnull
188 28994509 2004-04-21 devnull /* create xor/and masks, minimizing bits per pixel */
189 28994509 2004-04-21 devnull mkxorand(icon, icon->img->chan == GREY8);
190 28994509 2004-04-21 devnull }
191 28994509 2004-04-21 devnull
192 28994509 2004-04-21 devnull void*
193 28994509 2004-04-21 devnull emalloc(int len)
194 28994509 2004-04-21 devnull {
195 28994509 2004-04-21 devnull void *x;
196 28994509 2004-04-21 devnull
197 28994509 2004-04-21 devnull x = mallocz(len, 1);
198 28994509 2004-04-21 devnull if(x == nil)
199 28994509 2004-04-21 devnull sysfatal("memory: %r");
200 28994509 2004-04-21 devnull return x;
201 28994509 2004-04-21 devnull }
202 28994509 2004-04-21 devnull
203 28994509 2004-04-21 devnull /* convert to 8 bit */
204 28994509 2004-04-21 devnull void
205 28994509 2004-04-21 devnull mk8bit(Icon *icon, int grey)
206 28994509 2004-04-21 devnull {
207 28994509 2004-04-21 devnull Image *img;
208 28994509 2004-04-21 devnull
209 28994509 2004-04-21 devnull img = allocimage(display, icon->img->r, grey ? GREY8 : CMAP8, 0, DNofill);
210 28994509 2004-04-21 devnull if(img == nil)
211 28994509 2004-04-21 devnull sysfatal("can't allocimage: %r");
212 28994509 2004-04-21 devnull draw(img, img->r, icon->img, nil, ZP);
213 28994509 2004-04-21 devnull freeimage(icon->img);
214 28994509 2004-04-21 devnull icon->img = img;
215 28994509 2004-04-21 devnull }
216 28994509 2004-04-21 devnull
217 28994509 2004-04-21 devnull /* make xor and and mask */
218 28994509 2004-04-21 devnull void
219 28994509 2004-04-21 devnull mkxorand(Icon *icon, int grey)
220 28994509 2004-04-21 devnull {
221 28994509 2004-04-21 devnull int i, x, y, s, sa;
222 28994509 2004-04-21 devnull uchar xx[256];
223 28994509 2004-04-21 devnull uchar *data, *p, *e;
224 28994509 2004-04-21 devnull int ndata;
225 28994509 2004-04-21 devnull uchar *mp;
226 28994509 2004-04-21 devnull int ncolor;
227 28994509 2004-04-21 devnull ulong color;
228 28994509 2004-04-21 devnull int bits;
229 28994509 2004-04-21 devnull uchar andbyte, xorbyte;
230 28994509 2004-04-21 devnull uchar *ato, *xto;
231 28994509 2004-04-21 devnull int xorrl, andrl;
232 28994509 2004-04-21 devnull
233 28994509 2004-04-21 devnull ndata = icon->h * icon->w;
234 28994509 2004-04-21 devnull data = emalloc(ndata);
235 28994509 2004-04-21 devnull if(unloadimage(icon->img, icon->img->r, data, ndata) < 0)
236 28994509 2004-04-21 devnull sysfatal("can't unload %s: %r", icon->file);
237 28994509 2004-04-21 devnull e = data + ndata;
238 28994509 2004-04-21 devnull
239 28994509 2004-04-21 devnull /* find colors used */
240 28994509 2004-04-21 devnull memset(xx, 0, sizeof xx);
241 28994509 2004-04-21 devnull for(p = data; p < e; p++)
242 28994509 2004-04-21 devnull xx[*p]++;
243 28994509 2004-04-21 devnull
244 28994509 2004-04-21 devnull /* count the colors and create a mapping from plan 9 */
245 28994509 2004-04-21 devnull mp = icon->map;
246 28994509 2004-04-21 devnull ncolor = 0;
247 28994509 2004-04-21 devnull for(i = 0; i < 256; i++){
248 28994509 2004-04-21 devnull if(xx[i] == 0)
249 28994509 2004-04-21 devnull continue;
250 28994509 2004-04-21 devnull if(grey){
251 28994509 2004-04-21 devnull *mp++ = i;
252 28994509 2004-04-21 devnull *mp++ = i;
253 28994509 2004-04-21 devnull *mp++ = i;
254 28994509 2004-04-21 devnull *mp++ = 0;
255 28994509 2004-04-21 devnull } else {
256 28994509 2004-04-21 devnull color = cmap2rgb(i);
257 28994509 2004-04-21 devnull *mp++ = color;
258 28994509 2004-04-21 devnull *mp++ = color>>8;
259 28994509 2004-04-21 devnull *mp++ = color>>16;
260 28994509 2004-04-21 devnull *mp++ = 0;
261 28994509 2004-04-21 devnull }
262 28994509 2004-04-21 devnull xx[i] = ncolor;
263 28994509 2004-04-21 devnull ncolor++;
264 28994509 2004-04-21 devnull }
265 28994509 2004-04-21 devnull
266 28994509 2004-04-21 devnull /* get minimum number of pixels per bit (with a color map) */
267 28994509 2004-04-21 devnull if(ncolor <= 2){
268 28994509 2004-04-21 devnull ncolor = 2;
269 28994509 2004-04-21 devnull bits = 1;
270 28994509 2004-04-21 devnull } else if(ncolor <= 4){
271 28994509 2004-04-21 devnull ncolor = 4;
272 28994509 2004-04-21 devnull bits = 2;
273 28994509 2004-04-21 devnull } else if(ncolor <= 16){
274 28994509 2004-04-21 devnull ncolor = 16;
275 28994509 2004-04-21 devnull bits = 4;
276 28994509 2004-04-21 devnull } else {
277 28994509 2004-04-21 devnull ncolor = 256;
278 28994509 2004-04-21 devnull bits = 8;
279 28994509 2004-04-21 devnull }
280 28994509 2004-04-21 devnull icon->bits = bits;
281 28994509 2004-04-21 devnull icon->ncolor = ncolor;
282 28994509 2004-04-21 devnull
283 28994509 2004-04-21 devnull /* the xor mask rows are justified to a 32 bit boundary */
284 28994509 2004-04-21 devnull /* the and mask is 1 bit grey */
285 28994509 2004-04-21 devnull xorrl = 4*((bits*icon->w + 31)/32);
286 28994509 2004-04-21 devnull andrl = 4*((icon->w + 31)/32);
287 28994509 2004-04-21 devnull icon->xor = emalloc(xorrl * icon->h);
288 28994509 2004-04-21 devnull icon->and = emalloc(andrl * icon->h);
289 28994509 2004-04-21 devnull icon->xorlen = xorrl*icon->h;
290 28994509 2004-04-21 devnull icon->andlen = andrl*icon->h;
291 28994509 2004-04-21 devnull
292 28994509 2004-04-21 devnull /* make both masks. they're upside down relative to plan9 ones */
293 28994509 2004-04-21 devnull p = data;
294 28994509 2004-04-21 devnull for(y = 0; y < icon->h; y++){
295 28994509 2004-04-21 devnull andbyte = 0;
296 28994509 2004-04-21 devnull xorbyte = 0;
297 28994509 2004-04-21 devnull sa = s = 0;
298 28994509 2004-04-21 devnull xto = icon->xor + (icon->h-1-y)*xorrl;
299 28994509 2004-04-21 devnull ato = icon->and + (icon->h-1-y)*andrl;
300 28994509 2004-04-21 devnull for(x = 0; x < icon->w; x++){
301 28994509 2004-04-21 devnull xorbyte <<= bits;
302 28994509 2004-04-21 devnull xorbyte |= xx[*p];
303 28994509 2004-04-21 devnull s += bits;
304 28994509 2004-04-21 devnull if(s == 8){
305 28994509 2004-04-21 devnull *xto++ = xorbyte;
306 28994509 2004-04-21 devnull xorbyte = 0;
307 28994509 2004-04-21 devnull s = 0;
308 28994509 2004-04-21 devnull }
309 28994509 2004-04-21 devnull andbyte <<= 1;
310 28994509 2004-04-21 devnull if(*p == 0xff)
311 28994509 2004-04-21 devnull andbyte |= 1;
312 28994509 2004-04-21 devnull sa++;
313 28994509 2004-04-21 devnull if(sa == 0){
314 28994509 2004-04-21 devnull *ato++ = andbyte;
315 28994509 2004-04-21 devnull sa = 0;
316 28994509 2004-04-21 devnull andbyte = 0;
317 28994509 2004-04-21 devnull }
318 28994509 2004-04-21 devnull p++;
319 28994509 2004-04-21 devnull }
320 28994509 2004-04-21 devnull }
321 28994509 2004-04-21 devnull free(data);
322 28994509 2004-04-21 devnull }