LCOV - code coverage report
Current view: top level - media/libyuv/libyuv/source - scale_common.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 757 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 50 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright 2013 The LibYuv Project Authors. All rights reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS. All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "libyuv/scale.h"
      12             : 
      13             : #include <assert.h>
      14             : #include <string.h>
      15             : 
      16             : #include "libyuv/cpu_id.h"
      17             : #include "libyuv/planar_functions.h"  // For CopyARGB
      18             : #include "libyuv/row.h"
      19             : #include "libyuv/scale_row.h"
      20             : 
      21             : #ifdef __cplusplus
      22             : namespace libyuv {
      23             : extern "C" {
      24             : #endif
      25             : 
      26           0 : static __inline int Abs(int v) {
      27           0 :   return v >= 0 ? v : -v;
      28             : }
      29             : 
      30             : // CPU agnostic row functions
      31           0 : void ScaleRowDown2_C(const uint8* src_ptr,
      32             :                      ptrdiff_t src_stride,
      33             :                      uint8* dst,
      34             :                      int dst_width) {
      35             :   int x;
      36             :   (void)src_stride;
      37           0 :   for (x = 0; x < dst_width - 1; x += 2) {
      38           0 :     dst[0] = src_ptr[1];
      39           0 :     dst[1] = src_ptr[3];
      40           0 :     dst += 2;
      41           0 :     src_ptr += 4;
      42             :   }
      43           0 :   if (dst_width & 1) {
      44           0 :     dst[0] = src_ptr[1];
      45             :   }
      46           0 : }
      47             : 
      48           0 : void ScaleRowDown2_16_C(const uint16* src_ptr,
      49             :                         ptrdiff_t src_stride,
      50             :                         uint16* dst,
      51             :                         int dst_width) {
      52             :   int x;
      53             :   (void)src_stride;
      54           0 :   for (x = 0; x < dst_width - 1; x += 2) {
      55           0 :     dst[0] = src_ptr[1];
      56           0 :     dst[1] = src_ptr[3];
      57           0 :     dst += 2;
      58           0 :     src_ptr += 4;
      59             :   }
      60           0 :   if (dst_width & 1) {
      61           0 :     dst[0] = src_ptr[1];
      62             :   }
      63           0 : }
      64             : 
      65           0 : void ScaleRowDown2Linear_C(const uint8* src_ptr,
      66             :                            ptrdiff_t src_stride,
      67             :                            uint8* dst,
      68             :                            int dst_width) {
      69           0 :   const uint8* s = src_ptr;
      70             :   int x;
      71             :   (void)src_stride;
      72           0 :   for (x = 0; x < dst_width - 1; x += 2) {
      73           0 :     dst[0] = (s[0] + s[1] + 1) >> 1;
      74           0 :     dst[1] = (s[2] + s[3] + 1) >> 1;
      75           0 :     dst += 2;
      76           0 :     s += 4;
      77             :   }
      78           0 :   if (dst_width & 1) {
      79           0 :     dst[0] = (s[0] + s[1] + 1) >> 1;
      80             :   }
      81           0 : }
      82             : 
      83           0 : void ScaleRowDown2Linear_16_C(const uint16* src_ptr,
      84             :                               ptrdiff_t src_stride,
      85             :                               uint16* dst,
      86             :                               int dst_width) {
      87           0 :   const uint16* s = src_ptr;
      88             :   int x;
      89             :   (void)src_stride;
      90           0 :   for (x = 0; x < dst_width - 1; x += 2) {
      91           0 :     dst[0] = (s[0] + s[1] + 1) >> 1;
      92           0 :     dst[1] = (s[2] + s[3] + 1) >> 1;
      93           0 :     dst += 2;
      94           0 :     s += 4;
      95             :   }
      96           0 :   if (dst_width & 1) {
      97           0 :     dst[0] = (s[0] + s[1] + 1) >> 1;
      98             :   }
      99           0 : }
     100             : 
     101           0 : void ScaleRowDown2Box_C(const uint8* src_ptr,
     102             :                         ptrdiff_t src_stride,
     103             :                         uint8* dst,
     104             :                         int dst_width) {
     105           0 :   const uint8* s = src_ptr;
     106           0 :   const uint8* t = src_ptr + src_stride;
     107             :   int x;
     108           0 :   for (x = 0; x < dst_width - 1; x += 2) {
     109           0 :     dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
     110           0 :     dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2;
     111           0 :     dst += 2;
     112           0 :     s += 4;
     113           0 :     t += 4;
     114             :   }
     115           0 :   if (dst_width & 1) {
     116           0 :     dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
     117             :   }
     118           0 : }
     119             : 
     120           0 : void ScaleRowDown2Box_Odd_C(const uint8* src_ptr,
     121             :                             ptrdiff_t src_stride,
     122             :                             uint8* dst,
     123             :                             int dst_width) {
     124           0 :   const uint8* s = src_ptr;
     125           0 :   const uint8* t = src_ptr + src_stride;
     126             :   int x;
     127           0 :   dst_width -= 1;
     128           0 :   for (x = 0; x < dst_width - 1; x += 2) {
     129           0 :     dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
     130           0 :     dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2;
     131           0 :     dst += 2;
     132           0 :     s += 4;
     133           0 :     t += 4;
     134             :   }
     135           0 :   if (dst_width & 1) {
     136           0 :     dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
     137           0 :     dst += 1;
     138           0 :     s += 2;
     139           0 :     t += 2;
     140             :   }
     141           0 :   dst[0] = (s[0] + t[0] + 1) >> 1;
     142           0 : }
     143             : 
     144           0 : void ScaleRowDown2Box_16_C(const uint16* src_ptr,
     145             :                            ptrdiff_t src_stride,
     146             :                            uint16* dst,
     147             :                            int dst_width) {
     148           0 :   const uint16* s = src_ptr;
     149           0 :   const uint16* t = src_ptr + src_stride;
     150             :   int x;
     151           0 :   for (x = 0; x < dst_width - 1; x += 2) {
     152           0 :     dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
     153           0 :     dst[1] = (s[2] + s[3] + t[2] + t[3] + 2) >> 2;
     154           0 :     dst += 2;
     155           0 :     s += 4;
     156           0 :     t += 4;
     157             :   }
     158           0 :   if (dst_width & 1) {
     159           0 :     dst[0] = (s[0] + s[1] + t[0] + t[1] + 2) >> 2;
     160             :   }
     161           0 : }
     162             : 
     163           0 : void ScaleRowDown4_C(const uint8* src_ptr,
     164             :                      ptrdiff_t src_stride,
     165             :                      uint8* dst,
     166             :                      int dst_width) {
     167             :   int x;
     168             :   (void)src_stride;
     169           0 :   for (x = 0; x < dst_width - 1; x += 2) {
     170           0 :     dst[0] = src_ptr[2];
     171           0 :     dst[1] = src_ptr[6];
     172           0 :     dst += 2;
     173           0 :     src_ptr += 8;
     174             :   }
     175           0 :   if (dst_width & 1) {
     176           0 :     dst[0] = src_ptr[2];
     177             :   }
     178           0 : }
     179             : 
     180           0 : void ScaleRowDown4_16_C(const uint16* src_ptr,
     181             :                         ptrdiff_t src_stride,
     182             :                         uint16* dst,
     183             :                         int dst_width) {
     184             :   int x;
     185             :   (void)src_stride;
     186           0 :   for (x = 0; x < dst_width - 1; x += 2) {
     187           0 :     dst[0] = src_ptr[2];
     188           0 :     dst[1] = src_ptr[6];
     189           0 :     dst += 2;
     190           0 :     src_ptr += 8;
     191             :   }
     192           0 :   if (dst_width & 1) {
     193           0 :     dst[0] = src_ptr[2];
     194             :   }
     195           0 : }
     196             : 
     197           0 : void ScaleRowDown4Box_C(const uint8* src_ptr,
     198             :                         ptrdiff_t src_stride,
     199             :                         uint8* dst,
     200             :                         int dst_width) {
     201           0 :   intptr_t stride = src_stride;
     202             :   int x;
     203           0 :   for (x = 0; x < dst_width - 1; x += 2) {
     204           0 :     dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
     205           0 :               src_ptr[stride + 0] + src_ptr[stride + 1] + src_ptr[stride + 2] +
     206           0 :               src_ptr[stride + 3] + src_ptr[stride * 2 + 0] +
     207           0 :               src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2] +
     208           0 :               src_ptr[stride * 2 + 3] + src_ptr[stride * 3 + 0] +
     209           0 :               src_ptr[stride * 3 + 1] + src_ptr[stride * 3 + 2] +
     210           0 :               src_ptr[stride * 3 + 3] + 8) >>
     211           0 :              4;
     212           0 :     dst[1] = (src_ptr[4] + src_ptr[5] + src_ptr[6] + src_ptr[7] +
     213           0 :               src_ptr[stride + 4] + src_ptr[stride + 5] + src_ptr[stride + 6] +
     214           0 :               src_ptr[stride + 7] + src_ptr[stride * 2 + 4] +
     215           0 :               src_ptr[stride * 2 + 5] + src_ptr[stride * 2 + 6] +
     216           0 :               src_ptr[stride * 2 + 7] + src_ptr[stride * 3 + 4] +
     217           0 :               src_ptr[stride * 3 + 5] + src_ptr[stride * 3 + 6] +
     218           0 :               src_ptr[stride * 3 + 7] + 8) >>
     219           0 :              4;
     220           0 :     dst += 2;
     221           0 :     src_ptr += 8;
     222             :   }
     223           0 :   if (dst_width & 1) {
     224           0 :     dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
     225           0 :               src_ptr[stride + 0] + src_ptr[stride + 1] + src_ptr[stride + 2] +
     226           0 :               src_ptr[stride + 3] + src_ptr[stride * 2 + 0] +
     227           0 :               src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2] +
     228           0 :               src_ptr[stride * 2 + 3] + src_ptr[stride * 3 + 0] +
     229           0 :               src_ptr[stride * 3 + 1] + src_ptr[stride * 3 + 2] +
     230           0 :               src_ptr[stride * 3 + 3] + 8) >>
     231           0 :              4;
     232             :   }
     233           0 : }
     234             : 
     235           0 : void ScaleRowDown4Box_16_C(const uint16* src_ptr,
     236             :                            ptrdiff_t src_stride,
     237             :                            uint16* dst,
     238             :                            int dst_width) {
     239           0 :   intptr_t stride = src_stride;
     240             :   int x;
     241           0 :   for (x = 0; x < dst_width - 1; x += 2) {
     242           0 :     dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
     243           0 :               src_ptr[stride + 0] + src_ptr[stride + 1] + src_ptr[stride + 2] +
     244           0 :               src_ptr[stride + 3] + src_ptr[stride * 2 + 0] +
     245           0 :               src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2] +
     246           0 :               src_ptr[stride * 2 + 3] + src_ptr[stride * 3 + 0] +
     247           0 :               src_ptr[stride * 3 + 1] + src_ptr[stride * 3 + 2] +
     248           0 :               src_ptr[stride * 3 + 3] + 8) >>
     249           0 :              4;
     250           0 :     dst[1] = (src_ptr[4] + src_ptr[5] + src_ptr[6] + src_ptr[7] +
     251           0 :               src_ptr[stride + 4] + src_ptr[stride + 5] + src_ptr[stride + 6] +
     252           0 :               src_ptr[stride + 7] + src_ptr[stride * 2 + 4] +
     253           0 :               src_ptr[stride * 2 + 5] + src_ptr[stride * 2 + 6] +
     254           0 :               src_ptr[stride * 2 + 7] + src_ptr[stride * 3 + 4] +
     255           0 :               src_ptr[stride * 3 + 5] + src_ptr[stride * 3 + 6] +
     256           0 :               src_ptr[stride * 3 + 7] + 8) >>
     257           0 :              4;
     258           0 :     dst += 2;
     259           0 :     src_ptr += 8;
     260             :   }
     261           0 :   if (dst_width & 1) {
     262           0 :     dst[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[3] +
     263           0 :               src_ptr[stride + 0] + src_ptr[stride + 1] + src_ptr[stride + 2] +
     264           0 :               src_ptr[stride + 3] + src_ptr[stride * 2 + 0] +
     265           0 :               src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2] +
     266           0 :               src_ptr[stride * 2 + 3] + src_ptr[stride * 3 + 0] +
     267           0 :               src_ptr[stride * 3 + 1] + src_ptr[stride * 3 + 2] +
     268           0 :               src_ptr[stride * 3 + 3] + 8) >>
     269           0 :              4;
     270             :   }
     271           0 : }
     272             : 
     273           0 : void ScaleRowDown34_C(const uint8* src_ptr,
     274             :                       ptrdiff_t src_stride,
     275             :                       uint8* dst,
     276             :                       int dst_width) {
     277             :   int x;
     278             :   (void)src_stride;
     279           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     280           0 :   for (x = 0; x < dst_width; x += 3) {
     281           0 :     dst[0] = src_ptr[0];
     282           0 :     dst[1] = src_ptr[1];
     283           0 :     dst[2] = src_ptr[3];
     284           0 :     dst += 3;
     285           0 :     src_ptr += 4;
     286             :   }
     287           0 : }
     288             : 
     289           0 : void ScaleRowDown34_16_C(const uint16* src_ptr,
     290             :                          ptrdiff_t src_stride,
     291             :                          uint16* dst,
     292             :                          int dst_width) {
     293             :   int x;
     294             :   (void)src_stride;
     295           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     296           0 :   for (x = 0; x < dst_width; x += 3) {
     297           0 :     dst[0] = src_ptr[0];
     298           0 :     dst[1] = src_ptr[1];
     299           0 :     dst[2] = src_ptr[3];
     300           0 :     dst += 3;
     301           0 :     src_ptr += 4;
     302             :   }
     303           0 : }
     304             : 
     305             : // Filter rows 0 and 1 together, 3 : 1
     306           0 : void ScaleRowDown34_0_Box_C(const uint8* src_ptr,
     307             :                             ptrdiff_t src_stride,
     308             :                             uint8* d,
     309             :                             int dst_width) {
     310           0 :   const uint8* s = src_ptr;
     311           0 :   const uint8* t = src_ptr + src_stride;
     312             :   int x;
     313           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     314           0 :   for (x = 0; x < dst_width; x += 3) {
     315           0 :     uint8 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
     316           0 :     uint8 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
     317           0 :     uint8 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
     318           0 :     uint8 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
     319           0 :     uint8 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
     320           0 :     uint8 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
     321           0 :     d[0] = (a0 * 3 + b0 + 2) >> 2;
     322           0 :     d[1] = (a1 * 3 + b1 + 2) >> 2;
     323           0 :     d[2] = (a2 * 3 + b2 + 2) >> 2;
     324           0 :     d += 3;
     325           0 :     s += 4;
     326           0 :     t += 4;
     327             :   }
     328           0 : }
     329             : 
     330           0 : void ScaleRowDown34_0_Box_16_C(const uint16* src_ptr,
     331             :                                ptrdiff_t src_stride,
     332             :                                uint16* d,
     333             :                                int dst_width) {
     334           0 :   const uint16* s = src_ptr;
     335           0 :   const uint16* t = src_ptr + src_stride;
     336             :   int x;
     337           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     338           0 :   for (x = 0; x < dst_width; x += 3) {
     339           0 :     uint16 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
     340           0 :     uint16 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
     341           0 :     uint16 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
     342           0 :     uint16 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
     343           0 :     uint16 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
     344           0 :     uint16 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
     345           0 :     d[0] = (a0 * 3 + b0 + 2) >> 2;
     346           0 :     d[1] = (a1 * 3 + b1 + 2) >> 2;
     347           0 :     d[2] = (a2 * 3 + b2 + 2) >> 2;
     348           0 :     d += 3;
     349           0 :     s += 4;
     350           0 :     t += 4;
     351             :   }
     352           0 : }
     353             : 
     354             : // Filter rows 1 and 2 together, 1 : 1
     355           0 : void ScaleRowDown34_1_Box_C(const uint8* src_ptr,
     356             :                             ptrdiff_t src_stride,
     357             :                             uint8* d,
     358             :                             int dst_width) {
     359           0 :   const uint8* s = src_ptr;
     360           0 :   const uint8* t = src_ptr + src_stride;
     361             :   int x;
     362           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     363           0 :   for (x = 0; x < dst_width; x += 3) {
     364           0 :     uint8 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
     365           0 :     uint8 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
     366           0 :     uint8 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
     367           0 :     uint8 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
     368           0 :     uint8 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
     369           0 :     uint8 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
     370           0 :     d[0] = (a0 + b0 + 1) >> 1;
     371           0 :     d[1] = (a1 + b1 + 1) >> 1;
     372           0 :     d[2] = (a2 + b2 + 1) >> 1;
     373           0 :     d += 3;
     374           0 :     s += 4;
     375           0 :     t += 4;
     376             :   }
     377           0 : }
     378             : 
     379           0 : void ScaleRowDown34_1_Box_16_C(const uint16* src_ptr,
     380             :                                ptrdiff_t src_stride,
     381             :                                uint16* d,
     382             :                                int dst_width) {
     383           0 :   const uint16* s = src_ptr;
     384           0 :   const uint16* t = src_ptr + src_stride;
     385             :   int x;
     386           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     387           0 :   for (x = 0; x < dst_width; x += 3) {
     388           0 :     uint16 a0 = (s[0] * 3 + s[1] * 1 + 2) >> 2;
     389           0 :     uint16 a1 = (s[1] * 1 + s[2] * 1 + 1) >> 1;
     390           0 :     uint16 a2 = (s[2] * 1 + s[3] * 3 + 2) >> 2;
     391           0 :     uint16 b0 = (t[0] * 3 + t[1] * 1 + 2) >> 2;
     392           0 :     uint16 b1 = (t[1] * 1 + t[2] * 1 + 1) >> 1;
     393           0 :     uint16 b2 = (t[2] * 1 + t[3] * 3 + 2) >> 2;
     394           0 :     d[0] = (a0 + b0 + 1) >> 1;
     395           0 :     d[1] = (a1 + b1 + 1) >> 1;
     396           0 :     d[2] = (a2 + b2 + 1) >> 1;
     397           0 :     d += 3;
     398           0 :     s += 4;
     399           0 :     t += 4;
     400             :   }
     401           0 : }
     402             : 
     403             : // Scales a single row of pixels using point sampling.
     404           0 : void ScaleCols_C(uint8* dst_ptr,
     405             :                  const uint8* src_ptr,
     406             :                  int dst_width,
     407             :                  int x,
     408             :                  int dx) {
     409             :   int j;
     410           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     411           0 :     dst_ptr[0] = src_ptr[x >> 16];
     412           0 :     x += dx;
     413           0 :     dst_ptr[1] = src_ptr[x >> 16];
     414           0 :     x += dx;
     415           0 :     dst_ptr += 2;
     416             :   }
     417           0 :   if (dst_width & 1) {
     418           0 :     dst_ptr[0] = src_ptr[x >> 16];
     419             :   }
     420           0 : }
     421             : 
     422           0 : void ScaleCols_16_C(uint16* dst_ptr,
     423             :                     const uint16* src_ptr,
     424             :                     int dst_width,
     425             :                     int x,
     426             :                     int dx) {
     427             :   int j;
     428           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     429           0 :     dst_ptr[0] = src_ptr[x >> 16];
     430           0 :     x += dx;
     431           0 :     dst_ptr[1] = src_ptr[x >> 16];
     432           0 :     x += dx;
     433           0 :     dst_ptr += 2;
     434             :   }
     435           0 :   if (dst_width & 1) {
     436           0 :     dst_ptr[0] = src_ptr[x >> 16];
     437             :   }
     438           0 : }
     439             : 
     440             : // Scales a single row of pixels up by 2x using point sampling.
     441           0 : void ScaleColsUp2_C(uint8* dst_ptr,
     442             :                     const uint8* src_ptr,
     443             :                     int dst_width,
     444             :                     int x,
     445             :                     int dx) {
     446             :   int j;
     447             :   (void)x;
     448             :   (void)dx;
     449           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     450           0 :     dst_ptr[1] = dst_ptr[0] = src_ptr[0];
     451           0 :     src_ptr += 1;
     452           0 :     dst_ptr += 2;
     453             :   }
     454           0 :   if (dst_width & 1) {
     455           0 :     dst_ptr[0] = src_ptr[0];
     456             :   }
     457           0 : }
     458             : 
     459           0 : void ScaleColsUp2_16_C(uint16* dst_ptr,
     460             :                        const uint16* src_ptr,
     461             :                        int dst_width,
     462             :                        int x,
     463             :                        int dx) {
     464             :   int j;
     465             :   (void)x;
     466             :   (void)dx;
     467           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     468           0 :     dst_ptr[1] = dst_ptr[0] = src_ptr[0];
     469           0 :     src_ptr += 1;
     470           0 :     dst_ptr += 2;
     471             :   }
     472           0 :   if (dst_width & 1) {
     473           0 :     dst_ptr[0] = src_ptr[0];
     474             :   }
     475           0 : }
     476             : 
     477             : // (1-f)a + fb can be replaced with a + f(b-a)
     478             : #if defined(__arm__) || defined(__aarch64__)
     479             : #define BLENDER(a, b, f) \
     480             :   (uint8)((int)(a) + ((((int)((f)) * ((int)(b) - (int)(a))) + 0x8000) >> 16))
     481             : #else
     482             : // Intel uses 7 bit math with rounding.
     483             : #define BLENDER(a, b, f) \
     484             :   (uint8)((int)(a) + (((int)((f) >> 9) * ((int)(b) - (int)(a)) + 0x40) >> 7))
     485             : #endif
     486             : 
     487           0 : void ScaleFilterCols_C(uint8* dst_ptr,
     488             :                        const uint8* src_ptr,
     489             :                        int dst_width,
     490             :                        int x,
     491             :                        int dx) {
     492             :   int j;
     493           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     494           0 :     int xi = x >> 16;
     495           0 :     int a = src_ptr[xi];
     496           0 :     int b = src_ptr[xi + 1];
     497           0 :     dst_ptr[0] = BLENDER(a, b, x & 0xffff);
     498           0 :     x += dx;
     499           0 :     xi = x >> 16;
     500           0 :     a = src_ptr[xi];
     501           0 :     b = src_ptr[xi + 1];
     502           0 :     dst_ptr[1] = BLENDER(a, b, x & 0xffff);
     503           0 :     x += dx;
     504           0 :     dst_ptr += 2;
     505             :   }
     506           0 :   if (dst_width & 1) {
     507           0 :     int xi = x >> 16;
     508           0 :     int a = src_ptr[xi];
     509           0 :     int b = src_ptr[xi + 1];
     510           0 :     dst_ptr[0] = BLENDER(a, b, x & 0xffff);
     511             :   }
     512           0 : }
     513             : 
     514           0 : void ScaleFilterCols64_C(uint8* dst_ptr,
     515             :                          const uint8* src_ptr,
     516             :                          int dst_width,
     517             :                          int x32,
     518             :                          int dx) {
     519           0 :   int64 x = (int64)(x32);
     520             :   int j;
     521           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     522           0 :     int64 xi = x >> 16;
     523           0 :     int a = src_ptr[xi];
     524           0 :     int b = src_ptr[xi + 1];
     525           0 :     dst_ptr[0] = BLENDER(a, b, x & 0xffff);
     526           0 :     x += dx;
     527           0 :     xi = x >> 16;
     528           0 :     a = src_ptr[xi];
     529           0 :     b = src_ptr[xi + 1];
     530           0 :     dst_ptr[1] = BLENDER(a, b, x & 0xffff);
     531           0 :     x += dx;
     532           0 :     dst_ptr += 2;
     533             :   }
     534           0 :   if (dst_width & 1) {
     535           0 :     int64 xi = x >> 16;
     536           0 :     int a = src_ptr[xi];
     537           0 :     int b = src_ptr[xi + 1];
     538           0 :     dst_ptr[0] = BLENDER(a, b, x & 0xffff);
     539             :   }
     540           0 : }
     541             : #undef BLENDER
     542             : 
     543             : // Same as 8 bit arm blender but return is cast to uint16
     544             : #define BLENDER(a, b, f) \
     545             :   (uint16)((int)(a) + ((((int)((f)) * ((int)(b) - (int)(a))) + 0x8000) >> 16))
     546             : 
     547           0 : void ScaleFilterCols_16_C(uint16* dst_ptr,
     548             :                           const uint16* src_ptr,
     549             :                           int dst_width,
     550             :                           int x,
     551             :                           int dx) {
     552             :   int j;
     553           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     554           0 :     int xi = x >> 16;
     555           0 :     int a = src_ptr[xi];
     556           0 :     int b = src_ptr[xi + 1];
     557           0 :     dst_ptr[0] = BLENDER(a, b, x & 0xffff);
     558           0 :     x += dx;
     559           0 :     xi = x >> 16;
     560           0 :     a = src_ptr[xi];
     561           0 :     b = src_ptr[xi + 1];
     562           0 :     dst_ptr[1] = BLENDER(a, b, x & 0xffff);
     563           0 :     x += dx;
     564           0 :     dst_ptr += 2;
     565             :   }
     566           0 :   if (dst_width & 1) {
     567           0 :     int xi = x >> 16;
     568           0 :     int a = src_ptr[xi];
     569           0 :     int b = src_ptr[xi + 1];
     570           0 :     dst_ptr[0] = BLENDER(a, b, x & 0xffff);
     571             :   }
     572           0 : }
     573             : 
     574           0 : void ScaleFilterCols64_16_C(uint16* dst_ptr,
     575             :                             const uint16* src_ptr,
     576             :                             int dst_width,
     577             :                             int x32,
     578             :                             int dx) {
     579           0 :   int64 x = (int64)(x32);
     580             :   int j;
     581           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     582           0 :     int64 xi = x >> 16;
     583           0 :     int a = src_ptr[xi];
     584           0 :     int b = src_ptr[xi + 1];
     585           0 :     dst_ptr[0] = BLENDER(a, b, x & 0xffff);
     586           0 :     x += dx;
     587           0 :     xi = x >> 16;
     588           0 :     a = src_ptr[xi];
     589           0 :     b = src_ptr[xi + 1];
     590           0 :     dst_ptr[1] = BLENDER(a, b, x & 0xffff);
     591           0 :     x += dx;
     592           0 :     dst_ptr += 2;
     593             :   }
     594           0 :   if (dst_width & 1) {
     595           0 :     int64 xi = x >> 16;
     596           0 :     int a = src_ptr[xi];
     597           0 :     int b = src_ptr[xi + 1];
     598           0 :     dst_ptr[0] = BLENDER(a, b, x & 0xffff);
     599             :   }
     600           0 : }
     601             : #undef BLENDER
     602             : 
     603           0 : void ScaleRowDown38_C(const uint8* src_ptr,
     604             :                       ptrdiff_t src_stride,
     605             :                       uint8* dst,
     606             :                       int dst_width) {
     607             :   int x;
     608             :   (void)src_stride;
     609           0 :   assert(dst_width % 3 == 0);
     610           0 :   for (x = 0; x < dst_width; x += 3) {
     611           0 :     dst[0] = src_ptr[0];
     612           0 :     dst[1] = src_ptr[3];
     613           0 :     dst[2] = src_ptr[6];
     614           0 :     dst += 3;
     615           0 :     src_ptr += 8;
     616             :   }
     617           0 : }
     618             : 
     619           0 : void ScaleRowDown38_16_C(const uint16* src_ptr,
     620             :                          ptrdiff_t src_stride,
     621             :                          uint16* dst,
     622             :                          int dst_width) {
     623             :   int x;
     624             :   (void)src_stride;
     625           0 :   assert(dst_width % 3 == 0);
     626           0 :   for (x = 0; x < dst_width; x += 3) {
     627           0 :     dst[0] = src_ptr[0];
     628           0 :     dst[1] = src_ptr[3];
     629           0 :     dst[2] = src_ptr[6];
     630           0 :     dst += 3;
     631           0 :     src_ptr += 8;
     632             :   }
     633           0 : }
     634             : 
     635             : // 8x3 -> 3x1
     636           0 : void ScaleRowDown38_3_Box_C(const uint8* src_ptr,
     637             :                             ptrdiff_t src_stride,
     638             :                             uint8* dst_ptr,
     639             :                             int dst_width) {
     640           0 :   intptr_t stride = src_stride;
     641             :   int i;
     642           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     643           0 :   for (i = 0; i < dst_width; i += 3) {
     644           0 :     dst_ptr[0] =
     645           0 :         (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[stride + 0] +
     646           0 :          src_ptr[stride + 1] + src_ptr[stride + 2] + src_ptr[stride * 2 + 0] +
     647           0 :          src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2]) *
     648           0 :             (65536 / 9) >>
     649           0 :         16;
     650           0 :     dst_ptr[1] =
     651           0 :         (src_ptr[3] + src_ptr[4] + src_ptr[5] + src_ptr[stride + 3] +
     652           0 :          src_ptr[stride + 4] + src_ptr[stride + 5] + src_ptr[stride * 2 + 3] +
     653           0 :          src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5]) *
     654           0 :             (65536 / 9) >>
     655           0 :         16;
     656           0 :     dst_ptr[2] =
     657           0 :         (src_ptr[6] + src_ptr[7] + src_ptr[stride + 6] + src_ptr[stride + 7] +
     658           0 :          src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7]) *
     659           0 :             (65536 / 6) >>
     660           0 :         16;
     661           0 :     src_ptr += 8;
     662           0 :     dst_ptr += 3;
     663             :   }
     664           0 : }
     665             : 
     666           0 : void ScaleRowDown38_3_Box_16_C(const uint16* src_ptr,
     667             :                                ptrdiff_t src_stride,
     668             :                                uint16* dst_ptr,
     669             :                                int dst_width) {
     670           0 :   intptr_t stride = src_stride;
     671             :   int i;
     672           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     673           0 :   for (i = 0; i < dst_width; i += 3) {
     674           0 :     dst_ptr[0] =
     675           0 :         (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[stride + 0] +
     676           0 :          src_ptr[stride + 1] + src_ptr[stride + 2] + src_ptr[stride * 2 + 0] +
     677           0 :          src_ptr[stride * 2 + 1] + src_ptr[stride * 2 + 2]) *
     678           0 :             (65536 / 9) >>
     679           0 :         16;
     680           0 :     dst_ptr[1] =
     681           0 :         (src_ptr[3] + src_ptr[4] + src_ptr[5] + src_ptr[stride + 3] +
     682           0 :          src_ptr[stride + 4] + src_ptr[stride + 5] + src_ptr[stride * 2 + 3] +
     683           0 :          src_ptr[stride * 2 + 4] + src_ptr[stride * 2 + 5]) *
     684           0 :             (65536 / 9) >>
     685           0 :         16;
     686           0 :     dst_ptr[2] =
     687           0 :         (src_ptr[6] + src_ptr[7] + src_ptr[stride + 6] + src_ptr[stride + 7] +
     688           0 :          src_ptr[stride * 2 + 6] + src_ptr[stride * 2 + 7]) *
     689           0 :             (65536 / 6) >>
     690           0 :         16;
     691           0 :     src_ptr += 8;
     692           0 :     dst_ptr += 3;
     693             :   }
     694           0 : }
     695             : 
     696             : // 8x2 -> 3x1
     697           0 : void ScaleRowDown38_2_Box_C(const uint8* src_ptr,
     698             :                             ptrdiff_t src_stride,
     699             :                             uint8* dst_ptr,
     700             :                             int dst_width) {
     701           0 :   intptr_t stride = src_stride;
     702             :   int i;
     703           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     704           0 :   for (i = 0; i < dst_width; i += 3) {
     705           0 :     dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[stride + 0] +
     706           0 :                   src_ptr[stride + 1] + src_ptr[stride + 2]) *
     707           0 :                      (65536 / 6) >>
     708           0 :                  16;
     709           0 :     dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] + src_ptr[stride + 3] +
     710           0 :                   src_ptr[stride + 4] + src_ptr[stride + 5]) *
     711           0 :                      (65536 / 6) >>
     712           0 :                  16;
     713           0 :     dst_ptr[2] =
     714           0 :         (src_ptr[6] + src_ptr[7] + src_ptr[stride + 6] + src_ptr[stride + 7]) *
     715           0 :             (65536 / 4) >>
     716           0 :         16;
     717           0 :     src_ptr += 8;
     718           0 :     dst_ptr += 3;
     719             :   }
     720           0 : }
     721             : 
     722           0 : void ScaleRowDown38_2_Box_16_C(const uint16* src_ptr,
     723             :                                ptrdiff_t src_stride,
     724             :                                uint16* dst_ptr,
     725             :                                int dst_width) {
     726           0 :   intptr_t stride = src_stride;
     727             :   int i;
     728           0 :   assert((dst_width % 3 == 0) && (dst_width > 0));
     729           0 :   for (i = 0; i < dst_width; i += 3) {
     730           0 :     dst_ptr[0] = (src_ptr[0] + src_ptr[1] + src_ptr[2] + src_ptr[stride + 0] +
     731           0 :                   src_ptr[stride + 1] + src_ptr[stride + 2]) *
     732           0 :                      (65536 / 6) >>
     733           0 :                  16;
     734           0 :     dst_ptr[1] = (src_ptr[3] + src_ptr[4] + src_ptr[5] + src_ptr[stride + 3] +
     735           0 :                   src_ptr[stride + 4] + src_ptr[stride + 5]) *
     736           0 :                      (65536 / 6) >>
     737           0 :                  16;
     738           0 :     dst_ptr[2] =
     739           0 :         (src_ptr[6] + src_ptr[7] + src_ptr[stride + 6] + src_ptr[stride + 7]) *
     740           0 :             (65536 / 4) >>
     741           0 :         16;
     742           0 :     src_ptr += 8;
     743           0 :     dst_ptr += 3;
     744             :   }
     745           0 : }
     746             : 
     747           0 : void ScaleAddRow_C(const uint8* src_ptr, uint16* dst_ptr, int src_width) {
     748             :   int x;
     749           0 :   assert(src_width > 0);
     750           0 :   for (x = 0; x < src_width - 1; x += 2) {
     751           0 :     dst_ptr[0] += src_ptr[0];
     752           0 :     dst_ptr[1] += src_ptr[1];
     753           0 :     src_ptr += 2;
     754           0 :     dst_ptr += 2;
     755             :   }
     756           0 :   if (src_width & 1) {
     757           0 :     dst_ptr[0] += src_ptr[0];
     758             :   }
     759           0 : }
     760             : 
     761           0 : void ScaleAddRow_16_C(const uint16* src_ptr, uint32* dst_ptr, int src_width) {
     762             :   int x;
     763           0 :   assert(src_width > 0);
     764           0 :   for (x = 0; x < src_width - 1; x += 2) {
     765           0 :     dst_ptr[0] += src_ptr[0];
     766           0 :     dst_ptr[1] += src_ptr[1];
     767           0 :     src_ptr += 2;
     768           0 :     dst_ptr += 2;
     769             :   }
     770           0 :   if (src_width & 1) {
     771           0 :     dst_ptr[0] += src_ptr[0];
     772             :   }
     773           0 : }
     774             : 
     775           0 : void ScaleARGBRowDown2_C(const uint8* src_argb,
     776             :                          ptrdiff_t src_stride,
     777             :                          uint8* dst_argb,
     778             :                          int dst_width) {
     779           0 :   const uint32* src = (const uint32*)(src_argb);
     780           0 :   uint32* dst = (uint32*)(dst_argb);
     781             :   int x;
     782             :   (void)src_stride;
     783           0 :   for (x = 0; x < dst_width - 1; x += 2) {
     784           0 :     dst[0] = src[1];
     785           0 :     dst[1] = src[3];
     786           0 :     src += 4;
     787           0 :     dst += 2;
     788             :   }
     789           0 :   if (dst_width & 1) {
     790           0 :     dst[0] = src[1];
     791             :   }
     792           0 : }
     793             : 
     794           0 : void ScaleARGBRowDown2Linear_C(const uint8* src_argb,
     795             :                                ptrdiff_t src_stride,
     796             :                                uint8* dst_argb,
     797             :                                int dst_width) {
     798             :   int x;
     799             :   (void)src_stride;
     800           0 :   for (x = 0; x < dst_width; ++x) {
     801           0 :     dst_argb[0] = (src_argb[0] + src_argb[4] + 1) >> 1;
     802           0 :     dst_argb[1] = (src_argb[1] + src_argb[5] + 1) >> 1;
     803           0 :     dst_argb[2] = (src_argb[2] + src_argb[6] + 1) >> 1;
     804           0 :     dst_argb[3] = (src_argb[3] + src_argb[7] + 1) >> 1;
     805           0 :     src_argb += 8;
     806           0 :     dst_argb += 4;
     807             :   }
     808           0 : }
     809             : 
     810           0 : void ScaleARGBRowDown2Box_C(const uint8* src_argb,
     811             :                             ptrdiff_t src_stride,
     812             :                             uint8* dst_argb,
     813             :                             int dst_width) {
     814             :   int x;
     815           0 :   for (x = 0; x < dst_width; ++x) {
     816           0 :     dst_argb[0] = (src_argb[0] + src_argb[4] + src_argb[src_stride] +
     817           0 :                    src_argb[src_stride + 4] + 2) >>
     818           0 :                   2;
     819           0 :     dst_argb[1] = (src_argb[1] + src_argb[5] + src_argb[src_stride + 1] +
     820           0 :                    src_argb[src_stride + 5] + 2) >>
     821           0 :                   2;
     822           0 :     dst_argb[2] = (src_argb[2] + src_argb[6] + src_argb[src_stride + 2] +
     823           0 :                    src_argb[src_stride + 6] + 2) >>
     824           0 :                   2;
     825           0 :     dst_argb[3] = (src_argb[3] + src_argb[7] + src_argb[src_stride + 3] +
     826           0 :                    src_argb[src_stride + 7] + 2) >>
     827           0 :                   2;
     828           0 :     src_argb += 8;
     829           0 :     dst_argb += 4;
     830             :   }
     831           0 : }
     832             : 
     833           0 : void ScaleARGBRowDownEven_C(const uint8* src_argb,
     834             :                             ptrdiff_t src_stride,
     835             :                             int src_stepx,
     836             :                             uint8* dst_argb,
     837             :                             int dst_width) {
     838           0 :   const uint32* src = (const uint32*)(src_argb);
     839           0 :   uint32* dst = (uint32*)(dst_argb);
     840             :   (void)src_stride;
     841             :   int x;
     842           0 :   for (x = 0; x < dst_width - 1; x += 2) {
     843           0 :     dst[0] = src[0];
     844           0 :     dst[1] = src[src_stepx];
     845           0 :     src += src_stepx * 2;
     846           0 :     dst += 2;
     847             :   }
     848           0 :   if (dst_width & 1) {
     849           0 :     dst[0] = src[0];
     850             :   }
     851           0 : }
     852             : 
     853           0 : void ScaleARGBRowDownEvenBox_C(const uint8* src_argb,
     854             :                                ptrdiff_t src_stride,
     855             :                                int src_stepx,
     856             :                                uint8* dst_argb,
     857             :                                int dst_width) {
     858             :   int x;
     859           0 :   for (x = 0; x < dst_width; ++x) {
     860           0 :     dst_argb[0] = (src_argb[0] + src_argb[4] + src_argb[src_stride] +
     861           0 :                    src_argb[src_stride + 4] + 2) >>
     862           0 :                   2;
     863           0 :     dst_argb[1] = (src_argb[1] + src_argb[5] + src_argb[src_stride + 1] +
     864           0 :                    src_argb[src_stride + 5] + 2) >>
     865           0 :                   2;
     866           0 :     dst_argb[2] = (src_argb[2] + src_argb[6] + src_argb[src_stride + 2] +
     867           0 :                    src_argb[src_stride + 6] + 2) >>
     868           0 :                   2;
     869           0 :     dst_argb[3] = (src_argb[3] + src_argb[7] + src_argb[src_stride + 3] +
     870           0 :                    src_argb[src_stride + 7] + 2) >>
     871           0 :                   2;
     872           0 :     src_argb += src_stepx * 4;
     873           0 :     dst_argb += 4;
     874             :   }
     875           0 : }
     876             : 
     877             : // Scales a single row of pixels using point sampling.
     878           0 : void ScaleARGBCols_C(uint8* dst_argb,
     879             :                      const uint8* src_argb,
     880             :                      int dst_width,
     881             :                      int x,
     882             :                      int dx) {
     883           0 :   const uint32* src = (const uint32*)(src_argb);
     884           0 :   uint32* dst = (uint32*)(dst_argb);
     885             :   int j;
     886           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     887           0 :     dst[0] = src[x >> 16];
     888           0 :     x += dx;
     889           0 :     dst[1] = src[x >> 16];
     890           0 :     x += dx;
     891           0 :     dst += 2;
     892             :   }
     893           0 :   if (dst_width & 1) {
     894           0 :     dst[0] = src[x >> 16];
     895             :   }
     896           0 : }
     897             : 
     898           0 : void ScaleARGBCols64_C(uint8* dst_argb,
     899             :                        const uint8* src_argb,
     900             :                        int dst_width,
     901             :                        int x32,
     902             :                        int dx) {
     903           0 :   int64 x = (int64)(x32);
     904           0 :   const uint32* src = (const uint32*)(src_argb);
     905           0 :   uint32* dst = (uint32*)(dst_argb);
     906             :   int j;
     907           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     908           0 :     dst[0] = src[x >> 16];
     909           0 :     x += dx;
     910           0 :     dst[1] = src[x >> 16];
     911           0 :     x += dx;
     912           0 :     dst += 2;
     913             :   }
     914           0 :   if (dst_width & 1) {
     915           0 :     dst[0] = src[x >> 16];
     916             :   }
     917           0 : }
     918             : 
     919             : // Scales a single row of pixels up by 2x using point sampling.
     920           0 : void ScaleARGBColsUp2_C(uint8* dst_argb,
     921             :                         const uint8* src_argb,
     922             :                         int dst_width,
     923             :                         int x,
     924             :                         int dx) {
     925           0 :   const uint32* src = (const uint32*)(src_argb);
     926           0 :   uint32* dst = (uint32*)(dst_argb);
     927             :   int j;
     928             :   (void)x;
     929             :   (void)dx;
     930           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     931           0 :     dst[1] = dst[0] = src[0];
     932           0 :     src += 1;
     933           0 :     dst += 2;
     934             :   }
     935           0 :   if (dst_width & 1) {
     936           0 :     dst[0] = src[0];
     937             :   }
     938           0 : }
     939             : 
     940             : // TODO(fbarchard): Replace 0x7f ^ f with 128-f.  bug=607.
     941             : // Mimics SSSE3 blender
     942             : #define BLENDER1(a, b, f) ((a) * (0x7f ^ f) + (b)*f) >> 7
     943             : #define BLENDERC(a, b, f, s) \
     944             :   (uint32)(BLENDER1(((a) >> s) & 255, ((b) >> s) & 255, f) << s)
     945             : #define BLENDER(a, b, f)                                                 \
     946             :   BLENDERC(a, b, f, 24) | BLENDERC(a, b, f, 16) | BLENDERC(a, b, f, 8) | \
     947             :       BLENDERC(a, b, f, 0)
     948             : 
     949           0 : void ScaleARGBFilterCols_C(uint8* dst_argb,
     950             :                            const uint8* src_argb,
     951             :                            int dst_width,
     952             :                            int x,
     953             :                            int dx) {
     954           0 :   const uint32* src = (const uint32*)(src_argb);
     955           0 :   uint32* dst = (uint32*)(dst_argb);
     956             :   int j;
     957           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     958           0 :     int xi = x >> 16;
     959           0 :     int xf = (x >> 9) & 0x7f;
     960           0 :     uint32 a = src[xi];
     961           0 :     uint32 b = src[xi + 1];
     962           0 :     dst[0] = BLENDER(a, b, xf);
     963           0 :     x += dx;
     964           0 :     xi = x >> 16;
     965           0 :     xf = (x >> 9) & 0x7f;
     966           0 :     a = src[xi];
     967           0 :     b = src[xi + 1];
     968           0 :     dst[1] = BLENDER(a, b, xf);
     969           0 :     x += dx;
     970           0 :     dst += 2;
     971             :   }
     972           0 :   if (dst_width & 1) {
     973           0 :     int xi = x >> 16;
     974           0 :     int xf = (x >> 9) & 0x7f;
     975           0 :     uint32 a = src[xi];
     976           0 :     uint32 b = src[xi + 1];
     977           0 :     dst[0] = BLENDER(a, b, xf);
     978             :   }
     979           0 : }
     980             : 
     981           0 : void ScaleARGBFilterCols64_C(uint8* dst_argb,
     982             :                              const uint8* src_argb,
     983             :                              int dst_width,
     984             :                              int x32,
     985             :                              int dx) {
     986           0 :   int64 x = (int64)(x32);
     987           0 :   const uint32* src = (const uint32*)(src_argb);
     988           0 :   uint32* dst = (uint32*)(dst_argb);
     989             :   int j;
     990           0 :   for (j = 0; j < dst_width - 1; j += 2) {
     991           0 :     int64 xi = x >> 16;
     992           0 :     int xf = (x >> 9) & 0x7f;
     993           0 :     uint32 a = src[xi];
     994           0 :     uint32 b = src[xi + 1];
     995           0 :     dst[0] = BLENDER(a, b, xf);
     996           0 :     x += dx;
     997           0 :     xi = x >> 16;
     998           0 :     xf = (x >> 9) & 0x7f;
     999           0 :     a = src[xi];
    1000           0 :     b = src[xi + 1];
    1001           0 :     dst[1] = BLENDER(a, b, xf);
    1002           0 :     x += dx;
    1003           0 :     dst += 2;
    1004             :   }
    1005           0 :   if (dst_width & 1) {
    1006           0 :     int64 xi = x >> 16;
    1007           0 :     int xf = (x >> 9) & 0x7f;
    1008           0 :     uint32 a = src[xi];
    1009           0 :     uint32 b = src[xi + 1];
    1010           0 :     dst[0] = BLENDER(a, b, xf);
    1011             :   }
    1012           0 : }
    1013             : #undef BLENDER1
    1014             : #undef BLENDERC
    1015             : #undef BLENDER
    1016             : 
    1017             : // Scale plane vertically with bilinear interpolation.
    1018           0 : void ScalePlaneVertical(int src_height,
    1019             :                         int dst_width,
    1020             :                         int dst_height,
    1021             :                         int src_stride,
    1022             :                         int dst_stride,
    1023             :                         const uint8* src_argb,
    1024             :                         uint8* dst_argb,
    1025             :                         int x,
    1026             :                         int y,
    1027             :                         int dy,
    1028             :                         int bpp,
    1029             :                         enum FilterMode filtering) {
    1030             :   // TODO(fbarchard): Allow higher bpp.
    1031           0 :   int dst_width_bytes = dst_width * bpp;
    1032             :   void (*InterpolateRow)(uint8 * dst_argb, const uint8* src_argb,
    1033             :                          ptrdiff_t src_stride, int dst_width,
    1034           0 :                          int source_y_fraction) = InterpolateRow_C;
    1035           0 :   const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
    1036             :   int j;
    1037           0 :   assert(bpp >= 1 && bpp <= 4);
    1038           0 :   assert(src_height != 0);
    1039           0 :   assert(dst_width > 0);
    1040           0 :   assert(dst_height > 0);
    1041           0 :   src_argb += (x >> 16) * bpp;
    1042             : #if defined(HAS_INTERPOLATEROW_SSSE3)
    1043           0 :   if (TestCpuFlag(kCpuHasSSSE3)) {
    1044           0 :     InterpolateRow = InterpolateRow_Any_SSSE3;
    1045           0 :     if (IS_ALIGNED(dst_width_bytes, 16)) {
    1046           0 :       InterpolateRow = InterpolateRow_SSSE3;
    1047             :     }
    1048             :   }
    1049             : #endif
    1050             : #if defined(HAS_INTERPOLATEROW_AVX2)
    1051           0 :   if (TestCpuFlag(kCpuHasAVX2)) {
    1052           0 :     InterpolateRow = InterpolateRow_Any_AVX2;
    1053           0 :     if (IS_ALIGNED(dst_width_bytes, 32)) {
    1054           0 :       InterpolateRow = InterpolateRow_AVX2;
    1055             :     }
    1056             :   }
    1057             : #endif
    1058             : #if defined(HAS_INTERPOLATEROW_NEON)
    1059             :   if (TestCpuFlag(kCpuHasNEON)) {
    1060             :     InterpolateRow = InterpolateRow_Any_NEON;
    1061             :     if (IS_ALIGNED(dst_width_bytes, 16)) {
    1062             :       InterpolateRow = InterpolateRow_NEON;
    1063             :     }
    1064             :   }
    1065             : #endif
    1066             : #if defined(HAS_INTERPOLATEROW_DSPR2)
    1067             :   if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(src_argb, 4) &&
    1068             :       IS_ALIGNED(src_stride, 4) && IS_ALIGNED(dst_argb, 4) &&
    1069             :       IS_ALIGNED(dst_stride, 4)) {
    1070             :     InterpolateRow = InterpolateRow_Any_DSPR2;
    1071             :     if (IS_ALIGNED(dst_width_bytes, 4)) {
    1072             :       InterpolateRow = InterpolateRow_DSPR2;
    1073             :     }
    1074             :   }
    1075             : #endif
    1076           0 :   for (j = 0; j < dst_height; ++j) {
    1077             :     int yi;
    1078             :     int yf;
    1079           0 :     if (y > max_y) {
    1080           0 :       y = max_y;
    1081             :     }
    1082           0 :     yi = y >> 16;
    1083           0 :     yf = filtering ? ((y >> 8) & 255) : 0;
    1084           0 :     InterpolateRow(dst_argb, src_argb + yi * src_stride, src_stride,
    1085           0 :                    dst_width_bytes, yf);
    1086           0 :     dst_argb += dst_stride;
    1087           0 :     y += dy;
    1088             :   }
    1089           0 : }
    1090           0 : void ScalePlaneVertical_16(int src_height,
    1091             :                            int dst_width,
    1092             :                            int dst_height,
    1093             :                            int src_stride,
    1094             :                            int dst_stride,
    1095             :                            const uint16* src_argb,
    1096             :                            uint16* dst_argb,
    1097             :                            int x,
    1098             :                            int y,
    1099             :                            int dy,
    1100             :                            int wpp,
    1101             :                            enum FilterMode filtering) {
    1102             :   // TODO(fbarchard): Allow higher wpp.
    1103           0 :   int dst_width_words = dst_width * wpp;
    1104             :   void (*InterpolateRow)(uint16 * dst_argb, const uint16* src_argb,
    1105             :                          ptrdiff_t src_stride, int dst_width,
    1106           0 :                          int source_y_fraction) = InterpolateRow_16_C;
    1107           0 :   const int max_y = (src_height > 1) ? ((src_height - 1) << 16) - 1 : 0;
    1108             :   int j;
    1109           0 :   assert(wpp >= 1 && wpp <= 2);
    1110           0 :   assert(src_height != 0);
    1111           0 :   assert(dst_width > 0);
    1112           0 :   assert(dst_height > 0);
    1113           0 :   src_argb += (x >> 16) * wpp;
    1114             : #if defined(HAS_INTERPOLATEROW_16_SSE2)
    1115             :   if (TestCpuFlag(kCpuHasSSE2)) {
    1116             :     InterpolateRow = InterpolateRow_Any_16_SSE2;
    1117             :     if (IS_ALIGNED(dst_width_bytes, 16)) {
    1118             :       InterpolateRow = InterpolateRow_16_SSE2;
    1119             :     }
    1120             :   }
    1121             : #endif
    1122             : #if defined(HAS_INTERPOLATEROW_16_SSSE3)
    1123             :   if (TestCpuFlag(kCpuHasSSSE3)) {
    1124             :     InterpolateRow = InterpolateRow_Any_16_SSSE3;
    1125             :     if (IS_ALIGNED(dst_width_bytes, 16)) {
    1126             :       InterpolateRow = InterpolateRow_16_SSSE3;
    1127             :     }
    1128             :   }
    1129             : #endif
    1130             : #if defined(HAS_INTERPOLATEROW_16_AVX2)
    1131             :   if (TestCpuFlag(kCpuHasAVX2)) {
    1132             :     InterpolateRow = InterpolateRow_Any_16_AVX2;
    1133             :     if (IS_ALIGNED(dst_width_bytes, 32)) {
    1134             :       InterpolateRow = InterpolateRow_16_AVX2;
    1135             :     }
    1136             :   }
    1137             : #endif
    1138             : #if defined(HAS_INTERPOLATEROW_16_NEON)
    1139             :   if (TestCpuFlag(kCpuHasNEON)) {
    1140             :     InterpolateRow = InterpolateRow_Any_16_NEON;
    1141             :     if (IS_ALIGNED(dst_width_bytes, 16)) {
    1142             :       InterpolateRow = InterpolateRow_16_NEON;
    1143             :     }
    1144             :   }
    1145             : #endif
    1146             : #if defined(HAS_INTERPOLATEROW_16_DSPR2)
    1147             :   if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(src_argb, 4) &&
    1148             :       IS_ALIGNED(src_stride, 4) && IS_ALIGNED(dst_argb, 4) &&
    1149             :       IS_ALIGNED(dst_stride, 4)) {
    1150             :     InterpolateRow = InterpolateRow_Any_16_DSPR2;
    1151             :     if (IS_ALIGNED(dst_width_bytes, 4)) {
    1152             :       InterpolateRow = InterpolateRow_16_DSPR2;
    1153             :     }
    1154             :   }
    1155             : #endif
    1156           0 :   for (j = 0; j < dst_height; ++j) {
    1157             :     int yi;
    1158             :     int yf;
    1159           0 :     if (y > max_y) {
    1160           0 :       y = max_y;
    1161             :     }
    1162           0 :     yi = y >> 16;
    1163           0 :     yf = filtering ? ((y >> 8) & 255) : 0;
    1164           0 :     InterpolateRow(dst_argb, src_argb + yi * src_stride, src_stride,
    1165           0 :                    dst_width_words, yf);
    1166           0 :     dst_argb += dst_stride;
    1167           0 :     y += dy;
    1168             :   }
    1169           0 : }
    1170             : 
    1171             : // Simplify the filtering based on scale factors.
    1172           0 : enum FilterMode ScaleFilterReduce(int src_width,
    1173             :                                   int src_height,
    1174             :                                   int dst_width,
    1175             :                                   int dst_height,
    1176             :                                   enum FilterMode filtering) {
    1177           0 :   if (src_width < 0) {
    1178           0 :     src_width = -src_width;
    1179             :   }
    1180           0 :   if (src_height < 0) {
    1181           0 :     src_height = -src_height;
    1182             :   }
    1183           0 :   if (filtering == kFilterBox) {
    1184             :     // If scaling both axis to 0.5 or larger, switch from Box to Bilinear.
    1185           0 :     if (dst_width * 2 >= src_width && dst_height * 2 >= src_height) {
    1186           0 :       filtering = kFilterBilinear;
    1187             :     }
    1188             :   }
    1189           0 :   if (filtering == kFilterBilinear) {
    1190           0 :     if (src_height == 1) {
    1191           0 :       filtering = kFilterLinear;
    1192             :     }
    1193             :     // TODO(fbarchard): Detect any odd scale factor and reduce to Linear.
    1194           0 :     if (dst_height == src_height || dst_height * 3 == src_height) {
    1195           0 :       filtering = kFilterLinear;
    1196             :     }
    1197             :     // TODO(fbarchard): Remove 1 pixel wide filter restriction, which is to
    1198             :     // avoid reading 2 pixels horizontally that causes memory exception.
    1199           0 :     if (src_width == 1) {
    1200           0 :       filtering = kFilterNone;
    1201             :     }
    1202             :   }
    1203           0 :   if (filtering == kFilterLinear) {
    1204           0 :     if (src_width == 1) {
    1205           0 :       filtering = kFilterNone;
    1206             :     }
    1207             :     // TODO(fbarchard): Detect any odd scale factor and reduce to None.
    1208           0 :     if (dst_width == src_width || dst_width * 3 == src_width) {
    1209           0 :       filtering = kFilterNone;
    1210             :     }
    1211             :   }
    1212           0 :   return filtering;
    1213             : }
    1214             : 
    1215             : // Divide num by div and return as 16.16 fixed point result.
    1216           0 : int FixedDiv_C(int num, int div) {
    1217           0 :   return (int)(((int64)(num) << 16) / div);
    1218             : }
    1219             : 
    1220             : // Divide num by div and return as 16.16 fixed point result.
    1221           0 : int FixedDiv1_C(int num, int div) {
    1222           0 :   return (int)((((int64)(num) << 16) - 0x00010001) / (div - 1));
    1223             : }
    1224             : 
    1225             : #define CENTERSTART(dx, s) (dx < 0) ? -((-dx >> 1) + s) : ((dx >> 1) + s)
    1226             : 
    1227             : // Compute slope values for stepping.
    1228           0 : void ScaleSlope(int src_width,
    1229             :                 int src_height,
    1230             :                 int dst_width,
    1231             :                 int dst_height,
    1232             :                 enum FilterMode filtering,
    1233             :                 int* x,
    1234             :                 int* y,
    1235             :                 int* dx,
    1236             :                 int* dy) {
    1237           0 :   assert(x != NULL);
    1238           0 :   assert(y != NULL);
    1239           0 :   assert(dx != NULL);
    1240           0 :   assert(dy != NULL);
    1241           0 :   assert(src_width != 0);
    1242           0 :   assert(src_height != 0);
    1243           0 :   assert(dst_width > 0);
    1244           0 :   assert(dst_height > 0);
    1245             :   // Check for 1 pixel and avoid FixedDiv overflow.
    1246           0 :   if (dst_width == 1 && src_width >= 32768) {
    1247           0 :     dst_width = src_width;
    1248             :   }
    1249           0 :   if (dst_height == 1 && src_height >= 32768) {
    1250           0 :     dst_height = src_height;
    1251             :   }
    1252           0 :   if (filtering == kFilterBox) {
    1253             :     // Scale step for point sampling duplicates all pixels equally.
    1254           0 :     *dx = FixedDiv(Abs(src_width), dst_width);
    1255           0 :     *dy = FixedDiv(src_height, dst_height);
    1256           0 :     *x = 0;
    1257           0 :     *y = 0;
    1258           0 :   } else if (filtering == kFilterBilinear) {
    1259             :     // Scale step for bilinear sampling renders last pixel once for upsample.
    1260           0 :     if (dst_width <= Abs(src_width)) {
    1261           0 :       *dx = FixedDiv(Abs(src_width), dst_width);
    1262           0 :       *x = CENTERSTART(*dx, -32768);  // Subtract 0.5 (32768) to center filter.
    1263           0 :     } else if (dst_width > 1) {
    1264           0 :       *dx = FixedDiv1(Abs(src_width), dst_width);
    1265           0 :       *x = 0;
    1266             :     }
    1267           0 :     if (dst_height <= src_height) {
    1268           0 :       *dy = FixedDiv(src_height, dst_height);
    1269           0 :       *y = CENTERSTART(*dy, -32768);  // Subtract 0.5 (32768) to center filter.
    1270           0 :     } else if (dst_height > 1) {
    1271           0 :       *dy = FixedDiv1(src_height, dst_height);
    1272           0 :       *y = 0;
    1273             :     }
    1274           0 :   } else if (filtering == kFilterLinear) {
    1275             :     // Scale step for bilinear sampling renders last pixel once for upsample.
    1276           0 :     if (dst_width <= Abs(src_width)) {
    1277           0 :       *dx = FixedDiv(Abs(src_width), dst_width);
    1278           0 :       *x = CENTERSTART(*dx, -32768);  // Subtract 0.5 (32768) to center filter.
    1279           0 :     } else if (dst_width > 1) {
    1280           0 :       *dx = FixedDiv1(Abs(src_width), dst_width);
    1281           0 :       *x = 0;
    1282             :     }
    1283           0 :     *dy = FixedDiv(src_height, dst_height);
    1284           0 :     *y = *dy >> 1;
    1285             :   } else {
    1286             :     // Scale step for point sampling duplicates all pixels equally.
    1287           0 :     *dx = FixedDiv(Abs(src_width), dst_width);
    1288           0 :     *dy = FixedDiv(src_height, dst_height);
    1289           0 :     *x = CENTERSTART(*dx, 0);
    1290           0 :     *y = CENTERSTART(*dy, 0);
    1291             :   }
    1292             :   // Negative src_width means horizontally mirror.
    1293           0 :   if (src_width < 0) {
    1294           0 :     *x += (dst_width - 1) * *dx;
    1295           0 :     *dx = -*dx;
    1296             :     // src_width = -src_width;   // Caller must do this.
    1297             :   }
    1298           0 : }
    1299             : #undef CENTERSTART
    1300             : 
    1301             : #ifdef __cplusplus
    1302             : }  // extern "C"
    1303             : }  // namespace libyuv
    1304             : #endif

Generated by: LCOV version 1.13