+static void unpremultiplyf32(const uint8_t *mmsrc, const uint8_t *aasrc,
+ uint8_t *ddst,
+ ptrdiff_t mlinesize, ptrdiff_t alinesize,
+ ptrdiff_t dlinesize,
+ int w, int h,
+ int half, int max, int offset)
+{
+ const float *msrc = (const float *)mmsrc;
+ const float *asrc = (const float *)aasrc;
+
+ float *dst = (float *)ddst;
+ int x, y;
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ if (asrc[x] > 0.0f)
+ dst[x] = msrc[x] / asrc[x];
+ else
+ dst[x] = msrc[x];
+ }
+
+ dst += dlinesize / 4;
+ msrc += mlinesize / 4;
+ asrc += alinesize / 4;
+ }
+}
+
+static void unpremultiplyf32offset(const uint8_t *mmsrc, const uint8_t *aasrc,
+ uint8_t *ddst,
+ ptrdiff_t mlinesize, ptrdiff_t alinesize,
+ ptrdiff_t dlinesize,
+ int w, int h,
+ int half, int max, int offset)
+{
+ const float *msrc = (const float *)mmsrc;
+ const float *asrc = (const float *)aasrc;
+
+ float *dst = (float *)ddst;
+ int x, y;
+
+ float offsetf = offset / 65535.0f;
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ if (asrc[x] > 0.0f)
+ dst[x] = (msrc[x] - offsetf) / asrc[x] + offsetf;
+ else
+ dst[x] = msrc[x];
+ }
+
+ dst += dlinesize / 4;
+ msrc += mlinesize / 4;
+ asrc += alinesize / 4;
+ }
+}
+
+static int premultiply_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+ PreMultiplyContext *s = ctx->priv;
+ ThreadData *td = arg;
+ AVFrame *out = td->d;
+ AVFrame *alpha = td->a;
+ AVFrame *base = td->m;
+ int p;
+
+ for (p = 0; p < s->nb_planes; p++) {
+ const int slice_start = (s->height[p] * jobnr) / nb_jobs;
+ const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs;
+
+ if (!((1 << p) & s->planes) || p == 3) {
+ av_image_copy_plane(out->data[p] + slice_start * out->linesize[p],
+ out->linesize[p],
+ base->data[p] + slice_start * base->linesize[p],
+ base->linesize[p],
+ s->linesize[p], slice_end - slice_start);
+ continue;
+ }
+
+ s->premultiply[p](base->data[p] + slice_start * base->linesize[p],
+ s->inplace ? alpha->data[3] + slice_start * alpha->linesize[3] :
+ alpha->data[0] + slice_start * alpha->linesize[0],
+ out->data[p] + slice_start * out->linesize[p],
+ base->linesize[p], s->inplace ? alpha->linesize[3] : alpha->linesize[0],
+ out->linesize[p],
+ s->width[p], slice_end - slice_start,
+ s->half, s->inverse ? s->max : s->depth, s->offset);
+ }
+
+ return 0;
+}
+