mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
41
tool/viz/lib/ansitrinsics.h
Normal file
41
tool/viz/lib/ansitrinsics.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_ANSITRINSICS_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_ANSITRINSICS_H_
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
static unsigned char avgb(unsigned char a, unsigned char b) {
|
||||
return (a + b + 1) / 2;
|
||||
}
|
||||
|
||||
static void pavgb(const unsigned char *restrict c,
|
||||
const unsigned char *restrict b, unsigned char *restrict a) {
|
||||
unsigned i;
|
||||
for (i = 0; i < 16; ++i) a[i] = avgb(c[i], b[i]);
|
||||
}
|
||||
|
||||
static void vpavgb(const unsigned char *restrict c,
|
||||
const unsigned char *restrict b, unsigned char *restrict a) {
|
||||
unsigned i;
|
||||
for (i = 0; i < 32; ++i) a[i] = avgb(c[i], b[i]);
|
||||
}
|
||||
|
||||
static void paddsw(const short c[8], const short b[8], short a[8]) {
|
||||
size_t j;
|
||||
for (j = 0; j < 8; ++j) {
|
||||
a[j] = MIN(SHRT_MAX, MAX(SHRT_MIN, b[j] + c[j]));
|
||||
}
|
||||
}
|
||||
|
||||
static void vpaddsw(const short c[16], const short b[16], short a[16]) {
|
||||
size_t j;
|
||||
for (j = 0; j < 16; ++j) {
|
||||
a[j] = MAX(SHRT_MIN, MIN(SHRT_MAX, b[j] + c[j]));
|
||||
}
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_ANSITRINSICS_H_ */
|
101
tool/viz/lib/bilinearscale.c
Normal file
101
tool/viz/lib/bilinearscale.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/twixt8.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/tinymath/emod.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/viz/lib/bilinearscale.h"
|
||||
|
||||
static void ComputeScalingSolution(long dn, long sn, double r, double o,
|
||||
unsigned char pct[dn + 1], int idx[dn + 1]) {
|
||||
long i;
|
||||
double x;
|
||||
o -= .5;
|
||||
o += (r - 1) / 2;
|
||||
for (i = 0; i < dn + 1; ++i) {
|
||||
x = o + i * r;
|
||||
idx[i] = MIN(sn - 1, MAX(0, lround(x)));
|
||||
pct[i] = lround((x - idx[i]) * 255) % 256;
|
||||
}
|
||||
}
|
||||
|
||||
static void BilinearScaler(long dcw, long dyw, long dxw,
|
||||
unsigned char dst[dcw][dyw][dxw], long scw, long syw,
|
||||
long sxw, const unsigned char src[scw][syw][sxw],
|
||||
long c0, long cn, long dyn, long dxn, long syn,
|
||||
long sxn, double ry, double rx, double oy, double ox,
|
||||
int iy[dyn + 1], unsigned char py[dyn + 1],
|
||||
int ix[dxn + 1], unsigned char px[dxn + 1],
|
||||
unsigned char db[dxn], unsigned char sb[2][sxn]) {
|
||||
long c, y, x, b;
|
||||
ComputeScalingSolution(dxn, sxn, rx, ox, px, ix);
|
||||
ComputeScalingSolution(dyn, syn, ry, oy, py, iy);
|
||||
for (c = c0; c < cn; ++c) {
|
||||
for (y = 0; y < dyn; ++y) {
|
||||
memcpy(sb[0], src[c][iy[y + 0]], sxn);
|
||||
memcpy(sb[1], src[c][iy[y + 1]], sxn);
|
||||
for (x = 0; x < dxn; ++x) {
|
||||
db[x] = twixt8(twixt8(sb[0][ix[x]], sb[0][ix[x + 1]], px[x]),
|
||||
twixt8(sb[1][ix[x]], sb[1][ix[x + 1]], px[x]), py[y]);
|
||||
}
|
||||
memcpy(dst[c][y], db, dxn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *BilinearScale(long dcw, long dyw, long dxw,
|
||||
unsigned char dst[dcw][dyw][dxw], long scw, long syw,
|
||||
long sxw, const unsigned char src[scw][syw][sxw], long c0,
|
||||
long cn, long dyn, long dxn, long syn, long sxn, double ry,
|
||||
double rx, double oy, double ox) {
|
||||
if (dyn > 0 && dxn > 0) {
|
||||
if (syn > 0 && sxn > 0) {
|
||||
DCHECK_LE(c0, cn);
|
||||
DCHECK_LE(cn, scw);
|
||||
DCHECK_LE(cn, dcw);
|
||||
DCHECK_LE(syn, syw);
|
||||
DCHECK_LE(sxn, sxw);
|
||||
DCHECK_LE(dyn, dyw);
|
||||
DCHECK_LE(dxn, dxw);
|
||||
DCHECK_LT(bsrl(cn) + bsrl(syn) + bsrl(sxn), 32);
|
||||
DCHECK_LT(bsrl(cn) + bsrl(dyn) + bsrl(dxn), 32);
|
||||
BilinearScaler(dcw, dyw, dxw, dst, scw, syw, sxw, src, c0, cn, dyn, dxn,
|
||||
syn, sxn, ry, rx, oy, ox,
|
||||
gc(xmemalign(64, ROUNDUP(sizeof(int) * (dyn + 1), 64))),
|
||||
gc(xmemalign(64, ROUNDUP(dyn + 1, 64))),
|
||||
gc(xmemalign(64, ROUNDUP(sizeof(int) * (dxn + 1), 64))),
|
||||
gc(xmemalign(64, ROUNDUP(dxn + 1, 64))),
|
||||
gc(xmemalign(64, ROUNDUP(dxn, 64))),
|
||||
gc(xmemalign(64, ROUNDUP(sxn, 64) * 2)));
|
||||
} else {
|
||||
memset(dst[c0], 0, &dst[cn][0][0] - &dst[c0][0][0]);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
14
tool/viz/lib/bilinearscale.h
Normal file
14
tool/viz/lib/bilinearscale.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_BILINEARSCALE_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_BILINEARSCALE_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void *BilinearScale(long dcw, long dyw, long dxw,
|
||||
unsigned char dst[dcw][dyw][dxw], long scw, long syw,
|
||||
long sxw, const unsigned char src[scw][syw][sxw], long,
|
||||
long, long, long, long, long, double, double, double,
|
||||
double);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_BILINEARSCALE_H_ */
|
30
tool/viz/lib/boxblur.c
Normal file
30
tool/viz/lib/boxblur.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "tool/viz/lib/convolve.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
|
||||
void boxblur(struct Graphic *g) {
|
||||
static const float kBoxBlurKernel[3][3] = {
|
||||
{+1.0, +1.0, +1.0},
|
||||
{+1.0, +1.0, +1.0},
|
||||
{+1.0, +1.0, +1.0},
|
||||
};
|
||||
convolve(g->yn, g->xn, g->b.p, 3, kBoxBlurKernel, 9.0, 0);
|
||||
}
|
40
tool/viz/lib/convoindex.c
Normal file
40
tool/viz/lib/convoindex.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "tool/viz/lib/convolution.h"
|
||||
|
||||
/**
|
||||
* Creates padded array of array indices.
|
||||
*
|
||||
* This can be used to virtualize the memory of a matrix in one
|
||||
* dimension, to make it easy to avoid out-of-bounds access.
|
||||
*
|
||||
* @return value needs free(retval - leftpad)
|
||||
*/
|
||||
unsigned *convoindex(unsigned leftpad, unsigned n, unsigned rightpad) {
|
||||
unsigned i, j, *p;
|
||||
if ((p = malloc(sizeof(unsigned) * (leftpad + n + rightpad)))) {
|
||||
i = 0;
|
||||
for (j = 0; j < leftpad; ++j) p[i++] = 0;
|
||||
for (j = 0; j < n; ++j) p[i++] = j;
|
||||
for (j = 0; j < rightpad; ++j) p[i++] = n - 1;
|
||||
}
|
||||
return p;
|
||||
}
|
67
tool/viz/lib/convolution.h
Normal file
67
tool/viz/lib/convolution.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_CONVOLUTION_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_CONVOLUTION_H_
|
||||
#include "dsp/core/q.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
/* clang-format off */
|
||||
|
||||
#define CONVROUND(X) ((int)lrint(X))
|
||||
|
||||
#define CONVOLVE1X1(COEFFICIENT, DY, DX) (COEFFICIENT * (img[iy[y DY]][ix[x DX]]))
|
||||
#define CONVOLVE1X12(IMG, COEFFICIENT, DY, DX) (COEFFICIENT * IMG[iy[y DY]][ix[x DX]])
|
||||
|
||||
#define CONVOLVE3X3(NORMALIZER, \
|
||||
C00, C01, C02, \
|
||||
C10, C11, C12, \
|
||||
C20, C21, C22) \
|
||||
(NORMALIZER * \
|
||||
(CONVOLVE1X1(C00,-1,-1)+CONVOLVE1X1(C01,-1,+0)+CONVOLVE1X1(C02,-1,+1)+ \
|
||||
CONVOLVE1X1(C10,+0,-1)+CONVOLVE1X1(C11,+0,+0)+CONVOLVE1X1(C12,+0,+1)+ \
|
||||
CONVOLVE1X1(C20,+1,-1)+CONVOLVE1X1(C21,+1,+0)+CONVOLVE1X1(C22,+1,+1)))
|
||||
|
||||
#define CONVOLVE3X6(NORMALIZER, \
|
||||
C00, C01, C02, \
|
||||
C10, C11, C12, \
|
||||
C20, C21, C22) \
|
||||
(NORMALIZER * \
|
||||
(CONVOLVE1X1(C00/2.f,-1,-1)+CONVOLVE1X1(C01/2.f,-1,+0)+CONVOLVE1X1(C02/2.f,-1,+1)+ \
|
||||
CONVOLVE1X1(C00/2.f,-1,-1)+CONVOLVE1X1(C01/2.f,-1,+0)+CONVOLVE1X1(C02/2.f,-1,+1)+ \
|
||||
CONVOLVE1X1(C10/2.f,+0,-1)+CONVOLVE1X1(C11/2.f,+0,+0)+CONVOLVE1X1(C12/2.f,+0,+1)+ \
|
||||
CONVOLVE1X1(C10/2.f,+0,-1)+CONVOLVE1X1(C11/2.f,+0,+0)+CONVOLVE1X1(C12/2.f,+0,+1)+ \
|
||||
CONVOLVE1X1(C20/2.f,+1,-1)+CONVOLVE1X1(C21/2.f,+1,+0)+CONVOLVE1X1(C22/2.f,+1,+1)+ \
|
||||
CONVOLVE1X1(C20/2.f,+1,-1)+CONVOLVE1X1(C21/2.f,+1,+0)+CONVOLVE1X1(C22/2.f,+1,+1)))
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#define CONVOLVE5X5(M, NORM, IMG, C00, C01, C02, C03, C04, C10, C11, C12, C13, \
|
||||
C14, C20, C21, C22, C23, C24, C30, C31, C32, C33, C34, \
|
||||
C40, C41, C42, C43, C44) \
|
||||
QRS(M, (CONVOLVE1X12(IMG, CONVROUND((NORM * C00) * (1 << M)), -2, -2) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C01) * (1 << M)), -2, -1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C02) * (1 << M)), -2, +0) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C03) * (1 << M)), -2, +1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C04) * (1 << M)), -2, +2) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C10) * (1 << M)), -1, -2) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C11) * (1 << M)), -1, -1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C12) * (1 << M)), -1, +0) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C13) * (1 << M)), -1, +1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C14) * (1 << M)), -1, +2) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C20) * (1 << M)), +0, -2) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C21) * (1 << M)), +0, -1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C22) * (1 << M)), +0, +0) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C23) * (1 << M)), +0, +1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C24) * (1 << M)), +0, +2) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C30) * (1 << M)), +1, -2) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C31) * (1 << M)), +1, -1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C32) * (1 << M)), +1, +0) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C33) * (1 << M)), +1, +1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C34) * (1 << M)), +1, +2) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C40) * (1 << M)), +2, -2) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C41) * (1 << M)), +2, -1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C42) * (1 << M)), +2, +0) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C43) * (1 << M)), +2, +1) + \
|
||||
CONVOLVE1X12(IMG, CONVROUND((NORM * C44) * (1 << M)), +2, +2)))
|
||||
|
||||
unsigned *convoindex(unsigned, unsigned, unsigned) mallocesque;
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_CONVOLUTION_H_ */
|
42
tool/viz/lib/convolve.h
Normal file
42
tool/viz/lib/convolve.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_CONVOLVE_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_CONVOLVE_H_
|
||||
#include "libc/bits/xmmintrin.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
forceinline void convolve(unsigned yn, unsigned xn, __m128 img[yn][xn], int KW,
|
||||
const float kernel[KW][KW], float C1, float C2) {
|
||||
/* TODO(jart): nontemporal herringbone strategy */
|
||||
float f;
|
||||
struct Graphic g;
|
||||
unsigned y, x, i, j;
|
||||
__v4sf p, kflip[KW][KW], (*tmp)[yn][xn];
|
||||
for (i = 0; i < KW; ++i) {
|
||||
for (j = 0; j < KW; ++j) {
|
||||
f = kernel[i][j] / C1;
|
||||
kflip[KW - i - 1][KW - j - 1] = (__v4sf){f, f, f, f};
|
||||
}
|
||||
}
|
||||
memset(&g, 0, sizeof(g));
|
||||
resizegraphic(&g, yn, xn);
|
||||
tmp = g.b.p;
|
||||
for (y = 0; y < yn - KW; ++y) {
|
||||
for (x = 0; x < xn - KW; ++x) {
|
||||
memset(&p, 0, sizeof(p));
|
||||
for (i = 0; i < KW; ++i) {
|
||||
for (j = 0; j < KW; ++j) {
|
||||
p += img[y + i][x + j] * kflip[i][j] + C2;
|
||||
}
|
||||
}
|
||||
memcpy(&(*tmp)[y + KW / 2][x + KW / 2], &p, sizeof(p));
|
||||
}
|
||||
}
|
||||
memcpy(img, tmp, yn * xn * sizeof(img[0][0]));
|
||||
bfree(&g.b);
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_CONVOLVE_H_ */
|
124
tool/viz/lib/dither.c
Normal file
124
tool/viz/lib/dither.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/quant.h"
|
||||
#include "libc/bits/hilbert.h"
|
||||
#include "libc/bits/morton.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
#include "tool/viz/lib/knobs.h"
|
||||
|
||||
#define CLAMP(X) MIN(255, MAX(0, X))
|
||||
|
||||
struct Dither {
|
||||
struct {
|
||||
int m5[32 * 32][2];
|
||||
int m4[16 * 16][2];
|
||||
int m3[8 * 8][2];
|
||||
int m2[4 * 4][2];
|
||||
int m1[2 * 2][2];
|
||||
int m0[2 * 2][2];
|
||||
} memory;
|
||||
struct Chunk {
|
||||
long b;
|
||||
void *c;
|
||||
} chunks[6];
|
||||
} kDither;
|
||||
|
||||
static struct Chunk ChunkInit(long b, int c[b * b][2]) {
|
||||
long i;
|
||||
axdx_t h;
|
||||
for (i = 0; i < b * b; ++i) {
|
||||
h = unhilbert(b, i);
|
||||
c[i][0] = h.ax;
|
||||
c[i][1] = h.dx;
|
||||
}
|
||||
return (struct Chunk){b, c};
|
||||
}
|
||||
|
||||
static optimizesize void DitherInit(struct Dither *d) {
|
||||
d->chunks[0] = ChunkInit(1 << 0, d->memory.m0);
|
||||
d->chunks[1] = ChunkInit(1 << 1, d->memory.m1);
|
||||
d->chunks[2] = ChunkInit(1 << 2, d->memory.m2);
|
||||
d->chunks[3] = ChunkInit(1 << 3, d->memory.m3);
|
||||
d->chunks[4] = ChunkInit(1 << 4, d->memory.m4);
|
||||
d->chunks[5] = ChunkInit(1 << 5, d->memory.m5);
|
||||
}
|
||||
|
||||
static int GetQuantError(unsigned char r, unsigned char g, unsigned char b) {
|
||||
struct TtyRgb q = tty2rgb(rgb2tty(r, g, b));
|
||||
return ((r - q.r) + (g - q.g) + (b - q.b)) / 3;
|
||||
}
|
||||
|
||||
static int SerpentineDitherSq2(long yw, long xw, unsigned char rgb[3][yw][xw],
|
||||
long y, long x, long b, const int ci[b * b][2],
|
||||
int e) {
|
||||
long i;
|
||||
for (i = 0; i < b * b; ++i) {
|
||||
e = GetQuantError((rgb[0][y + ci[i][0]][x + ci[i][1]] =
|
||||
CLAMP(rgb[0][y + ci[i][0]][x + ci[i][1]] + e)),
|
||||
(rgb[1][y + ci[i][0]][x + ci[i][1]] =
|
||||
CLAMP(rgb[1][y + ci[i][0]][x + ci[i][1]] + e)),
|
||||
(rgb[2][y + ci[i][0]][x + ci[i][1]] =
|
||||
CLAMP(rgb[2][y + ci[i][0]][x + ci[i][1]] + e))) *
|
||||
15 / 16;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static void SerpentineDither(long yw, long xw, unsigned char rgb[3][yw][xw],
|
||||
long yn, long xn, long y, long x, long r,
|
||||
const struct Dither *d) {
|
||||
void *c;
|
||||
long b, e, i, j, n, m;
|
||||
e = 0;
|
||||
b = d->chunks[r].b;
|
||||
c = d->chunks[r].c;
|
||||
n = (yn - y) / b;
|
||||
m = (xn - x) / b;
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j < m; ++j) {
|
||||
e = SerpentineDitherSq2(yw, xw, rgb, y + i * b, x + j * b, b, c, 0);
|
||||
}
|
||||
}
|
||||
if (r) {
|
||||
SerpentineDither(yw, xw, rgb, yn, xn, y + 0 * 0, x + m * b, r - 1, d);
|
||||
SerpentineDither(yw, xw, rgb, yn, xn, y + n * b, x + 0 * 0, r - 1, d);
|
||||
SerpentineDither(yw, xw, rgb, yn, xn, y + n * b, x + m * b, r - 1, d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes color banding go away a little in low color modes.
|
||||
*/
|
||||
void dither(long yw, long xw, unsigned char rgb[3][yw][xw], long yn, long xn) {
|
||||
static bool once;
|
||||
if (!once) {
|
||||
DitherInit(&kDither);
|
||||
once = true;
|
||||
}
|
||||
SerpentineDither(yw, xw, rgb, yn, xn, 0, 0, ARRAYLEN(kDither.chunks) - 1,
|
||||
&kDither);
|
||||
}
|
54
tool/viz/lib/doublechrominance.S
Normal file
54
tool/viz/lib/doublechrominance.S
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
/ Duplicates chrominance samples horizontally, e.g.
|
||||
/
|
||||
/ 12345678--------
|
||||
/ → 1122334455667788
|
||||
/
|
||||
/ @param %edi is size of %rsi array in bytes
|
||||
/ @param %rsi is char[edi/16][16] output and %rsi==%rdx is OK
|
||||
/ @param %rdx is char[edi/16][8] input
|
||||
/ @return %rax is %rsi
|
||||
doublechrominance:
|
||||
.leafprologue
|
||||
.profilable
|
||||
shr $1,%edi # backwards algorithm
|
||||
jbe 1f # do nothing if !n || n%2
|
||||
mov %edi,%ecx
|
||||
shr $4,%ecx
|
||||
shl $4,%ecx
|
||||
0: cmp %edi,%ecx
|
||||
je 0f
|
||||
dec %edi
|
||||
movzbl (%rdx,%rdi),%eax
|
||||
mov %al,(%rsi,%rdi,2)
|
||||
mov %al,1(%rsi,%rdi,2)
|
||||
jmp 0b
|
||||
0: sub $8,%edi
|
||||
movq (%rdx,%rdi),%xmm0
|
||||
punpcklbw %xmm0,%xmm0
|
||||
movdqu %xmm0,(%rsi,%rdi,2)
|
||||
jnz 0b
|
||||
1: mov %rsi,%rax
|
||||
.leafepilogue
|
||||
.endfn doublechrominance,globl
|
||||
.yoink __FILE__
|
31
tool/viz/lib/emboss.c
Normal file
31
tool/viz/lib/emboss.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "tool/viz/lib/convolve.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
/* clang-format off */
|
||||
|
||||
void emboss(struct Graphic *g) {
|
||||
static const float kEmbossKernel[3][3] = {
|
||||
{-2.0, -1.0, +0.0},
|
||||
{-1.0, +1.0, +1.0},
|
||||
{+0.0, +1.0, +2.0},
|
||||
};
|
||||
convolve(g->yn, g->xn, g->b.p, 3, kEmbossKernel, 1, 0);
|
||||
}
|
59
tool/viz/lib/formatmatrix-byte.c
Normal file
59
tool/viz/lib/formatmatrix-byte.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
#include "tool/viz/lib/stringbuilder.h"
|
||||
|
||||
static void *ConvertByteMatrixToStringTable(long yn, long xn, char *T[yn][xn],
|
||||
const unsigned char M[yn][xn]) {
|
||||
long y, x;
|
||||
assert(yn && xn && !T[0][0]);
|
||||
for (y = 0; y < yn; ++y) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
T[y][x] = xasprintf("%d", M[y][x]);
|
||||
}
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
void FormatMatrixByte(long yn, long xn, const unsigned char M[yn][xn],
|
||||
int emit(), void *arg, StringTableFormatter formatter,
|
||||
const char *param1, const char *param2,
|
||||
const char *param3) {
|
||||
FreeStringTableCells(
|
||||
yn, xn,
|
||||
formatter(yn, xn,
|
||||
ConvertByteMatrixToStringTable(
|
||||
yn, xn, gc(calloc(yn * xn, sizeof(char *))), M),
|
||||
emit, arg, param1, param2, param3));
|
||||
}
|
||||
|
||||
char *StringifyMatrixByte(long yn, long xn, const unsigned char M[yn][xn],
|
||||
StringTableFormatter formatter, const char *param1,
|
||||
const char *param2, const char *param3) {
|
||||
struct StringBuilder *sb = NewStringBuilder();
|
||||
FormatMatrixByte(yn, xn, M, StringBuilderAppend, sb, formatter, param1,
|
||||
param2, param3);
|
||||
return FreeStringBuilder(sb);
|
||||
}
|
65
tool/viz/lib/formatmatrix-double.c
Normal file
65
tool/viz/lib/formatmatrix-double.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
#include "tool/viz/lib/stringbuilder.h"
|
||||
|
||||
static void *ConvertMatrixToStringTable(long yn, long xn, char *T[yn][xn],
|
||||
const double M[yn][xn], double digs,
|
||||
double rounder(double)) {
|
||||
double f;
|
||||
long y, x;
|
||||
assert(yn && xn && !T[0][0]);
|
||||
for (y = 0; y < yn; ++y) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
T[y][x] = xdtoa(RoundDecimalPlaces(M[y][x], digs, rounder));
|
||||
}
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
void FormatMatrixDouble(long yn, long xn, const double M[yn][xn], int emit(),
|
||||
void *arg, StringTableFormatter formatter,
|
||||
const char *param1, const char *param2,
|
||||
const char *param3, double digs,
|
||||
double rounder(double)) {
|
||||
FreeStringTableCells(
|
||||
yn, xn,
|
||||
formatter(
|
||||
yn, xn,
|
||||
ConvertMatrixToStringTable(
|
||||
yn, xn, gc(calloc(yn * xn, sizeof(char *))), M, digs, rounder),
|
||||
emit, arg, param1, param2, param3));
|
||||
}
|
||||
|
||||
char *StringifyMatrixDouble(long yn, long xn, const double M[yn][xn],
|
||||
StringTableFormatter formatter, const char *param1,
|
||||
const char *param2, const char *param3, double digs,
|
||||
double rounder(double)) {
|
||||
struct StringBuilder *sb = NewStringBuilder();
|
||||
FormatMatrixDouble(yn, xn, M, StringBuilderAppend, sb, formatter, param1,
|
||||
param2, param3, digs, rounder);
|
||||
return FreeStringBuilder(sb);
|
||||
}
|
57
tool/viz/lib/formatmatrix-float.c
Normal file
57
tool/viz/lib/formatmatrix-float.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
|
||||
static void *ConvertFloatToDoubleMatrix(long yn, long xn, double Md[yn][xn],
|
||||
const float Mf[yn][xn]) {
|
||||
long y, x;
|
||||
for (y = 0; y < yn; ++y) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
Md[y][x] = Mf[y][x];
|
||||
}
|
||||
}
|
||||
return Md;
|
||||
}
|
||||
|
||||
void FormatMatrixFloat(long yn, long xn, const float M[yn][xn], int emit(),
|
||||
void *arg, StringTableFormatter formatter,
|
||||
const char *param1, const char *param2,
|
||||
const char *param3, double digs,
|
||||
double rounder(double)) {
|
||||
FormatMatrixDouble(yn, xn,
|
||||
ConvertFloatToDoubleMatrix(
|
||||
yn, xn, gc(xcalloc(yn * xn, sizeof(double))), M),
|
||||
emit, arg, formatter, param1, param2, param3, digs,
|
||||
rounder);
|
||||
}
|
||||
|
||||
char *StringifyMatrixFloat(long yn, long xn, const float M[yn][xn],
|
||||
StringTableFormatter formatter, const char *param1,
|
||||
const char *param2, const char *param3, double digs,
|
||||
double rounder(double)) {
|
||||
return StringifyMatrixDouble(
|
||||
yn, xn,
|
||||
ConvertFloatToDoubleMatrix(yn, xn, gc(xcalloc(yn * xn, sizeof(double))),
|
||||
M),
|
||||
formatter, param1, param2, param3, digs, rounder);
|
||||
}
|
59
tool/viz/lib/formatmatrix-short.c
Normal file
59
tool/viz/lib/formatmatrix-short.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
#include "tool/viz/lib/stringbuilder.h"
|
||||
|
||||
static void *ConvertShortMatrixToStringTable(long yn, long xn, char *T[yn][xn],
|
||||
const short M[yn][xn]) {
|
||||
long y, x;
|
||||
assert(yn && xn && !T[0][0]);
|
||||
for (y = 0; y < yn; ++y) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
T[y][x] = xasprintf("%d", M[y][x]);
|
||||
}
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
void FormatMatrixShort(long yn, long xn, const short M[yn][xn], int emit(),
|
||||
void *arg, StringTableFormatter formatter,
|
||||
const char *param1, const char *param2,
|
||||
const char *param3) {
|
||||
FreeStringTableCells(
|
||||
yn, xn,
|
||||
formatter(yn, xn,
|
||||
ConvertShortMatrixToStringTable(
|
||||
yn, xn, gc(xcalloc(yn * xn, sizeof(char *))), M),
|
||||
emit, arg, param1, param2, param3));
|
||||
}
|
||||
|
||||
char *StringifyMatrixShort(long yn, long xn, const short M[yn][xn],
|
||||
StringTableFormatter formatter, const char *param1,
|
||||
const char *param2, const char *param3) {
|
||||
struct StringBuilder *sb = NewStringBuilder();
|
||||
FormatMatrixShort(yn, xn, M, StringBuilderAppend, sb, formatter, param1,
|
||||
param2, param3);
|
||||
return FreeStringBuilder(sb);
|
||||
}
|
126
tool/viz/lib/formatstringtable-assembly.c
Normal file
126
tool/viz/lib/formatstringtable-assembly.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/unicode/unicode.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
|
||||
#define STREQ(A, B) (strcasecmp(A, B) == 0)
|
||||
|
||||
static int GetArrayAlignment(long yn, long xn, int w, int align) {
|
||||
/* abi guaranteed to 16 after which gcc / clang disagree */
|
||||
int i, r;
|
||||
r = i = align;
|
||||
while ((i *= 2) <= __BIGGEST_ALIGNMENT__) {
|
||||
if (yn * xn * w >= i) {
|
||||
r = i;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static const char *GetStorageSpecifier(const char *type, int *out_width,
|
||||
int *out_align) {
|
||||
if (STREQ(type, "unsigned char") || STREQ(type, "char") ||
|
||||
STREQ(type, "signed char")) {
|
||||
*out_width = 1;
|
||||
*out_align = 1;
|
||||
return "byte";
|
||||
} else if (STREQ(type, "unsigned short") || STREQ(type, "short") ||
|
||||
STREQ(type, "signed short")) {
|
||||
*out_width = 2;
|
||||
*out_align = 2;
|
||||
return "short";
|
||||
} else if (STREQ(type, "unsigned int") || STREQ(type, "unsigned") ||
|
||||
STREQ(type, "int") || STREQ(type, "signed int")) {
|
||||
*out_width = 4;
|
||||
*out_align = 4;
|
||||
return "long";
|
||||
} else if (STREQ(type, "unsigned long") || STREQ(type, "unsigned") ||
|
||||
STREQ(type, "long") || STREQ(type, "signed long")) {
|
||||
*out_width = 8;
|
||||
*out_align = 8;
|
||||
return "quad";
|
||||
} else if (STREQ(type, "float")) {
|
||||
*out_width = 4;
|
||||
*out_align = 4;
|
||||
return "float";
|
||||
} else if (STREQ(type, "double")) {
|
||||
*out_width = 8;
|
||||
*out_align = 8;
|
||||
return "double";
|
||||
} else {
|
||||
*out_width = __BIGGEST_ALIGNMENT__;
|
||||
*out_align = __BIGGEST_ALIGNMENT__;
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
static void EmitSection(long yn, long xn, int w, int arrayalign, int emit(),
|
||||
void *a) {
|
||||
char alignstr[20];
|
||||
uint64toarray_radix10(arrayalign, alignstr);
|
||||
if (arrayalign <= 8 && yn * xn * w == 8) {
|
||||
emit("\t.rodata.cst", a);
|
||||
emit("8\n", a);
|
||||
} else if (arrayalign <= 16 && yn * xn * w == 16) {
|
||||
emit("\t.rodata.cst", a);
|
||||
emit("16\n", a);
|
||||
} else if (arrayalign <= 32 && yn * xn * w == 32) {
|
||||
emit("\t.rodata.cst", a);
|
||||
emit("32\n", a);
|
||||
} else if (arrayalign <= 64 && yn * xn * w == 64) {
|
||||
emit("\t.rodata.cst", a);
|
||||
emit("64\n", a);
|
||||
} else {
|
||||
emit("\t.rodata\n", a);
|
||||
emit("\t.align\t", a);
|
||||
emit(alignstr, a);
|
||||
emit("\n", a);
|
||||
}
|
||||
}
|
||||
|
||||
void *FormatStringTableAsAssembly(long yn, long xn, const char *const T[yn][xn],
|
||||
int emit(), void *a, const char *type,
|
||||
const char *name, const char *scope) {
|
||||
int w, align;
|
||||
const char *storage;
|
||||
char ynstr[20], xnstr[20];
|
||||
name = firstnonnull(name, "M");
|
||||
storage = GetStorageSpecifier(firstnonnull(type, "long"), &w, &align);
|
||||
uint64toarray_radix10(yn, ynstr);
|
||||
uint64toarray_radix10(xn, xnstr);
|
||||
EmitSection(yn, xn, w, GetArrayAlignment(yn, xn, w, align), emit, a);
|
||||
emit(name, a);
|
||||
emit(":", a);
|
||||
if (strwidth(name) >= 8) emit("\n", a);
|
||||
FormatStringTable(yn, xn, T, emit, a, gc(xstrcat("\t.", storage, "\t")), ",",
|
||||
"\n");
|
||||
emit("\t.endobj\t", a);
|
||||
emit(name, a);
|
||||
emit(",", a);
|
||||
emit(firstnonnull(scope, "globl"), a);
|
||||
emit("\n\t.previous\n", a);
|
||||
return (/* unconst */ void *)T;
|
||||
}
|
28
tool/viz/lib/formatstringtable-assertion.c
Normal file
28
tool/viz/lib/formatstringtable-assertion.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
|
||||
void *FormatStringTableForAssertion(long yn, long xn,
|
||||
const char *const T[yn][xn], int emit(),
|
||||
void *a, const char *ignored1,
|
||||
const char *ignored2,
|
||||
const char *ignored3) {
|
||||
return FormatStringTable(yn, xn, T, emit, a, "\n", " ", "");
|
||||
}
|
26
tool/viz/lib/formatstringtable-basic.c
Normal file
26
tool/viz/lib/formatstringtable-basic.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
|
||||
void *FormatStringTableBasic(long yn, long xn, const char *const T[yn][xn],
|
||||
int emit(), void *a, const char *ignored1,
|
||||
const char *ignored2, const char *ignored3) {
|
||||
return FormatStringTable(yn, xn, T, emit, a, "", " ", "\n");
|
||||
}
|
41
tool/viz/lib/formatstringtable-code.c
Normal file
41
tool/viz/lib/formatstringtable-code.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/conv/itoa.h"
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
|
||||
void *FormatStringTableAsCode(long yn, long xn, const char *const T[yn][xn],
|
||||
int emit(), void *arg, const char *type,
|
||||
const char *name, const char *ignored) {
|
||||
char ynstr[20], xnstr[20];
|
||||
uint64toarray_radix10(yn, ynstr);
|
||||
uint64toarray_radix10(xn, xnstr);
|
||||
emit(type, arg);
|
||||
emit(" ", arg);
|
||||
emit(firstnonnull(name, "M"), arg);
|
||||
emit("[", arg);
|
||||
emit(ynstr, arg);
|
||||
emit("][", arg);
|
||||
emit(xnstr, arg);
|
||||
emit("] = {", arg);
|
||||
FormatStringTable(yn, xn, T, emit, arg, "\n {", ", ", "},");
|
||||
emit("\n};\n", arg);
|
||||
return (/* unconst */ void *)T;
|
||||
}
|
66
tool/viz/lib/formatstringtable-testlib.h
Normal file
66
tool/viz/lib/formatstringtable-testlib.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_FORMATSTRINGTABLE_TESTLIB_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_FORMATSTRINGTABLE_TESTLIB_H_
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/**
|
||||
* Tests matrix contains expected content w/ string compare.
|
||||
*
|
||||
* @param M is 2D double array
|
||||
* @param WANT is a multi-line string of formatted matrix
|
||||
*/
|
||||
#define EXPECT_DBLMATRIXEQ(DIGS, RND, YN, XN, M, WANT, ...) \
|
||||
EXPECT_MATRIXEQ_(__FILE__, __LINE__, __FUNCTION__, YN, XN, M, #M, WANT, \
|
||||
StringifyMatrixDouble, NULL, NULL, NULL, DIGS, RND)
|
||||
|
||||
/**
|
||||
* Tests matrix contains expected content w/ string compare.
|
||||
*
|
||||
* @param M is 2D float array
|
||||
* @param WANT is a multi-line string of formatted matrix
|
||||
*/
|
||||
#define EXPECT_FLTMATRIXEQ(DIGS, RND, YN, XN, M, WANT, ...) \
|
||||
EXPECT_MATRIXEQ_(__FILE__, __LINE__, __FUNCTION__, YN, XN, M, #M, WANT, \
|
||||
StringifyMatrixFloat, NULL, NULL, NULL, DIGS, RND)
|
||||
|
||||
/**
|
||||
* Tests matrix contains expected content w/ string compare.
|
||||
*
|
||||
* @param M is 2D unsigned char array
|
||||
* @param WANT is a multi-line string of formatted matrix
|
||||
*/
|
||||
#define EXPECT_BYTEMATRIXEQ(YN, XN, XW, M, WANT, ...) \
|
||||
EXPECT_MATRIXEQ_(__FILE__, __LINE__, __FUNCTION__, YN, XN, M, #M, WANT, \
|
||||
StringifyMatrixByte, NULL, NULL, NULL)
|
||||
|
||||
/**
|
||||
* Tests matrix contains expected content w/ string compare.
|
||||
*
|
||||
* @param M is 2D unsigned short array
|
||||
* @param WANT is a multi-line string of formatted matrix
|
||||
*/
|
||||
#define EXPECT_SHRTMATRIXEQ(YN, XN, M, WANT, ...) \
|
||||
EXPECT_MATRIXEQ_(__FILE__, __LINE__, __FUNCTION__, YN, XN, M, #M, WANT, \
|
||||
StringifyMatrixShort, NULL, NULL, NULL)
|
||||
|
||||
#define EXPECT_MATRIXEQ_(FILE, LINE, FUNC, YN, XN, M, MC, WANT, F, ...) \
|
||||
do { \
|
||||
char *Got; \
|
||||
const char *Want; \
|
||||
Want = (WANT); \
|
||||
Got = F(YN, XN, M, FormatStringTableForAssertion, __VA_ARGS__); \
|
||||
if (testlib_strequals(sizeof(char), Want, Got)) { \
|
||||
testlib_free(Got); \
|
||||
} else { \
|
||||
TESTLIB_ONFAIL(FILE, FUNC); \
|
||||
TESTLIB_SHOWERROR(testlib_showerror_expect_matrixeq, LINE, "...", MC, \
|
||||
testlib_formatstr(sizeof(char), Want, -1), \
|
||||
testlib_formatstr(sizeof(char), Got, -1), ""); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_FORMATSTRINGTABLE_TESTLIB_H_ */
|
60
tool/viz/lib/formatstringtable.c
Normal file
60
tool/viz/lib/formatstringtable.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/unicode/unicode.h"
|
||||
#include "tool/viz/lib/formatstringtable.h"
|
||||
|
||||
void *FreeStringTableCells(long yn, long xn, char *T[yn][xn]) {
|
||||
long y, x;
|
||||
for (y = 0; y < yn; ++y) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
free_s(&T[y][x]);
|
||||
}
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
static unsigned GetBiggestCellWidth(long yn, long xn,
|
||||
const char *const T[yn][xn]) {
|
||||
long w, y, x;
|
||||
for (w = y = 0; y < yn; ++y) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
w = max(w, strwidth(T[y][x]));
|
||||
}
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
void *FormatStringTable(long yn, long xn, const char *const T[yn][xn],
|
||||
int emit(), void *a, const char *startrow,
|
||||
const char *comma, const char *endrow) {
|
||||
long w, y, x, i, n;
|
||||
w = GetBiggestCellWidth(yn, xn, T);
|
||||
for (y = 0; y < yn; ++y) {
|
||||
emit(startrow, a);
|
||||
for (x = 0; x < xn; ++x) {
|
||||
if (x) emit(comma, a);
|
||||
for (n = w - strwidth(T[y][x]), i = 0; i < n; ++i) emit(" ", a);
|
||||
emit(T[y][x], a);
|
||||
}
|
||||
emit(endrow, a);
|
||||
}
|
||||
return (/* unconst */ void *)T;
|
||||
}
|
49
tool/viz/lib/formatstringtable.h
Normal file
49
tool/viz/lib/formatstringtable.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_FORMATSTRINGTABLE_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_FORMATSTRINGTABLE_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
typedef void *StringTableFormatter(long yn, long xn, const char *const[yn][xn],
|
||||
int emit(), void *, const char *,
|
||||
const char *, const char *);
|
||||
|
||||
StringTableFormatter FormatStringTable;
|
||||
StringTableFormatter FormatStringTableBasic;
|
||||
StringTableFormatter FormatStringTableAsCode;
|
||||
StringTableFormatter FormatStringTableAsAssembly;
|
||||
StringTableFormatter FormatStringTableForAssertion;
|
||||
|
||||
void *FreeStringTableCells(long yn, long xn, char *[yn][xn]);
|
||||
|
||||
void FormatMatrixDouble(long yn, long xn, const double[yn][xn], int emit(),
|
||||
void *, StringTableFormatter, const char *,
|
||||
const char *, const char *, double,
|
||||
double rounder(double));
|
||||
void FormatMatrixFloat(long yn, long xn, const float[yn][xn], int emit(),
|
||||
void *, StringTableFormatter, const char *, const char *,
|
||||
const char *, double, double rounder(double));
|
||||
void FormatMatrixByte(long yn, long xn, const unsigned char[yn][xn], int emit(),
|
||||
void *, StringTableFormatter, const char *, const char *,
|
||||
const char *);
|
||||
void FormatMatrixShort(long yn, long xn, const short[yn][xn], int emit(),
|
||||
void *, StringTableFormatter, const char *, const char *,
|
||||
const char *);
|
||||
|
||||
char *StringifyMatrixDouble(long yn, long xn, const double[yn][xn],
|
||||
StringTableFormatter, const char *, const char *,
|
||||
const char *, double,
|
||||
double rounder(double)) mallocesque;
|
||||
char *StringifyMatrixFloat(long yn, long xn, const float[yn][xn],
|
||||
StringTableFormatter, const char *, const char *,
|
||||
const char *, double,
|
||||
double rounder(double)) mallocesque;
|
||||
char *StringifyMatrixByte(long yn, long xn, const unsigned char[yn][xn],
|
||||
StringTableFormatter, const char *, const char *,
|
||||
const char *) mallocesque;
|
||||
char *StringifyMatrixShort(long yn, long xn, const short[yn][xn],
|
||||
StringTableFormatter, const char *, const char *,
|
||||
const char *) mallocesque;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_FORMATSTRINGTABLE_H_ */
|
71
tool/viz/lib/gaussian.c
Normal file
71
tool/viz/lib/gaussian.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/xmmintrin.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "tool/viz/lib/convolution.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
|
||||
/**
|
||||
* Blurs image.
|
||||
* @see https://en.wikipedia.org/wiki/Kernel_(image_processing)
|
||||
*/
|
||||
long gaussian(long yn, long xn, unsigned char img[3][yn][xn]) {
|
||||
#if 0
|
||||
long rc, c, y, x, b;
|
||||
unsigned *iy, *ix;
|
||||
unsigned char(*ta)[3][xn];
|
||||
iy = convoindex(2, yn, 2);
|
||||
ix = convoindex(2, xn, 2);
|
||||
ta = memalign(32, xn * 3);
|
||||
if (ta && ix && iy) {
|
||||
iy += 2;
|
||||
ix += 2;
|
||||
for (c = 0; c < 3; ++c) {
|
||||
for (y = 0; y < yn + 3; ++y) {
|
||||
if (y >= 3) memcpy(img[c][y - 3], (*ta)[y % 3], xn);
|
||||
if (y < yn) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
b = CONVOLVE5X5(/* clang-format off */
|
||||
15, (1 / 256.), img[c],
|
||||
1, 4, 6, 4, 1,
|
||||
4, 16, 24, 16, 4,
|
||||
6, 24, 36, 24, 6,
|
||||
4, 16, 24, 16, 4,
|
||||
1, 4, 6, 4, 1
|
||||
/* clang-format on */);
|
||||
(*ta)[y % 3][x] = MIN(255, MAX(0, b));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = enomem();
|
||||
}
|
||||
free(ta);
|
||||
if (ix) free(ix - 2);
|
||||
if (iy) free(iy - 2);
|
||||
return rc;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
33
tool/viz/lib/getxtermcodes.c
Normal file
33
tool/viz/lib/getxtermcodes.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/quant.h"
|
||||
#include "libc/bits/xmmintrin.h"
|
||||
#include "libc/macros.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
|
||||
void getxtermcodes(struct TtyRgb *p, const struct Graphic *g) {
|
||||
unsigned y, x;
|
||||
unsigned char(*img)[3][g->yn][g->xn] = g->b.p;
|
||||
for (y = 0; y < g->yn; ++y) {
|
||||
for (x = 0; x < g->xn; ++x) {
|
||||
*p++ = rgb2tty((*img)[0][y][x], (*img)[1][y][x], (*img)[2][y][x]);
|
||||
}
|
||||
}
|
||||
}
|
545
tool/viz/lib/glyphs.c
Normal file
545
tool/viz/lib/glyphs.c
Normal file
|
@ -0,0 +1,545 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
// The modes below use various unicodes for 'progresssive' pixelization:
|
||||
// each mode supersets the previous to increase resolution more and more.
|
||||
// Ideally, a fully dense mapping of the (Y*X) space defined by kGlyph size
|
||||
// would produce a picture perfect image, but at the cost of sampling speed.
|
||||
// Therefore, supersets are parcimonious: they only add the minimal set of
|
||||
// missing shapes that can increase resolution.
|
||||
// Ideally, this should be based on a study of the residual, but some logic
|
||||
// can go a long way: after some block pixelization, will need diagonals
|
||||
// FIXME: then shouldn't box drawing go right after braille?
|
||||
|
||||
// TODO: explain the differences between each mode:
|
||||
// Mode A is full, empty, half blocks top and bottom: , █,▄,▀
|
||||
// Mode B superset: with quadrants: ▐,▌,▝,▙,▗,▛,▖,▜,▘,▟,▞,▚,
|
||||
// Mode C superset: with fractional eights along X and Y
|
||||
// _,▁,▂,▃,▄,▅,▆,▇ :█:▉,▊,▋,▌,▍,▎,▏
|
||||
// Mode X use box drawing, mode X use diagonal blocks, mode X use braille etc
|
||||
|
||||
#define W(B, S) B##U << S
|
||||
#define G(AA, AB, AC, AD, BA, BB, BC, BD, CA, CB, CC, CD, DA, DB, DC, DD, EA, \
|
||||
EB, EC, ED, FA, FB, FC, FD, GA, GB, GC, GD, HA, HB, HC, HD) \
|
||||
(W(AA, 000) | W(AB, 001) | W(AC, 002) | W(AD, 003) | W(BA, 004) | \
|
||||
W(BB, 005) | W(BC, 006) | W(BD, 007) | W(CA, 010) | W(CB, 011) | \
|
||||
W(CC, 012) | W(CD, 013) | W(DA, 014) | W(DB, 015) | W(DC, 016) | \
|
||||
W(DD, 017) | W(EA, 020) | W(EB, 021) | W(EC, 022) | W(ED, 023) | \
|
||||
W(FA, 024) | W(FB, 025) | W(FC, 026) | W(FD, 027) | W(GA, 030) | \
|
||||
W(GB, 031) | W(GC, 032) | W(GD, 033) | W(HA, 034) | W(HB, 035) | \
|
||||
W(HC, 036) | W(HD, 037))
|
||||
|
||||
// The glyph size it set by the resolution of the most precise mode, ex:
|
||||
// - Mode C: along the X axis, need >= 8 steps for the 8 fractional width
|
||||
// FIXME: now we can only use 4 chars instead of the extra ▉,▊,▋,▌,▍,▎,▏
|
||||
//
|
||||
// - Mode X: along the Y axis, need >= 8 steps to separate the maximal 6 dots
|
||||
// from the space left below, seen by overimposing an underline ⠿_
|
||||
// along the 3 dots, the Y axis is least 1,0,1,0,1,0,0,1 so 8 steps
|
||||
//
|
||||
// Problem: fonts are taller than wider, and terminals are tradionally 80x24, so
|
||||
// - we shouldn't use square glyphs, 8x16 seems to be the minimal size
|
||||
// - we should adapt the conversion to BMP to avoid accidental Y downsampling
|
||||
|
||||
const uint32_t kGlyphs[] = /* clang-format off */ {
|
||||
/* U+0020 ' ' empty block [ascii:20,cp437:20] */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* U+2588 '█' full block [cp437] */
|
||||
G(1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1),
|
||||
/* U+2584 '▄' lower half block [cp437:dc] */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1),
|
||||
/* U+2580 '▀' upper half block [cp437] */
|
||||
G(1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
// Mode B
|
||||
/* U+2590 '▐' right half block [cp437:de] */
|
||||
G(0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1),
|
||||
/* U+258c '▌' left half block [cp437] */
|
||||
G(1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0),
|
||||
/* U+259d '▝' quadrant upper right */
|
||||
G(0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* U+2599 '▙' quadrant upper left and lower left and lower right */
|
||||
G(1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,0),
|
||||
/* U+2597 '▗' quadrant lower right */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1),
|
||||
/* U+259b '▛' quadrant upper left and upper right and lower left */
|
||||
G(1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,1),
|
||||
/* U+2596 '▖' quadrant lower left */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0),
|
||||
/* U+259c '▜' quadrant upper left and upper right and lower right */
|
||||
G(1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,0),
|
||||
/* U+2598 '▘' quadrant upper left */
|
||||
G(1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* U+259F '▟' quadrant upper right and lower left and lower right */
|
||||
G(0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,0),
|
||||
/* U+259e '▞' quadrant upper right and lower left */
|
||||
G(0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0),
|
||||
/* U+259a '▚' quadrant upper left and lower right */
|
||||
G(1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,1,0),
|
||||
// Mode C
|
||||
/* U+2594 '▔' upper one eighth block */
|
||||
G(1,1,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* U+2581 '▁' lower one eighth block */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1),
|
||||
/* U+2582 '▂' lower one quarter block */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
1,1,1,1),
|
||||
/* U+2583 '▃' lower three eighths block */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1),
|
||||
/* U+2585 '▃' lower five eighths block */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1),
|
||||
/* U+2586 '▆' lower three quarters block */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1),
|
||||
/* U+2587 '▇' lower seven eighths block */
|
||||
G(0,0,0,0,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
1,1,1,1),
|
||||
/* U+258e '▎' left one quarter block */
|
||||
G(1,0,0,0,
|
||||
1,0,0,0,
|
||||
1,0,0,0,
|
||||
1,0,0,0,
|
||||
1,0,0,0,
|
||||
1,0,0,0,
|
||||
1,0,0,0,
|
||||
1,0,0,0),
|
||||
/* U+258a '▊' left three quarters block */
|
||||
G(1,1,1,0,
|
||||
1,1,1,0,
|
||||
1,1,1,0,
|
||||
1,1,1,0,
|
||||
1,1,1,0,
|
||||
1,1,1,0,
|
||||
1,1,1,0,
|
||||
1,1,1,0),
|
||||
/* ▁ *\
|
||||
2501▕━▎box drawings heavy horizontal
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
25019▕┉▎box drawings heavy quadruple dash horizontal
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,0,1,0,
|
||||
0,1,0,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
2503▕┃▎box drawings heavy vertical
|
||||
\* ▔ */
|
||||
G(0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0),
|
||||
/* ▁ *\
|
||||
254b▕╋▎box drawings heavy vertical and horizontal
|
||||
\* ▔ */
|
||||
G(0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
1,1,1,1,
|
||||
1,1,1,1,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0),
|
||||
/* ▁ *\
|
||||
2579▕╹▎box drawings heavy up
|
||||
\* ▔ */
|
||||
G(0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
257a▕╺▎box drawings heavy right
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,1,1,
|
||||
0,0,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
257b▕╻▎box drawings heavy down
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0),
|
||||
/* ▁ *\
|
||||
2578▕╸▎box drawings heavy left
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,0,0,
|
||||
1,1,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
250f▕┏▎box drawings heavy down and right
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,1,1,1,
|
||||
0,1,1,1,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0),
|
||||
/* ▁ *\
|
||||
251b▕┛▎box drawings heavy up and left
|
||||
\* ▔ */
|
||||
G(0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
1,1,1,0,
|
||||
1,1,1,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
2513▕┓▎box drawings heavy down and left
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,0,
|
||||
1,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0),
|
||||
/* ▁ *\
|
||||
2517▕┗▎box drawings heavy up and right
|
||||
\* ▔ */
|
||||
G(0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,0,
|
||||
0,1,1,1,
|
||||
0,1,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
25E2▕◢▎black lower right triangle
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,1,
|
||||
0,0,1,1,
|
||||
1,1,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
25E3▕◣▎black lower left triangle
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,0,0,0,
|
||||
1,1,0,0,
|
||||
1,1,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
25E4▕◥▎black upper right triangle
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
0,0,1,1,
|
||||
0,0,0,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
25E5▕◤▎black upper left triangle
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
1,1,0,0,
|
||||
1,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
2500▕═▎box drawings double horizontal
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
23BB▕⎻▎horizontal scan line 3
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
/* ▁ *\
|
||||
23BD▕⎼▎horizontal scan line 9
|
||||
\* ▔ */
|
||||
G(0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
0,0,0,0,
|
||||
1,1,1,1,
|
||||
0,0,0,0,
|
||||
0,0,0,0),
|
||||
} /* clang-format on */;
|
||||
|
||||
const char16_t kRunes[] = {
|
||||
u' ', /* 0020 empty block [ascii:20,cp437:20] */
|
||||
u'█', /* 2588 full block [cp437] */
|
||||
u'▄', /* 2584 lower half block [cp437:dc] */
|
||||
u'▀', /* 2580 upper half block [cp437] */
|
||||
u'▐', /* 2590 right half block [cp437:de] */
|
||||
u'▌', /* 258C left half block */
|
||||
u'▝', /* 259D quadrant upper right */
|
||||
u'▙', /* 2599 quadrant upper left and lower left and lower right */
|
||||
u'▗', /* 2597 quadrant lower right */
|
||||
u'▛', /* 259B quadrant upper left and upper right and lower left */
|
||||
u'▖', /* 2596 quadrant lower left */
|
||||
u'▜', /* 259C quadrant upper left and upper right and lower right */
|
||||
u'▘', /* 2598 quadrant upper left */
|
||||
u'▟', /* 259F quadrant upper right and lower left and lower right */
|
||||
u'▞', /* 259E quadrant upper right and lower left */
|
||||
u'▚', /* 259A quadrant upper left and lower right */
|
||||
u'▔', /* 2594 upper one eighth block */
|
||||
u'▁', /* 2581 lower one eighth block */
|
||||
u'▂', /* 2582 lower one quarter block */
|
||||
u'▃', /* 2583 lower three eighths block */
|
||||
u'▅', /* 2585 lower five eighths block */
|
||||
u'▆', /* 2586 lower three quarters block */
|
||||
u'▇', /* 2587 lower seven eighths block */
|
||||
u'▎', /* 258E left one quarter block */
|
||||
u'▊', /* 258A left three quarters block */
|
||||
u'━', /* 2501 box drawings heavy horizontal */
|
||||
u'┉', /* 2509 box drawings heavy quadruple dash horizontal */
|
||||
u'┃', /* 2503 box drawings heavy vertical */
|
||||
u'╋', /* 254B box drawings heavy vertical & horiz. */
|
||||
u'╹', /* 2579 box drawings heavy up */
|
||||
u'╺', /* 257A box drawings heavy right */
|
||||
u'╻', /* 257B box drawings heavy down */
|
||||
u'╸', /* 2578 box drawings heavy left */
|
||||
u'┏', /* 250F box drawings heavy down and right */
|
||||
u'┛', /* 251B box drawings heavy up and left */
|
||||
u'┓', /* 2513 box drawings heavy down and left */
|
||||
u'┗', /* 2517 box drawings heavy up and right */
|
||||
u'◢', /* 25E2 black lower right triangle */
|
||||
u'◣', /* 25E3 black lower left triangle */
|
||||
u'◥', /* 25E4 black upper right triangle */
|
||||
u'◤', /* 25E5 black upper left triangle */
|
||||
u'═', /* 2550 box drawings double horizontal */
|
||||
u'⎻', /* 23BB horizontal scan line 3 */
|
||||
u'⎼', /* 23BD horizontal scan line 9 */
|
||||
};
|
58
tool/viz/lib/graphic.h
Normal file
58
tool/viz/lib/graphic.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_GRAPHIC_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_GRAPHIC_H_
|
||||
#include "dsp/tty/quant.h"
|
||||
#include "libc/runtime/buffer.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct Graphic {
|
||||
union {
|
||||
struct GuardedBuffer b;
|
||||
char *bytes;
|
||||
float (*lum)[2][8];
|
||||
float (*rgba)[2][2];
|
||||
};
|
||||
unsigned yn, xn;
|
||||
unsigned ys, xs;
|
||||
unsigned bs, es;
|
||||
};
|
||||
|
||||
void dither(long yw, long xw, unsigned char[3][yw][xw], long, long);
|
||||
struct Graphic *resizegraphic(struct Graphic *, size_t, size_t);
|
||||
void getxtermcodes(struct TtyRgb *, const struct Graphic *);
|
||||
void ycbcr2lum(struct Graphic *, uint8_t *, uint8_t *, uint8_t *, size_t,
|
||||
size_t, size_t);
|
||||
|
||||
long sharpen(long cn, long yw, long xw, unsigned char[cn][yw][xw], long, long);
|
||||
long unsharp(long cn, long yw, long xw, unsigned char[cn][yw][xw], long, long);
|
||||
long gaussian(long yn, long xn, unsigned char[3][yn][xn]);
|
||||
void sobel(struct Graphic *);
|
||||
extern void (*ycbcr2rgb)(struct Graphic *, uint8_t *, uint8_t *, uint8_t *,
|
||||
size_t, size_t, size_t);
|
||||
|
||||
void emboss(struct Graphic *);
|
||||
void boxblur(struct Graphic *);
|
||||
double perlin3(double, double, double);
|
||||
|
||||
void stdgamma(unsigned n, __m128 rgba[n]);
|
||||
void lingamma(unsigned n, __m128 rgba[n]);
|
||||
|
||||
void OldBilinearScale(size_t dyw, size_t dxw, __v4sf dst[dyw][dxw], size_t syw,
|
||||
size_t sxw, __v4sf src[syw][sxw], size_t dyn, size_t dxn,
|
||||
size_t syn, size_t sxn);
|
||||
|
||||
int MagicScale(unsigned dyn, unsigned dxn, __v4sf dst[dyn][dxn], unsigned syn,
|
||||
unsigned sxn, __v4sf src[syn][sxn]);
|
||||
|
||||
void interlace(size_t dyn, size_t dxn, float dst[dyn][dxn][4], size_t syn,
|
||||
size_t sxn, size_t ssw, unsigned char reds[syn][ssw],
|
||||
unsigned char greens[syn][ssw], unsigned char blues[syn][ssw]);
|
||||
|
||||
void WriteToFrameBuffer(size_t dyn, size_t dxn, unsigned char dst[dyn][dxn][4],
|
||||
size_t syn, size_t sxn, float src[syn][sxn][4],
|
||||
size_t yn, size_t xn);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_GRAPHIC_H_ */
|
35
tool/viz/lib/halfblit.c
Normal file
35
tool/viz/lib/halfblit.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/check.h"
|
||||
#include "tool/viz/lib/halfblit.h"
|
||||
|
||||
void *halfblit(size_t n, void *block) {
|
||||
unsigned y, x;
|
||||
char(*dst)[n << 0][n << 0] = block;
|
||||
char(*src)[n << 1][n << 1] = block;
|
||||
DCHECK_GE(n, 2);
|
||||
DCHECK_ALIGNED(16, block);
|
||||
for (y = 0; y < n; ++y) {
|
||||
for (x = 0; x < n; ++x) {
|
||||
(*dst)[y][x] = (*src)[y][x];
|
||||
}
|
||||
}
|
||||
return block;
|
||||
}
|
10
tool/viz/lib/halfblit.h
Normal file
10
tool/viz/lib/halfblit.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_HALFBLIT_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_HALFBLIT_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void *halfblit(size_t, void *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_HALFBLIT_H_ */
|
21
tool/viz/lib/knobs.h
Normal file
21
tool/viz/lib/knobs.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_KNOBS_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_KNOBS_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern bool pf1_;
|
||||
extern bool pf2_;
|
||||
extern bool pf3_;
|
||||
extern bool pf4_;
|
||||
extern bool pf5_;
|
||||
extern bool pf6_;
|
||||
extern bool pf7_;
|
||||
extern bool pf8_;
|
||||
extern bool pf9_;
|
||||
extern bool pf10_;
|
||||
extern bool pf11_;
|
||||
extern bool pf12_;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_KNOBS_H_ */
|
106
tool/viz/lib/perlin3.c
Normal file
106
tool/viz/lib/perlin3.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
|
||||
static int perm[513];
|
||||
|
||||
static double lerp(double t, double a, double b) { return a + t * (b - a); }
|
||||
|
||||
static double fade(double t) {
|
||||
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
|
||||
}
|
||||
|
||||
static double grad(int hash, double x, double y, double z) {
|
||||
int h;
|
||||
double u, v;
|
||||
h = hash & 15;
|
||||
u = h < 8 ? x : y;
|
||||
v = h < 4 ? y : (h == 12 || h == 14) ? x : z;
|
||||
return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perlin's improved noise algorithm.
|
||||
*
|
||||
* @see http://mrl.nyu.edu/~perlin/noise/
|
||||
* @note it's bryce3d cgi basically
|
||||
*/
|
||||
double perlin3(double x, double y, double z) /* clang-format off */ {
|
||||
double u, v, w;
|
||||
int X, Y, Z, AA, AB, BA, BB;
|
||||
X = floor(x);
|
||||
Y = floor(y);
|
||||
Z = floor(z);
|
||||
X &= 0xff;
|
||||
Y &= 0xff;
|
||||
Z &= 0xff;
|
||||
x -= floor(x);
|
||||
y -= floor(y);
|
||||
z -= floor(z);
|
||||
u = fade(x);
|
||||
v = fade(y);
|
||||
w = fade(z);
|
||||
AA = perm[perm[X ] + Y ] + Z;
|
||||
AB = perm[perm[X ] + Y + 1] + Z;
|
||||
BA = perm[perm[X + 1] + Y ] + Z;
|
||||
BB = perm[perm[X + 1] + Y + 1] + Z;
|
||||
return lerp(w, lerp(v, lerp(u, grad(perm[AA ], x , y , z ),
|
||||
grad(perm[BA ], x - 1, y , z )),
|
||||
lerp(u, grad(perm[AB ], x , y - 1, z ),
|
||||
grad(perm[BB ], x - 1, y - 1, z ))),
|
||||
lerp(v, lerp(u, grad(perm[AA + 1], x , y , z - 1),
|
||||
grad(perm[BA + 1], x - 1, y , z - 1)),
|
||||
lerp(u, grad(perm[AB + 1], x , y - 1, z - 1),
|
||||
grad(perm[BB + 1], x - 1, y - 1, z - 1))));
|
||||
} /* clang-format on */
|
||||
|
||||
static const uint8_t kPerm[] = {
|
||||
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7,
|
||||
225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190,
|
||||
6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117,
|
||||
35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136,
|
||||
171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158,
|
||||
231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46,
|
||||
245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209,
|
||||
76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86,
|
||||
164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5,
|
||||
202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16,
|
||||
58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44,
|
||||
154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253,
|
||||
19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97,
|
||||
228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51,
|
||||
145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184,
|
||||
84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
|
||||
222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156,
|
||||
180,
|
||||
};
|
||||
|
||||
static nooptimize textstartup void init(void) {
|
||||
unsigned i;
|
||||
for (i = 0; i < 256; ++i) {
|
||||
perm[i] = kPerm[i];
|
||||
perm[i + 256] = kPerm[i];
|
||||
}
|
||||
}
|
||||
|
||||
INITIALIZER(400, _init_perlin3, init());
|
38
tool/viz/lib/resizegraphic.c
Normal file
38
tool/viz/lib/resizegraphic.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/xmmintrin.h"
|
||||
#include "libc/runtime/buffer.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
|
||||
/**
|
||||
* Allocates graphic.
|
||||
*
|
||||
* @param g should be zero initialized before first call
|
||||
* @note bfree(g->b) needs to be called later
|
||||
*/
|
||||
struct Graphic *resizegraphic(struct Graphic *g, size_t yn, size_t xn) {
|
||||
/* assert(xn % 2 == 0); */ /* todo: ughhh this whole thing is wrong */
|
||||
yn &= ~1;
|
||||
balloc(&g->b, 64, yn * xn * sizeof(__m128) + /* wut */ PAGESIZE);
|
||||
g->yn = yn;
|
||||
g->xn = xn;
|
||||
return g;
|
||||
}
|
12
tool/viz/lib/scale.h
Normal file
12
tool/viz/lib/scale.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_SCALE_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_SCALE_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void *Scale(long dcw, long dyw, long dxw, float dst[dcw][dyw][dxw], long scw,
|
||||
long syw, long sxw, const float src[scw][syw][sxw], long, long,
|
||||
long, long, long, long, double, double, double, double);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_SCALE_H_ */
|
71
tool/viz/lib/sharpen.c
Normal file
71
tool/viz/lib/sharpen.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/ks8.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/viz/lib/convolution.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
|
||||
#define SHARPEN(...) KS8(0, 0, 0, 0, -1, -1, 5, -1, -1, 0, 0, 0, __VA_ARGS__)
|
||||
|
||||
long sharpen(long cn, long yw, long xw, unsigned char p[cn][yw][xw], long yn,
|
||||
long xn) {
|
||||
long rc, c, y, x;
|
||||
short(*ta)[3][xn];
|
||||
unsigned *iy, *ix;
|
||||
if (yn >= 3 && xn > 0) {
|
||||
ta = memalign(32, sizeof(short) * xn * 3);
|
||||
iy = convoindex(1, yn, 1);
|
||||
ix = convoindex(1, xn, 1);
|
||||
if (ta && iy && ix) {
|
||||
iy += 1;
|
||||
ix += 1;
|
||||
for (c = 0; c < 3; ++c) {
|
||||
for (y = 0; y < yn + 3; ++y) {
|
||||
if (y >= 3) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
p[c][y - 3][x] = MIN(255, MAX(0, (*ta)[y % 3][x]));
|
||||
}
|
||||
}
|
||||
if (y < yn) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
(*ta)[y % 3][x] =
|
||||
SHARPEN(p[c][iy[y - 1]][x], p[c][y][ix[x - 1]], p[c][y][x],
|
||||
p[c][y][ix[x + 1]], p[c][iy[y + 1]][x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = enomem();
|
||||
}
|
||||
free(ta);
|
||||
if (ix) free(ix - 1);
|
||||
if (iy) free(iy - 1);
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
return rc;
|
||||
}
|
76
tool/viz/lib/sobel.c
Normal file
76
tool/viz/lib/sobel.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "tool/viz/lib/convolve.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
|
||||
#define LCB {
|
||||
#define RCB }
|
||||
#define BROADCAST(X) LCB X, X, X, X RCB
|
||||
#define FLIP(A, B, C) LCB C, B, A RCB
|
||||
|
||||
forceinline void ConvolveGradient(unsigned yn, unsigned xn,
|
||||
float (*img)[yn][xn][4], unsigned KW,
|
||||
const float (*ky)[KW][KW][4],
|
||||
const float (*kx)[KW][KW][4]) {
|
||||
size_t size;
|
||||
unsigned y, x, i, j, k;
|
||||
float py[4], px[4], (*tmp)[yn][xn][4];
|
||||
tmp = mapanon((size = ROUNDUP(sizeof(float) * 4 * xn * yn, FRAMESIZE)));
|
||||
for (y = 0; y < yn - KW + 1; ++y) {
|
||||
for (x = 0; x < xn - KW + 1; ++x) {
|
||||
for (k = 0; k < 4; ++k) py[k] = 0;
|
||||
for (k = 0; k < 4; ++k) px[k] = 0;
|
||||
for (i = 0; i < KW; ++i) {
|
||||
for (j = 0; j < KW; ++j) {
|
||||
for (k = 0; k < 4; ++k) {
|
||||
py[k] += (*ky)[i][j][k] * (*img)[y + i][x + j][k];
|
||||
px[k] += (*kx)[i][j][k] * (*img)[y + i][x + j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (k = 0; k < 4; ++k) {
|
||||
(*tmp)[y + KW / 2][x + KW / 2][k] = sqrt(py[k] * py[k] + px[k] * px[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(img, tmp, sizeof(float) * 4 * xn * yn);
|
||||
munmap(tmp, size);
|
||||
}
|
||||
|
||||
void sobel(struct Graphic* g) {
|
||||
static const float kSobelEmbossKernelY[3][3][4] =
|
||||
FLIP(FLIP(BROADCAST(+1), BROADCAST(+2), BROADCAST(+1)),
|
||||
FLIP(BROADCAST(+0), BROADCAST(+0), BROADCAST(+0)),
|
||||
FLIP(BROADCAST(-1), BROADCAST(-2), BROADCAST(-1)));
|
||||
static const float kSobelEmbossKernelX[3][3][4] =
|
||||
FLIP(FLIP(BROADCAST(-1), BROADCAST(+0), BROADCAST(+1)),
|
||||
FLIP(BROADCAST(-2), BROADCAST(+0), BROADCAST(+2)),
|
||||
FLIP(BROADCAST(-1), BROADCAST(+0), BROADCAST(+1)));
|
||||
if (g->yn >= 3 && g->xn >= 3) {
|
||||
ConvolveGradient(g->yn, g->xn, g->b.p, 3, &kSobelEmbossKernelY,
|
||||
&kSobelEmbossKernelX);
|
||||
}
|
||||
}
|
56
tool/viz/lib/stringbuilder.c
Normal file
56
tool/viz/lib/stringbuilder.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/viz/lib/stringbuilder.h"
|
||||
|
||||
static noinline void StringBuilderGrow(size_t need, struct StringBuilder *sb) {
|
||||
size_t n2;
|
||||
n2 = MAX(16, sb->n);
|
||||
while (sb->i + need > n2) n2 += n2 >> 1;
|
||||
sb->p = xrealloc(sb->p, n2);
|
||||
sb->n = n2;
|
||||
}
|
||||
|
||||
struct StringBuilder *NewStringBuilder(void) {
|
||||
return xcalloc(1, sizeof(struct StringBuilder));
|
||||
}
|
||||
|
||||
int StringBuilderAppend(const char *s, struct StringBuilder *sb) {
|
||||
size_t size;
|
||||
CHECK_LE(sb->i, sb->n);
|
||||
size = strlen(s);
|
||||
if (sb->i + size + 1 > sb->n) StringBuilderGrow(size + 1, sb);
|
||||
memcpy(sb->p + sb->i, s, size + 1);
|
||||
sb->i += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *FreeStringBuilder(struct StringBuilder *sb) {
|
||||
char *res;
|
||||
CHECK_LE(sb->i, sb->n);
|
||||
CHECK_EQ('\0', sb->p[sb->i]);
|
||||
res = xrealloc(sb->p, sb->i + 1);
|
||||
free(sb);
|
||||
return res;
|
||||
}
|
21
tool/viz/lib/stringbuilder.h
Normal file
21
tool/viz/lib/stringbuilder.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_STRINGBUILDER_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_STRINGBUILDER_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct StringBuilder {
|
||||
size_t i, n;
|
||||
char *p;
|
||||
};
|
||||
|
||||
struct StringBuilder *NewStringBuilder(void) mallocesque returnsnonnull;
|
||||
|
||||
int StringBuilderAppend(const char *, struct StringBuilder *)
|
||||
paramsnonnull((2));
|
||||
|
||||
char *FreeStringBuilder(struct StringBuilder *) mallocesque returnsnonnull
|
||||
paramsnonnull();
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_STRINGBUILDER_H_ */
|
29
tool/viz/lib/thunks/expect_matrixeq.S
Normal file
29
tool/viz/lib/thunks/expect_matrixeq.S
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
.text.unlikely
|
||||
testlib_showerror_expect_matrixeq:
|
||||
push $FALSE
|
||||
pushstr "EXPECT_MATRIXEQ"
|
||||
pushstr "="
|
||||
jmp testlib_showerror_jump
|
||||
.endfn testlib_showerror_expect_matrixeq,globl,hidden
|
||||
.previous
|
73
tool/viz/lib/unsharp.c
Normal file
73
tool/viz/lib/unsharp.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/viz/lib/convolution.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
|
||||
/**
|
||||
* Enhances image detail.
|
||||
* @see https://en.wikipedia.org/wiki/Kernel_(image_processing)
|
||||
*/
|
||||
long unsharp(long cn, long yw, long xw, unsigned char img[cn][yw][xw], long yn,
|
||||
long xn) {
|
||||
long rc, c, y, x;
|
||||
unsigned *iy, *ix;
|
||||
short(*t)[3][xn] = xmemalign(64, sizeof(short) * xn * 3);
|
||||
iy = convoindex(2, yn, 2);
|
||||
ix = convoindex(2, xn, 2);
|
||||
if (t && ix && iy) {
|
||||
iy += 2;
|
||||
ix += 2;
|
||||
for (c = 0; c < 3; ++c) {
|
||||
for (y = 0; y < yn + 3; ++y) {
|
||||
if (y >= 3) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
img[c][y - 3][x] = MIN(255, MAX(0, (*t)[y % 3][x]));
|
||||
}
|
||||
memset((*t)[y % 3], 0, sizeof(short) * xn);
|
||||
}
|
||||
if (y < yn) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
(*t)[y % 3][x] = CONVOLVE5X5(/* clang-format off */
|
||||
7, (-1 / 256.), img[c],
|
||||
1, 4, 6, 4, 1,
|
||||
4, 16, 24, 16, 4,
|
||||
6, 24,-476, 24, 6,
|
||||
4, 16, 24, 16, 4,
|
||||
1, 4, 6, 4, 1
|
||||
/* clang-format on */);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = enomem();
|
||||
}
|
||||
free(t);
|
||||
if (ix) free(ix - 2);
|
||||
if (iy) free(iy - 2);
|
||||
return rc;
|
||||
}
|
120
tool/viz/lib/vizlib.mk
Normal file
120
tool/viz/lib/vizlib.mk
Normal file
|
@ -0,0 +1,120 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += TOOL_VIZ_LIB
|
||||
|
||||
TOOL_VIZ_LIB_ARTIFACTS += TOOL_VIZ_LIB_A
|
||||
TOOL_VIZ_LIB = $(TOOL_VIZ_LIB_A_DEPS) $(TOOL_VIZ_LIB_A)
|
||||
TOOL_VIZ_LIB_A = o/$(MODE)/tool/viz/lib/vizlib.a
|
||||
TOOL_VIZ_LIB_A_HDRS = $(filter %.h,$(TOOL_VIZ_LIB_A_FILES))
|
||||
TOOL_VIZ_LIB_A_SRCS_S = $(filter %.S,$(TOOL_VIZ_LIB_A_FILES))
|
||||
TOOL_VIZ_LIB_A_SRCS_C = $(filter %.c,$(TOOL_VIZ_LIB_A_FILES))
|
||||
TOOL_VIZ_LIB_A_CHECKS = $(TOOL_VIZ_LIB_A).pkg
|
||||
|
||||
TOOL_VIZ_LIB_A_FILES := \
|
||||
$(wildcard tool/viz/lib/*) \
|
||||
$(wildcard tool/viz/lib/thunks/*)
|
||||
|
||||
TOOL_VIZ_LIB_A_SRCS = \
|
||||
$(TOOL_VIZ_LIB_A_SRCS_S) \
|
||||
$(TOOL_VIZ_LIB_A_SRCS_C)
|
||||
|
||||
TOOL_VIZ_LIB_A_OBJS = \
|
||||
$(TOOL_VIZ_LIB_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(TOOL_VIZ_LIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(TOOL_VIZ_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
TOOL_VIZ_LIB_A_DIRECTDEPS = \
|
||||
DSP_TTY \
|
||||
DSP_CORE \
|
||||
DSP_SCALE \
|
||||
LIBC_INTRIN \
|
||||
LIBC_ALG \
|
||||
LIBC_BITS \
|
||||
LIBC_CALLS \
|
||||
LIBC_CONV \
|
||||
LIBC_FMT \
|
||||
LIBC_SYSV \
|
||||
LIBC_UNICODE \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_LOG \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_STDIO \
|
||||
LIBC_STUBS \
|
||||
LIBC_STR \
|
||||
LIBC_X \
|
||||
THIRD_PARTY_AVIR \
|
||||
THIRD_PARTY_DTOA \
|
||||
THIRD_PARTY_DLMALLOC
|
||||
|
||||
TOOL_VIZ_LIB_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(TOOL_VIZ_LIB_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
o/$(MODE)/tool/viz/lib/pmaddubsw.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fvect-cost-model=unlimited
|
||||
|
||||
o/$(MODE)/tool/viz/lib/scale.o \
|
||||
o/$(MODE)/tool/viz/lib/writetoframebuffer.o \
|
||||
o/$(MODE)/tool/viz/lib/lab.o \
|
||||
o/$(MODE)/tool/viz/lib/xyz.o \
|
||||
o/$(MODE)/tool/viz/lib/doublechrominance.o \
|
||||
o/$(MODE)/tool/viz/lib/doublechrominance.o \
|
||||
o/$(MODE)/tool/viz/lib/doublechrominance.o \
|
||||
o/$(MODE)/tool/viz/lib/interlace.o \
|
||||
o/$(MODE)/tool/viz/lib/bilinearscale.o \
|
||||
o/$(MODE)/tool/viz/lib/oldbilinearscale.o \
|
||||
o/$(MODE)/tool/viz/lib/boxblur.o \
|
||||
o/$(MODE)/tool/viz/lib/dither.o \
|
||||
o/$(MODE)/tool/viz/lib/emboss.o \
|
||||
o/$(MODE)/tool/viz/lib/getxtermcodes.o \
|
||||
o/$(MODE)/tool/viz/lib/lingamma.o \
|
||||
o/$(MODE)/tool/viz/lib/perlin3.o \
|
||||
o/$(MODE)/tool/viz/lib/resizegraphic.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
#o/$(MODE)/tool/viz/lib/scale.o \
|
||||
o/$(MODE)/tool/viz/lib/writetoframebuffer.o \
|
||||
o/$(MODE)/tool/viz/lib/interlace.o \
|
||||
o/$(MODE)/tool/viz/lib/magicscale.o \
|
||||
o/$(MODE)/tool/viz/lib/halfblit.o \
|
||||
o/$(MODE)/tool/viz/lib/byte2float.o \
|
||||
o/$(MODE)/tool/viz/lib/ycbcr2rgb2.o \
|
||||
o/$(MODE)/tool/viz/lib/magickernel.o \
|
||||
o/$(MODE)/tool/viz/lib/lolquist.o \
|
||||
o/$(MODE)/tool/viz/lib/getxtermcodes.o \
|
||||
o/$(MODE)/tool/viz/lib/unsharp.o \
|
||||
o/$(MODE)/tool/viz/lib/gaussian.o: \
|
||||
CC = $(CLANG)
|
||||
|
||||
o/$(MODE)/tool/viz/lib/printmatrix.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(IEEE_MATH)
|
||||
|
||||
$(TOOL_VIZ_LIB_A): \
|
||||
tool/viz/lib/ \
|
||||
$(TOOL_VIZ_LIB_A).pkg \
|
||||
$(TOOL_VIZ_LIB_A_OBJS)
|
||||
|
||||
$(TOOL_VIZ_LIB_A).pkg: \
|
||||
$(TOOL_VIZ_LIB_A_OBJS) \
|
||||
$(foreach x,$(TOOL_VIZ_LIB_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
$(TOOL_VIZ_LIB_A_OBJS): tool/viz/lib/vizlib.mk
|
||||
|
||||
TOOL_VIZ_LIB_LIBS = $(foreach x,$(TOOL_VIZ_LIB_ARTIFACTS),$($(x)))
|
||||
TOOL_VIZ_LIB_SRCS = $(foreach x,$(TOOL_VIZ_LIB_ARTIFACTS),$($(x)_SRCS))
|
||||
TOOL_VIZ_LIB_HDRS = $(foreach x,$(TOOL_VIZ_LIB_ARTIFACTS),$($(x)_HDRS))
|
||||
TOOL_VIZ_LIB_BINS = $(foreach x,$(TOOL_VIZ_LIB_ARTIFACTS),$($(x)_BINS))
|
||||
TOOL_VIZ_LIB_CHECKS = $(foreach x,$(TOOL_VIZ_LIB_ARTIFACTS),$($(x)_CHECKS))
|
||||
TOOL_VIZ_LIB_OBJS = $(foreach x,$(TOOL_VIZ_LIB_ARTIFACTS),$($(x)_OBJS))
|
||||
TOOL_VIZ_LIB_TESTS = $(foreach x,$(TOOL_VIZ_LIB_ARTIFACTS),$($(x)_TESTS))
|
||||
|
||||
.PHONY: o/$(MODE)/tool/viz/lib
|
||||
o/$(MODE)/tool/viz/lib: $(TOOL_VIZ_LIB_CHECKS)
|
42
tool/viz/lib/writetoframebuffer.c
Normal file
42
tool/viz/lib/writetoframebuffer.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
|
||||
void WriteToFrameBuffer(size_t dyn, size_t dxn, unsigned char dst[dyn][dxn][4],
|
||||
size_t syn, size_t sxn, float src[syn][sxn][4],
|
||||
size_t yn, size_t xn) {
|
||||
int ipix[4];
|
||||
float fpix[4];
|
||||
unsigned y, x, k, upix[4];
|
||||
for (y = 0; y < yn; ++y) {
|
||||
for (x = 0; x < xn; ++x) {
|
||||
for (k = 0; k < 4; ++k) fpix[k] = src[y][x][k];
|
||||
for (k = 0; k < 4; ++k) fpix[k] *= 255;
|
||||
for (k = 0; k < 4; ++k) ipix[k] = fpix[k] + .5f;
|
||||
for (k = 0; k < 4; ++k) upix[k] = MAX(0, ipix[k]);
|
||||
for (k = 0; k < 4; ++k) upix[k] = MIN(255, upix[k]);
|
||||
dst[y][x][0] = upix[2];
|
||||
dst[y][x][1] = upix[1];
|
||||
dst[y][x][2] = upix[0];
|
||||
dst[y][x][3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
34
tool/viz/lib/ycbcr.h
Normal file
34
tool/viz/lib/ycbcr.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_VIZ_LIB_YCBCR_H_
|
||||
#define COSMOPOLITAN_TOOL_VIZ_LIB_YCBCR_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct YCbCr;
|
||||
|
||||
extern const double kBt601Primaries[3];
|
||||
extern const double kBt709Primaries[3];
|
||||
|
||||
extern long magikarp_latency_;
|
||||
extern long ycbcr2rgb_latency_;
|
||||
|
||||
void Y2Rgb(long yn, long xn, unsigned char[restrict 3][yn][xn], long yys,
|
||||
long yxs, const unsigned char[restrict yys][yxs], const int[4][4],
|
||||
const unsigned char[256]);
|
||||
void YCbCr2Rgb(long yn, long xn, unsigned char[restrict 3][yn][xn], long yys,
|
||||
long yxs, const unsigned char[restrict yys][yxs], long cys,
|
||||
long cxs, const unsigned char[restrict cys][cxs],
|
||||
const unsigned char[restrict cys][cxs], const int[4][4],
|
||||
const int[3][4], const unsigned char[256]);
|
||||
|
||||
void YCbCrFree(struct YCbCr **);
|
||||
void YCbCrInit(struct YCbCr **, bool, int, double, const double[3],
|
||||
const double[3]);
|
||||
void *YCbCr2RgbScale(long dyn, long dxn, unsigned char[restrict 3][dyn][dxn],
|
||||
long yys, long yxs, unsigned char[restrict yys][yxs],
|
||||
long cys, long cxs, unsigned char[restrict cys][cxs],
|
||||
unsigned char[restrict cys][cxs], long, long, long, long,
|
||||
double, double, double, double, struct YCbCr **);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_YCBCR_H_ */
|
395
tool/viz/lib/ycbcr2rgb3.c
Normal file
395
tool/viz/lib/ycbcr2rgb3.c
Normal file
|
@ -0,0 +1,395 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/c11.h"
|
||||
#include "dsp/core/c1331.h"
|
||||
#include "dsp/core/c1331s.h"
|
||||
#include "dsp/core/c161.h"
|
||||
#include "dsp/core/core.h"
|
||||
#include "dsp/core/half.h"
|
||||
#include "dsp/core/illumination.h"
|
||||
#include "dsp/core/q.h"
|
||||
#include "dsp/scale/scale.h"
|
||||
#include "libc/bits/xmmintrin.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/intrin/pmulhrsw.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/gc.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/avir/lanczos.h"
|
||||
#include "tool/viz/lib/graphic.h"
|
||||
#include "tool/viz/lib/knobs.h"
|
||||
#include "tool/viz/lib/scale.h"
|
||||
#include "tool/viz/lib/ycbcr.h"
|
||||
|
||||
#define M 15
|
||||
#define CLAMP(X) MIN(255, MAX(0, X))
|
||||
|
||||
const double kBt601Primaries[] = {.299, .587, .114};
|
||||
const double kBt709Primaries[] = {871024 / 4096299., 8788810 / 12288897.,
|
||||
887015 / 12288897.};
|
||||
|
||||
const double kSrgbToXyz[3][3] = {
|
||||
{506752 / 1228815., 87881 / 245763., 12673 / 70218.},
|
||||
{87098 / 409605., 175762 / 245763., 12673 / 175545.},
|
||||
{7918 / 409605., 87881 / 737289., 1001167 / 1053270.},
|
||||
};
|
||||
|
||||
long magikarp_latency_;
|
||||
long gyarados_latency_;
|
||||
long ycbcr2rgb_latency_;
|
||||
long double magikarp_start_;
|
||||
|
||||
struct YCbCr {
|
||||
bool yonly;
|
||||
int magnums[8][4];
|
||||
int lighting[6][4];
|
||||
unsigned char transfer[2][256];
|
||||
struct YCbCrSamplingSolution {
|
||||
long dyn, dxn;
|
||||
long syn, sxn;
|
||||
double ry, rx;
|
||||
double oy, ox;
|
||||
double py, px;
|
||||
struct SamplingSolution *cy, *cx;
|
||||
} luma, chroma;
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes magnums for Y′CbCr decoding.
|
||||
*
|
||||
* @param swing should be 219 for TV, or 255 for JPEG
|
||||
* @param M is integer coefficient bits
|
||||
*/
|
||||
void YCbCrComputeCoefficients(int swing, double gamma,
|
||||
const double primaries[3],
|
||||
const double illuminant[3], int out_magnums[8][4],
|
||||
int out_lighting[6][4],
|
||||
unsigned char out_transfer[256]) {
|
||||
int i, j;
|
||||
double x;
|
||||
double f1[6][3];
|
||||
long longs[6][6];
|
||||
long bitlimit = roundup2pow(swing);
|
||||
long wordoffset = rounddown2pow((bitlimit - swing) / 2);
|
||||
long chromaswing = swing + 2 * (bitlimit / 2. - swing / 2. - wordoffset);
|
||||
long lumamin = wordoffset;
|
||||
long lumamax = wordoffset + swing;
|
||||
long diffmax = wordoffset + chromaswing - bitlimit / 2;
|
||||
long diffmin = -diffmax;
|
||||
double rEb = 1 - primaries[2] + primaries[0] + primaries[1];
|
||||
double rEgEb = 1 / primaries[1] * primaries[2] * rEb;
|
||||
double rEr = 1 - primaries[0] + primaries[1] + primaries[2];
|
||||
double rEgEr = 1 / primaries[1] * primaries[0] * rEr;
|
||||
double unswing = 1. / swing * bitlimit;
|
||||
double digital = 1. / swing * chromaswing;
|
||||
double reals[6][6] = {
|
||||
{rEr / digital},
|
||||
{-rEgEb / digital, -rEgEr / digital},
|
||||
{rEb / digital},
|
||||
{0, 0, unswing},
|
||||
};
|
||||
for (i = 0; i < 4; ++i) {
|
||||
GetIntegerCoefficients(longs[i], reals[i], M, diffmin, diffmax);
|
||||
}
|
||||
for (i = 0; i < 4; ++i) {
|
||||
for (j = 0; j < 4; ++j) {
|
||||
out_magnums[i][j] = longs[i][j];
|
||||
}
|
||||
}
|
||||
out_magnums[3][0] = wordoffset;
|
||||
out_magnums[3][1] = bitlimit / 2;
|
||||
GetChromaticAdaptationMatrix(f1, kIlluminantD65, illuminant);
|
||||
for (i = 0; i < 3; ++i) {
|
||||
for (j = 0; j < 3; ++j) {
|
||||
reals[i][j] = f1[i][j];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 6; ++i) {
|
||||
GetIntegerCoefficients(longs[i], reals[i], M, diffmin * 2, lumamax * 2);
|
||||
}
|
||||
for (i = 0; i < 6; ++i) {
|
||||
for (j = 0; j < 3; ++j) {
|
||||
out_lighting[i][j] = longs[i][j];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 256; ++i) {
|
||||
x = i;
|
||||
x /= 255;
|
||||
x = tv2pcgamma(x, gamma);
|
||||
x *= 255;
|
||||
out_transfer[i] = CLAMP(x);
|
||||
}
|
||||
memset(out_transfer, out_transfer[lumamin], lumamin);
|
||||
memset(out_transfer + lumamax + 1, out_transfer[lumamax], bitlimit - lumamax);
|
||||
}
|
||||
|
||||
void YCbCrInit(struct YCbCr **ycbcr, bool yonly, int swing, double gamma,
|
||||
const double gamut[3], const double illuminant[3]) {
|
||||
if (!*ycbcr) *ycbcr = xcalloc(1, sizeof(struct YCbCr));
|
||||
(*ycbcr)->yonly = yonly;
|
||||
memset((*ycbcr)->magnums, 0, sizeof((*ycbcr)->magnums));
|
||||
memset((*ycbcr)->lighting, 0, sizeof((*ycbcr)->lighting));
|
||||
YCbCrComputeCoefficients(swing, gamma, gamut, illuminant, (*ycbcr)->magnums,
|
||||
(*ycbcr)->lighting, (*ycbcr)->transfer[0]);
|
||||
imapxlatab((*ycbcr)->transfer[1]);
|
||||
}
|
||||
|
||||
void YCbCrFree(struct YCbCr **ycbcr) {
|
||||
if (*ycbcr) {
|
||||
FreeSamplingSolution((*ycbcr)->luma.cy), (*ycbcr)->luma.cy = NULL;
|
||||
FreeSamplingSolution((*ycbcr)->luma.cx), (*ycbcr)->luma.cx = NULL;
|
||||
FreeSamplingSolution((*ycbcr)->chroma.cy), (*ycbcr)->chroma.cy = NULL;
|
||||
FreeSamplingSolution((*ycbcr)->chroma.cx), (*ycbcr)->chroma.cx = NULL;
|
||||
free(*ycbcr), *ycbcr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void *YCbCrReallocPlane(long ys, long xs, const unsigned char p[ys][xs],
|
||||
long yn, long xn) {
|
||||
long y;
|
||||
unsigned char(*res)[yn][xn];
|
||||
res = xmemalign(32, yn * xn);
|
||||
for (y = 0; y < yn; ++y) {
|
||||
memcpy((*res)[y], p[y], xn);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void YCbCrComputeSamplingSolution(struct YCbCrSamplingSolution *scale, long dyn,
|
||||
long dxn, long syn, long sxn, double ry,
|
||||
double rx, double oy, double ox, double py,
|
||||
double px) {
|
||||
if (scale->dyn != dyn || scale->dxn != dxn || scale->syn != syn ||
|
||||
scale->sxn != sxn || fabs(scale->ry - ry) > .001 ||
|
||||
fabs(scale->rx - rx) > .001 || fabs(scale->oy - oy) > .001 ||
|
||||
fabs(scale->ox - ox) > .001 || fabs(scale->py - py) > .001 ||
|
||||
fabs(scale->px - px) > .001) {
|
||||
LOGF("recomputing sampling solution");
|
||||
FreeSamplingSolution(scale->cy), scale->cy = NULL;
|
||||
FreeSamplingSolution(scale->cx), scale->cx = NULL;
|
||||
scale->cy = ComputeSamplingSolution(dyn, syn, ry, oy, py);
|
||||
scale->cx = ComputeSamplingSolution(dxn, sxn, rx, ox, px);
|
||||
scale->dyn = dyn, scale->dxn = dxn;
|
||||
scale->syn = syn, scale->sxn = sxn;
|
||||
scale->ry = ry, scale->rx = rx;
|
||||
scale->oy = oy, scale->ox = ox;
|
||||
scale->py = py, scale->px = px;
|
||||
}
|
||||
}
|
||||
|
||||
void Y2Rgb(long yn, long xn, unsigned char RGB[restrict 3][yn][xn], long yys,
|
||||
long yxs, const unsigned char Y[restrict yys][yxs],
|
||||
const int K[8][4], const unsigned char T[256]) {
|
||||
long i, j;
|
||||
for (i = 0; i < yn; ++i) {
|
||||
for (j = 0; j < xn; ++j) {
|
||||
RGB[0][i][j] = T[Y[i][j]];
|
||||
}
|
||||
}
|
||||
memcpy(RGB[1], RGB[0], yn * xn);
|
||||
memcpy(RGB[2], RGB[0], yn * xn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Y′CbCr samples to RGB.
|
||||
*/
|
||||
void YCbCr2Rgb(long yn, long xn, unsigned char RGB[restrict 3][yn][xn],
|
||||
long yys, long yxs, const unsigned char Y[restrict yys][yxs],
|
||||
long cys, long cxs, const unsigned char Cb[restrict cys][cxs],
|
||||
const unsigned char Cr[restrict cys][cxs], const int K[8][4],
|
||||
const int L[6][4], const unsigned char T[256]) {
|
||||
long i, j;
|
||||
short y, u, v, r, g, b, A, B, C;
|
||||
for (i = 0; i < yn; ++i) {
|
||||
for (j = 0; j < xn; ++j) {
|
||||
y = Y[i][j];
|
||||
u = Cb[i][j] - K[3][1];
|
||||
v = Cr[i][j] - K[3][1];
|
||||
r = y + QRS(M, v * K[0][0]);
|
||||
g = y + QRS(M, u * K[1][0] + v * K[1][1]);
|
||||
b = y + QRS(M, u * K[2][0]);
|
||||
r = QRS(M, (MIN(235, MAX(16, r)) - K[3][0]) * K[3][2]);
|
||||
g = QRS(M, (MIN(235, MAX(16, g)) - K[3][0]) * K[3][2]);
|
||||
b = QRS(M, (MIN(235, MAX(16, b)) - K[3][0]) * K[3][2]);
|
||||
RGB[0][i][j] = CLAMP(QRS(M, r * L[0][0] + g * L[0][1] + b * L[0][2]));
|
||||
RGB[1][i][j] = CLAMP(QRS(M, r * L[1][0] + g * L[1][1] + b * L[1][2]));
|
||||
RGB[2][i][j] = CLAMP(QRS(M, r * L[2][0] + g * L[2][1] + b * L[2][2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void YCbCrConvert(struct YCbCr *me, long yn, long xn,
|
||||
unsigned char RGB[restrict 3][yn][xn], long yys, long yxs,
|
||||
const unsigned char Y[restrict yys][yxs], long cys, long cxs,
|
||||
unsigned char Cb[restrict cys][cxs],
|
||||
unsigned char Cr[restrict cys][cxs]) {
|
||||
long double ts;
|
||||
ts = nowl();
|
||||
if (!me->yonly) {
|
||||
YCbCr2Rgb(yn, xn, RGB, yys, yxs, Y, cys, cxs, Cb, Cr, me->magnums,
|
||||
me->lighting, me->transfer[pf10_]);
|
||||
} else {
|
||||
Y2Rgb(yn, xn, RGB, yys, yxs, Y, me->magnums, me->transfer[pf10_]);
|
||||
}
|
||||
ycbcr2rgb_latency_ = lroundl((nowl() - ts) * 1e6l);
|
||||
}
|
||||
|
||||
void YCbCr2RgbScaler(struct YCbCr *me, long dyn, long dxn,
|
||||
unsigned char RGB[restrict 3][dyn][dxn], long yys,
|
||||
long yxs, unsigned char Y[restrict yys][yxs], long cys,
|
||||
long cxs, unsigned char Cb[restrict cys][cxs],
|
||||
unsigned char Cr[restrict cys][cxs], long yyn, long yxn,
|
||||
long cyn, long cxn, double syn, double sxn, double pry,
|
||||
double prx) {
|
||||
long double ts;
|
||||
long y, x, scyn, scxn;
|
||||
double yry, yrx, cry, crx, yoy, yox, coy, cox, err, oy;
|
||||
scyn = syn * cyn / yyn;
|
||||
scxn = sxn * cxn / yxn;
|
||||
if (HALF(yxn) > dxn && HALF(scxn) > dxn) {
|
||||
YCbCr2RgbScaler(me, dyn, dxn, RGB, yys, yxs,
|
||||
Magikarp2xX(yys, yxs, Y, syn, sxn), cys, cxs,
|
||||
Magkern2xX(cys, cxs, Cb, scyn, scxn),
|
||||
Magkern2xX(cys, cxs, Cr, scyn, scxn), yyn, HALF(yxn), cyn,
|
||||
HALF(cxn), syn, sxn / 2, pry, prx);
|
||||
} else if (HALF(yyn) > dyn && HALF(scyn) > dyn) {
|
||||
YCbCr2RgbScaler(me, dyn, dxn, RGB, yys, yxs,
|
||||
Magikarp2xY(yys, yxs, Y, syn, sxn), cys, cxs,
|
||||
Magkern2xY(cys, cxs, Cb, scyn, scxn),
|
||||
Magkern2xY(cys, cxs, Cr, scyn, scxn), HALF(yyn), yxn,
|
||||
HALF(cyn), scxn, syn / 2, sxn, pry, prx);
|
||||
} else {
|
||||
magikarp_latency_ = lroundl((nowl() - magikarp_start_) * 1e6l);
|
||||
ts = nowl();
|
||||
yry = syn / dyn;
|
||||
yrx = sxn / dxn;
|
||||
cry = syn * cyn / yyn / dyn;
|
||||
crx = sxn * cxn / yxn / dxn;
|
||||
yoy = syn / scyn / 2 - pry * .5;
|
||||
yox = sxn / scxn / 2 - prx * .5;
|
||||
coy = syn / scyn / 2 - pry * .5;
|
||||
cox = sxn / scxn / 2 - prx * .5;
|
||||
LOGF("gyarados pry=%.3f prx=%.3f syn=%.3f sxn=%.3f dyn=%ld dxn=%ld "
|
||||
"yyn=%ld "
|
||||
"yxn=%ld cyn=%ld cxn=%ld yry=%.3f yrx=%.3f cry=%.3f crx=%.3f "
|
||||
"yoy=%.3f "
|
||||
"yox=%.3f coy=%.3f cox=%.3f",
|
||||
pry, prx, syn, sxn, dyn, dxn, yyn, yxn, cyn, cxn, yry, yrx, cry, crx,
|
||||
yoy, yox, coy, cox);
|
||||
YCbCrComputeSamplingSolution(&me->luma, dyn, dxn, syn, sxn, yry, yrx, yoy,
|
||||
yox, pry, prx);
|
||||
YCbCrComputeSamplingSolution(&me->chroma, dyn, dxn, scyn, scxn, cry, crx,
|
||||
coy, cox, pry, prx);
|
||||
if (pf8_) sharpen(1, yys, yxs, (void *)Y, yyn, yxn);
|
||||
if (pf9_) unsharp(1, yys, yxs, (void *)Y, yyn, yxn);
|
||||
GyaradosUint8(yys, yxs, Y, yys, yxs, Y, dyn, dxn, syn, sxn, 0, 255,
|
||||
me->luma.cy, me->luma.cx, true);
|
||||
GyaradosUint8(cys, cxs, Cb, cys, cxs, Cb, dyn, dxn, scyn, scxn, 0, 255,
|
||||
me->chroma.cy, me->chroma.cx, false);
|
||||
GyaradosUint8(cys, cxs, Cr, cys, cxs, Cr, dyn, dxn, scyn, scxn, 0, 255,
|
||||
me->chroma.cy, me->chroma.cx, false);
|
||||
gyarados_latency_ = lround((nowl() - ts) * 1e6l);
|
||||
YCbCrConvert(me, dyn, dxn, RGB, yys, yxs, Y, cys, cxs, Cb, Cr);
|
||||
LOGF("done");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Y′CbCr frame for PC display.
|
||||
*
|
||||
* "[The] experiments of Professor J. D. Forbes, which I
|
||||
* witnessed… [established] that blue and yellow do not
|
||||
* make green but a pinkish tint, when neither prevails
|
||||
* in the combination [and the] result of mixing yellow
|
||||
* and blue was, I believe, not previously known.
|
||||
* — James Clerk Maxwell
|
||||
*
|
||||
* This function converts TV to PC graphics. We do that by
|
||||
*
|
||||
* 1. decimating w/ facebook magikarp photoshop cubic sharpen
|
||||
* 2. upsampling color difference planes, to be as big as luma plane
|
||||
* 3. converting color format
|
||||
* 4. expanding dynamic range
|
||||
* 5. transferring gamma from TV to PC convention
|
||||
* 6. resampling again to exact requested display / pixel geometry
|
||||
*
|
||||
* @param dyn/dxn is display height/width after scaling/conversion
|
||||
* @param RGB points to memory for packed de-interlaced RGB output
|
||||
* @param Y′ ∈ [16,235] is the luminance plane a gamma-corrected RGB
|
||||
* weighted sum; a.k.a. black/white legacy component part of the
|
||||
* TV signal; which may be used independently of the chrominance
|
||||
* planes; and decodes to the range [0,1]
|
||||
* @param Cb/Cr ∈ [16,240] is blue/red chrominance difference planes
|
||||
* which (if sampled at a different rate) will get stretched out
|
||||
* over the luma plane appropriately
|
||||
* @param yys/yxs dimensions luma sample array
|
||||
* @param cys/cxs dimensions chroma sample arrays
|
||||
* @param yyn/yxn is number of samples in luma signal
|
||||
* @param cyn/cxn is number of samples in each chroma signal
|
||||
* @param syn/sxn is size of source signal
|
||||
* @param pry/prx is pixel aspect ratio, e.g. 1,1
|
||||
* @return RGB
|
||||
*/
|
||||
void *YCbCr2RgbScale(long dyn, long dxn,
|
||||
unsigned char RGB[restrict 3][dyn][dxn], long yys,
|
||||
long yxs, unsigned char Y[restrict yys][yxs], long cys,
|
||||
long cxs, unsigned char Cb[restrict cys][cxs],
|
||||
unsigned char Cr[restrict cys][cxs], long yyn, long yxn,
|
||||
long cyn, long cxn, double syn, double sxn, double pry,
|
||||
double prx, struct YCbCr **ycbcr) {
|
||||
long minyys, minyxs, mincys, mincxs;
|
||||
CHECK_LE(yyn, yys);
|
||||
CHECK_LE(yxn, yxs);
|
||||
CHECK_LE(cyn, cys);
|
||||
CHECK_LE(cxn, cxs);
|
||||
LOGF("magikarp2x");
|
||||
magikarp_start_ = nowl();
|
||||
minyys = MAX(ceil(syn), MAX(yyn, ceil(dyn * pry)));
|
||||
minyxs = MAX(ceil(sxn), MAX(yxn, ceil(dxn * prx)));
|
||||
mincys = MAX(cyn, ceil(dyn * pry));
|
||||
mincxs = MAX(cxn, ceil(dxn * prx));
|
||||
YCbCr2RgbScaler(*ycbcr, dyn, dxn, RGB, MAX(yys, minyys), MAX(yxs, minyxs),
|
||||
(yys >= minyys && yxs >= minyxs
|
||||
? Y
|
||||
: gc(YCbCrReallocPlane(yys, yxs, Y, minyys, minyxs))),
|
||||
MAX(cys, mincys), MAX(cxs, mincxs),
|
||||
(cys >= mincys && cxs >= mincxs
|
||||
? Cb
|
||||
: gc(YCbCrReallocPlane(cys, cxs, Cb, mincys, mincxs))),
|
||||
(cys >= mincys && cxs >= mincxs
|
||||
? Cr
|
||||
: gc(YCbCrReallocPlane(cys, cxs, Cr, mincys, mincxs))),
|
||||
yyn, yxn, cyn, cxn, syn, sxn, pry, prx);
|
||||
return RGB;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue