shithub: riscv

Download patch

ref: b5bbc62dda13b59487769fab7d715d0b8e580115
parent: 0bc540a495210f4b140de4010c8a13d54e1ebf0b
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Sun Sep 4 19:51:14 EDT 2011

libdraw: fix unloadimage() for wide images, libmemdraw: work arround width limit by outputting uncompressed image in writememimage() if compressed blocksize exceeds chunk limit

--- a/sys/src/libdraw/unloadimage.c
+++ b/sys/src/libdraw/unloadimage.c
@@ -5,8 +5,8 @@
 int
 unloadimage(Image *i, Rectangle r, uchar *data, int ndata)
 {
-	int bpl, n, ntot, dy;
-	uchar *a;
+	int bpl, n, chunk, dx, dy;
+	uchar *a, *start;
 	Display *d;
 
 	if(!rectinrect(r, i->r)){
@@ -18,36 +18,41 @@
 		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 */
-	ntot = 0;
 	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 == 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+13, r.min.x+dx);
 		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;
+		if(read(d->fd, data, n) < 0)
+			return -1;
+		data += bpl*dy;
 		r.min.y += dy;
 	}
-	return ntot;
+	return data - start;
 }
--- a/sys/src/libmemdraw/read.c
+++ b/sys/src/libmemdraw/read.c
@@ -85,10 +85,6 @@
 		dy = maxy - miny;
 		if(dy*l > chunk)
 			dy = chunk/l;
-		if(dy <= 0){
-			werrstr("readmemimage: image too wide for buffer");
-			goto Err;
-		}
 		n = dy*l;
 		m = readn(fd, tmp, n);
 		if(m != n){
--- a/sys/src/libmemdraw/write.c
+++ b/sys/src/libmemdraw/write.c
@@ -43,16 +43,9 @@
 	bpl = bytesperline(r, i->depth);
 	n = Dy(r)*bpl;
 	data = malloc(n);
-	ncblock = _compblocksize(r, i->depth);
-	outbuf = malloc(ncblock);
-	hash = malloc(NHASH*sizeof(Hlist));
-	chain = malloc(NMEM*sizeof(Hlist));
-	if(data == 0 || outbuf == 0 || hash == 0 || chain == 0){
-	ErrOut:
+	if(data == 0){
+	ErrOut0:
 		free(data);
-		free(outbuf);
-		free(hash);
-		free(chain);
 		return -1;
 	}
 	for(miny = r.min.y; miny != r.max.y; miny += dy){
@@ -59,10 +52,36 @@
 		dy = r.max.y-miny;
 		if(dy*bpl > CHUNK)
 			dy = CHUNK/bpl;
+		if(dy <= 0)
+			dy = 1;
 		nb = unloadmemimage(i, Rect(r.min.x, miny, r.max.x, miny+dy),
 			data+(miny-r.min.y)*bpl, dy*bpl);
 		if(nb != dy*bpl)
-			goto ErrOut;
+			goto ErrOut0;
+	}
+
+	ncblock = _compblocksize(r, i->depth);
+
+	if(ncblock > CHUNK){
+		sprint(hdr, "%11s %11d %11d %11d %11d ",
+			chantostr(cbuf, i->chan), r.min.x, r.min.y, r.max.x, r.max.y);
+		if(write(fd, hdr, 5*12) != 5*12)
+			goto ErrOut0;
+		if(write(fd, data, n) != n)
+			goto ErrOut0;
+		free(data);
+		return 0;
+	}
+
+	outbuf = malloc(ncblock);
+	hash = malloc(NHASH*sizeof(Hlist));
+	chain = malloc(NMEM*sizeof(Hlist));
+	if(outbuf == 0 || hash == 0 || chain == 0){
+	ErrOut:
+		free(outbuf);
+		free(hash);
+		free(chain);
+		goto ErrOut0;
 	}
 	sprint(hdr, "compressed\n%11s %11d %11d %11d %11d ",
 		chantostr(cbuf, i->chan), r.min.x, r.min.y, r.max.x, r.max.y);