1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2012 Google Inc. All Rights Reserved. 2a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license 40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source 50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found 60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may 70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree. 8a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// ----------------------------------------------------------------------------- 9a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 10a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Rescaling functions 11a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// 12a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Author: Skal (pascal.massimino@gmail.com) 13a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 14a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include <assert.h> 15a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include <stdlib.h> 16e8a1b86cc3afe4791ab40d89240c40797a400131James Zern#include <string.h> 1733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "../dsp/dsp.h" 187c8da7ce66017295a65ec028084b90800be377f8James Zern#include "./rescaler.h" 1933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 2033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 2133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 2233f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height, 23e8a1b86cc3afe4791ab40d89240c40797a400131James Zern uint8_t* const dst, 24e8a1b86cc3afe4791ab40d89240c40797a400131James Zern int dst_width, int dst_height, int dst_stride, 25e8a1b86cc3afe4791ab40d89240c40797a400131James Zern int num_channels, rescaler_t* const work) { 26e8a1b86cc3afe4791ab40d89240c40797a400131James Zern const int x_add = src_width, x_sub = dst_width; 27e8a1b86cc3afe4791ab40d89240c40797a400131James Zern const int y_add = src_height, y_sub = dst_height; 2833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->x_expand = (src_width < dst_width); 29e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->y_expand = (src_height < dst_height); 3033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->src_width = src_width; 3133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->src_height = src_height; 3233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->dst_width = dst_width; 3333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->dst_height = dst_height; 34e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->src_y = 0; 35e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->dst_y = 0; 3633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->dst = dst; 3733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->dst_stride = dst_stride; 3833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->num_channels = num_channels; 39e8a1b86cc3afe4791ab40d89240c40797a400131James Zern 4033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora // for 'x_expand', we use bilinear interpolation 41e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->x_add = wrk->x_expand ? (x_sub - 1) : x_add; 4233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->x_sub = wrk->x_expand ? (x_add - 1) : x_sub; 43e8a1b86cc3afe4791ab40d89240c40797a400131James Zern if (!wrk->x_expand) { // fx_scale is not used otherwise 44e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->fx_scale = WEBP_RESCALER_FRAC(1, wrk->x_sub); 45e8a1b86cc3afe4791ab40d89240c40797a400131James Zern } 46e8a1b86cc3afe4791ab40d89240c40797a400131James Zern // vertical scaling parameters 47e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->y_add = wrk->y_expand ? y_add - 1 : y_add; 48e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->y_sub = wrk->y_expand ? y_sub - 1 : y_sub; 49e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->y_accum = wrk->y_expand ? wrk->y_sub : wrk->y_add; 50e8a1b86cc3afe4791ab40d89240c40797a400131James Zern if (!wrk->y_expand) { 51e8a1b86cc3afe4791ab40d89240c40797a400131James Zern // this is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast. 52e8a1b86cc3afe4791ab40d89240c40797a400131James Zern const uint64_t ratio = 53e8a1b86cc3afe4791ab40d89240c40797a400131James Zern (uint64_t)dst_height * WEBP_RESCALER_ONE / (wrk->x_add * wrk->y_add); 54e8a1b86cc3afe4791ab40d89240c40797a400131James Zern if (ratio != (uint32_t)ratio) { 55e8a1b86cc3afe4791ab40d89240c40797a400131James Zern // We can't represent the ratio with the current fixed-point precision. 56e8a1b86cc3afe4791ab40d89240c40797a400131James Zern // => We special-case fxy_scale = 0, in WebPRescalerExportRow(). 57e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->fxy_scale = 0; 58e8a1b86cc3afe4791ab40d89240c40797a400131James Zern } else { 59e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->fxy_scale = (uint32_t)ratio; 60e8a1b86cc3afe4791ab40d89240c40797a400131James Zern } 61e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->y_sub); 62e8a1b86cc3afe4791ab40d89240c40797a400131James Zern } else { 63e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->fy_scale = WEBP_RESCALER_FRAC(1, wrk->x_add); 64e8a1b86cc3afe4791ab40d89240c40797a400131James Zern // wrk->fxy_scale is unused here. 65e8a1b86cc3afe4791ab40d89240c40797a400131James Zern } 6633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->irow = work; 6733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora wrk->frow = work + num_channels * dst_width; 68e8a1b86cc3afe4791ab40d89240c40797a400131James Zern memset(work, 0, 2 * dst_width * num_channels * sizeof(*work)); 6933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 707c8da7ce66017295a65ec028084b90800be377f8James Zern WebPRescalerDspInit(); 717c8da7ce66017295a65ec028084b90800be377f8James Zern} 727c8da7ce66017295a65ec028084b90800be377f8James Zern 737c8da7ce66017295a65ec028084b90800be377f8James Zernint WebPRescalerGetScaledDimensions(int src_width, int src_height, 747c8da7ce66017295a65ec028084b90800be377f8James Zern int* const scaled_width, 757c8da7ce66017295a65ec028084b90800be377f8James Zern int* const scaled_height) { 767c8da7ce66017295a65ec028084b90800be377f8James Zern assert(scaled_width != NULL); 777c8da7ce66017295a65ec028084b90800be377f8James Zern assert(scaled_height != NULL); 787c8da7ce66017295a65ec028084b90800be377f8James Zern { 797c8da7ce66017295a65ec028084b90800be377f8James Zern int width = *scaled_width; 807c8da7ce66017295a65ec028084b90800be377f8James Zern int height = *scaled_height; 817c8da7ce66017295a65ec028084b90800be377f8James Zern 827c8da7ce66017295a65ec028084b90800be377f8James Zern // if width is unspecified, scale original proportionally to height ratio. 837c8da7ce66017295a65ec028084b90800be377f8James Zern if (width == 0) { 847c8da7ce66017295a65ec028084b90800be377f8James Zern width = (src_width * height + src_height / 2) / src_height; 8533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 867c8da7ce66017295a65ec028084b90800be377f8James Zern // if height is unspecified, scale original proportionally to width ratio. 877c8da7ce66017295a65ec028084b90800be377f8James Zern if (height == 0) { 887c8da7ce66017295a65ec028084b90800be377f8James Zern height = (src_height * width + src_width / 2) / src_width; 897c8da7ce66017295a65ec028084b90800be377f8James Zern } 907c8da7ce66017295a65ec028084b90800be377f8James Zern // Check if the overall dimensions still make sense. 917c8da7ce66017295a65ec028084b90800be377f8James Zern if (width <= 0 || height <= 0) { 927c8da7ce66017295a65ec028084b90800be377f8James Zern return 0; 937c8da7ce66017295a65ec028084b90800be377f8James Zern } 947c8da7ce66017295a65ec028084b90800be377f8James Zern 957c8da7ce66017295a65ec028084b90800be377f8James Zern *scaled_width = width; 967c8da7ce66017295a65ec028084b90800be377f8James Zern *scaled_height = height; 977c8da7ce66017295a65ec028084b90800be377f8James Zern return 1; 98a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 99a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 100a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 101a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 102a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// all-in-one calls 103a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 1048b720228d581a84fd173b6dcb2fa295b59db489aVikas Aroraint WebPRescaleNeededLines(const WebPRescaler* const wrk, int max_num_lines) { 1058b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora const int num_lines = (wrk->y_accum + wrk->y_sub - 1) / wrk->y_sub; 1068b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora return (num_lines > max_num_lines) ? max_num_lines : num_lines; 1078b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora} 1088b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora 109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint WebPRescalerImport(WebPRescaler* const wrk, int num_lines, 110a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint8_t* src, int src_stride) { 111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int total_imported = 0; 112e8a1b86cc3afe4791ab40d89240c40797a400131James Zern while (total_imported < num_lines && !WebPRescalerHasPendingOutput(wrk)) { 113e8a1b86cc3afe4791ab40d89240c40797a400131James Zern if (wrk->y_expand) { 114e8a1b86cc3afe4791ab40d89240c40797a400131James Zern rescaler_t* const tmp = wrk->irow; 115e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->irow = wrk->frow; 116e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->frow = tmp; 117e8a1b86cc3afe4791ab40d89240c40797a400131James Zern } 118e8a1b86cc3afe4791ab40d89240c40797a400131James Zern WebPRescalerImportRow(wrk, src); 119e8a1b86cc3afe4791ab40d89240c40797a400131James Zern if (!wrk->y_expand) { // Accumulate the contribution of the new row. 120e8a1b86cc3afe4791ab40d89240c40797a400131James Zern int x; 121e8a1b86cc3afe4791ab40d89240c40797a400131James Zern for (x = 0; x < wrk->num_channels * wrk->dst_width; ++x) { 122e8a1b86cc3afe4791ab40d89240c40797a400131James Zern wrk->irow[x] += wrk->frow[x]; 123e8a1b86cc3afe4791ab40d89240c40797a400131James Zern } 124a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 125e8a1b86cc3afe4791ab40d89240c40797a400131James Zern ++wrk->src_y; 126a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora src += src_stride; 127a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++total_imported; 128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora wrk->y_accum -= wrk->y_sub; 129a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return total_imported; 131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 133a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint WebPRescalerExport(WebPRescaler* const rescaler) { 134a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int total_exported = 0; 135a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora while (WebPRescalerHasPendingOutput(rescaler)) { 136e8a1b86cc3afe4791ab40d89240c40797a400131James Zern WebPRescalerExportRow(rescaler); 137a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ++total_exported; 138a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 139a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return total_exported; 140a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 141a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 142a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 143