diff --git a/src/lib/visual.c b/src/lib/visual.c index 56d372dfe..a4649debe 100644 --- a/src/lib/visual.c +++ b/src/lib/visual.c @@ -899,3 +899,40 @@ int ncvisual_resize(ncvisual* nc, int rows, int cols){ } return visual_implementation->visual_resize(nc, rows, cols); } + +// Inflate each pixel of 'bmap' to 'scale'x'scale' pixels square, using the +// same color as the original pixel. +static inline void* +inflate_bitmap(const uint32_t* bmap, int scale, int rows, int stride, int cols){ + size_t size = rows * cols * scale * scale * sizeof(*bmap); + uint32_t* ret = malloc(size); + if(ret){ + for(int y = 0 ; y < rows ; ++y){ + const uint32_t* src = bmap + y * (stride / sizeof(*bmap)); + for(int yi = 0 ; yi < scale ; ++yi){ + uint32_t* dst = ret + (y * scale + yi) * cols * scale; + for(int x = 0 ; x < cols ; ++x){ + for(int xi = 0 ; xi < scale ; ++xi){ + dst[x * scale + xi] = src[x]; + } + } + } + } + } + return ret; +} + +int ncvisual_inflate(ncvisual* n, int scale){ + if(scale <= 0){ + return -1; + } + void* inflaton = inflate_bitmap(n->data, scale, n->rows, n->rowstride, n->cols); + if(inflaton == NULL){ + return -1; + } + n->rows *= scale; + n->cols *= scale; + n->rowstride = 4 * n->cols; + ncvisual_set_data(n, inflaton, true); + return 0; +} diff --git a/src/tests/visual.cpp b/src/tests/visual.cpp index 8f0ce4486..d5559481d 100644 --- a/src/tests/visual.cpp +++ b/src/tests/visual.cpp @@ -1,4 +1,5 @@ #include "main.h" +#include "visual-details.h" #include TEST_CASE("Visual") { @@ -34,6 +35,33 @@ TEST_CASE("Visual") { ncplane_destroy(n); } + SUBCASE("InflateBitmap") { + const uint32_t pixels[4] = { htole(0xffff0000), htole(0xff00ff00), htole(0xff0000ff), htole(0xffffffff) }; + auto ncv = ncvisual_from_rgba(pixels, 2, 8, 2); + REQUIRE(ncv); + CHECK(0 == ncvisual_inflate(ncv, 3)); + CHECK(0 == notcurses_render(nc_)); + CHECK(6 == ncv->rows); + CHECK(6 == ncv->cols); + for(int y = 0 ; y < 3 ; ++y){ + for(int x = 0 ; x < 3 ; ++x){ + CHECK(pixels[0] == ncv->data[y * ncv->cols + x]); + } + for(int x = 3 ; x < 6 ; ++x){ + CHECK(pixels[1] == ncv->data[y * ncv->cols + x]); + } + } + for(int y = 3 ; y < 6 ; ++y){ + for(int x = 0 ; x < 3 ; ++x){ + CHECK(pixels[2] == ncv->data[y * ncv->cols + x]); + } + for(int x = 3 ; x < 6 ; ++x){ + CHECK(pixels[3] == ncv->data[y * ncv->cols + x]); + } + } + ncvisual_destroy(ncv); + } + SUBCASE("LoadRGBAFromMemory") { int dimy, dimx; ncplane_dim_yx(ncp_, &dimy, &dimx);