Go to the documentation of this file.
45 #define MAX_DENSITY 255
46 #define MAX_DENSITY_ALPHA 64
66 #define VC_SIZE (1 << VC_SHIFT)
67 #define VC_AREA (VC_SIZE * VC_SIZE)
68 #define VC_MASK (VC_SIZE - 1)
71 #define VC_KSIZE (2 * VC_RADIUS + 1)
116 #define OFFSET(x) offsetof(LatticePalContext, x)
117 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
120 {
"max_colors",
"set the maximum number of palette entries to use",
OFFSET(max_colors),
AV_OPT_TYPE_INT, {.i64=256}, 2, 256,
FLAGS },
161 { 0, 55, 14, 68, 3, 58, 17, 72, },
162 { 37, 18, 50, 32, 40, 22, 54, 35, },
163 { 9, 64, 5, 59, 13, 67, 8, 63, },
164 { 46, 27, 41, 23, 49, 31, 44, 26, },
165 { 2, 57, 16, 71, 1, 56, 15, 70, },
166 { 39, 21, 52, 34, 38, 19, 51, 33, },
167 { 11, 66, 7, 62, 10, 65, 6, 60, },
168 { 48, 30, 43, 25, 47, 29, 42, 24, },
175 static void vc_splat(
float *energy,
const float *kern,
int pos,
float sign)
180 const int y = (py + dy) &
VC_MASK;
182 float *erow = &energy[y <<
VC_SHIFT];
185 erow[(
px + dx) &
VC_MASK] += sign * krow[dx];
194 static int vc_extreme(
const float *energy,
const uint8_t *
bits,
int want_set,
int find_max)
200 if (
bits[
i] != want_set)
202 if (best < 0 || (find_max ? energy[
i] > beste : energy[
i] < beste)) {
220 float *e1,
const float *kern,
AVLFG *lfg)
227 memset(energy, 0,
VC_AREA *
sizeof(*energy));
230 for (placed = 0; placed < n1;) {
253 memcpy(e1, energy,
VC_AREA *
sizeof(*e1));
254 for (
int r = n1 - 1;
r >= 0;
r--) {
283 const int N =
s->density;
284 const int nc =
s->nc;
288 for (
int i = 0;
i < nc;
i++) {
297 for (
int i = 1;
i < nc;
i++)
300 dir = d[k] >= 0.f ? 1 : -1;
301 if (
f[k] + dir < 0 ||
f[k] + dir >
N)
318 for (
int i = 1;
i <
s->nc;
i++)
325 if (
s->nb_used ==
s->nb_alloc) {
326 const int na =
FFMAX(
s->nb_alloc * 2, 512);
333 e = &
s->list[
s->nb_used];
338 e->
ci[3] =
s->nc == 4 ?
f[3] : 0;
341 s->cell[
pos] = idx = ++
s->nb_used;
343 s->list[idx - 1].count++;
363 const uint8_t *
val =
s->idx2val;
364 const int dim =
s->dim;
365 const int i0 = ci[0], i1 = ci[1], i2 = ci[2], i3 = ci[3];
366 const int v0 =
val[i0], v1 =
val[i1], v2 =
val[i2], v3 =
val[i3];
367 int best = -1, bestd = INT_MAX;
369 if (
s->nb_alive > 0 &&
s->nb_alive <= 1024) {
370 for (
int k = 0; k <
s->nb_alive; k++) {
371 const int j =
s->alive_arr[k];
377 dv =
val[o->
ci[0]] - v0; d2 = dv * dv;
378 dv =
val[o->
ci[1]] - v1; d2 += dv * dv;
379 dv =
val[o->
ci[2]] - v2; d2 += dv * dv;
380 dv =
val[o->
ci[3]] - v3; d2 += dv * dv;
386 *out_d2 = best >= 0 ? bestd : 0;
390 #define CHECK_CELL3(a, b, c) do { \
391 const int e = s->cell[((a) * dim + (b)) * dim + (c)]; \
392 if (e > 0 && e - 1 != self && list[e - 1].alive) { \
393 const int dr = val[a] - v0; \
394 const int dg = val[b] - v1; \
395 const int db = val[c] - v2; \
396 const int d2 = dr * dr + dg * dg + db * db; \
404 #define CHECK_CELL4(a, b, c, l) do { \
405 const int e = s->cell[(((a) * dim + (b)) * dim + (c)) * dim + (l)]; \
406 if (e > 0 && e - 1 != self && list[e - 1].alive) { \
407 const int dr = val[a] - v0; \
408 const int dg = val[b] - v1; \
409 const int db = val[c] - v2; \
410 const int da_ = val[l] - v3; \
411 const int d2 = dr * dr + dg * dg + db * db + da_ * da_; \
419 for (
int r = 1;
r <
dim;
r++) {
420 if (best >= 0 && (
int64_t)
r *
s->min_gap *
r *
s->min_gap > bestd)
423 const int da =
FFABS(
a - i0);
430 if (!((
a +
b +
c) & 1))
433 if (i2 -
r >= 0 && !((
a +
b + i2 -
r) & 1))
435 if (i2 +
r <
dim && !((
a +
b + i2 +
r) & 1))
442 if (!((
a +
b +
c + l) & 1))
445 if (i3 -
r >= 0 && !((
a +
b +
c + i3 -
r) & 1))
447 if (i3 +
r <
dim && !((
a +
b +
c + i3 +
r) & 1))
458 *out_d2 = best >= 0 ? bestd : 0;
467 s->list[
self].d2 = d2;
479 while (
i > 0 && heap[(
i - 1) / 2].imp > imp) {
480 heap[
i] = heap[(
i - 1) / 2];
490 const HeapEnt last = heap[--*nb];
493 while ((
c = 2 *
i + 1) < *nb) {
494 if (
c + 1 < *nb && heap[
c + 1].imp < heap[
c].imp)
496 if (heap[
c].imp >= last.
imp)
520 int nb_heap = 0, cap =
s->nb_used + 64;
526 if (
s->alive_alloc <
s->nb_used) {
531 if (!
s->alive_arr || !
s->alive_pos) {
535 s->alive_alloc =
s->nb_used;
538 for (
int i = 0;
i <
s->nb_used;
i++) {
541 s->alive_pos[
i] =
s->nb_alive;
542 s->alive_arr[
s->nb_alive++] =
i;
546 for (
int k = 0; k <
s->nb_alive; k++) {
547 const int i =
s->alive_arr[k];
553 while (alive > target) {
555 const int i = top.
idx;
563 if (imp != top.
imp) {
565 if (nb_heap == cap) {
581 s->alive_arr[
s->alive_pos[
i]] =
s->alive_arr[--
s->nb_alive];
582 s->alive_pos[
s->alive_arr[
s->nb_alive]] =
s->alive_pos[
i];
592 return (
s->nc == 4 ? (uint32_t)
s->idx2val[e->
ci[3]] << 24 : 0xFF000000) |
593 s->idx2val[e->
ci[0]] << 16 |
594 s->idx2val[e->
ci[1]] << 8 |
595 s->idx2val[e->
ci[2]];
617 const int ro =
s->ro, go =
s->go, bo =
s->bo, ao =
s->ao, pixstep =
s->pixstep;
618 const int nc =
s->nc;
619 const uint32_t *pal = (
const uint32_t *)
out->data[1];
621 memset(
s->err[0], 0, (
w + 2) * nc *
sizeof(*
s->err[0]));
622 memset(
s->err[1], 0, (
w + 2) * nc *
sizeof(*
s->err[1]));
624 for (
int y = 0; y <
h; y++) {
626 uint8_t *
dst =
out->data[0] + y *
out->linesize[0];
627 const int dir = (y & 1) ? -1 : 1;
628 const int x0 = dir > 0 ? 0 :
w - 1;
629 int32_t *err_cur =
s->err[ y & 1] + nc;
630 int32_t *err_next =
s->err[(y + 1) & 1] + nc;
634 memset(err_next - nc, 0, (
w + 2) * nc *
sizeof(*err_next));
636 for (
int k = 0; k <
w; k++) {
637 const int x = x0 + k * dir;
638 const int32_t *e = &err_cur[x * nc];
650 for (
int i = 1;
i < nc;
i++)
653 slot1 =
s->cell[
pos];
655 const uint8_t *
val =
s->idx2val;
658 for (
int k = 0; k <
s->nb_alive; k++) {
659 const PalEntry *o = &
s->list[
s->alive_arr[k]];
662 dv =
val[o->
ci[0]] -
val[
f[0]]; d2 = dv * dv;
663 dv =
val[o->
ci[1]] -
val[
f[1]]; d2 += dv * dv;
664 dv =
val[o->
ci[2]] -
val[
f[2]]; d2 += dv * dv;
666 dv =
val[o->
ci[3]] -
val[
f[3]]; d2 += dv * dv;
673 if (
s->nb_touched ==
s->touched_alloc) {
674 const int na =
FFMAX(
s->touched_alloc * 2, 1024);
679 s->touched_alloc = na;
681 s->touched[
s->nb_touched++] =
pos;
682 s->cell[
pos] = slot1;
687 for (
int i = 0;
i < nc;
i++) {
688 static const int sh[4] = { 16, 8, 0, 24 };
689 const int qerr =
px[
i] - (int)(
c >> sh[
i] & 0xff);
691 err_cur [(x + dir) * nc +
i] += qerr * 7;
692 err_next[(x - dir) * nc +
i] += qerr * 3;
693 err_next[ x * nc +
i] += qerr * 5;
694 err_next[(x + dir) * nc +
i] += qerr;
715 const int nc =
s->nc;
716 const uint32_t *pal = (
const uint32_t *)
out->data[1];
717 const uint8_t *
val =
s->idx2val;
720 memset(
s->err[0], 0, (
w + 2) * nc *
sizeof(*
s->err[0]));
721 memset(
s->err[1], 0, (
w + 2) * nc *
sizeof(*
s->err[1]));
723 for (
int y = 0; y <
h; y++) {
724 const uint32_t *ppos =
s->pixpos + (size_t)y *
w;
725 uint8_t *
dst =
out->data[0] + y *
out->linesize[0];
726 const int dir = (y & 1) ? -1 : 1;
727 const int x0 = dir > 0 ? 0 :
w - 1;
728 int32_t *err_cur =
s->err[ y & 1] + nc;
729 int32_t *err_next =
s->err[(y + 1) & 1] + nc;
733 memset(err_next - nc, 0, (
w + 2) * nc *
sizeof(*err_next));
735 for (
int k = 0; k <
w; k++) {
736 const int x = x0 + k * dir;
738 const int32_t *e = &err_cur[x * nc];
742 if (e1->
alive && !(e[0] | e[1] | e[2] | (nc == 4 ? e[3] : 0))) {
749 for (
int i = 0;
i < nc;
i++)
754 for (
int i = 1;
i < nc;
i++)
759 slot =
list[v - 1].nn;
766 for (
int j = 0; j <
s->nb_alive; j++) {
770 dv =
val[o->
ci[0]] -
val[
f[0]]; d2 = dv * dv;
771 dv =
val[o->
ci[1]] -
val[
f[1]]; d2 += dv * dv;
772 dv =
val[o->
ci[2]] -
val[
f[2]]; d2 += dv * dv;
774 dv =
val[o->
ci[3]] -
val[
f[3]]; d2 += dv * dv;
781 if (
s->nb_touched ==
s->touched_alloc) {
782 const int na =
FFMAX(
s->touched_alloc * 2, 1024);
787 s->touched_alloc = na;
789 s->touched[
s->nb_touched++] =
pos;
790 s->cell[
pos] = -(slot + 1);
795 for (
int i = 0;
i < nc;
i++) {
796 static const int sh[4] = { 16, 8, 0, 24 };
797 const int qerr =
px[
i] - (int)(
c >> sh[
i] & 0xff);
799 err_cur [(x + dir) * nc +
i] += qerr * 7;
800 err_next[(x - dir) * nc +
i] += qerr * 3;
801 err_next[ x * nc +
i] += qerr * 5;
802 err_next[(x + dir) * nc +
i] += qerr;
819 const int ro =
s->ro, go =
s->go, bo =
s->bo, ao =
s->ao, pixstep =
s->pixstep;
820 const int nc =
s->nc;
821 const uint8_t *
val =
s->idx2val;
824 for (
int k = 0; k <
s->nb_alive; k++)
825 list[
s->alive_arr[k]].count = 0;
827 memset(
s->err[0], 0, (
w + 2) * nc *
sizeof(*
s->err[0]));
828 memset(
s->err[1], 0, (
w + 2) * nc *
sizeof(*
s->err[1]));
830 for (
int y = 0; y <
h; y++) {
832 uint32_t *ppos =
s->pixpos + (size_t)y *
w;
833 const int dir = (y & 1) ? -1 : 1;
834 const int x0 = dir > 0 ? 0 :
w - 1;
835 int32_t *err_cur =
s->err[ y & 1] + nc;
836 int32_t *err_next =
s->err[(y + 1) & 1] + nc;
840 memset(err_next - nc, 0, (
w + 2) * nc *
sizeof(*err_next));
842 for (
int k = 0; k <
w; k++) {
843 const int x = x0 + k * dir;
844 const int32_t *e = &err_cur[x * nc];
856 for (
int i = 1;
i < nc;
i++)
860 if (v > 0 &&
list[v - 1].alive) {
862 }
else if (v < 0 &&
list[-v - 1].alive) {
865 const uint8_t fci[4] = {
f[0],
f[1],
f[2], nc == 4 ?
f[3] : 0 };
870 if (
s->nb_touched ==
s->touched_alloc) {
871 const int na =
FFMAX(
s->touched_alloc * 2, 1024);
876 s->touched_alloc = na;
878 s->touched[
s->nb_touched++] =
pos;
880 s->cell[
pos] = -(j + 1);
886 for (
int i = 0;
i < nc;
i++) {
889 err_cur [(x + dir) * nc +
i] += qerr * 7;
890 err_next[(x - dir) * nc +
i] += qerr * 3;
891 err_next[ x * nc +
i] += qerr * 5;
892 err_next[(x + dir) * nc +
i] += qerr;
910 int alive =
s->nb_used;
912 while (alive >
s->max_colors) {
913 const int excess = alive -
s->max_colors;
914 const int target =
s->max_colors + excess / 2;
926 for (
int k = 0; k <
s->nb_alive;) {
927 const int i =
s->alive_arr[k];
929 if (!
s->list[
i].count) {
930 s->list[
i].alive = 0;
931 s->alive_arr[k] =
s->alive_arr[--
s->nb_alive];
932 s->alive_pos[
s->alive_arr[k]] = k;
947 const int ro =
s->ro, go =
s->go, bo =
s->bo, ao =
s->ao, pixstep =
s->pixstep;
948 const int nc =
s->nc;
951 int ret, reduced = 0;
965 memset(
s->err[0], 0, (
w + 2) * nc *
sizeof(*
s->err[0]));
966 memset(
s->err[1], 0, (
w + 2) * nc *
sizeof(*
s->err[1]));
970 for (
int y = 0; y <
h; y++) {
972 uint32_t *ppos =
s->pixpos + (size_t)y *
w;
980 const int dir = (y & 1) ? -1 : 1;
981 const int x0 = dir > 0 ? 0 :
w - 1;
982 int32_t *err_cur =
s->err[ y & 1] + nc;
983 int32_t *err_next =
s->err[(y + 1) & 1] + nc;
985 memset(err_next - nc, 0, (
w + 2) * nc *
sizeof(*err_next));
987 for (
int k = 0; k <
w; k++) {
988 const int x = x0 + k * dir;
989 const int32_t *e = &err_cur[x * nc];
1005 for (
int i = 0;
i < nc;
i++) {
1006 const int qerr =
px[
i] -
s->idx2val[
f[
i]];
1008 err_cur [(x + dir) * nc +
i] += qerr * 7;
1009 err_next[(x - dir) * nc +
i] += qerr * 3;
1010 err_next[ x * nc +
i] += qerr * 5;
1011 err_next[(x + dir) * nc +
i] += qerr;
1020 for (
int i = 0;
i < nc;
i++)
1021 dt[
i] = (blue ?
s->blue_dither[
i] :
s->ordered_dither[
i]) + rowoff;
1023 for (
int x = 0; x <
w; x++) {
1024 px[0] =
src[x * pixstep + ro] + dt[0][x &
mask];
1025 px[1] =
src[x * pixstep + go] + dt[1][x &
mask];
1026 px[2] =
src[x * pixstep + bo] + dt[2][x &
mask];
1028 px[3] = (ao >= 0 ?
src[x * pixstep + ao] : 255) + dt[3][x &
mask];
1039 for (
int x = 0; x <
w; x++) {
1040 px[0] =
src[x * pixstep + ro];
1041 px[1] =
src[x * pixstep + go];
1042 px[2] =
src[x * pixstep + bo];
1044 px[3] = ao >= 0 ?
src[x * pixstep + ao] : 255;
1057 reduced =
s->nb_used >
s->max_colors;
1066 "pts %"PRId64
": %d lattice colors used, %d dropped\n",
1067 in->
pts,
s->nb_used,
s->nb_used -
s->nb_alive);
1079 for (
int i = 0;
i <
s->nb_used;
i++) {
1088 if (!claimed[slot] &&
s->prev_pal[slot] ==
c) {
1095 for (
int i = 0;
i <
s->nb_used;
i++) {
1105 const uint32_t
p =
s->prev_pal[slot];
1106 const int da = (int)(
p >> 24 ) - (int)(
c >> 24 );
1107 const int dr = (int)(
p >> 16 & 0xff) - (int)(
c >> 16 & 0xff);
1108 const int dg = (int)(
p >> 8 & 0xff) - (int)(
c >> 8 & 0xff);
1109 const int db = (int)(
p & 0xff) - (int)(
c & 0xff);
1110 const int64_t d2 = (
int64_t)da * da + dr * dr + dg * dg + db * db;
1112 if (!claimed[slot] && d2 < bd) {
1121 pal = (uint32_t *)
out->data[1];
1123 for (
int i = 0;
i <
s->nb_used;
i++) {
1132 for (
int i = 0;
i <
s->nb_used;
i++) {
1137 e->
nn =
s->list[e->
nn].nn;
1144 for (
int y = 0; y <
h; y++) {
1145 const uint32_t *ppos =
s->pixpos + (size_t)y *
w;
1146 uint8_t *
dst =
out->data[0] + y *
out->linesize[0];
1148 for (
int x = 0; x <
w; x++)
1149 dst[x] =
s->list[ppos[x]].nn;
1158 for (
int i = 0;
i <
s->nb_used;
i++)
1159 s->cell[
s->list[
i].pos] =
s->list[
i].nn + 1;
1165 for (
int i = 0;
i <
s->nb_used;
i++)
1166 s->cell[
s->list[
i].pos] =
s->list[
i].nn;
1167 for (
int y = 0; y <
h; y++) {
1168 const uint32_t *ppos =
s->pixpos + (size_t)y *
w;
1169 uint8_t *
dst =
out->data[0] + y *
out->linesize[0];
1171 for (
int x = 0; x <
w; x++)
1172 dst[x] =
s->cell[ppos[x]];
1177 for (
int i = 0;
i <
s->nb_used;
i++)
1178 s->cell[
s->list[
i].pos] = 0;
1179 for (
int i = 0;
i <
s->nb_touched;
i++)
1180 s->cell[
s->touched[
i]] = 0;
1187 for (
int i = 0;
i <
s->nb_used;
i++)
1188 s->cell[
s->list[
i].pos] = 0;
1189 for (
int i = 0;
i <
s->nb_touched;
i++)
1190 s->cell[
s->touched[
i]] = 0;
1202 const int N =
s->density;
1204 s->pixstep =
desc->comp[0].step;
1205 s->ro =
desc->comp[0].offset;
1206 s->go =
desc->comp[1].offset;
1207 s->bo =
desc->comp[2].offset;
1209 ?
desc->comp[3].offset : -1;
1210 s->nc =
s->alpha ? 4 : 3;
1214 "density is limited to %d when the alpha channel is quantized\n",
1219 s->scale =
N / 255.f;
1220 for (
int i = 0;
i <=
N;
i++)
1224 s->prev_pal[
i] = 0xFF000000;
1229 s->min_gap =
FFMIN(
s->min_gap,
s->idx2val[
i] -
s->idx2val[
i - 1]);
1232 s->cell =
av_calloc(
s->nc == 4 ? (
size_t)
s->dim *
s->dim *
s->dim *
s->dim
1233 : (
size_t)
s->dim *
s->dim *
s->dim,
1237 if (!
s->cell || !
s->pixpos)
1257 const float amp = 2.f * 255.f /
N;
1258 for (
int y = 0; y < 8; y++) {
1259 for (
int x = 0; x < 8; x++) {
1260 const int i = y << 3 | x;
1287 const float step = 255.f /
N;
1289 uint16_t *ranks[4] = {
NULL };
1304 for (
int p = 0;
p <
s->nc &&
ret >= 0;
p++) {
1308 if (!
s->blue_dither[
p])
1310 if (!ranks[
p] || !
s->blue_dither[
p]) {
1320 const float a = (ranks[0][
i] + 0.5f) /
VC_AREA;
1321 const float b = (ranks[1][
i] + 0.5f) /
VC_AREA;
1322 const float c = (ranks[2][
i] + 0.5f) /
VC_AREA;
1327 const float dd = (ranks[3][
i] + 0.5f) /
VC_AREA;
1348 for (
int i = 0;
i < 2;
i++) {
1365 for (
int i = 0;
i < 4;
i++)
1385 .
p.
name =
"latticepal",
1386 .p.description =
NULL_IF_CONFIG_SMALL(
"Convert RGB to PAL8 using a per-frame FCC lattice palette."),
1387 .p.priv_class = &latticepal_class,
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
static int config_input(AVFilterLink *inlink)
AVPixelFormat
Pixel format.
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
static void vc_generate(uint16_t *rank, uint8_t *bits, float *energy, float *e1, const float *kern, AVLFG *lfg)
Generate a void-and-cluster blue noise rank matrix (Ulichney 1993): every cell gets a unique rank in ...
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int alpha
quantize the alpha channel too (D4 lattice)
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
This structure describes decoded (raw) audio or video data.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
#define u(width, name, range_min, range_max)
int32_t * cell
dim^nc table: lattice cell -> list index + 1, 0 if unused
int64_t imp
impact of the removal when the entry was pushed
AVFILTER_DEFINE_CLASS(latticepal)
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
const char * name
Filter name.
int * blue_dither[4]
per-channel blue noise offsets spanning one lattice period
int pos
lattice cell position, ((i * dim + j) * dim + k) [* dim + l]
A link between two filters.
static int batch_assign(LatticePalContext *s, const AVFrame *in)
Rediffuse the whole frame against the current live colors and reassign every pixel,...
static const AVOption latticepal_options[]
static av_cold void uninit(AVFilterContext *ctx)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
static int nearest_alive(LatticePalContext *s, const uint8_t ci[4], int self, int *out_d2)
Find the nearest live color of the used color list, excluding self (pass -1 to match any live color).
static double b1(void *priv, double x, double y)
int density
lattice steps per color axis
static void heap_push(HeapEnt *heap, int *nb, int64_t imp, int idx)
int pixstep
bytes per input pixel
PalEntry * list
colors used by the current frame
static double val(void *priv, double ch)
static const AVFilterPad latticepal_inputs[]
int max_colors
palette entries to use at most
uint8_t alive
still part of the palette while reducing
static __device__ float fabsf(float a)
int refine
rediffuse the error of dropped colors
#define FILTER_QUERY_FUNC2(func)
A filter pad used for either input or output.
static int vc_extreme(const float *energy, const uint8_t *bits, int want_set, int find_max)
Position of the extreme energy value among the cells whose bit equals want_set: the tightest cluster ...
int idx
used color list index
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
const FFFilter ff_vf_latticepal
static HeapEnt heap_pop(HeapEnt *heap, int *nb)
int * alive_pos
position of each live color in alive_arr
static const uint16_t dither[8][8]
#define FILTER_OUTPUTS(array)
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
@ DITHERING_FLOYD_STEINBERG
#define CHECK_CELL3(a, b, c)
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
static AVFormatContext * ctx
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
int min_gap
smallest idx2val increment
static void vc_splat(float *energy, const float *kern, int pos, float sign)
Add (sign > 0) or remove (sign < 0) the Gaussian energy contribution of a minority pixel at position ...
Describe the class of an AVClass context structure.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
static av_always_inline int color_inc(LatticePalContext *s, const int f[4])
Account one pixel using the lattice color with indices f, registering the color in the cell table and...
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
int ao
byte offsets of R, G, B, A in an input pixel, ao < 0: opaque
uint32_t prev_pal[AVPALETTE_COUNT]
previous frame's palette, for stable slot assignment
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
static av_always_inline uint32_t entry_color(const LatticePalContext *s, const PalEntry *e)
Palette color (AARRGGBB) of a used color list entry.
Context structure for the Lagged Fibonacci PRNG.
static int refine_residual(LatticePalContext *s, AVFrame *out, const AVFrame *in)
Residual refinement pass: rediffuse only the error of the dropped colors, using the first pass quanti...
int d2
squared RGB(A) distance to nn
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
#define i(width, name, range_min, range_max)
int * touched
cells filled on demand by the refinement pass
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
int dim
density + 1, lattice cells per axis
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
int32_t * err[2]
Floyd-Steinberg error rows, nc ints per pixel.
uint8_t ci[4]
lattice indices of the color
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
#define MAX_DENSITY_ALPHA
uint8_t idx2val[MAX_DENSITY+1]
lattice index -> 8-bit component value
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
int nc
quantized components, 3 or 4
int ordered_dither[4][8 *8]
per-channel bayer offsets spanning one lattice period
int w
agreed upon image width
#define av_malloc_array(a, b)
const char * name
Pad name.
void * av_calloc(size_t nmemb, size_t size)
int nb_alive
entries in alive_arr, 0 outside reduction/remap
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
int64_t count
pixels quantizing to this color, incl. absorbed ones
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
static int reduce_colors(LatticePalContext *s, int target)
Reduce the live colors down to target by repeatedly dropping the color whose removal has the least im...
#define FILTER_INPUTS(array)
static void nn_search(LatticePalContext *s, int self)
int h
agreed upon image height
#define CHECK_CELL4(a, b, c, l)
static int reduce_batched(LatticePalContext *s, const AVFrame *in)
Batched reduction: instead of dropping all excess colors against the first pass statistics,...
static const uint8_t dither_8x8_73[8][8]
@ AV_OPT_TYPE_INT
Underlying C type is int.
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
int nn
nearest live color while reducing, then palette slot
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
static av_always_inline void quant_dn(const LatticePalContext *s, const int *in, int f[4])
Quantize a color to the nearest point of the scaled D3 (FCC) or D4 lattice.
AVFilter p
The public AVFilter.
uint32_t * pixpos
per-pixel cell position of the quantized color
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
int * alive_arr
compact list of live color indices while reducing
static int refine_full(LatticePalContext *s, AVFrame *out, const AVFrame *in)
Full refinement pass: rediffuse the whole frame against the final palette.
static const int16_t alpha[]
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.