ncvisual_rotate: move to arbitrary rads

pull/600/head
nick black 4 years ago
parent ad22661560
commit 219f6bdd27
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -71,8 +71,7 @@ int normal_demo(struct notcurses* nc){
if(!ncv){
return -1;
}
// FIXME use smaller rotations once supported
for(int i = 1 ; i < 4 ; ++i){
for(int i = 1 ; i < 100 ; ++i){
if(ncvisual_rotate(ncv, M_PI / 2)){
return -1;
}

@ -113,7 +113,8 @@ auto ncvisual_from_plane(const ncplane* n, int begy, int begx, int leny, int len
}
int dimy, dimx;
ncplane_dim_yx(n, &dimy, &dimx);
struct ncvisual* ncv = ncvisual_from_rgba(n->nc, rgba, n->leny, n->lenx * 4, n->lenx);
// FIXME needs to make use of begy, begx, leny, lenx!
auto* ncv = ncvisual_from_rgba(n->nc, rgba, n->leny, n->lenx * 4, n->lenx);
if(ncv == nullptr){
free(rgba);
return nullptr;
@ -155,83 +156,75 @@ auto ncvisual_setplane(ncvisual* ncv, ncplane* n) -> int {
return ret;
}
// pi/2 rads counterclockwise
static int
ncvisual_rotate_ccw(struct ncvisual* ncv){
if(ncv->data == nullptr){
return -1;
}
ncplane* n = ncvisual_plane(ncv);
ncplane* newp = rotate_plane(n);
if(newp == nullptr){
return -1;
}
assert(ncv->rowstride / 4 >= ncv->dstwidth);
auto data = static_cast<uint32_t*>(malloc(ncv->dstheight * ncv->dstwidth * 4));
if(data == nullptr){
ncplane_destroy(newp);
return -1;
}
// Each row of the target plane is taken from a column of the source plane.
// As the target row grows (down), the source column shrinks (moves left).
// work from the top to bottom and left to right of the dest. min y goes to
// min x. max y goes to max x. max x goes to min y. min x goes to max y.
for(int targy = 0 ; targy < ncv->dstwidth ; ++targy){
for(int targx = 0 ; targx < ncv->dstheight ; ++targx){
const int x = ncv->dstwidth - 1 - targy;
const int y = targx;
//fprintf(stderr, "CW: %d/%d (%08x) -> %d/%d (stride: %d)\n", y, x, ncv->data[y * (ncv->rowstride / 4) + x], targy, targx, ncv->rowstride);
data[targy * ncv->dstheight + targx] = ncv->data[y * (ncv->rowstride / 4) + x];
//fprintf(stderr, "CCW: %d/%d -> %d/%d\n", y, x, targy, targx);
// if we're rotating around our center, we can't require any radius greater
// than our longer length. rotation can thus be held entirely within a square
// plane having length of our longest length. after one rotation, this decays
// to the same square throughout any rotations.
static auto
rotate_new_geom(ncvisual* ncv, double rads, double *stheta, double *ctheta) -> int {
*stheta = sin(rads);
*ctheta = cos(rads);
const int scaledy = ncv->ncp->leny * encoding_vert_scale(ncv);
const int diam = scaledy < ncv->ncp->lenx ? ncv->ncp->lenx : scaledy;
//fprintf(stderr, "rotating %d -> %d / %d\n", ncv->ncp->leny, scaledy, ncv->ncp->lenx);
if(ncv->ncp->lenx != scaledy){
if(ncplane_resize_simple(ncv->ncp, diam / encoding_vert_scale(ncv), diam) < 0){
return -1;
}
}
int ret = ncplane_destroy(n);
ncvisual_set_data(ncv, data, true);
int tmp = ncv->dstwidth;
ncv->dstwidth = ncv->dstheight;
ncv->dstheight = tmp;
ncv->rowstride = ncv->dstwidth * 4;
ncv->ncp = newp;
return ret;
return diam;
}
auto ncvisual_rotate(struct ncvisual* ncv, double rads) -> int {
if(rads == -M_PI / 2){
return ncvisual_rotate_ccw(ncv);
}
if(rads != M_PI / 2){
auto ncvisual_rotate(ncvisual* ncv, double rads) -> int {
if(ncv->data == nullptr){
return -1;
}
if(ncv->data == nullptr){
double stheta, ctheta; // sine, cosine
auto diam = rotate_new_geom(ncv, rads, &stheta, &ctheta);
if(diam <= 0){
return -1;
}
ncplane* n = ncvisual_plane(ncv);
ncplane* newp = rotate_plane(n);
ncplane* newp = rotate_plane(n); // FIXME how to resize properly?
if(newp == nullptr){
return -1;
}
// pixel diameter
int pdiam = ncv->dstheight > ncv->dstwidth ? ncv->dstheight : ncv->dstwidth;
//fprintf(stderr, "stride: %d height: %d width: %d\n", ncv->rowstride, ncv->dstheight, ncv->dstwidth);
assert(ncv->rowstride / 4 >= ncv->dstwidth);
auto data = static_cast<uint32_t*>(malloc(ncv->dstheight * ncv->dstwidth * 4));
auto data = static_cast<uint32_t*>(malloc(pdiam * pdiam * 4));
if(data == nullptr){
ncplane_destroy(newp);
return -1;
}
// targy <- x, targx <- ncv->dstheight - y - 1
for(int targy = 0 ; targy < ncv->dstwidth ; ++targy){
for(int targx = 0 ; targx < ncv->dstheight ; ++targx){
const int x = targy;
const int y = ncv->dstheight - 1 - targx;
int centx = ncv->dstwidth / 2; // pixel center
int centy = ncv->dstheight / 2;
//fprintf(stderr, "DIAM: %d CENTER: %d/%d LEN: %d/%d\n", diam, centy, centx, ncv->ncp->leny, ncv->ncp->lenx);
for(int y = 0 ; y < ncv->dstheight ; ++y){
for(int x = 0 ; x < ncv->dstwidth ; ++x){
const int convy = y - centy; // converted coordinates
const int convx = x - centx;
const int targy = convx * stheta + convy * ctheta;
const int targx = convx * ctheta + convy * stheta;
const int deconvy = targy + pdiam / 2;
const int deconvx = targx + pdiam / 2;
//fprintf(stderr, "%d/%d -> %d/%d -> %d/%d -> %d/%d\n", y, x, convy, convx, targy, targx, deconvy, deconvx);
assert(deconvy >= 0);
assert(deconvx >= 0);
assert(deconvy < pdiam);
assert(deconvx < pdiam);
data[deconvy * pdiam + deconvx] = ncv->data[y * (ncv->rowstride / 4) + x];
//fprintf(stderr, "CW: %d/%d (%08x) -> %d/%d (stride: %d)\n", y, x, ncv->data[y * (ncv->rowstride / 4) + x], targy, targx, ncv->rowstride);
data[targy * ncv->dstheight + targx] = ncv->data[y * (ncv->rowstride / 4) + x];
// data[targy * ncv->dstheight + targx] = ncv->data[y * (ncv->rowstride / 4) + x];
//fprintf(stderr, "wrote %08x to %d (%d)\n", data[targy * ncv->dstheight + targx], targy * ncv->dstheight + targx, (targy * ncv->dstheight + targx) * 4);
}
}
int ret = ncplane_destroy(n);
ncvisual_set_data(ncv, data, true);
int tmp = ncv->dstwidth;
ncv->dstwidth = ncv->dstheight;
ncv->dstheight = tmp;
ncv->dstwidth = pdiam;
ncv->dstheight = pdiam;
ncv->rowstride = ncv->dstwidth * 4;
ncv->ncp = newp;
return ret;
@ -243,6 +236,7 @@ auto ncvisual_from_rgba(notcurses* nc, const void* rgba, int rows,
return nullptr;
}
ncvisual* ncv = ncvisual_create(1);
set_encoding_vert_scale(nc, ncv);
//fprintf(stderr, "ROWS: %d STRIDE: %d (%d) COLS: %d\n", rows, rowstride, rowstride / 4, cols);
ncv->rowstride = rowstride;
ncv->ncobj = nc;
@ -800,7 +794,7 @@ nc_err_e ncvisual_decode(ncvisual* nc){
return NCERR_UNIMPLEMENTED;
}
int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, nc_err_e* ncerr,
int ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr,
float timespec, streamcb streamer, void* curry){
(void)nc;
(void)ncv;
@ -986,7 +980,7 @@ nc_err_e ncvisual_decode(ncvisual* nc){
return NCERR_SUCCESS;
}
int ncvisual_stream(struct notcurses* nc, struct ncvisual* ncv, nc_err_e* ncerr,
int ncvisual_stream(notcurses* nc, ncvisual* ncv, nc_err_e* ncerr,
float timescale, streamcb streamer, void* curry){
*ncerr = NCERR_SUCCESS;
int frame = 1;

Loading…
Cancel
Save