summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@centraldogma>2011-09-04 23:51:14 +0200
committercinap_lenrek <cinap_lenrek@centraldogma>2011-09-04 23:51:14 +0200
commitb5bbc62dda13b59487769fab7d715d0b8e580115 (patch)
treeb5daae38b7a27127f2ca73d8d9a1c3572bf6965d
parent0bc540a495210f4b140de4010c8a13d54e1ebf0b (diff)
downloadplan9front-b5bbc62dda13b59487769fab7d715d0b8e580115.tar.xz
libdraw: fix unloadimage() for wide images, libmemdraw: work arround width limit by outputting uncompressed image in writememimage() if compressed blocksize exceeds chunk limit
-rw-r--r--sys/src/libdraw/unloadimage.c39
-rw-r--r--sys/src/libmemdraw/read.c4
-rw-r--r--sys/src/libmemdraw/write.c39
3 files changed, 51 insertions, 31 deletions
diff --git a/sys/src/libdraw/unloadimage.c b/sys/src/libdraw/unloadimage.c
index ead36b0c8..741c73b6b 100644
--- 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 @@ unloadimage(Image *i, Rectangle r, uchar *data, int ndata)
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;
}
diff --git a/sys/src/libmemdraw/read.c b/sys/src/libmemdraw/read.c
index 12be6530b..125568ca4 100644
--- a/sys/src/libmemdraw/read.c
+++ b/sys/src/libmemdraw/read.c
@@ -85,10 +85,6 @@ readmemimage(int fd)
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){
diff --git a/sys/src/libmemdraw/write.c b/sys/src/libmemdraw/write.c
index a8816ed04..cde12dfbc 100644
--- a/sys/src/libmemdraw/write.c
+++ b/sys/src/libmemdraw/write.c
@@ -43,26 +43,45 @@ writememimage(int fd, Memimage *i)
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){
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);