int unloadimage(Image *i, Rectangle r, uchar *data, int ndata) { int bpl, n, chunk, dx, dy; uchar *a, *start; Display *d; if(!rectinrect(r, i->r)) { werrstr("unloadimage: bad rectangle"); return -1; } bpl = bytesperline(r, i->depth); if(ndata < bpl*Dy(r)) { werrstr("unloadimage: buffer too small"); return -1; } start = data; d = i->display; chunk = d->bufsize; flushimage(d, 0); /* make sure subsequent flush is for us only */ while(r.min.y < r.max.y) { dx = Dx(r); dy = chunk/bpl; if(dy <= 0) { dy = 1; dx = ((chunk*dx)/bpl) & ~7; n = bytesperline(Rect(r.min.x, r.min.y, r.min.x+dx, r.min.y+dy), i->depth); if(unloadimage(i, Rect(r.min.x+dx, r.min.y, r.max.x, r.min.y+dy), data+n, bpl-n) < 0) return -1; } else { if(dy > Dy(r)) dy = Dy(r); n = bpl*dy; } a = bufimage(d, 1+4+4*4); if(a == nil) { werrstr("unloadimage: %r"); return -1; } a[0] = 'r'; BPLONG(a+1, i->id); BPLONG(a+5, r.min.x); BPLONG(a+9, r.min.y); BPLONG(a+13, r.min.x+dx); BPLONG(a+17, r.min.y+dy); if(flushimage(d, 0) < 0) return -1; if(read(d->fd, data, n) < 0) return -1; data += bpl*dy; r.min.y += dy; } return data - start; }
void writeuncompressed(int fd, Memimage *m) { char chanstr[32]; int bpl, y, j; uchar *buf; if(chantostr(chanstr, m->chan) == nil) sysfatal("can't convert channel descriptor: %r"); fprint(fd, "%11s %11d %11d %11d %11d ", chanstr, m->r.min.x, m->r.min.y, m->r.max.x, m->r.max.y); bpl = bytesperline(m->r, m->depth); buf = malloc(bpl); if(buf == nil) sysfatal("malloc failed: %r"); for(y=m->r.min.y; y<m->r.max.y; y++){ j = unloadmemimage(m, Rect(m->r.min.x, y, m->r.max.x, y+1), buf, bpl); if(j != bpl) sysfatal("image unload failed: %r"); if(write(fd, buf, bpl) != bpl) sysfatal("write failed: %r"); } free(buf); }
int loadimage(Image *i, Rectangle r, uchar *data, int ndata) { long dy; int n, bpl; uchar *a; int chunk; chunk = i->display->bufsize - 64; if(!rectinrect(r, i->r)){ werrstr("loadimage: bad rectangle"); return -1; } bpl = bytesperline(r, i->depth); n = bpl*Dy(r); if(n > ndata){ werrstr("loadimage: insufficient data"); return -1; } ndata = 0; while(r.max.y > r.min.y){ dy = r.max.y - r.min.y; if(dy*bpl > chunk) dy = chunk/bpl; if(dy <= 0){ werrstr("loadimage: image too wide for buffer"); return -1; } n = dy*bpl; a = bufimage(i->display, 21+n); if(a == nil){ werrstr("bufimage failed"); return -1; } a[0] = 'y'; BPLONG(a+1, i->id); BPLONG(a+5, r.min.x); BPLONG(a+9, r.min.y); BPLONG(a+13, r.max.x); BPLONG(a+17, r.min.y+dy); memmove(a+21, data, n); ndata += n; data += n; r.min.y += dy; } if(flushimage(i->display, 0) < 0) return -1; return ndata; }
int unloadimage(Image *i, Rectangle r, uchar *data, int ndata) { int bpl, n, ntot, dy; uchar *a; Display *d; if(!rectinrect(r, i->r)){ werrstr("unloadimage: bad rectangle"); return -1; } bpl = bytesperline(r, i->depth); if(ndata < bpl*Dy(r)){ werrstr("unloadimage: buffer too small"); return -1; } d = i->display; flushimage(d, 0); /* make sure subsequent flush is for us only */ ntot = 0; while(r.min.y < r.max.y){ a = bufimage(d, 1+4+4*4); if(a == 0){ werrstr("unloadimage: %r"); return -1; } dy = 8000/bpl; if(dy <= 0){ werrstr("unloadimage: image too wide"); return -1; } if(dy > Dy(r)) dy = Dy(r); a[0] = 'r'; BPLONG(a+1, i->id); BPLONG(a+5, r.min.x); BPLONG(a+9, r.min.y); BPLONG(a+13, r.max.x); BPLONG(a+17, r.min.y+dy); if(flushimage(d, 0) < 0) return -1; n = read(d->fd, data+ntot, ndata-ntot); if(n < 0) return n; ntot += n; r.min.y += dy; } return ntot; }
void getimage(Cimage *ci, Rune *altr) { Rectangle r; Memimage *mi; Image *i, *i2; char buf[128]; uchar *bits; int nbits; mi = ci->mi; if(mi == nil) { snprint(buf, sizeof(buf), "[%S]", altr ? altr : L"IMG"); r.min = Pt(0, 0); r.max.x = 2*Space + stringwidth(font, buf); r.max.y = 2*Space + font->height; ci->i = eallocimage(display, r, GREY1, 1, DBlack); r.min.x += Space; r.min.y += Space; string(ci->i, r.min, display->white, ZP, font, buf); return; } nbits = bytesperline(mi->r, mi->depth)*Dy(mi->r); bits = emalloc(nbits); unloadmemimage(mi, mi->r, bits, nbits); /* /* get rid of alpha channel from transparent gif * / if(mi->depth == 16){ for(y=1; y<nbits; y+=2) bits[y>>1] = bits[y]; } */ i = eallocimage(display, mi->r, mi->chan, 0, DNofill); loadimage(i, i->r, bits, nbits); i2 = eallocimage(display, i->r, RGB24, 1, DNofill); draw(i2, i2->r, display->black, nil, ZP); draw(i2, i2->r, i, nil, i->r.min); free(bits); freememimage(mi); freeimage(i); ci->i = i2; ci->mi = nil; }
int unloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { int y, l; uchar *q; if(!rectinrect(r, i->r)) return -1; l = bytesperline(r, i->depth); if(ndata < l*Dy(r)) return -1; ndata = l*Dy(r); q = byteaddr(i, r.min); for(y=r.min.y; y<r.max.y; y++){ memmove(data, q, l); q += i->width*sizeof(ulong); data += l; } return ndata; }
void imagebits(Biobuf *ioutb, Memimage *im) { int spb; int bitoff; int j, n, n4, i, bpl, nrest; int lsf; uchar c85[6], *data, *src, *dst; Memimage *tmp; Rectangle r; tmp = nil; if (debug) fprint(2, "imagebits, r=%d %d %d %d, depth=%d\n", im->r.min.x, im->r.min.y, im->r.max.x, im->r.max.y, im->depth); width = Dx(im->r); height = Dy(im->r); bps = im->depth; /* # bits per sample */ bitoff = 0; /* # bit offset of beginning sample within first byte */ if (bps < 8) { spb = 8 / bps; bitoff = (im->r.min.x % spb) * bps; } if (bitoff != 0) { /* # Postscript image wants beginning of line at beginning of byte */ r = im->r; r.min.x -= bitoff/im->depth; r.max.x -= bitoff/im->depth; tmp = allocmemimage(r, im->chan); if(tmp == nil){ fprint(2, "p9bitpost: allocmemimage failed: %r\n"); exits("alloc"); } memimagedraw(tmp, r, im, im->r.min, nil, ZP, S); im = tmp; } lsf = 0; /* compact data to remove word-boundary padding */ bpl = bytesperline(im->r, im->depth); n = bpl*Dy(im->r); data = malloc(n); if(data == nil){ fprint(2, "p9bitpost: malloc failed: %r\n"); exits("malloc"); } for(i=0; i<Dy(im->r); i++){ /* memmove(data+bpl*i, byteaddr(im, Pt(im->r.min.x, im->r.min.y+i)), bpl); with inversion */ dst = data+bpl*i; src = byteaddr(im, Pt(im->r.min.x, im->r.min.y+i)); for(j=0; j<bpl; j++) *dst++ = 255 - *src++; } n4 = (n / 4) * 4; for (i = 0; i < n4; i += 4){ cmap2ascii85(data+i, c85); lsf += strlen((char *)c85); Bprint(ioutb, "%s", (char *)c85); if (lsf > 74) { Bprint(ioutb, "\n"); lsf = 0; } } nrest = n - n4; if (nrest != 0) { uchar foo[4]; for (i=0; i<nrest; i++) foo[i] = data[n4+i]; for (i=nrest; i<4; i++) foo[i] = '\0'; cmap2ascii85(foo, c85); if (strcmp((char *)c85, "z") == 0 ) strcpy((char *)c85, "!!!!!"); Bprint(ioutb, "%.*s", nrest+1, (char *)c85); } Bprint(ioutb, "\n~>"); Bprint(ioutb, "\n"); freememimage(tmp); }
int _cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) { int y, bpl, c, cnt, offs; uchar mem[NMEM], *memp, *omemp, *emem, *linep, *elinep, *u, *eu; if(!rectinrect(r, i->r)) return -1; bpl = bytesperline(r, i->depth); u = data; eu = data+ndata; memp = mem; emem = mem+NMEM; y = r.min.y; linep = byteaddr(i, Pt(r.min.x, y)); elinep = linep+bpl; for(;;){ if(linep == elinep){ if(++y == r.max.y) break; linep = byteaddr(i, Pt(r.min.x, y)); elinep = linep+bpl; } if(u == eu){ /* buffer too small */ return -1; } c = *u++; if(c >= 128){ for(cnt=c-128+1; cnt!=0 ;--cnt){ if(u == eu){ /* buffer too small */ return -1; } if(linep == elinep){ /* phase error */ return -1; } *linep++ = *u; *memp++ = *u++; if(memp == emem) memp = mem; } } else{ if(u == eu) /* short buffer */ return -1; offs = *u++ + ((c&3)<<8)+1; if(memp-mem < offs) omemp = memp+(NMEM-offs); else omemp = memp-offs; for(cnt=(c>>2)+NMATCH; cnt!=0; --cnt){ if(linep == elinep) /* phase error */ return -1; *linep++ = *omemp; *memp++ = *omemp++; if(omemp == emem) omemp = mem; if(memp == emem) memp = mem; } } } return u-data; }
static void xread(Req *r) { int i, size, height, ascent; vlong path; Fmt fmt; XFont *f; char *data; Memsubfont *sf; Memimage *m; path = r->fid->qid.path; switch(QTYPE(path)) { case Qroot: dirread9p(r, rootgen, nil); break; case Qfontdir: dirread9p(r, fontgen, r->fid); break; case Qsizedir: dirread9p(r, sizegen, r->fid); break; case Qfontfile: fmtstrinit(&fmt); f = &xfont[QFONT(path)]; load(f); if(f->unit == 0 && f->loadheight == nil) { readstr(r, "font missing\n"); break; } height = 0; ascent = 0; if(f->unit > 0) { height = f->height * (int)QSIZE(path)/f->unit + 0.99999999; ascent = height - (int)(-f->originy * (int)QSIZE(path)/f->unit + 0.99999999); } if(f->loadheight != nil) f->loadheight(f, QSIZE(path), &height, &ascent); fmtprint(&fmt, "%11d %11d\n", height, ascent); for(i=0; i<nelem(f->range); i++) { if(f->range[i] == 0) continue; fmtprint(&fmt, "0x%04x 0x%04x x%04x.bit\n", i*SubfontSize, ((i+1)*SubfontSize) - 1, i*SubfontSize); } data = fmtstrflush(&fmt); readstr(r, data); free(data); break; case Qsubfontfile: f = &xfont[QFONT(path)]; load(f); if(r->fid->aux == nil) { r->fid->aux = mksubfont(f, f->name, QRANGE(path)*SubfontSize, ((QRANGE(path)+1)*SubfontSize)-1, QSIZE(path), QANTIALIAS(path)); if(r->fid->aux == nil) { responderrstr(r); return; } } sf = r->fid->aux; m = sf->bits; if(r->ifcall.offset < 5*12) { char *chan; if(QANTIALIAS(path)) chan = "k8"; else chan = "k1"; data = smprint("%11s %11d %11d %11d %11d ", chan, m->r.min.x, m->r.min.y, m->r.max.x, m->r.max.y); readstr(r, data); free(data); break; } r->ifcall.offset -= 5*12; size = bytesperline(m->r, chantodepth(m->chan)) * Dy(m->r); if(r->ifcall.offset < size) { readbuf(r, byteaddr(m, m->r.min), size); break; } r->ifcall.offset -= size; data = emalloc9p(3*12+6*(sf->n+1)); sprint(data, "%11d %11d %11d ", sf->n, sf->height, sf->ascent); packinfo(sf->info, (uchar*)data+3*12, sf->n); readbuf(r, data, 3*12+6*(sf->n+1)); free(data); break; } respond(r, nil); }