133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Copyright 2014 Google Inc. All Rights Reserved.
233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//
333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Use of this source code is governed by a BSD-style license
433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// that can be found in the COPYING file in the root of the source
533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// tree. An additional intellectual property rights grant can be found
633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// in the file PATENTS. All contributing project authors may
733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// be found in the AUTHORS file in the root of the source tree.
833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// -----------------------------------------------------------------------------
933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//
1033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// WebPPicture tools: copy, crop, rescaling and view.
1133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//
1233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Author: Skal (pascal.massimino@gmail.com)
1333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
1433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include <assert.h>
1533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include <stdlib.h>
1633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
1733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "./vp8enci.h"
1833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "../utils/rescaler.h"
1933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "../utils/utils.h"
2033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
2133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define HALVE(x) (((x) + 1) >> 1)
2233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
2333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them
2433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// into 'dst'. Mark 'dst' as not owning any memory.
2533f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void PictureGrabSpecs(const WebPPicture* const src,
2633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                             WebPPicture* const dst) {
2733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  assert(src != NULL && dst != NULL);
2833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  *dst = *src;
2933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPPictureResetBuffers(dst);
3033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
3133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
3233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------
3333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
3433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Adjust top-left corner to chroma sample position.
3533f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void SnapTopLeftPosition(const WebPPicture* const pic,
3633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                int* const left, int* const top) {
3733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!pic->use_argb) {
3833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    *left &= ~1;
3933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    *top &= ~1;
4033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
4133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
4233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
4333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Adjust top-left corner and verify that the sub-rectangle is valid.
4433f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic int AdjustAndCheckRectangle(const WebPPicture* const pic,
4533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                   int* const left, int* const top,
4633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                                   int width, int height) {
4733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  SnapTopLeftPosition(pic, left, top);
4833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if ((*left) < 0 || (*top) < 0) return 0;
4933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (width <= 0 || height <= 0) return 0;
5033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if ((*left) + width > pic->width) return 0;
5133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if ((*top) + height > pic->height) return 0;
5233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return 1;
5333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
5433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
5533f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) {
5633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (src == NULL || dst == NULL) return 0;
5733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (src == dst) return 1;
5833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
5933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  PictureGrabSpecs(src, dst);
6033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!WebPPictureAlloc(dst)) return 0;
6133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
6233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!src->use_argb) {
637c8da7ce66017295a65ec028084b90800be377f8James Zern    WebPCopyPlane(src->y, src->y_stride,
647c8da7ce66017295a65ec028084b90800be377f8James Zern                  dst->y, dst->y_stride, dst->width, dst->height);
657c8da7ce66017295a65ec028084b90800be377f8James Zern    WebPCopyPlane(src->u, src->uv_stride, dst->u, dst->uv_stride,
667c8da7ce66017295a65ec028084b90800be377f8James Zern                  HALVE(dst->width), HALVE(dst->height));
677c8da7ce66017295a65ec028084b90800be377f8James Zern    WebPCopyPlane(src->v, src->uv_stride, dst->v, dst->uv_stride,
687c8da7ce66017295a65ec028084b90800be377f8James Zern                  HALVE(dst->width), HALVE(dst->height));
6933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (dst->a != NULL)  {
707c8da7ce66017295a65ec028084b90800be377f8James Zern      WebPCopyPlane(src->a, src->a_stride,
717c8da7ce66017295a65ec028084b90800be377f8James Zern                    dst->a, dst->a_stride, dst->width, dst->height);
7233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
7333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  } else {
747c8da7ce66017295a65ec028084b90800be377f8James Zern    WebPCopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride,
757c8da7ce66017295a65ec028084b90800be377f8James Zern                  (uint8_t*)dst->argb, 4 * dst->argb_stride,
767c8da7ce66017295a65ec028084b90800be377f8James Zern                  4 * dst->width, dst->height);
7733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
7833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return 1;
7933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
8033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
8133f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureIsView(const WebPPicture* picture) {
8233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (picture == NULL) return 0;
8333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (picture->use_argb) {
8433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    return (picture->memory_argb_ == NULL);
8533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
8633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return (picture->memory_ == NULL);
8733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
8833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
8933f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureView(const WebPPicture* src,
9033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                    int left, int top, int width, int height,
9133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                    WebPPicture* dst) {
9233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (src == NULL || dst == NULL) return 0;
9333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
9433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // verify rectangle position.
9533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0;
9633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
9733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (src != dst) {  // beware of aliasing! We don't want to leak 'memory_'.
9833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    PictureGrabSpecs(src, dst);
9933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
10033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  dst->width = width;
10133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  dst->height = height;
10233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!src->use_argb) {
10333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    dst->y = src->y + top * src->y_stride + left;
10433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1);
10533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1);
10633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    dst->y_stride = src->y_stride;
10733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    dst->uv_stride = src->uv_stride;
10833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (src->a != NULL) {
10933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      dst->a = src->a + top * src->a_stride + left;
11033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      dst->a_stride = src->a_stride;
11133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
11233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  } else {
11333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    dst->argb = src->argb + top * src->argb_stride + left;
11433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    dst->argb_stride = src->argb_stride;
11533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
11633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return 1;
11733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
11833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
11933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------
12033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Picture cropping
12133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
12233f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureCrop(WebPPicture* pic,
12333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                    int left, int top, int width, int height) {
12433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPPicture tmp;
12533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
12633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (pic == NULL) return 0;
12733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0;
12833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
12933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  PictureGrabSpecs(pic, &tmp);
13033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  tmp.width = width;
13133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  tmp.height = height;
13233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!WebPPictureAlloc(&tmp)) return 0;
13333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
13433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!pic->use_argb) {
13533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int y_offset = top * pic->y_stride + left;
13633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int uv_offset = (top / 2) * pic->uv_stride + left / 2;
1377c8da7ce66017295a65ec028084b90800be377f8James Zern    WebPCopyPlane(pic->y + y_offset, pic->y_stride,
1387c8da7ce66017295a65ec028084b90800be377f8James Zern                  tmp.y, tmp.y_stride, width, height);
1397c8da7ce66017295a65ec028084b90800be377f8James Zern    WebPCopyPlane(pic->u + uv_offset, pic->uv_stride,
1407c8da7ce66017295a65ec028084b90800be377f8James Zern                  tmp.u, tmp.uv_stride, HALVE(width), HALVE(height));
1417c8da7ce66017295a65ec028084b90800be377f8James Zern    WebPCopyPlane(pic->v + uv_offset, pic->uv_stride,
1427c8da7ce66017295a65ec028084b90800be377f8James Zern                  tmp.v, tmp.uv_stride, HALVE(width), HALVE(height));
14333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
14433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (tmp.a != NULL) {
14533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      const int a_offset = top * pic->a_stride + left;
1467c8da7ce66017295a65ec028084b90800be377f8James Zern      WebPCopyPlane(pic->a + a_offset, pic->a_stride,
1477c8da7ce66017295a65ec028084b90800be377f8James Zern                    tmp.a, tmp.a_stride, width, height);
14833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
14933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  } else {
15033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const uint8_t* const src =
15133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora        (const uint8_t*)(pic->argb + top * pic->argb_stride + left);
1527c8da7ce66017295a65ec028084b90800be377f8James Zern    WebPCopyPlane(src, pic->argb_stride * 4, (uint8_t*)tmp.argb,
1537c8da7ce66017295a65ec028084b90800be377f8James Zern                  tmp.argb_stride * 4, width * 4, height);
15433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
15533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPPictureFree(pic);
15633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  *pic = tmp;
15733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return 1;
15833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
15933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
16033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------
16133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Simple picture rescaler
16233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
16333f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void RescalePlane(const uint8_t* src,
16433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                         int src_width, int src_height, int src_stride,
16533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                         uint8_t* dst,
16633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                         int dst_width, int dst_height, int dst_stride,
167e8a1b86cc3afe4791ab40d89240c40797a400131James Zern                         rescaler_t* const work,
16833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                         int num_channels) {
16933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPRescaler rescaler;
17033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int y = 0;
17133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPRescalerInit(&rescaler, src_width, src_height,
17233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                   dst, dst_width, dst_height, dst_stride,
173e8a1b86cc3afe4791ab40d89240c40797a400131James Zern                   num_channels, work);
17433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  while (y < src_height) {
17533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    y += WebPRescalerImport(&rescaler, src_height - y,
17633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                            src + y * src_stride, src_stride);
17733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPRescalerExport(&rescaler);
17833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
17933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
18033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
18133f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) {
18233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  assert(pic->argb != NULL);
18333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb),
18433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                   pic->width, pic->height, inverse);
18533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
18633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
18733f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void AlphaMultiplyY(WebPPicture* const pic, int inverse) {
18833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (pic->a != NULL) {
18933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride,
19033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 pic->width, pic->height, inverse);
19133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
19233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
19333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
19433f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureRescale(WebPPicture* pic, int width, int height) {
19533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPPicture tmp;
19633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int prev_width, prev_height;
197e8a1b86cc3afe4791ab40d89240c40797a400131James Zern  rescaler_t* work;
19833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
19933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (pic == NULL) return 0;
20033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  prev_width = pic->width;
20133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  prev_height = pic->height;
2027c8da7ce66017295a65ec028084b90800be377f8James Zern  if (!WebPRescalerGetScaledDimensions(
2037c8da7ce66017295a65ec028084b90800be377f8James Zern          prev_width, prev_height, &width, &height)) {
2047c8da7ce66017295a65ec028084b90800be377f8James Zern    return 0;
20533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
20633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
20733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  PictureGrabSpecs(pic, &tmp);
20833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  tmp.width = width;
20933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  tmp.height = height;
21033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!WebPPictureAlloc(&tmp)) return 0;
21133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
21233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (!pic->use_argb) {
213e8a1b86cc3afe4791ab40d89240c40797a400131James Zern    work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work));
21433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (work == NULL) {
21533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      WebPPictureFree(&tmp);
21633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      return 0;
21733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
21833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // If present, we need to rescale alpha first (for AlphaMultiplyY).
21933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (pic->a != NULL) {
22033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      WebPInitAlphaProcessing();
22133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      RescalePlane(pic->a, prev_width, prev_height, pic->a_stride,
22233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                   tmp.a, width, height, tmp.a_stride, work, 1);
22333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
22433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
22533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // We take transparency into account on the luma plane only. That's not
22633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // totally exact blending, but still is a good approximation.
22733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    AlphaMultiplyY(pic, 0);
22833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    RescalePlane(pic->y, prev_width, prev_height, pic->y_stride,
22933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 tmp.y, width, height, tmp.y_stride, work, 1);
23033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    AlphaMultiplyY(&tmp, 1);
23133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
23233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    RescalePlane(pic->u,
23333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
23433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 tmp.u,
23533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
23633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    RescalePlane(pic->v,
23733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 HALVE(prev_width), HALVE(prev_height), pic->uv_stride,
23833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 tmp.v,
23933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 HALVE(width), HALVE(height), tmp.uv_stride, work, 1);
24033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  } else {
241e8a1b86cc3afe4791ab40d89240c40797a400131James Zern    work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work));
24233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (work == NULL) {
24333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      WebPPictureFree(&tmp);
24433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      return 0;
24533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    }
24633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // In order to correctly interpolate colors, we need to apply the alpha
24733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // weighting first (black-matting), scale the RGB values, and remove
24833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    // the premultiplication afterward (while preserving the alpha channel).
24933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPInitAlphaProcessing();
25033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    AlphaMultiplyARGB(pic, 0);
25133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    RescalePlane((const uint8_t*)pic->argb, prev_width, prev_height,
25233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 pic->argb_stride * 4,
25333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 (uint8_t*)tmp.argb, width, height,
25433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 tmp.argb_stride * 4,
25533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                 work, 4);
25633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    AlphaMultiplyARGB(&tmp, 1);
25733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
25833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPPictureFree(pic);
25933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(work);
26033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  *pic = tmp;
26133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return 1;
26233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
26333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
26433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------
265