xref: /plan9/sys/src/cmd/unix/drawterm/libmemdraw/cread.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <draw.h>
4*8ccd4a63SDavid du Colombier #include <memdraw.h>
57dd7cddfSDavid du Colombier 
67dd7cddfSDavid du Colombier Memimage*
creadmemimage(int fd)77dd7cddfSDavid du Colombier creadmemimage(int fd)
87dd7cddfSDavid du Colombier {
97dd7cddfSDavid du Colombier 	char hdr[5*12+1];
107dd7cddfSDavid du Colombier 	Rectangle r;
11*8ccd4a63SDavid du Colombier 	int m, nb, miny, maxy, new, ldepth, ncblock;
127dd7cddfSDavid du Colombier 	uchar *buf;
137dd7cddfSDavid du Colombier 	Memimage *i;
147dd7cddfSDavid du Colombier 	ulong chan;
157dd7cddfSDavid du Colombier 
16*8ccd4a63SDavid du Colombier 	if(readn(fd, hdr, 5*12) != 5*12){
17*8ccd4a63SDavid du Colombier 		werrstr("readmemimage: short header (2)");
187dd7cddfSDavid du Colombier 		return nil;
19*8ccd4a63SDavid du Colombier 	}
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	/*
227dd7cddfSDavid du Colombier 	 * distinguish new channel descriptor from old ldepth.
237dd7cddfSDavid du Colombier 	 * channel descriptors have letters as well as numbers,
247dd7cddfSDavid du Colombier 	 * while ldepths are a single digit formatted as %-11d.
257dd7cddfSDavid du Colombier 	 */
267dd7cddfSDavid du Colombier 	new = 0;
277dd7cddfSDavid du Colombier 	for(m=0; m<10; m++){
287dd7cddfSDavid du Colombier 		if(hdr[m] != ' '){
297dd7cddfSDavid du Colombier 			new = 1;
307dd7cddfSDavid du Colombier 			break;
317dd7cddfSDavid du Colombier 		}
327dd7cddfSDavid du Colombier 	}
337dd7cddfSDavid du Colombier 	if(hdr[11] != ' '){
347dd7cddfSDavid du Colombier 		werrstr("creadimage: bad format");
357dd7cddfSDavid du Colombier 		return nil;
367dd7cddfSDavid du Colombier 	}
377dd7cddfSDavid du Colombier 	if(new){
387dd7cddfSDavid du Colombier 		hdr[11] = '\0';
397dd7cddfSDavid du Colombier 		if((chan = strtochan(hdr)) == 0){
407dd7cddfSDavid du Colombier 			werrstr("creadimage: bad channel string %s", hdr);
417dd7cddfSDavid du Colombier 			return nil;
427dd7cddfSDavid du Colombier 		}
437dd7cddfSDavid du Colombier 	}else{
447dd7cddfSDavid du Colombier 		ldepth = ((int)hdr[10])-'0';
457dd7cddfSDavid du Colombier 		if(ldepth<0 || ldepth>3){
467dd7cddfSDavid du Colombier 			werrstr("creadimage: bad ldepth %d", ldepth);
477dd7cddfSDavid du Colombier 			return nil;
487dd7cddfSDavid du Colombier 		}
497dd7cddfSDavid du Colombier 		chan = drawld2chan[ldepth];
507dd7cddfSDavid du Colombier 	}
517dd7cddfSDavid du Colombier 	r.min.x=atoi(hdr+1*12);
527dd7cddfSDavid du Colombier 	r.min.y=atoi(hdr+2*12);
537dd7cddfSDavid du Colombier 	r.max.x=atoi(hdr+3*12);
547dd7cddfSDavid du Colombier 	r.max.y=atoi(hdr+4*12);
557dd7cddfSDavid du Colombier 	if(r.min.x>r.max.x || r.min.y>r.max.y){
567dd7cddfSDavid du Colombier 		werrstr("creadimage: bad rectangle");
577dd7cddfSDavid du Colombier 		return nil;
587dd7cddfSDavid du Colombier 	}
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier 	i = allocmemimage(r, chan);
617dd7cddfSDavid du Colombier 	if(i == nil)
627dd7cddfSDavid du Colombier 		return nil;
63*8ccd4a63SDavid du Colombier 	ncblock = _compblocksize(r, i->depth);
64*8ccd4a63SDavid du Colombier 	buf = malloc(ncblock);
657dd7cddfSDavid du Colombier 	if(buf == nil)
667dd7cddfSDavid du Colombier 		goto Errout;
677dd7cddfSDavid du Colombier 	miny = r.min.y;
687dd7cddfSDavid du Colombier 	while(miny != r.max.y){
697dd7cddfSDavid du Colombier 		if(readn(fd, hdr, 2*12) != 2*12){
70*8ccd4a63SDavid du Colombier 		Shortread:
71*8ccd4a63SDavid du Colombier 			werrstr("readmemimage: short read");
727dd7cddfSDavid du Colombier 		Errout:
737dd7cddfSDavid du Colombier 			freememimage(i);
747dd7cddfSDavid du Colombier 			free(buf);
757dd7cddfSDavid du Colombier 			return nil;
767dd7cddfSDavid du Colombier 		}
777dd7cddfSDavid du Colombier 		maxy = atoi(hdr+0*12);
787dd7cddfSDavid du Colombier 		nb = atoi(hdr+1*12);
797dd7cddfSDavid du Colombier 		if(maxy<=miny || r.max.y<maxy){
807dd7cddfSDavid du Colombier 			werrstr("readimage: bad maxy %d", maxy);
817dd7cddfSDavid du Colombier 			goto Errout;
827dd7cddfSDavid du Colombier 		}
83*8ccd4a63SDavid du Colombier 		if(nb<=0 || ncblock<nb){
847dd7cddfSDavid du Colombier 			werrstr("readimage: bad count %d", nb);
857dd7cddfSDavid du Colombier 			goto Errout;
867dd7cddfSDavid du Colombier 		}
877dd7cddfSDavid du Colombier 		if(readn(fd, buf, nb)!=nb)
88*8ccd4a63SDavid du Colombier 			goto Shortread;
897dd7cddfSDavid du Colombier 		if(!new)	/* old image: flip the data bits */
90*8ccd4a63SDavid du Colombier 			_twiddlecompressed(buf, nb);
917dd7cddfSDavid du Colombier 		cloadmemimage(i, Rect(r.min.x, miny, r.max.x, maxy), buf, nb);
927dd7cddfSDavid du Colombier 		miny = maxy;
937dd7cddfSDavid du Colombier 	}
947dd7cddfSDavid du Colombier 	free(buf);
957dd7cddfSDavid du Colombier 	return i;
967dd7cddfSDavid du Colombier }
97