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