mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
generalize ncvisual_inflate() to ncvisual_resize_noninterpolative() #1738
This commit is contained in:
parent
9d47666dfe
commit
6fcaad3c5d
3
NEWS.md
3
NEWS.md
@ -8,6 +8,9 @@ rearrangements of Notcurses.
|
|||||||
scaling was not performed without a linked multimedia backend).
|
scaling was not performed without a linked multimedia backend).
|
||||||
* `NCVISUAL_OPTION_BLEND` used with `NCBLIT_PIXEL` will now, when the Kitty
|
* `NCVISUAL_OPTION_BLEND` used with `NCBLIT_PIXEL` will now, when the Kitty
|
||||||
graphics protocol is in use, cut the alpha of each pixel in half.
|
graphics protocol is in use, cut the alpha of each pixel in half.
|
||||||
|
* `ncvisual_inflate()` has been rewritten as a wrapper around the new
|
||||||
|
function `ncvisual_resize_noninterpolative()`, and deprecated. It will be
|
||||||
|
removed for ABI3. Godspeed, `ncvisual_inflate()`; we hardly knew ye.
|
||||||
|
|
||||||
* 2.3.2 (2021-06-03)
|
* 2.3.2 (2021-06-03)
|
||||||
* Fixed a bug affecting certain scalings of `ncvisual` objects created from
|
* Fixed a bug affecting certain scalings of `ncvisual` objects created from
|
||||||
|
6
USAGE.md
6
USAGE.md
@ -3127,9 +3127,9 @@ int ncvisual_rotate(struct ncvisual* n, double rads);
|
|||||||
// transformation, unless the size is unchanged.
|
// transformation, unless the size is unchanged.
|
||||||
int ncvisual_resize(struct ncvisual* n, int rows, int cols);
|
int ncvisual_resize(struct ncvisual* n, int rows, int cols);
|
||||||
|
|
||||||
// Inflate each pixel in the image to 'scale'x'scale' pixels. It is an error
|
// Scale the visual to 'rows' X 'columns' pixels, using non-interpolative
|
||||||
// if 'scale' is less than 1. The original color is retained.
|
// (naive) scaling. No new colors will be introduced as a result.
|
||||||
int ncvisual_inflate(struct ncvisual* n, int scale);
|
int ncvisual_resize_noninterpolative(struct ncvisual* n, int rows, int cols);
|
||||||
|
|
||||||
// Polyfill at the specified location within the ncvisual 'n', using 'rgba'.
|
// Polyfill at the specified location within the ncvisual 'n', using 'rgba'.
|
||||||
int ncvisual_polyfill_yx(struct ncvisual* n, int y, int x, uint32_t rgba);
|
int ncvisual_polyfill_yx(struct ncvisual* n, int y, int x, uint32_t rgba);
|
||||||
|
@ -78,7 +78,7 @@ typedef int (*streamcb)(struct notcurses*, struct ncvisual*, void*);
|
|||||||
|
|
||||||
**int ncvisual_resize(struct ncvisual* ***n***, int ***rows***, int ***cols***);**
|
**int ncvisual_resize(struct ncvisual* ***n***, int ***rows***, int ***cols***);**
|
||||||
|
|
||||||
**int ncvisual_inflate(struct ncvisual* ***n***, int ***scale***);**
|
**int ncvisual_resize_noninterpolative(struct ncvisual* ***n***, int ***rows***, int ***cols***);**
|
||||||
|
|
||||||
**int ncvisual_polyfill_yx(struct ncvisual* ***n***, int ***y***, int ***x***, uint32_t ***rgba***);**
|
**int ncvisual_polyfill_yx(struct ncvisual* ***n***, int ***y***, int ***x***, uint32_t ***rgba***);**
|
||||||
|
|
||||||
@ -114,13 +114,13 @@ per frame. **ncvisual_decode_loop** will return to the first frame,
|
|||||||
as if **ncvisual_decode** had never been called.
|
as if **ncvisual_decode** had never been called.
|
||||||
|
|
||||||
Once the visual is loaded, it can be transformed using **ncvisual_rotate**,
|
Once the visual is loaded, it can be transformed using **ncvisual_rotate**,
|
||||||
**ncvisual_resize**, and **ncvisual_inflate**. These are persistent operations,
|
**ncvisual_resize**, and **ncvisual_resize_noninterpolative**. These are
|
||||||
unlike any scaling that takes place at render time. If a subtitle is associated
|
persistent operations, unlike any scaling that takes place at render time. If a
|
||||||
with the frame, it can be acquired with **ncvisual_subtitle**.
|
subtitle is associated with the frame, it can be acquired with
|
||||||
**ncvisual_resize** uses the media layer's best scheme to enlarge or shrink the
|
**ncvisual_subtitle**. **ncvisual_resize** uses the media layer's best scheme
|
||||||
original data, typically involving some interpolation. **ncvisual_inflate**
|
to enlarge or shrink the original data, typically involving some interpolation.
|
||||||
maps each pixel to ***scale***x***scale*** pixels square, retaining the
|
**ncvisual_resize_noninterpolative** performs a naive linear sampling,
|
||||||
original color; it is an error if ***scale*** is less than one.
|
retaining only original colors.
|
||||||
|
|
||||||
**ncvisual_from_rgba** and **ncvisual_from_bgra** both require a number of
|
**ncvisual_from_rgba** and **ncvisual_from_bgra** both require a number of
|
||||||
***rows***, a number of image columns **cols**, and a virtual row length of
|
***rows***, a number of image columns **cols**, and a virtual row length of
|
||||||
@ -228,9 +228,8 @@ instance **NCSCALE_SCALE_HIRES** and a large image), more rows and columns will
|
|||||||
result in more effective resolution.
|
result in more effective resolution.
|
||||||
|
|
||||||
A string can be transformed to a scaling mode with **notcurses_lex_scalemode**,
|
A string can be transformed to a scaling mode with **notcurses_lex_scalemode**,
|
||||||
recognizing **stretch**, **scalehi**, **hires**, **scale**, **inflate**, and
|
recognizing **stretch**, **scalehi**, **hires**, **scale**, and **none**.
|
||||||
**none**. Conversion in the opposite direction is performed with
|
Conversion in the opposite direction is performed with **notcurses_str_scalemode**.
|
||||||
**notcurses_str_scalemode**.
|
|
||||||
|
|
||||||
Assuming a cell is twice as tall as it is wide, **NCBLIT_1x1** (and indeed
|
Assuming a cell is twice as tall as it is wide, **NCBLIT_1x1** (and indeed
|
||||||
any NxN blitter) will stretch an image by a factor of 2 in the vertical
|
any NxN blitter) will stretch an image by a factor of 2 in the vertical
|
||||||
|
@ -2530,9 +2530,9 @@ API int ncvisual_rotate(struct ncvisual* n, double rads)
|
|||||||
API int ncvisual_resize(struct ncvisual* n, int rows, int cols)
|
API int ncvisual_resize(struct ncvisual* n, int rows, int cols)
|
||||||
__attribute__ ((nonnull (1)));
|
__attribute__ ((nonnull (1)));
|
||||||
|
|
||||||
// Inflate each pixel in the image to 'scale'x'scale' pixels. It is an error
|
// Scale the visual to 'rows' X 'columns' pixels, using non-interpolative
|
||||||
// if 'scale' is less than 1. The original color is retained.
|
// (naive) scaling. No new colors will be introduced as a result.
|
||||||
API int ncvisual_inflate(struct ncvisual* n, int scale)
|
API int ncvisual_resize_noninterpolative(struct ncvisual* n, int rows, int cols)
|
||||||
__attribute__ ((nonnull (1)));
|
__attribute__ ((nonnull (1)));
|
||||||
|
|
||||||
// Polyfill at the specified location within the ncvisual 'n', using 'rgba'.
|
// Polyfill at the specified location within the ncvisual 'n', using 'rgba'.
|
||||||
@ -4269,6 +4269,12 @@ channels_set_bg_default(uint64_t* channels){
|
|||||||
return ncchannels_set_bg_default(channels);
|
return ncchannels_set_bg_default(channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inflate each pixel in the image to 'scale'x'scale' pixels. It is an error
|
||||||
|
// if 'scale' is less than 1. The original color is retained.
|
||||||
|
// Deprecated; use ncvisual_resize_noninterpolative(), which this now wraps.
|
||||||
|
API __attribute__ ((deprecated)) int ncvisual_inflate(struct ncvisual* n, int scale)
|
||||||
|
__attribute__ ((nonnull (1)));
|
||||||
|
|
||||||
typedef ncpalette palette256;
|
typedef ncpalette palette256;
|
||||||
|
|
||||||
typedef nccell cell; // FIXME backwards-compat, remove in ABI3
|
typedef nccell cell; // FIXME backwards-compat, remove in ABI3
|
||||||
|
@ -1620,6 +1620,7 @@ resize_bitmap(const uint32_t* bmap, int srows, int scols, size_t sstride,
|
|||||||
if(dstride < dcols * sizeof(*bmap)){
|
if(dstride < dcols * sizeof(*bmap)){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// FIXME if parameters match current setup, do nothing, and return bmap
|
||||||
size_t size = drows * dstride;
|
size_t size = drows * dstride;
|
||||||
uint32_t* ret = (uint32_t*)malloc(size);
|
uint32_t* ret = (uint32_t*)malloc(size);
|
||||||
if(ret == NULL){
|
if(ret == NULL){
|
||||||
|
@ -640,18 +640,7 @@ ncvisual* ncvisual_from_bgra(const void* bgra, int rows, int rowstride, int cols
|
|||||||
|
|
||||||
int ncvisual_resize(ncvisual* nc, int rows, int cols){
|
int ncvisual_resize(ncvisual* nc, int rows, int cols){
|
||||||
if(!visual_implementation){
|
if(!visual_implementation){
|
||||||
size_t dstride = pad_for_image(cols * 4);
|
return ncvisual_resize_noninterpolative(nc, rows, cols);
|
||||||
uint32_t* r = resize_bitmap(nc->data, nc->pixy, nc->pixx, nc->rowstride,
|
|
||||||
rows, cols, dstride);
|
|
||||||
if(r == NULL){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ncvisual_set_data(nc, r, true);
|
|
||||||
nc->rowstride = dstride;
|
|
||||||
nc->pixy = rows;
|
|
||||||
nc->pixx = cols;
|
|
||||||
ncvisual_details_seed(nc);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if(visual_implementation->visual_resize(nc, rows, cols)){
|
if(visual_implementation->visual_resize(nc, rows, cols)){
|
||||||
return -1;
|
return -1;
|
||||||
@ -659,6 +648,21 @@ int ncvisual_resize(ncvisual* nc, int rows, int cols){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ncvisual_resize_noninterpolative(ncvisual* n, int rows, int cols){
|
||||||
|
size_t dstride = pad_for_image(cols * 4);
|
||||||
|
uint32_t* r = resize_bitmap(n->data, n->pixy, n->pixx, n->rowstride,
|
||||||
|
rows, cols, dstride);
|
||||||
|
if(r == NULL){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ncvisual_set_data(n, r, true);
|
||||||
|
n->rowstride = dstride;
|
||||||
|
n->pixy = rows;
|
||||||
|
n->pixx = cols;
|
||||||
|
ncvisual_details_seed(n);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// by the end, disprows/dispcols refer to the number of source rows/cols (in
|
// by the end, disprows/dispcols refer to the number of source rows/cols (in
|
||||||
// pixels), which will be mapped to a region of cells scaled by the encodings).
|
// pixels), which will be mapped to a region of cells scaled by the encodings).
|
||||||
// the blit will begin at placey/placex (in terms of cells). begy/begx define
|
// the blit will begin at placey/placex (in terms of cells). begy/begx define
|
||||||
@ -1119,16 +1123,5 @@ int ncvisual_inflate(ncvisual* n, int scale){
|
|||||||
if(scale <= 0){
|
if(scale <= 0){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
size_t dstride = pad_for_image(4 * n->pixx * scale);
|
return ncvisual_resize_noninterpolative(n, n->pixy * scale, n->pixx * scale);
|
||||||
uint32_t* inflaton = resize_bitmap(n->data, n->pixy, n->pixx, n->rowstride,
|
|
||||||
n->pixy * scale, n->pixx * scale, dstride);
|
|
||||||
if(inflaton == NULL){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ncvisual_set_data(n, inflaton, true);
|
|
||||||
n->pixy *= scale;
|
|
||||||
n->pixx *= scale;
|
|
||||||
n->rowstride = dstride;
|
|
||||||
ncvisual_details_seed(n);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ TEST_CASE("Bitmaps") {
|
|||||||
ncplane_set_base(bigp, "x", 0, white);
|
ncplane_set_base(bigp, "x", 0, white);
|
||||||
CHECK(vopts.n == ncvisual_render(nc_, ncv, &vopts));
|
CHECK(vopts.n == ncvisual_render(nc_, ncv, &vopts));
|
||||||
CHECK(0 == notcurses_render(nc_));
|
CHECK(0 == notcurses_render(nc_));
|
||||||
CHECK(0 == ncvisual_inflate(ncv, 4));
|
CHECK(0 == ncvisual_resize_noninterpolative(ncv, ncv->pixy * 4, ncv->pixx * 4));
|
||||||
CHECK(4 * nc_->tcache.cellpixy == ncv->pixy);
|
CHECK(4 * nc_->tcache.cellpixy == ncv->pixy);
|
||||||
CHECK(4 * nc_->tcache.cellpixx == ncv->pixx);
|
CHECK(4 * nc_->tcache.cellpixx == ncv->pixx);
|
||||||
vopts.y = 1;
|
vopts.y = 1;
|
||||||
@ -345,7 +345,7 @@ TEST_CASE("Bitmaps") {
|
|||||||
vopts.scaling = NCSCALE_SCALE;
|
vopts.scaling = NCSCALE_SCALE;
|
||||||
ncvisual_render(nc_, ncv, &vopts);
|
ncvisual_render(nc_, ncv, &vopts);
|
||||||
CHECK(4 == ncplane_dim_x(vopts.n));
|
CHECK(4 == ncplane_dim_x(vopts.n));
|
||||||
ncvisual_inflate(ncv, 4);
|
CHECK(0 == ncvisual_resize_noninterpolative(ncv, ncv->pixy * 4, ncv->pixx * 4));
|
||||||
vopts.n = nullptr;
|
vopts.n = nullptr;
|
||||||
vopts.y = 2;
|
vopts.y = 2;
|
||||||
vopts.x = 5;
|
vopts.x = 5;
|
||||||
|
@ -136,7 +136,7 @@ TEST_CASE("Visual") {
|
|||||||
};
|
};
|
||||||
auto newn = ncvisual_render(nc_, ncv, &vopts);
|
auto newn = ncvisual_render(nc_, ncv, &vopts);
|
||||||
CHECK(0 == notcurses_render(nc_));
|
CHECK(0 == notcurses_render(nc_));
|
||||||
CHECK(0 == ncvisual_inflate(ncv, 3));
|
CHECK(0 == ncvisual_resize_noninterpolative(ncv, ncv->pixy * 3, ncv->pixx * 3));
|
||||||
CHECK(6 == ncv->pixy);
|
CHECK(6 == ncv->pixy);
|
||||||
CHECK(6 == ncv->pixx);
|
CHECK(6 == ncv->pixx);
|
||||||
for(int y = 0 ; y < 3 ; ++y){
|
for(int y = 0 ; y < 3 ; ++y){
|
||||||
@ -772,7 +772,7 @@ TEST_CASE("Visual") {
|
|||||||
CHECK(0 == ncvisual_blitter_geom(nc_, ncv, &opts, &odimy, &odimx, nullptr, nullptr, nullptr));
|
CHECK(0 == ncvisual_blitter_geom(nc_, ncv, &opts, &odimy, &odimx, nullptr, nullptr, nullptr));
|
||||||
CHECK(ncvisual_render(nc_, ncv, &opts));
|
CHECK(ncvisual_render(nc_, ncv, &opts));
|
||||||
CHECK(0 == notcurses_render(nc_));
|
CHECK(0 == notcurses_render(nc_));
|
||||||
CHECK(0 == ncvisual_inflate(ncv, 2));
|
CHECK(0 == ncvisual_resize_noninterpolative(ncv, ncv->pixy * 2, ncv->pixx * 2));
|
||||||
CHECK(0 == ncvisual_blitter_geom(nc_, ncv, &opts, &ndimy, &ndimx, nullptr, nullptr, nullptr));
|
CHECK(0 == ncvisual_blitter_geom(nc_, ncv, &opts, &ndimy, &ndimx, nullptr, nullptr, nullptr));
|
||||||
CHECK(ndimy == odimy * 2);
|
CHECK(ndimy == odimy * 2);
|
||||||
CHECK(ndimx == odimx * 2);
|
CHECK(ndimx == odimx * 2);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user