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