libdraw: fix unloadimage() for wide images, libmemdraw: work arround width limit by outputting uncompressed image in writememimage() if compressed blocksize exceeds chunk limit
This commit is contained in:
parent
0bc540a495
commit
b5bbc62dda
3 changed files with 51 additions and 31 deletions
|
@ -5,8 +5,8 @@
|
||||||
int
|
int
|
||||||
unloadimage(Image *i, Rectangle r, uchar *data, int ndata)
|
unloadimage(Image *i, Rectangle r, uchar *data, int ndata)
|
||||||
{
|
{
|
||||||
int bpl, n, ntot, dy;
|
int bpl, n, chunk, dx, dy;
|
||||||
uchar *a;
|
uchar *a, *start;
|
||||||
Display *d;
|
Display *d;
|
||||||
|
|
||||||
if(!rectinrect(r, i->r)){
|
if(!rectinrect(r, i->r)){
|
||||||
|
@ -18,36 +18,41 @@ unloadimage(Image *i, Rectangle r, uchar *data, int ndata)
|
||||||
werrstr("unloadimage: buffer too small");
|
werrstr("unloadimage: buffer too small");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
start = data;
|
||||||
d = i->display;
|
d = i->display;
|
||||||
|
chunk = d->bufsize;
|
||||||
flushimage(d, 0); /* make sure subsequent flush is for us only */
|
flushimage(d, 0); /* make sure subsequent flush is for us only */
|
||||||
ntot = 0;
|
|
||||||
while(r.min.y < r.max.y){
|
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);
|
a = bufimage(d, 1+4+4*4);
|
||||||
if(a == 0){
|
if(a == 0){
|
||||||
werrstr("unloadimage: %r");
|
werrstr("unloadimage: %r");
|
||||||
return -1;
|
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';
|
a[0] = 'r';
|
||||||
BPLONG(a+1, i->id);
|
BPLONG(a+1, i->id);
|
||||||
BPLONG(a+5, r.min.x);
|
BPLONG(a+5, r.min.x);
|
||||||
BPLONG(a+9, r.min.y);
|
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);
|
BPLONG(a+17, r.min.y+dy);
|
||||||
if(flushimage(d, 0) < 0)
|
if(flushimage(d, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
n = read(d->fd, data+ntot, ndata-ntot);
|
if(read(d->fd, data, n) < 0)
|
||||||
if(n < 0)
|
return -1;
|
||||||
return n;
|
data += bpl*dy;
|
||||||
ntot += n;
|
|
||||||
r.min.y += dy;
|
r.min.y += dy;
|
||||||
}
|
}
|
||||||
return ntot;
|
return data - start;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,10 +85,6 @@ readmemimage(int fd)
|
||||||
dy = maxy - miny;
|
dy = maxy - miny;
|
||||||
if(dy*l > chunk)
|
if(dy*l > chunk)
|
||||||
dy = chunk/l;
|
dy = chunk/l;
|
||||||
if(dy <= 0){
|
|
||||||
werrstr("readmemimage: image too wide for buffer");
|
|
||||||
goto Err;
|
|
||||||
}
|
|
||||||
n = dy*l;
|
n = dy*l;
|
||||||
m = readn(fd, tmp, n);
|
m = readn(fd, tmp, n);
|
||||||
if(m != n){
|
if(m != n){
|
||||||
|
|
|
@ -43,26 +43,45 @@ writememimage(int fd, Memimage *i)
|
||||||
bpl = bytesperline(r, i->depth);
|
bpl = bytesperline(r, i->depth);
|
||||||
n = Dy(r)*bpl;
|
n = Dy(r)*bpl;
|
||||||
data = malloc(n);
|
data = malloc(n);
|
||||||
ncblock = _compblocksize(r, i->depth);
|
if(data == 0){
|
||||||
outbuf = malloc(ncblock);
|
ErrOut0:
|
||||||
hash = malloc(NHASH*sizeof(Hlist));
|
|
||||||
chain = malloc(NMEM*sizeof(Hlist));
|
|
||||||
if(data == 0 || outbuf == 0 || hash == 0 || chain == 0){
|
|
||||||
ErrOut:
|
|
||||||
free(data);
|
free(data);
|
||||||
free(outbuf);
|
|
||||||
free(hash);
|
|
||||||
free(chain);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
for(miny = r.min.y; miny != r.max.y; miny += dy){
|
for(miny = r.min.y; miny != r.max.y; miny += dy){
|
||||||
dy = r.max.y-miny;
|
dy = r.max.y-miny;
|
||||||
if(dy*bpl > CHUNK)
|
if(dy*bpl > CHUNK)
|
||||||
dy = CHUNK/bpl;
|
dy = CHUNK/bpl;
|
||||||
|
if(dy <= 0)
|
||||||
|
dy = 1;
|
||||||
nb = unloadmemimage(i, Rect(r.min.x, miny, r.max.x, miny+dy),
|
nb = unloadmemimage(i, Rect(r.min.x, miny, r.max.x, miny+dy),
|
||||||
data+(miny-r.min.y)*bpl, dy*bpl);
|
data+(miny-r.min.y)*bpl, dy*bpl);
|
||||||
if(nb != 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 ",
|
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);
|
chantostr(cbuf, i->chan), r.min.x, r.min.y, r.max.x, r.max.y);
|
||||||
|
|
Loading…
Reference in a new issue