ref: f7ce9af61db9b0d072dad403cb98d8bad4224dda
dir: /sample.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <event.h>
#include "blie.h"
/* direct copy from /sys/src/cmd/iconv.c:/^writeuncompressed */
static 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);
}
/*
* uses external program for resampling in a pipe.
* I can see several improvements for performance:
*
* 1. only scaling what's needed, which means calculating
* the rectangle we want, extracting that to a
* separate image for resampling.
* 2. integrate resample functionality in this program
* 3. only resample if zoom level or data changes.
* at the moment, it resamples when panning.
*/
static Memimage*
resample(Memimage *src, int nx, int ny)
{
int pin[2];
int pout[2];
int re, ro;
char x[11], y[11];
Memimage *tm;
Dir *dir;
snprint(x, sizeof(x), "%d", nx);
snprint(y, sizeof(y), "%d", ny);
if (pipe(pout) < 0) {
close(pout[0]);
close(pout[1]);
goto Err;
}
if (pipe(pin) < 0) {
close(pout[0]);
close(pout[1]);
close(pin[0]);
close(pin[1]);
goto Err;
}
dir = dirfstat(pin[0]);
if (!dir) {
free(dir);
goto Err;
}
dir->length = src->width * Dy(src->r) * sizeof(ulong) + 12 * 5;
if (!dirfwstat(pin[0], dir)) {
free(dir);
goto Err;
}
free(dir);
switch (fork()) {
case -1: /* error */
goto Err;
case 0: /* child */
dup(pin[1], 0);
dup(pout[1], 1);
close(pin[0]);
close(pout[0]);
execl("/bin/resample", "resample", "-x", x, "-y", y, nil);
sysfatal("cannot exec: %r");
default: /* parent */
close(pout[1]);
close(pin[1]);
re = pout[0];
ro = pin[0];
}
writeuncompressed(ro, src);
tm = readmemimage(re);
if (!tm) {
close(re);
close(ro);
goto Err;
}
close(re);
close(ro);
return tm;
Err:
fprint(2, "resample: %r\n");
return nil;
}
void
sampleview(Image *img, Memimage *src)
{
Memimage *tmi;
Memimage *tsi;
Rectangle r;
int nw;
r.min = ZP;
r.max = Pt(Dx(img->r), Dy(img->r));
tsi = resample(src, Dx(src->r)*vstate.zoom, Dy(src->r)*vstate.zoom);
if (!tsi)
return;
tmi = allocmemimage(r, img->chan);
memfillcolor(tmi, DBlack);
memimagedraw(tmi, tmi->r, tsi, addpt(tmi->r.min, vstate.offset), nil, ZP, S);
nw = tmi->width * tmi->r.max.y * sizeof(ulong); // tmi->r.max.y == Dy(tmi->r)
draw(img, img->r, display->black, nil, ZP);
loadimage(img, img->r, tmi->data->bdata, nw);
freememimage(tsi);
freememimage(tmi);
}