From fb13b148e95d6a4c2151c2e3c4fe7a19c41fa4b3 Mon Sep 17 00:00:00 2001 From: nick black Date: Sat, 6 Jun 2020 19:34:48 -0400 Subject: [PATCH] add Pixel API --- NEWS.md | 1 + USAGE.md | 42 +++++++++++++++++++++++++++++++++++ include/notcurses/notcurses.h | 36 ++++++++++++++++++++++++++++++ src/demo/yield.c | 17 +++++--------- src/lib/visual.cpp | 1 - 5 files changed, 85 insertions(+), 12 deletions(-) diff --git a/NEWS.md b/NEWS.md index 348353941..bce28d8c7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,7 @@ rearrangements of Notcurses. with a `const struct ncvisual_options*`. `NCBLIT_DEFAULT` will use `NCBLITTER_2x1` (with fallback) in this context. The `->n` field must be non-`NULL`--new planes will not be created. + * Added a Pixel API for working directly with the contents of `ncvisual`s. * Added `ncplane_notcurses_const()`. * 1.4.4.1 (2020-06-01) diff --git a/USAGE.md b/USAGE.md index 9c91a28b6..868fd8470 100644 --- a/USAGE.md +++ b/USAGE.md @@ -2638,6 +2638,48 @@ struct ncvisual* ncvisual_from_file(const char* file, nc_err_e* ncerr); nc_err_e ncvisual_decode(struct ncvisual* nc); ``` +### Pixels + +It is sometimes desirable to modify the pixels of an `ncvisual` directly. + +```c +static inline int +pixel_set_r(uint32_t* pixel, int r){ + if(r > 255 || r < 0){ + return -1; + } + *pixel = (*pixel & 0xffffff00ul) | (r); + return 0; +} + +static inline int +pixel_set_g(uint32_t* pixel, int g){ + if(g > 255 || g < 0){ + return -1; + } + *pixel = (*pixel & 0xff00fffful) | (g << 16u); + return 0; +} + +static inline int +pixel_set_b(uint32_t* pixel, int b){ + if(b > 255 || b < 0){ + return -1; + } + *pixel = (*pixel & 0xffff00fful) | (b << 8u); + return 0; +} + +// set the RGB values of an RGB pixel +static inline int +pixel_set_rgb(uint32_t* pixel, int r, int g, int b){ + if(pixel_set_r(pixel, r) || pixel_set_g(pixel, g) || pixel_set_b(pixel, b)){ + return -1; + } + return 0; +} +``` + ## C++ Marek Habersack has contributed (and maintains) C++ wrappers installed to diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index f6d3c49cf..3ec27aaed 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -193,6 +193,42 @@ channel_set_rgb(unsigned* channel, int r, int g, int b){ return 0; } +static inline int +pixel_set_r(uint32_t* pixel, int r){ + if(r > 255 || r < 0){ + return -1; + } + *pixel = (*pixel & 0xffffff00ul) | (r); + return 0; +} + +static inline int +pixel_set_g(uint32_t* pixel, int g){ + if(g > 255 || g < 0){ + return -1; + } + *pixel = (*pixel & 0xff00fffful) | (g << 16u); + return 0; +} + +static inline int +pixel_set_b(uint32_t* pixel, int b){ + if(b > 255 || b < 0){ + return -1; + } + *pixel = (*pixel & 0xffff00fful) | (b << 8u); + return 0; +} + +// set the RGB values of an RGB pixel +static inline int +pixel_set_rgb(uint32_t* pixel, int r, int g, int b){ + if(pixel_set_r(pixel, r) || pixel_set_g(pixel, g) || pixel_set_b(pixel, b)){ + return -1; + } + return 0; +} + // Set the three 8-bit components of a 32-bit channel, and mark it as not using // the default color. Retain the other bits unchanged. r, g, and b will be // clipped to the range [0..255]. diff --git a/src/demo/yield.c b/src/demo/yield.c index 6d246c53b..a3e738039 100644 --- a/src/demo/yield.c +++ b/src/demo/yield.c @@ -31,21 +31,19 @@ int yield_demo(struct notcurses* nc){ int vy, vx, vscaley, vscalex; ncvisual_geom(nc, wmv, vopts.blitter, &vy, &vx, &vscaley, &vscalex); struct timespec scaled; - int threshold_painted = vy * vx * 10 / 9; - const int ITER = 128; - timespec_div(&demodelay, ITER, &scaled); + int threshold_painted = (vy * vscaley) * (vx * vscalex) / 2; + timespec_div(&demodelay, 128, &scaled); int tfilled = 0; - for(int i = 0 ; i < ITER ; ++i){ + while(tfilled < threshold_painted){ int pfilled; do{ int x = random() % (vx); int y = random() % (vy); uint32_t pixel = 0; ncvisual_at_yx(wmv, y, x, &pixel); - uint32_t channel = 0; - channel_set_rgb(&channel, 0x80, channel_g(pixel), channel_b(pixel)); -//fprintf(stderr, "POLY: %d/%d\n", y, x); - pfilled = ncvisual_polyfill_yx(wmv, y, x, channel); + uint32_t newpixel = 0; + pixel_set_rgb(&newpixel, 0xff, channel_g(pixel), channel_b(pixel)); + pfilled = ncvisual_polyfill_yx(wmv, y, x, newpixel); if(pfilled < 0){ ncvisual_destroy(wmv); return -1; @@ -58,9 +56,6 @@ int yield_demo(struct notcurses* nc){ } DEMO_RENDER(nc); demo_nanosleep(nc, &scaled); - if(tfilled >= threshold_painted){ - break; - } } ncvisual_destroy(wmv); diff --git a/src/lib/visual.cpp b/src/lib/visual.cpp index c9797c8a2..48749a634 100644 --- a/src/lib/visual.cpp +++ b/src/lib/visual.cpp @@ -538,7 +538,6 @@ auto ncvisual_polyfill_recurse(ncvisual* n, int y, int x, if(*pixel != match || *pixel == rgba){ return 0; } -//fprintf(stderr, "%d/%d: %08x -> %08x\n", y, x, *pixel, rgba); *pixel = rgba; int ret = 1; ret += ncvisual_polyfill_recurse(n, y - 1, x, rgba, match);