+static void find_min_max(NormalizeContext *s, AVFrame *in, NormalizeLocal min[3], NormalizeLocal max[3])
+{
+ for (int c = 0; c < 3; c++)
+ min[c].in = max[c].in = in->data[0][s->co[c]];
+ for (int y = 0; y < in->height; y++) {
+ uint8_t *inp = in->data[0] + y * in->linesize[0];
+ for (int x = 0; x < in->width; x++) {
+ for (int c = 0; c < 3; c++) {
+ min[c].in = FFMIN(min[c].in, inp[s->co[c]]);
+ max[c].in = FFMAX(max[c].in, inp[s->co[c]]);
+ }
+ inp += s->step;
+ }
+ }
+}
+
+static void process(NormalizeContext *s, AVFrame *in, AVFrame *out)
+{
+ for (int y = 0; y < in->height; y++) {
+ uint8_t *inp = in->data[0] + y * in->linesize[0];
+ uint8_t *outp = out->data[0] + y * out->linesize[0];
+ for (int x = 0; x < in->width; x++) {
+ for (int c = 0; c < 3; c++)
+ outp[s->co[c]] = s->lut[c][inp[s->co[c]]];
+ if (s->num_components == 4)
+ // Copy alpha as-is.
+ outp[s->co[3]] = inp[s->co[3]];
+ inp += s->step;
+ outp += s->step;
+ }
+ }
+}
+
+static void find_min_max_planar(NormalizeContext *s, AVFrame *in, NormalizeLocal min[3], NormalizeLocal max[3])
+{
+ min[0].in = max[0].in = in->data[2][0];
+ min[1].in = max[1].in = in->data[0][0];
+ min[2].in = max[2].in = in->data[1][0];
+ for (int y = 0; y < in->height; y++) {
+ uint8_t *inrp = in->data[2] + y * in->linesize[2];
+ uint8_t *ingp = in->data[0] + y * in->linesize[0];
+ uint8_t *inbp = in->data[1] + y * in->linesize[1];
+ for (int x = 0; x < in->width; x++) {
+ min[0].in = FFMIN(min[0].in, inrp[x]);
+ max[0].in = FFMAX(max[0].in, inrp[x]);
+ min[1].in = FFMIN(min[1].in, ingp[x]);
+ max[1].in = FFMAX(max[1].in, ingp[x]);
+ min[2].in = FFMIN(min[2].in, inbp[x]);
+ max[2].in = FFMAX(max[2].in, inbp[x]);
+ }
+ }
+}
+
+static void process_planar(NormalizeContext *s, AVFrame *in, AVFrame *out)
+{
+ for (int y = 0; y < in->height; y++) {
+ uint8_t *inrp = in->data[2] + y * in->linesize[2];
+ uint8_t *ingp = in->data[0] + y * in->linesize[0];
+ uint8_t *inbp = in->data[1] + y * in->linesize[1];
+ uint8_t *inap = in->data[3] + y * in->linesize[3];
+ uint8_t *outrp = out->data[2] + y * out->linesize[2];
+ uint8_t *outgp = out->data[0] + y * out->linesize[0];
+ uint8_t *outbp = out->data[1] + y * out->linesize[1];
+ uint8_t *outap = out->data[3] + y * out->linesize[3];
+ for (int x = 0; x < in->width; x++) {
+ outrp[x] = s->lut[0][inrp[x]];
+ outgp[x] = s->lut[1][ingp[x]];
+ outbp[x] = s->lut[2][inbp[x]];
+ if (s->num_components == 4)
+ outap[x] = inap[x];
+ }
+ }
+}
+
+static void find_min_max_16(NormalizeContext *s, AVFrame *in, NormalizeLocal min[3], NormalizeLocal max[3])
+{
+ for (int c = 0; c < 3; c++)
+ min[c].in = max[c].in = AV_RN16(in->data[0] + 2 * s->co[c]);
+ for (int y = 0; y < in->height; y++) {
+ uint16_t *inp = (uint16_t *)(in->data[0] + y * in->linesize[0]);
+ for (int x = 0; x < in->width; x++) {
+ for (int c = 0; c < 3; c++) {
+ min[c].in = FFMIN(min[c].in, inp[s->co[c]]);
+ max[c].in = FFMAX(max[c].in, inp[s->co[c]]);
+ }
+ inp += s->step;
+ }
+ }
+}
+
+static void process_16(NormalizeContext *s, AVFrame *in, AVFrame *out)
+{
+ for (int y = 0; y < in->height; y++) {
+ uint16_t *inp = (uint16_t *)(in->data[0] + y * in->linesize[0]);
+ uint16_t *outp = (uint16_t *)(out->data[0] + y * out->linesize[0]);
+ for (int x = 0; x < in->width; x++) {
+ for (int c = 0; c < 3; c++)
+ outp[s->co[c]] = s->lut[c][inp[s->co[c]]];
+ if (s->num_components == 4)
+ // Copy alpha as-is.
+ outp[s->co[3]] = inp[s->co[3]];
+ inp += s->step;
+ outp += s->step;
+ }
+ }
+}
+
+static void find_min_max_planar_16(NormalizeContext *s, AVFrame *in, NormalizeLocal min[3], NormalizeLocal max[3])
+{
+ min[0].in = max[0].in = AV_RN16(in->data[2]);
+ min[1].in = max[1].in = AV_RN16(in->data[0]);
+ min[2].in = max[2].in = AV_RN16(in->data[1]);
+ for (int y = 0; y < in->height; y++) {
+ uint16_t *inrp = (uint16_t *)(in->data[2] + y * in->linesize[2]);
+ uint16_t *ingp = (uint16_t *)(in->data[0] + y * in->linesize[0]);
+ uint16_t *inbp = (uint16_t *)(in->data[1] + y * in->linesize[1]);
+ for (int x = 0; x < in->width; x++) {
+ min[0].in = FFMIN(min[0].in, inrp[x]);
+ max[0].in = FFMAX(max[0].in, inrp[x]);
+ min[1].in = FFMIN(min[1].in, ingp[x]);
+ max[1].in = FFMAX(max[1].in, ingp[x]);
+ min[2].in = FFMIN(min[2].in, inbp[x]);
+ max[2].in = FFMAX(max[2].in, inbp[x]);
+ }
+ }
+}
+
+static void process_planar_16(NormalizeContext *s, AVFrame *in, AVFrame *out)
+{
+ for (int y = 0; y < in->height; y++) {
+ uint16_t *inrp = (uint16_t *)(in->data[2] + y * in->linesize[2]);
+ uint16_t *ingp = (uint16_t *)(in->data[0] + y * in->linesize[0]);
+ uint16_t *inbp = (uint16_t *)(in->data[1] + y * in->linesize[1]);
+ uint16_t *inap = (uint16_t *)(in->data[3] + y * in->linesize[3]);
+ uint16_t *outrp = (uint16_t *)(out->data[2] + y * out->linesize[2]);
+ uint16_t *outgp = (uint16_t *)(out->data[0] + y * out->linesize[0]);
+ uint16_t *outbp = (uint16_t *)(out->data[1] + y * out->linesize[1]);
+ uint16_t *outap = (uint16_t *)(out->data[3] + y * out->linesize[3]);
+ for (int x = 0; x < in->width; x++) {
+ outrp[x] = s->lut[0][inrp[x]];
+ outgp[x] = s->lut[1][ingp[x]];
+ outbp[x] = s->lut[2][inbp[x]];
+ if (s->num_components == 4)
+ outap[x] = inap[x];
+ }
+ }
+}
+