diff --git a/src/info/main.c b/src/info/main.c index 2d9f64791..2a9728496 100644 --- a/src/info/main.c +++ b/src/info/main.c @@ -333,10 +333,12 @@ tinfo_debug_bitmaps(struct ncplane* n, const tinfo* ti, const char* indent){ }else{ ncplane_printf(n, "%ssixel colorregs: %u\n", indent, ti->color_registers); } + }else if(ti->pixel_move == NULL){ + ncplane_printf(n, "%siTerm2 graphics support\n", indent); }else if(ti->sixel_maxy_pristine){ - ncplane_printf(n, "%srgba pixel graphics supported\n", indent); + ncplane_printf(n, "%srgba pixel graphics support\n", indent); }else{ - ncplane_printf(n, "%srgba pixel animation supported\n", indent); + ncplane_printf(n, "%srgba pixel animation support\n", indent); } char* path = prefix_data("notcurses.png"); if(path){ diff --git a/src/lib/base64.h b/src/lib/base64.h new file mode 100644 index 000000000..0121478fc --- /dev/null +++ b/src/lib/base64.h @@ -0,0 +1,113 @@ +#ifndef NOTCURSES_PNG +#define NOTCURSES_PNG + +#ifdef __cplusplus +extern "C" { +#endif + +// lookup table for base64 +static unsigned const char b64subs[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +// every 3 RGBA pixels (96 bits) become 16 base64-encoded bytes (128 bits). if +// there are only 2 pixels available, those 64 bits become 12 bytes. if there +// is only 1 pixel available, those 32 bits become 8 bytes. (pcount + 1) * 4 +// bytes are used, plus a null terminator. we thus must receive 17. +static inline void +base64_rgba3(const uint32_t* pixels, size_t pcount, char* b64, bool wipe[static 3], + uint32_t transcolor){ + uint32_t pixel = *pixels++; + unsigned r = ncpixel_r(pixel); + unsigned g = ncpixel_g(pixel); + unsigned b = ncpixel_b(pixel); + // we go ahead and take advantage of kitty's ability to reproduce 8-bit + // alphas by copying it in directly, rather than mapping to {0, 255}. + unsigned a = ncpixel_a(pixel); + if(wipe[0] || rgba_trans_p(pixel, transcolor)){ + a = 0; + } + b64[0] = b64subs[(r & 0xfc) >> 2]; + b64[1] = b64subs[(r & 0x3 << 4) | ((g & 0xf0) >> 4)]; + b64[2] = b64subs[((g & 0xf) << 2) | ((b & 0xc0) >> 6)]; + b64[3] = b64subs[b & 0x3f]; + b64[4] = b64subs[(a & 0xfc) >> 2]; + if(pcount == 1){ + b64[5] = b64subs[(a & 0x3) << 4]; + b64[6] = '='; + b64[7] = '='; + b64[8] = '\0'; + return; + } + b64[5] = (a & 0x3) << 4; + pixel = *pixels++; + r = ncpixel_r(pixel); + g = ncpixel_g(pixel); + b = ncpixel_b(pixel); + a = wipe[1] ? 0 : rgba_trans_p(pixel, transcolor) ? 0 : 255; + b64[5] = b64subs[b64[5] | ((r & 0xf0) >> 4)]; + b64[6] = b64subs[((r & 0xf) << 2) | ((g & 0xc0) >> 6u)]; + b64[7] = b64subs[g & 0x3f]; + b64[8] = b64subs[(b & 0xfc) >> 2]; + b64[9] = b64subs[((b & 0x3) << 4) | ((a & 0xf0) >> 4)]; + if(pcount == 2){ + b64[10] = b64subs[(a & 0xf) << 2]; + b64[11] = '='; + b64[12] = '\0'; + return; + } + b64[10] = (a & 0xf) << 2; + pixel = *pixels; + r = ncpixel_r(pixel); + g = ncpixel_g(pixel); + b = ncpixel_b(pixel); + a = wipe[2] ? 0 : rgba_trans_p(pixel, transcolor) ? 0 : 255; + b64[10] = b64subs[b64[10] | ((r & 0xc0) >> 6)]; + b64[11] = b64subs[r & 0x3f]; + b64[12] = b64subs[(g & 0xfc) >> 2]; + b64[13] = b64subs[((g & 0x3) << 4) | ((b & 0xf0) >> 4)]; + b64[14] = b64subs[((b & 0xf) << 2) | ((a & 0xc0) >> 6)]; + b64[15] = b64subs[a & 0x3f]; + b64[16] = '\0'; +} + +// convert 3 8-bit bytes into 4 base64-encoded characters +static inline void +base64x3(const unsigned char* src, char* b64){ + uint8_t a = src[0] >> 2u; + uint8_t b = ((src[0] & 0x3u) << 4u) + ((src[1] & 0xf0u) >> 4u); + uint8_t c = ((src[1] & 0x0fu) << 2u) + ((src[2] & 0xc0u) >> 6u); + uint8_t d = src[2] & 0x3f; + b64[0] = b64subs[a]; + b64[1] = b64subs[b]; + b64[2] = b64subs[c]; + b64[3] = b64subs[d]; +} + +// finalize a base64 stream with 3 or fewer 8-bit bytes +static inline void +base64final(const unsigned char* src, char* b64, size_t b){ + if(b == 3){ + base64x3(src, b64); + }else if(b == 2){ + uint8_t s0 = src[0] >> 2u; + uint8_t s1 = ((src[0] & 0x3u) << 4u) + ((src[1] & 0xf0u) >> 4u); + uint8_t s2 = ((src[1] & 0x0fu) << 2u); + b64[0] = b64subs[s0]; + b64[1] = b64subs[s1]; + b64[2] = b64subs[s2]; + b64[3] = '='; + }else{ // b == 1 + uint8_t s0 = src[0] >> 2u; + uint8_t s1 = (src[0] & 0x3u) << 4u; + b64[0] = b64subs[s0]; + b64[1] = b64subs[s1]; + b64[2] = '='; + b64[3] = '='; + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/lib/blit.c b/src/lib/blit.c index eb054c2a9..302eacaa2 100644 --- a/src/lib/blit.c +++ b/src/lib/blit.c @@ -63,8 +63,7 @@ rgba_trans_q(const unsigned char* p, uint32_t transcolor){ // Retarded RGBA blitter (ASCII only). static inline int tria_blit_ascii(ncplane* nc, int linesize, const void* data, - int leny, int lenx, const blitterargs* bargs, - int bpp){ + int leny, int lenx, const blitterargs* bargs){ //fprintf(stderr, "ASCII %d X %d @ %d X %d (%p) place: %d X %d\n", leny, lenx, bargs->begy, bargs->begx, data, bargs->u.cell.placey, bargs->u.cell.placex); const bool blendcolors = bargs->flags & NCVISUAL_OPTION_BLEND; int dimy, dimx, x, y; @@ -85,8 +84,8 @@ tria_blit_ascii(ncplane* nc, int linesize, const void* data, if(x < 0){ continue; } - const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * bpp / CHAR_BIT); -//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]); + const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * 4); +//fprintf(stderr, "[%04d/%04d] lsize: %d %02x %02x %02x %02x\n", y, x, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]); nccell* c = ncplane_cell_ref_yx(nc, y, x); // use the default for the background, as that's the only way it's // effective in that case anyway @@ -118,7 +117,7 @@ tria_blit_ascii(ncplane* nc, int linesize, const void* data, // combined with 1:1 pixel aspect ratio. static inline int tria_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, - const blitterargs* bargs, int bpp){ + const blitterargs* bargs){ const bool blendcolors = bargs->flags & NCVISUAL_OPTION_BLEND; //fprintf(stderr, "HALF %d X %d @ %d X %d (%p) place: %d X %d\n", leny, lenx, bargs->begy, bargs->begx, data, bargs->u.cell.placey, bargs->u.cell.placex); uint32_t transcolor = bargs->transcolor; @@ -140,12 +139,12 @@ tria_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, if(x < 0){ continue; } - const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * bpp / CHAR_BIT); + const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * 4); const unsigned char* rgbbase_down = zeroes; if(visy < bargs->begy + leny - 1){ - rgbbase_down = dat + (linesize * (visy + 1)) + (visx * bpp / CHAR_BIT); + rgbbase_down = dat + (linesize * (visy + 1)) + (visx * 4); } -//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]); +//fprintf(stderr, "[%04d/%04d] lsize: %d %02x %02x %02x %02x\n", y, x, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]); nccell* c = ncplane_cell_ref_yx(nc, y, x); // use the default for the background, as that's the only way it's // effective in that case anyway @@ -450,7 +449,7 @@ qtrans_check(nccell* c, unsigned blendcolors, // our disposal (foreground and background), we lose some fidelity. static inline int quadrant_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, - const blitterargs* bargs, int bpp){ + const blitterargs* bargs){ const unsigned nointerpolate = bargs->flags & NCVISUAL_OPTION_NOINTERPOLATE; const bool blendcolors = bargs->flags & NCVISUAL_OPTION_BLEND; int dimy, dimx, x, y; @@ -472,20 +471,20 @@ quadrant_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, if(x < 0){ continue; } - const unsigned char* rgbbase_tl = dat + (linesize * visy) + (visx * bpp / CHAR_BIT); + const unsigned char* rgbbase_tl = dat + (linesize * visy) + (visx * 4); const unsigned char* rgbbase_tr = zeroes; const unsigned char* rgbbase_bl = zeroes; const unsigned char* rgbbase_br = zeroes; if(visx < bargs->begx + lenx - 1){ - rgbbase_tr = dat + (linesize * visy) + ((visx + 1) * bpp / CHAR_BIT); + rgbbase_tr = dat + (linesize * visy) + ((visx + 1) * 4); if(visy < bargs->begy + leny - 1){ - rgbbase_br = dat + (linesize * (visy + 1)) + ((visx + 1) * bpp / CHAR_BIT); + rgbbase_br = dat + (linesize * (visy + 1)) + ((visx + 1) * 4); } } if(visy < bargs->begy + leny - 1){ - rgbbase_bl = dat + (linesize * (visy + 1)) + (visx * bpp / CHAR_BIT); + rgbbase_bl = dat + (linesize * (visy + 1)) + (visx * 4); } -//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_tl[0], rgbbase_tr[1], rgbbase_bl[2], rgbbase_br[3]); +//fprintf(stderr, "[%04d/%04d] lsize: %d %02x %02x %02x %02x\n", y, x, linesize, rgbbase_tl[0], rgbbase_tr[1], rgbbase_bl[2], rgbbase_br[3]); nccell* c = ncplane_cell_ref_yx(nc, y, x); c->channels = 0; c->stylemask = 0; @@ -671,7 +670,7 @@ sex_trans_check(cell* c, const uint32_t rgbas[6], unsigned blendcolors, // our disposal (foreground and background), we lose some fidelity. static inline int sextant_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, - const blitterargs* bargs, int bpp){ + const blitterargs* bargs){ const unsigned nointerpolate = bargs->flags & NCVISUAL_OPTION_NOINTERPOLATE; const bool blendcolors = bargs->flags & NCVISUAL_OPTION_BLEND; int dimy, dimx, x, y; @@ -693,20 +692,20 @@ sextant_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, continue; } uint32_t rgbas[6] = { 0, 0, 0, 0, 0, 0 }; - memcpy(&rgbas[0], (dat + (linesize * visy) + (visx * bpp / CHAR_BIT)), sizeof(*rgbas)); + memcpy(&rgbas[0], (dat + (linesize * visy) + (visx * 4)), sizeof(*rgbas)); if(visx < bargs->begx + lenx - 1){ - memcpy(&rgbas[1], (dat + (linesize * visy) + ((visx + 1) * bpp / CHAR_BIT)), sizeof(*rgbas)); + memcpy(&rgbas[1], (dat + (linesize * visy) + ((visx + 1) * 4)), sizeof(*rgbas)); if(visy < bargs->begy + leny - 1){ - memcpy(&rgbas[3], (dat + (linesize * (visy + 1)) + ((visx + 1) * bpp / CHAR_BIT)), sizeof(*rgbas)); + memcpy(&rgbas[3], (dat + (linesize * (visy + 1)) + ((visx + 1) * 4)), sizeof(*rgbas)); if(visy < bargs->begy + leny - 2){ - memcpy(&rgbas[5], (dat + (linesize * (visy + 2)) + ((visx + 1) * bpp / CHAR_BIT)), sizeof(*rgbas)); + memcpy(&rgbas[5], (dat + (linesize * (visy + 2)) + ((visx + 1) * 4)), sizeof(*rgbas)); } } } if(visy < bargs->begy + leny - 1){ - memcpy(&rgbas[2], (dat + (linesize * (visy + 1)) + (visx * bpp / CHAR_BIT)), sizeof(*rgbas)); + memcpy(&rgbas[2], (dat + (linesize * (visy + 1)) + (visx * 4)), sizeof(*rgbas)); if(visy < bargs->begy + leny - 2){ - memcpy(&rgbas[4], (dat + (linesize * (visy + 2)) + (visx * bpp / CHAR_BIT)), sizeof(*rgbas)); + memcpy(&rgbas[4], (dat + (linesize * (visy + 2)) + (visx * 4)), sizeof(*rgbas)); } } nccell* c = ncplane_cell_ref_yx(nc, y, x); @@ -746,7 +745,7 @@ fold_rgb8(unsigned* restrict r, unsigned* restrict g, unsigned* restrict b, // resolution. always transparent background. static inline int braille_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, - const blitterargs* bargs, int bpp){ + const blitterargs* bargs){ const bool blendcolors = bargs->flags & NCVISUAL_OPTION_BLEND; int dimy, dimx, x, y; int total = 0; // number of cells written @@ -766,7 +765,7 @@ braille_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, if(x < 0){ continue; } - const uint32_t* rgbbase_l0 = (const uint32_t*)(dat + (linesize * visy) + (visx * bpp / CHAR_BIT)); + const uint32_t* rgbbase_l0 = (const uint32_t*)(dat + (linesize * visy) + (visx * 4)); const uint32_t* rgbbase_r0 = &zeroes32; const uint32_t* rgbbase_l1 = &zeroes32; const uint32_t* rgbbase_r1 = &zeroes32; @@ -778,23 +777,23 @@ braille_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, unsigned blends = 0; unsigned egcidx = 0; if(visx < bargs->begx + lenx - 1){ - rgbbase_r0 = (const uint32_t*)(dat + (linesize * visy) + ((visx + 1) * bpp / CHAR_BIT)); + rgbbase_r0 = (const uint32_t*)(dat + (linesize * visy) + ((visx + 1) * 4)); if(visy < bargs->begy + leny - 1){ - rgbbase_r1 = (const uint32_t*)(dat + (linesize * (visy + 1)) + ((visx + 1) * bpp / CHAR_BIT)); + rgbbase_r1 = (const uint32_t*)(dat + (linesize * (visy + 1)) + ((visx + 1) * 4)); if(visy < bargs->begy + leny - 2){ - rgbbase_r2 = (const uint32_t*)(dat + (linesize * (visy + 2)) + ((visx + 1) * bpp / CHAR_BIT)); + rgbbase_r2 = (const uint32_t*)(dat + (linesize * (visy + 2)) + ((visx + 1) * 4)); if(visy < bargs->begy + leny - 3){ - rgbbase_r3 = (const uint32_t*)(dat + (linesize * (visy + 3)) + ((visx + 1) * bpp / CHAR_BIT)); + rgbbase_r3 = (const uint32_t*)(dat + (linesize * (visy + 3)) + ((visx + 1) * 4)); } } } } if(visy < bargs->begy + leny - 1){ - rgbbase_l1 = (const uint32_t*)(dat + (linesize * (visy + 1)) + (visx * bpp / CHAR_BIT)); + rgbbase_l1 = (const uint32_t*)(dat + (linesize * (visy + 1)) + (visx * 4)); if(visy < bargs->begy + leny - 2){ - rgbbase_l2 = (const uint32_t*)(dat + (linesize * (visy + 2)) + (visx * bpp / CHAR_BIT)); + rgbbase_l2 = (const uint32_t*)(dat + (linesize * (visy + 2)) + (visx * 4)); if(visy < bargs->begy + leny - 3){ - rgbbase_l3 = (const uint32_t*)(dat + (linesize * (visy + 3)) + (visx * bpp / CHAR_BIT)); + rgbbase_l3 = (const uint32_t*)(dat + (linesize * (visy + 3)) + (visx * 4)); } } } @@ -836,7 +835,7 @@ braille_blit(ncplane* nc, int linesize, const void* data, int leny, int lenx, egcidx |= 128u; fold_rgb8(&r, &g, &b, rgbbase_r3, &blends); } -//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]); +//fprintf(stderr, "[%04d/%04d] lsize: %d %02x %02x %02x %02x\n", y, x, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]); nccell* c = ncplane_cell_ref_yx(nc, y, x); // use the default for the background, as that's the only way it's // effective in that case anyway @@ -1076,7 +1075,7 @@ int ncblit_rgba(const void* data, int linesize, const struct ncvisual_options* v }, }, }; - return bset->blit(nc, linesize, data, leny, lenx, &bargs, 32); + return bset->blit(nc, linesize, data, leny, lenx, &bargs); } ncblitter_e ncvisual_media_defblitter(const notcurses* nc, ncscale_e scale){ diff --git a/src/lib/internal.h b/src/lib/internal.h index 75b5c930c..e6e2fcb9c 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -404,8 +404,7 @@ typedef struct blitterargs { // from scaling. we might actually need more pixels due to framing concerns, // in which case just assume transparent input pixels where needed. typedef int (*ncblitter)(struct ncplane* n, int linesize, const void* data, - int scaledy, int scaledx, const blitterargs* bargs, - int bpp); + int scaledy, int scaledx, const blitterargs* bargs); // a system for rendering RGBA pixels as text glyphs or sixel/kitty bitmaps struct blitset { @@ -1599,9 +1598,8 @@ const struct blitset* lookup_blitset(const tinfo* tcache, ncblitter_e setid, boo static inline int rgba_blit_dispatch(ncplane* nc, const struct blitset* bset, int linesize, const void* data, - int leny, int lenx, const blitterargs* bargs, - int bpp){ - return bset->blit(nc, linesize, data, leny, lenx, bargs, bpp); + int leny, int lenx, const blitterargs* bargs){ + return bset->blit(nc, linesize, data, leny, lenx, bargs); } static inline const struct blitset* diff --git a/src/lib/iterm.c b/src/lib/iterm.c new file mode 100644 index 000000000..5f4400f7b --- /dev/null +++ b/src/lib/iterm.c @@ -0,0 +1,102 @@ +// the iterm2 graphics protocol is based entirely around containerized formats +// https://iterm2.com/documentation-images.html + +#include +#include "internal.h" +#include "termdesc.h" +#include "sprite.h" +#include "png.h" + +// yank a cell out of the PNG by setting all of its alphas to 0. the alphas +// will be preserved in the auxvec. +int iterm_wipe(sprixel* s, int ycell, int xcell){ + return 0; +} + +// build a cell of the PNG back up by copying auxvec alphas to it. +int iterm_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec){ + return 0; +} + +// spit out the control sequence and data. +int iterm_draw(const ncpile *p, sprixel* s, FILE* out, int y, int x){ + if(fwrite(s->glyph, s->glyphlen, 1, out) != 1){ + return -1; + } + return s->glyphlen; +} + +// damage any cells underneath the graphic, destroying it. +int iterm_scrub(const ncpile* p, sprixel* s){ + return 0; +} + +static int +write_iterm_graphic(sprixel* s, const void* data, int leny, int stride, int lenx){ + s->glyph = NULL; + FILE* fp = open_memstream(&s->glyph, &s->glyphlen); + if(fp == NULL){ + return -1; + } + if(ncfputs("\e]1337;File=inline=1:", fp) == EOF){ + goto err; + } + // FIXME won't we need to pass TAM into write_png_b64()? + if(write_png_b64(data, leny, stride, lenx, fp)){ + goto err; + } + if(fclose(fp) == EOF){ + logerror("Error flushing %zuB (%s)\n", s->glyphlen, strerror(errno)); + free(s->glyph); + return -1; + } + return 0; + +err: + fclose(fp); + free(s->glyph); + s->glyph = NULL; + return -1; +} + +// create an iterm2 control sequence complete with base64-encoded PNG. +int iterm_blit(ncplane* n, int linesize, const void* data, + int leny, int lenx, const blitterargs* bargs){ + int cols = bargs->u.pixel.spx->dimx; + int rows = bargs->u.pixel.spx->dimy; + sprixel* s = bargs->u.pixel.spx; + tament* tam = NULL; + bool reuse = false; + void* png = NULL; + // if we have a sprixel attached to this plane, see if we can reuse it + // (we need the same dimensions) and thus immediately apply its T-A table. + if(n->tam){ + if(n->leny == rows && n->lenx == cols){ + tam = n->tam; + reuse = true; + } + } + int parse_start = 0; + if(!reuse){ + tam = malloc(sizeof(*tam) * rows * cols); + if(tam == NULL){ + goto error; + } + memset(tam, 0, sizeof(*tam) * rows * cols); + } + if(write_iterm_graphic(s, data, leny, linesize, lenx)){ + goto error; + } + if(plane_blit_sixel(s, s->glyph, s->glyphlen, leny, lenx, parse_start, tam) < 0){ + goto error; + } + return 1; + +error: + if(!reuse){ + free(tam); + } + free(png); + free(s->glyph); + return -1; +} diff --git a/src/lib/kitty.c b/src/lib/kitty.c index a7694042d..717c089e6 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -1,4 +1,5 @@ #include "internal.h" +#include "base64.h" // Kitty has its own bitmap graphics protocol, rather superior to DEC Sixel. // A header is written with various directives, followed by a number of @@ -36,10 +37,6 @@ // // https://sw.kovidgoyal.net/kitty/graphics-protocol.html -// lookup table for base64 -static unsigned const char b64subs[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - // convert a base64 character into its equivalent integer 0..63 static inline int b64idx(char b64){ @@ -56,67 +53,6 @@ b64idx(char b64){ } } -// every 3 RGBA pixels (96 bits) become 16 base64-encoded bytes (128 bits). if -// there are only 2 pixels available, those 64 bits become 12 bytes. if there -// is only 1 pixel available, those 32 bits become 8 bytes. (pcount + 1) * 4 -// bytes are used, plus a null terminator. we thus must receive 17. -static inline void -base64_rgba3(const uint32_t* pixels, size_t pcount, char* b64, bool wipe[static 3], - uint32_t transcolor){ - uint32_t pixel = *pixels++; - unsigned r = ncpixel_r(pixel); - unsigned g = ncpixel_g(pixel); - unsigned b = ncpixel_b(pixel); - // we go ahead and take advantage of kitty's ability to reproduce 8-bit - // alphas by copying it in directly, rather than mapping to {0, 255}. - unsigned a = ncpixel_a(pixel); - if(wipe[0] || rgba_trans_p(pixel, transcolor)){ - a = 0; - } - b64[0] = b64subs[(r & 0xfc) >> 2]; - b64[1] = b64subs[(r & 0x3 << 4) | ((g & 0xf0) >> 4)]; - b64[2] = b64subs[((g & 0xf) << 2) | ((b & 0xc0) >> 6)]; - b64[3] = b64subs[b & 0x3f]; - b64[4] = b64subs[(a & 0xfc) >> 2]; - if(pcount == 1){ - b64[5] = b64subs[(a & 0x3) << 4]; - b64[6] = '='; - b64[7] = '='; - b64[8] = '\0'; - return; - } - b64[5] = (a & 0x3) << 4; - pixel = *pixels++; - r = ncpixel_r(pixel); - g = ncpixel_g(pixel); - b = ncpixel_b(pixel); - a = wipe[1] ? 0 : rgba_trans_p(pixel, transcolor) ? 0 : 255; - b64[5] = b64subs[b64[5] | ((r & 0xf0) >> 4)]; - b64[6] = b64subs[((r & 0xf) << 2) | ((g & 0xc0) >> 6u)]; - b64[7] = b64subs[g & 0x3f]; - b64[8] = b64subs[(b & 0xfc) >> 2]; - b64[9] = b64subs[((b & 0x3) << 4) | ((a & 0xf0) >> 4)]; - if(pcount == 2){ - b64[10] = b64subs[(a & 0xf) << 2]; - b64[11] = '='; - b64[12] = '\0'; - return; - } - b64[10] = (a & 0xf) << 2; - pixel = *pixels; - r = ncpixel_r(pixel); - g = ncpixel_g(pixel); - b = ncpixel_b(pixel); - a = wipe[2] ? 0 : rgba_trans_p(pixel, transcolor) ? 0 : 255; - b64[10] = b64subs[b64[10] | ((r & 0xc0) >> 6)]; - b64[11] = b64subs[r & 0x3f]; - b64[12] = b64subs[(g & 0xfc) >> 2]; - b64[13] = b64subs[((g & 0x3) << 4) | ((b & 0xf0) >> 4)]; - b64[14] = b64subs[((b & 0xf) << 2) | ((a & 0xc0) >> 6)]; - b64[15] = b64subs[a & 0x3f]; - b64[16] = '\0'; -} - // null out part of a triplet (a triplet is 3 pixels, which map to 12 bytes, which map to // 16 bytes when base64 encoded). skip the initial |skip| pixels, and null out a maximum // of |max| pixels after that. returns the number of pixels nulled out. |max| must be @@ -782,13 +718,12 @@ error: } int kitty_blit(ncplane* n, int linesize, const void* data, int leny, int lenx, - const blitterargs* bargs, int bpp __attribute__ ((unused))){ + const blitterargs* bargs){ return kitty_blit_core(n, linesize, data, leny, lenx, bargs, false); } int kitty_blit_animated(ncplane* n, int linesize, const void* data, - int leny, int lenx, const blitterargs* bargs, - int bpp __attribute__ ((unused))){ + int leny, int lenx, const blitterargs* bargs){ return kitty_blit_core(n, linesize, data, leny, lenx, bargs, true); } @@ -800,8 +735,7 @@ int kitty_remove(int id, FILE* out){ return 0; } -// removes the kitty bitmap graphic identified by s->id, and damages those -// cells which weren't SPRIXCELL_OPAQUE +// damages cells underneath the graphic which weren't SPRIXCELL_OPAQUE int kitty_scrub(const ncpile* p, sprixel* s){ //fprintf(stderr, "FROM: %d/%d state: %d s->n: %p\n", s->movedfromy, s->movedfromx, s->invalidated, s->n); for(int yy = s->movedfromy ; yy < s->movedfromy + s->dimy && yy < p->dimy ; ++yy){ diff --git a/src/lib/png.c b/src/lib/png.c index 76f7f2c46..3997b19c7 100644 --- a/src/lib/png.c +++ b/src/lib/png.c @@ -1,9 +1,11 @@ #include +#include #include #include #include #include "visual-details.h" #include "internal.h" +#include "base64.h" #include "png.h" // http://www.libpng.org/pub/png/spec/1.2/PNG-Contents.html @@ -16,6 +18,7 @@ // [loser] languages which have difficulty dealing with unsigned values." #define CHUNK_MAX_DATA 0x80000000llu static const unsigned char PNGHEADER[] = "\x89PNG\x0d\x0a\x1a\x0a"; +static const unsigned char IEND[] = "\x00\x00\x00\x00IEND\xae\x42\x60\x82"; // FIXME replace with PCLMULQDQ method (and ARM CRC32 instruction) // this is taken from the PNG reference @@ -61,15 +64,15 @@ crc(const unsigned char *buf, int len){ // compress the ncvisual data suitably for PNG. this requires adding a byte // of filter type (currently always 0) before each scanline =[. static void* -compress_image(const ncvisual* ncv, size_t* dlen){ - z_stream zctx; +compress_image(const void* data, int rows, int rowstride, int cols, size_t* dlen){ + z_stream zctx = { }; int zret; if((zret = deflateInit(&zctx, Z_DEFAULT_COMPRESSION)) != Z_OK){ logerror("Couldn't get a deflate context (%d)\n", zret); return NULL; } // one byte per scanline for adaptive filtering type (always 0 for now) - uint64_t databytes = ncv->pixx * ncv->pixy * 4 + ncv->pixy; + uint64_t databytes = cols * rows * 4 + rows; unsigned long bound = deflateBound(&zctx, databytes); unsigned char* buf = malloc(bound); if(buf == NULL){ @@ -80,22 +83,23 @@ compress_image(const ncvisual* ncv, size_t* dlen){ zctx.next_out = buf; zctx.avail_out = bound; // enough space for a single scanline + filter byte - unsigned char* sbuf = malloc(1 + ncv->pixx * 4); + unsigned char* sbuf = malloc(1 + cols * 4); if(sbuf == NULL){ - logerror("Couldn't allocate %zuB\n", 1 + ncv->pixx * 4); - deflateEnd(&zctx); + logerror("Couldn't allocate %zuB\n", 1 + cols * 4); free(buf); + deflateEnd(&zctx); return NULL; } - for(int i = 0 ; i < ncv->pixy ; ++i){ + for(int i = 0 ; i < rows ; ++i){ if(zctx.avail_out == 0){ free(buf); free(sbuf); + deflateEnd(&zctx); return NULL; } - zctx.avail_in = ncv->pixx * 4 + 1; + zctx.avail_in = cols * 4 + 1; sbuf[0] = 0; - memcpy(sbuf + 1, ncv->data + ncv->rowstride * i, ncv->pixx * 4); + memcpy(sbuf + 1, data + rowstride * i, cols * 4); zctx.next_in = sbuf; if((zret = deflate(&zctx, Z_NO_FLUSH)) != Z_OK){ logerror("Error deflating %dB to %dB (%d)\n", zctx.avail_in, zctx.avail_out, zret); @@ -123,8 +127,9 @@ compress_image(const ncvisual* ncv, size_t* dlen){ // number of bytes necessary to encode (uncompressed) the visual specified by // |ncv|. on error, *|deflated| will be NULL. -size_t compute_png_size(const ncvisual* ncv, void** deflated, size_t* dlen){ - if((*deflated = compress_image(ncv, dlen)) == NULL){ +size_t compute_png_size(const void* data, int rows, int rowstride, int cols, + void** deflated, size_t* dlen){ + if((*deflated = compress_image(data, rows, rowstride, cols, dlen)) == NULL){ return 0; } //fprintf(stderr, "ACTUAL: %zu (0x%02x) (0x%02x)\n", *dlen, (*(char **)deflated)[*dlen - 1], (*(char**)deflated)[20]); @@ -150,21 +155,21 @@ chunk_crc(const unsigned char* buf){ logerror("Chunk length too large (%lu)\n", length); return 0; } - length += 4; // don't use length or crc fields + length += 4; // don't use length or crc fields (but type *is* covered) uint32_t crc32 = htonl(crc(buf + 4, length)); return crc32; } // write the ihdr at |buf|, which is guaranteed to be large enough (25B). static size_t -write_ihdr(const ncvisual* ncv, unsigned char* buf){ +write_ihdr(int rows, int cols, unsigned char buf[static 25]){ uint32_t length = htonl(IHDR_DATA_BYTES); memcpy(buf, &length, 4); static const char ctype[] = "IHDR"; memcpy(buf + 4, ctype, 4); - uint32_t width = htonl(ncv->pixx); + uint32_t width = htonl(cols); memcpy(buf + 8, &width, 4); - uint32_t height = htonl(ncv->pixy); + uint32_t height = htonl(rows); memcpy(buf + 12, &height, 4); uint8_t depth = 8; // 8 bits per channel memcpy(buf + 16, &depth, 1); @@ -208,8 +213,7 @@ write_idats(unsigned char* buf, const unsigned char* data, size_t dlen){ // write the constant 12B IEND chunk at |buf|. it contains no data. static size_t write_iend(unsigned char* buf){ - static const char iend[] = "\x00\x00\x00\x00IEND\xae\x42\x60\x82"; - memcpy(buf, iend, CHUNK_DESC_BYTES); + memcpy(buf, IEND, CHUNK_DESC_BYTES); return CHUNK_DESC_BYTES; } @@ -217,11 +221,11 @@ write_iend(unsigned char* buf){ // deflated data |deflated| of |dlen| bytes. |buf| must be large enough to // write all necessary data; it ought have been sized with compute_png_size(). static size_t -create_png(const ncvisual* ncv, void* buf, const unsigned char* deflated, +create_png(int rows, int cols, void* buf, const unsigned char* deflated, size_t dlen){ size_t written = sizeof(PNGHEADER) - 1; memcpy(buf, PNGHEADER, written); - size_t r = write_ihdr(ncv, (unsigned char*)buf + written); + size_t r = write_ihdr(rows, cols, (unsigned char*)buf + written); written += r; r = write_idats((unsigned char*)buf + written, deflated, dlen); written += r; @@ -239,12 +243,14 @@ mmap_round_size(size_t s){ // write a PNG, creating the buffer ourselves. it must be munmapped. the // resulting length is written to *bsize on success (the file/map might be // larger than this, but the end is immaterial padding). returns MMAP_FAILED -// on a failure. if |fd| is negative, an anonymous map will be made. -void* create_png_mmap(const ncvisual* ncv, size_t* bsize, int fd){ +// on a failure. if |fd| is negative, an anonymous map will be made. |rows| +// and |cols| are in pixels; |rowstride| is in bytes. +void* create_png_mmap(const void* data, int rows, int rowstride, int cols, + size_t* bsize, int fd){ void* deflated; size_t dlen; size_t mlen; - *bsize = compute_png_size(ncv, &deflated, &dlen); + *bsize = compute_png_size(data, rows, rowstride, cols, &deflated, &dlen); if(deflated == NULL){ logerror("Couldn't compress to %d\n", fd); return MAP_FAILED; @@ -262,19 +268,14 @@ void* create_png_mmap(const ncvisual* ncv, size_t* bsize, int fd){ loginfo("Set size of %d to %zuB\n", fd, mlen); } // FIXME hugetlb? - void* map = mmap(NULL, mlen, PROT_WRITE | PROT_READ, -#ifdef MAP_SHARED_VALIDATE - MAP_SHARED_VALIDATE | -#else - MAP_SHARED | -#endif + void* map = mmap(NULL, mlen, PROT_WRITE | PROT_READ, MAP_SHARED | (fd >= 0 ? 0 : MAP_ANONYMOUS), fd, 0); if(map == MAP_FAILED){ - logerror("Couldn't get %zuB map for %d\n", mlen, fd); + logerror("Couldn't get %zuB map for %d (%s)\n", mlen, fd, strerror(errno)); free(deflated); return MAP_FAILED; } - size_t w = create_png(ncv, map, deflated, dlen); + size_t w = create_png(rows, cols, map, deflated, dlen); free(deflated); loginfo("Wrote %zuB PNG to %d\n", w, fd); if(fd >= 0){ @@ -286,3 +287,115 @@ void* create_png_mmap(const ncvisual* ncv, size_t* bsize, int fd){ } return map; } + +struct b64ctx { + unsigned char src[3]; // try to convert three at a time + size_t srcidx; // how many src bytes we have +}; + +static int +fwrite64(const void* src, size_t osize, FILE* fp, struct b64ctx* bctx){ + size_t w = 0; + char b64[4]; + if(bctx->srcidx){ + size_t copy = sizeof(bctx->src) - bctx->srcidx; + // the unlikely event that we don't fill the bctx with our entire chunk... + if(copy > osize){ + memcpy(bctx->src + bctx->srcidx, src, osize); + bctx->srcidx += osize; + return 0; + } + memcpy(bctx->src + bctx->srcidx, src, copy); + base64x3(bctx->src, b64); + bctx->srcidx = 0; + if(fwrite(b64, 4, 1, fp) != 1){ + return -1; + } + w = copy; + } + // the bctx is now guaranteed to be empty + while(w + 3 <= osize){ + base64x3((const unsigned char*)src + w, b64); + if(fwrite(b64, 4, 1, fp) != 1){ + return -1; + } + w += 3; + } + // less than 3 remain; copy them into the bctx for further use + if(w < osize){ + bctx->srcidx = osize - w; + memcpy(bctx->src, src + w, bctx->srcidx); + } + return 1; +} + +static size_t +fwrite_idats(FILE* fp, const unsigned char* data, size_t dlen, + struct b64ctx* bctx){ + static const char ctype[] = "IDAT"; + uint32_t written = 0; + uint32_t dwritten = 0; + while(dlen){ + uint32_t thischunk = dlen; + if(thischunk > CHUNK_MAX_DATA){ + thischunk = CHUNK_MAX_DATA; + } + uint32_t nclen = htonl(thischunk); + if(fwrite64(&nclen, 4, fp, bctx) != 1 || + fwrite64(ctype, 4, fp, bctx) != 1 || + fwrite64(data + dwritten, thischunk, fp, bctx) != 1){ + return 0; + } +// FIXME horrible; PoC; do not retain! +unsigned char* crcbuf = malloc(thischunk + 8); +memcpy(crcbuf, &nclen, 4); +memcpy(crcbuf + 4, ctype, 4); +memcpy(crcbuf + 8, data + dwritten, thischunk); +// END horribleness + uint32_t crc = chunk_crc(crcbuf); +free(crcbuf); // FIXME well a bit more + if(fwrite64(&crc, 4, fp, bctx) != 1){ + return 0; + } + dlen -= thischunk; + dwritten += thischunk; + written += CHUNK_DESC_BYTES + thischunk; + } + return written; +} + +int write_png_b64(const void* data, int rows, int rowstride, int cols, FILE* fp){ + void* deflated; + size_t dlen; + compute_png_size(data, rows, rowstride, cols, &deflated, &dlen); + if(deflated == NULL){ + return -1; + } + struct b64ctx bctx = { }; + if(fwrite64(PNGHEADER, sizeof(PNGHEADER) - 1, fp, &bctx) != 1){ + free(deflated); + return -1; + } + unsigned char ihdr[25]; + write_ihdr(rows, cols, ihdr); + if(fwrite64(ihdr, sizeof(ihdr), fp, &bctx) != 1){ + free(deflated); + return -1; + } + if(fwrite_idats(fp, deflated, dlen, &bctx) == 0){ + free(deflated); + return -1; + } + free(deflated); + if(fwrite64(IEND, sizeof(IEND) - 1, fp, &bctx) != 1){ + return -1; + } + if(bctx.srcidx){ + char b64[4]; + base64final(bctx.src, b64, bctx.srcidx); + if(fwrite(b64, 4, 1, fp) != 1){ + return -1; + } + } + return 0; +} diff --git a/src/lib/png.h b/src/lib/png.h index e7217d67d..7e9b80cea 100644 --- a/src/lib/png.h +++ b/src/lib/png.h @@ -5,11 +5,17 @@ extern "C" { #endif +#include #include struct ncvisual; -void* create_png_mmap(const struct ncvisual* ncv, size_t* bsize, int fd); +void* create_png_mmap(const void* data, int rows, int rowstride, int cols, + size_t* bsize, int fd); + +// create the PNG, encode it using base64, and write it to |fp| +int write_png_b64(const void* data, int rows, int rowstride, int cols, + FILE* fp); #ifdef __cplusplus } diff --git a/src/lib/sixel.c b/src/lib/sixel.c index bd7d65145..a88fab86f 100644 --- a/src/lib/sixel.c +++ b/src/lib/sixel.c @@ -728,7 +728,7 @@ sixel_blit_inner(int leny, int lenx, sixeltable* stab, // |leny| and |lenx| are the scaled output geometry. we take |leny| up to the // nearest multiple of six greater than or equal to |leny|. int sixel_blit(ncplane* n, int linesize, const void* data, int leny, int lenx, - const blitterargs* bargs, int bpp __attribute__ ((unused))){ + const blitterargs* bargs){ int colorregs = bargs->u.pixel.colorregs; if(colorregs > 256){ colorregs = 256; diff --git a/src/lib/sprite.h b/src/lib/sprite.h index c2aa14da3..d486cef88 100644 --- a/src/lib/sprite.h +++ b/src/lib/sprite.h @@ -164,14 +164,19 @@ int kitty_wipe(sprixel* s, int ycell, int xcell); // wipes out a cell by animating an all-transparent cell, and integrating // it with the original image using the animation protocol of 0.20.0+. int kitty_wipe_animation(sprixel* s, int ycell, int xcell); +// wipes out a cell by changing the alpha value throughout the PNG cell to 0. +int iterm_wipe(sprixel* s, int ycell, int xcell); int sixel_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec); int kitty_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec); +int iterm_rebuild(sprixel* s, int ycell, int xcell, uint8_t* auxvec); int kitty_rebuild_animation(sprixel* s, int ycell, int xcell, uint8_t* auxvec); -int kitty_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x); -int kitty_move(sprixel* s, FILE* out, unsigned noscroll); int sixel_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x); +int kitty_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x); +int iterm_draw(const struct ncpile *p, sprixel* s, FILE* out, int y, int x); +int kitty_move(sprixel* s, FILE* out, unsigned noscroll); int sixel_scrub(const struct ncpile* p, sprixel* s); int kitty_scrub(const struct ncpile* p, sprixel* s); +int iterm_scrub(const struct ncpile* p, sprixel* s); int kitty_remove(int id, FILE* out); int kitty_clear_all(FILE* fp); int sixel_init(const tinfo* t, int fd); @@ -182,12 +187,13 @@ uint8_t* sixel_trans_auxvec(const struct tinfo* ti); uint8_t* kitty_trans_auxvec(const struct tinfo* ti); int kitty_commit(FILE* fp, sprixel* s, unsigned noscroll); int sixel_blit(struct ncplane* nc, int linesize, const void* data, - int leny, int lenx, const struct blitterargs* bargs, int bpp); + int leny, int lenx, const struct blitterargs* bargs); int kitty_blit(struct ncplane* nc, int linesize, const void* data, - int leny, int lenx, const struct blitterargs* bargs, int bpp); + int leny, int lenx, const struct blitterargs* bargs); +int iterm_blit(struct ncplane* nc, int linesize, const void* data, + int leny, int lenx, const struct blitterargs* bargs); int kitty_blit_animated(struct ncplane* n, int linesize, const void* data, - int leny, int lenx, const struct blitterargs* bargs, - int bpp); + int leny, int lenx, const struct blitterargs* bargs); #ifdef __cplusplus } diff --git a/src/lib/termdesc.c b/src/lib/termdesc.c index bed5c897c..3bf611176 100644 --- a/src/lib/termdesc.c +++ b/src/lib/termdesc.c @@ -55,6 +55,8 @@ setup_sixel_bitmaps(tinfo* ti, int fd, bool invert80){ ti->pixel_draw = sixel_draw; ti->pixel_scrub = sixel_scrub; ti->pixel_wipe = sixel_wipe; + ti->pixel_remove = NULL; + ti->pixel_move = NULL; ti->pixel_shutdown = sixel_shutdown; ti->pixel_rebuild = sixel_rebuild; ti->pixel_trans_auxvec = sixel_trans_auxvec; @@ -63,6 +65,26 @@ setup_sixel_bitmaps(tinfo* ti, int fd, bool invert80){ sprite_init(ti, fd); } +// iterm2 has a container-based protocol +static inline void +setup_iterm_bitmaps(tinfo* ti, int fd){ + ti->pixel_init = NULL; + ti->pixel_shutdown = NULL; + ti->sprixel_scale_height = 1; + ti->pixel_remove = NULL; + // be awarre: absence of pixel_move plus absence of sixel details is used by + // notcurses-info to determine iTerm2 support. + ti->pixel_move = NULL; + ti->color_registers = 0; + ti->pixel_draw = iterm_draw; + ti->pixel_scrub = iterm_scrub; + ti->pixel_wipe = iterm_wipe; + ti->pixel_rebuild = iterm_rebuild; + ti->pixel_trans_auxvec = kitty_trans_auxvec; + set_pixel_blitter(iterm_blit); + sprite_init(ti, fd); +} + // kitty 0.19.3 didn't have C=1, and thus needs sixel_maxy_pristine. it also // lacked animation, and thus requires the older interface. static inline void @@ -495,9 +517,9 @@ apply_term_heuristics(tinfo* ti, const char* termname, int fd, if(add_smulx_escapes(ti, tablelen, tableused)){ return -1; } - }else{ - termname = "XTerm"; } + // we don't yet want to use the iterm2 protocol in place of sixel + //setup_iterm_bitmaps(ti, fd); }else if(qterm == TERMINAL_XTERM){ termname = "XTerm"; // xterm 357 added color palette escapes XT{PUSH,POP,REPORT}COLORS @@ -511,10 +533,11 @@ apply_term_heuristics(tinfo* ti, const char* termname, int fd, ti->caps.quadrants = true; ti->caps.rgb = true; }else if(qterm == TERMINAL_ITERM){ - // iTerm implements DCS ASU, but no detection for it + // iTerm implements DCS ASU, but has no detection for it if(add_appsync_escapes_dcs(ti, tablelen, tableused)){ return -1; } + setup_iterm_bitmaps(ti, fd); }else if(qterm == TERMINAL_LINUX){ struct utsname un; if(uname(&un) == 0){ diff --git a/src/lib/termdesc.h b/src/lib/termdesc.h index 6b11a01f1..7d219fe78 100644 --- a/src/lib/termdesc.h +++ b/src/lib/termdesc.h @@ -8,8 +8,11 @@ extern "C" { // internal header, not installed #include "input.h" +#include +#include #include #include +#include struct ncpile; struct sprixel; diff --git a/src/lib/visual.c b/src/lib/visual.c index ca619d1f8..76ee4cb85 100644 --- a/src/lib/visual.c +++ b/src/lib/visual.c @@ -88,7 +88,7 @@ int ncvisual_blit(ncvisual* ncv, int rows, int cols, ncplane* n, return -1; } int ret = -1; - if(rgba_blit_dispatch(n, bset, stride, data, rows, cols, barg, 32) >= 0){ + if(rgba_blit_dispatch(n, bset, stride, data, rows, cols, barg) >= 0){ ret = 0; } if(data != ncv->data){ diff --git a/src/media/ffmpeg.c b/src/media/ffmpeg.c index 93baf9eaa..cceb4b57b 100644 --- a/src/media/ffmpeg.c +++ b/src/media/ffmpeg.c @@ -542,7 +542,7 @@ int ffmpeg_blit(ncvisual* ncv, int rows, int cols, ncplane* n, } //fprintf(stderr, "WHN NCV: %d/%d bargslen: %d/%d targ: %d/%d\n", inframe->width, inframe->height, bargs->leny, bargs->lenx, rows, cols); int ret = 0; - if(rgba_blit_dispatch(n, bset, stride, data, rows, cols, bargs, 32) < 0){ + if(rgba_blit_dispatch(n, bset, stride, data, rows, cols, bargs) < 0){ //fprintf(stderr, "rgba dispatch failed!\n"); ret = -1; } diff --git a/src/media/oiio-indep.c b/src/media/oiio-indep.c index b7d757af8..bce0cb5ed 100644 --- a/src/media/oiio-indep.c +++ b/src/media/oiio-indep.c @@ -6,9 +6,8 @@ int oiio_blit_dispatch(struct ncplane* nc, const struct blitset* bset, int linesize, const void* data, - int leny, int lenx, const blitterargs* bargs, - int bpp){ - if(rgba_blit_dispatch(nc, bset, linesize, data, leny, lenx, bargs, bpp) < 0){ + int leny, int lenx, const blitterargs* bargs){ + if(rgba_blit_dispatch(nc, bset, linesize, data, leny, lenx, bargs) < 0){ return -1; } return 0; diff --git a/src/media/oiio.cpp b/src/media/oiio.cpp index 740f4c6b9..5fb9dad16 100644 --- a/src/media/oiio.cpp +++ b/src/media/oiio.cpp @@ -150,7 +150,6 @@ int oiio_blit(struct ncvisual* ncv, int rows, int cols, //fprintf(stderr, "%d/%d -> %d/%d on the resize\n", ncv->pixy, ncv->pixx, rows, cols); void* data = nullptr; int stride; - int pstride; auto ibuf = std::make_unique(); if(ncv->details->ibuf && (ncv->pixx != cols || ncv->pixy != rows)){ // scale it // FIXME need to honor leny/lenx and begy/begx @@ -158,17 +157,15 @@ int oiio_blit(struct ncvisual* ncv, int rows, int cols, if(!OIIO::ImageBufAlgo::resize(*ibuf, *ncv->details->ibuf, "", 0, roi)){ return -1; } - pstride = ibuf->pixel_stride(); stride = ibuf->scanline_stride(); data = ibuf->localpixels(); //fprintf(stderr, "HAVE SOME NEW DATA: %p\n", ibuf->localpixels()); }else{ data = ncv->data; stride = ncv->rowstride; - pstride = 4; // FIXME need pixel_stride() if loaded from oiio... } //std::cerr << "output: " << ibuf->roi() << " stride: " << stride << " pstride: " << pstride << std::endl; - return oiio_blit_dispatch(n, bset, stride, data, rows, cols, bargs, pstride * CHAR_BIT); + return oiio_blit_dispatch(n, bset, stride, data, rows, cols, bargs); } // FIXME before we can enable this, we need build an OIIO::APPBUFFER-style diff --git a/src/media/oiio.h b/src/media/oiio.h index dfa7ae91a..2f5126b41 100644 --- a/src/media/oiio.h +++ b/src/media/oiio.h @@ -21,8 +21,7 @@ ncvisual* oiio_create(void); void oiio_destroy(ncvisual* ncv); int oiio_blit_dispatch(struct ncplane* nc, const struct blitset* bset, int linesize, const void* data, - int leny, int lenx, const blitterargs* bargs, - int bpp); + int leny, int lenx, const blitterargs* bargs); #ifdef __cplusplus }