LCOV - code coverage report
Current view: top level - dom/canvas - ImageBitmapColorUtils.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 829 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 135 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "ImageBitmapColorUtils.h"
       8             : #include "libyuv.h"
       9             : 
      10             : namespace mozilla {
      11             : namespace dom {
      12             : 
      13             : /*
      14             :  * Utility function form libyuv source files.
      15             :  */
      16           0 : static __inline int32 clamp0(int32 v) {
      17           0 :   return ((-(v) >> 31) & (v));
      18             : }
      19             : 
      20           0 : static __inline int32 clamp255(int32 v) {
      21           0 :   return (((255 - (v)) >> 31) | (v)) & 255;
      22             : }
      23             : 
      24           0 : static __inline uint32 Clamp(int32 val) {
      25           0 :   int v = clamp0(val);
      26           0 :   return (uint32)(clamp255(v));
      27             : }
      28             : 
      29             : #define YG 74 /* (int8)(1.164 * 64 + 0.5) */
      30             : 
      31             : #define UB 127 /* min(63,(int8)(2.018 * 64)) */
      32             : #define UG -25 /* (int8)(-0.391 * 64 - 0.5) */
      33             : #define UR 0
      34             : 
      35             : #define VB 0
      36             : #define VG -52 /* (int8)(-0.813 * 64 - 0.5) */
      37             : #define VR 102 /* (int8)(1.596 * 64 + 0.5) */
      38             : 
      39             : // Bias
      40             : #define BB UB * 128 + VB * 128
      41             : #define BG UG * 128 + VG * 128
      42             : #define BR UR * 128 + VR * 128
      43             : 
      44             : static __inline void
      45           0 : YuvPixel(uint8 y, uint8 u, uint8 v, uint8* b, uint8* g, uint8* r)
      46             : {
      47           0 :   int32 y1 = ((int32)(y) - 16) * YG;
      48           0 :   *b = Clamp((int32)((u * UB + v * VB) - (BB) + y1) >> 6);
      49           0 :   *g = Clamp((int32)((u * UG + v * VG) - (BG) + y1) >> 6);
      50           0 :   *r = Clamp((int32)((u * UR + v * VR) - (BR) + y1) >> 6);
      51           0 : }
      52             : 
      53             : static __inline int
      54           0 : RGBToY(uint8 r, uint8 g, uint8 b)
      55             : {
      56           0 :   return (66 * r + 129 * g +  25 * b + 0x1080) >> 8;
      57             : }
      58             : 
      59             : static __inline int
      60           0 : RGBToU(uint8 r, uint8 g, uint8 b)
      61             : {
      62           0 :   return (112 * b - 74 * g - 38 * r + 0x8080) >> 8;
      63             : }
      64             : 
      65             : static __inline int
      66           0 : RGBToV(uint8 r, uint8 g, uint8 b)
      67             : {
      68           0 :   return (112 * r - 94 * g - 18 * b + 0x8080) >> 8;
      69             : }
      70             : 
      71             : /*
      72             :  * Generic functions.
      73             :  */
      74             : template<int aSrcRIndex, int aSrcGIndex, int aSrcBIndex,
      75             :          int aDstRIndex, int aDstGIndex, int aDstBIndex, int aDstAIndex>
      76             : static int
      77           0 : RGBFamilyToRGBAFamily(const uint8_t* aSrcBuffer, int aSrcStride,
      78             :                       uint8_t* aDstBuffer, int aDstStride,
      79             :                       int aWidth, int aHeight)
      80             : {
      81             :   static_assert(aSrcRIndex == 0 || aSrcRIndex == 2, "Wrong SrcR index.");
      82             :   static_assert(aSrcGIndex == 1, "Wrong SrcG index.");
      83             :   static_assert(aSrcBIndex == 0 || aSrcBIndex == 2, "Wrong SrcB index.");
      84             :   static_assert(aDstRIndex == 0 || aDstRIndex == 2, "Wrong DstR index.");
      85             :   static_assert(aDstGIndex == 1, "Wrong DstG index.");
      86             :   static_assert(aDstBIndex == 0 || aDstBIndex == 2, "Wrong DstB index.");
      87             :   static_assert(aDstAIndex == 3, "Wrong DstA index.");
      88             : 
      89           0 :   for (int i = 0; i < aHeight; ++i) {
      90           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
      91           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
      92             : 
      93           0 :     for (int j = 0; j < aWidth; ++j) {
      94           0 :       uint8_t r = *(srcBuffer + aSrcRIndex);
      95           0 :       uint8_t g = *(srcBuffer + aSrcGIndex);
      96           0 :       uint8_t b = *(srcBuffer + aSrcBIndex);
      97           0 :       *(dstBuffer + aDstRIndex) = r;
      98           0 :       *(dstBuffer + aDstGIndex) = g;
      99           0 :       *(dstBuffer + aDstBIndex) = b;
     100           0 :       *(dstBuffer + aDstAIndex) = 255;
     101           0 :       srcBuffer += 3;
     102           0 :       dstBuffer += 4;
     103             :     }
     104             :   }
     105             : 
     106           0 :   return 0;
     107             : }
     108             : 
     109             : template<int aSrcRIndex, int aSrcGIndex, int aSrcBIndex,
     110             :          int aDstRIndex, int aDstGIndex, int aDstBIndex>
     111             : static int
     112           0 : RGBAFamilyToRGBFamily(const uint8_t* aSrcBuffer, int aSrcStride,
     113             :                       uint8_t* aDstBuffer, int aDstStride,
     114             :                       int aWidth, int aHeight)
     115             : {
     116             :   static_assert(aSrcRIndex == 0 || aSrcRIndex == 2, "Wrong SrcR index.");
     117             :   static_assert(aSrcGIndex == 1, "Wrong SrcG index.");
     118             :   static_assert(aSrcBIndex == 0 || aSrcBIndex == 2, "Wrong SrcB index.");
     119             :   static_assert(aDstRIndex == 0 || aDstRIndex == 2, "Wrong DstR index.");
     120             :   static_assert(aDstGIndex == 1, "Wrong DstG index.");
     121             :   static_assert(aDstBIndex == 0 || aDstBIndex == 2, "Wrong DstB index.");
     122             : 
     123           0 :   for (int i = 0; i < aHeight; ++i) {
     124           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
     125           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     126             : 
     127           0 :     for (int j = 0; j < aWidth; ++j) {
     128           0 :       uint8_t r = *(srcBuffer + aSrcRIndex);
     129           0 :       uint8_t g = *(srcBuffer + aSrcGIndex);
     130           0 :       uint8_t b = *(srcBuffer + aSrcBIndex);
     131           0 :       *(dstBuffer + aDstRIndex) = r;
     132           0 :       *(dstBuffer + aDstGIndex) = g;
     133           0 :       *(dstBuffer + aDstBIndex) = b;
     134           0 :       srcBuffer += 4;
     135           0 :       dstBuffer += 3;
     136             :     }
     137             :   }
     138             : 
     139           0 :   return 0;
     140             : }
     141             : 
     142             : template<int aPixel1YOffset, int aPixel1UOffset, int aPixel1VOffset,
     143             :          int aPixel2YOffset, int aPixel2UOffset, int aPixel2VOffset,
     144             :          int aYStep, int aUStep, int aVStep,
     145             :          int aRIndex, int aGIndex, int aBIndex>
     146             : void
     147           0 : YUVFamilyToRGBFamily_Row(const uint8_t* aYBuffer,
     148             :                          const uint8_t* aUBuffer,
     149             :                          const uint8_t* aVBuffer,
     150             :                          uint8_t* aDstBuffer,
     151             :                          int aWidth)
     152             : {
     153             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
     154             :   static_assert(aGIndex == 1, "Wrong G index.");
     155             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
     156             : 
     157           0 :   for (int j = 0; j < aWidth - 1; j += 2) {
     158           0 :     YuvPixel(aYBuffer[aPixel1YOffset], aUBuffer[aPixel1UOffset], aVBuffer[aPixel1VOffset],
     159             :              aDstBuffer + aBIndex, aDstBuffer + aGIndex, aDstBuffer + aRIndex);
     160           0 :     YuvPixel(aYBuffer[aPixel2YOffset], aUBuffer[aPixel2UOffset], aVBuffer[aPixel2VOffset],
     161             :              aDstBuffer + aBIndex + 3, aDstBuffer + aGIndex + 3, aDstBuffer + aRIndex + 3);
     162           0 :     aYBuffer += aYStep;
     163           0 :     aUBuffer += aUStep;
     164           0 :     aVBuffer += aVStep;
     165           0 :     aDstBuffer += 6;
     166             :   }
     167             : 
     168           0 :   if (aWidth & 1) {
     169           0 :     YuvPixel(aYBuffer[aPixel1YOffset], aUBuffer[aPixel1UOffset], aVBuffer[aPixel1VOffset],
     170             :              aDstBuffer + aBIndex, aDstBuffer + aGIndex, aDstBuffer + aRIndex);
     171             :   }
     172           0 : }
     173             : 
     174             : template<int aPixel1YOffset, int aPixel1UOffset, int aPixel1VOffset,
     175             :          int aPixel2YOffset, int aPixel2UOffset, int aPixel2VOffset,
     176             :          int aYStep, int aUStep, int aVStep,
     177             :          int aRIndex, int aGIndex, int aBIndex, int aAIndex>
     178             : void
     179           0 : YUVFamilyToRGBAFamily_Row(const uint8_t* aYBuffer,
     180             :                           const uint8_t* aUBuffer,
     181             :                           const uint8_t* aVBuffer,
     182             :                           uint8_t* aDstBuffer,
     183             :                           int aWidth)
     184             : {
     185             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
     186             :   static_assert(aGIndex == 1, "Wrong G index.");
     187             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
     188             :   static_assert(aAIndex == 3, "Wrong A index.");
     189             : 
     190           0 :   for (int j = 0; j < aWidth - 1; j += 2) {
     191           0 :     YuvPixel(aYBuffer[aPixel1YOffset], aUBuffer[aPixel1UOffset], aVBuffer[aPixel1VOffset],
     192             :              aDstBuffer + aBIndex, aDstBuffer + aGIndex, aDstBuffer + aRIndex);
     193           0 :     YuvPixel(aYBuffer[aPixel2YOffset], aUBuffer[aPixel2UOffset], aVBuffer[aPixel2VOffset],
     194             :              aDstBuffer + aBIndex + 4, aDstBuffer + aGIndex + 4, aDstBuffer + aRIndex + 4);
     195           0 :     aDstBuffer[aAIndex] = 255;
     196           0 :     aDstBuffer[aAIndex + 4] = 255;
     197             : 
     198           0 :     aYBuffer += aYStep;
     199           0 :     aUBuffer += aUStep;
     200           0 :     aVBuffer += aVStep;
     201           0 :     aDstBuffer += 8;
     202             :   }
     203             : 
     204           0 :   if (aWidth & 1) {
     205           0 :     YuvPixel(aYBuffer[aPixel1YOffset], aUBuffer[aPixel1UOffset], aVBuffer[aPixel1VOffset],
     206             :              aDstBuffer + aBIndex, aDstBuffer + aGIndex, aDstBuffer + aRIndex);
     207           0 :     aDstBuffer[aAIndex] = 255;
     208             :   }
     209           0 : }
     210             : 
     211             : template< int aRIndex, int aGIndex, int aBIndex>
     212             : static void
     213           0 : RGBFamilyToY_Row(const uint8_t* aSrcBuffer, uint8_t* aYBuffer, int aWidth)
     214             : {
     215             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
     216             :   static_assert(aGIndex == 1, "Wrong G index.");
     217             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
     218             : 
     219           0 :   for (int j = 0; j < aWidth - 1; j += 2) {
     220           0 :     aYBuffer[0] = RGBToY(aSrcBuffer[aRIndex], aSrcBuffer[aGIndex], aSrcBuffer[aBIndex]);
     221           0 :     aYBuffer[1] = RGBToY(aSrcBuffer[aRIndex + 3], aSrcBuffer[aGIndex + 3], aSrcBuffer[aBIndex + 3]);
     222             : 
     223           0 :     aYBuffer += 2;
     224           0 :     aSrcBuffer += 3 * 2;
     225             :   }
     226             : 
     227           0 :   if (aWidth & 1) {
     228           0 :     aYBuffer[0] = RGBToY(aSrcBuffer[aRIndex], aSrcBuffer[aGIndex], aSrcBuffer[aBIndex]);
     229             :   }
     230           0 : }
     231             : 
     232             : template< int aRIndex, int aGIndex, int aBIndex, int aUStep, int aVStep>
     233             : static void
     234           0 : RGBFamilyToUV_Row(const uint8_t* aSrcBuffer, int aSrcStride,
     235             :                   uint8_t* aUBuffer, uint8_t* aVBuffer, int aWidth)
     236             : {
     237             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
     238             :   static_assert(aGIndex == 1, "Wrong G index.");
     239             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
     240             : 
     241           0 :   uint8_t averageR = 0;
     242           0 :   uint8_t averageG = 0;
     243           0 :   uint8_t averageB = 0;
     244             : 
     245           0 :   const uint8_t* aSrcBufferNextRow = aSrcBuffer + aSrcStride;
     246           0 :   for (int j = 0; j < aWidth - 1; j += 2) {
     247           0 :     averageR = (aSrcBuffer[aRIndex] + aSrcBuffer[aRIndex + 3] + aSrcBufferNextRow[aRIndex] + aSrcBufferNextRow[aRIndex + 3]) >> 2;
     248           0 :     averageG = (aSrcBuffer[aGIndex] + aSrcBuffer[aGIndex + 3] + aSrcBufferNextRow[aGIndex] + aSrcBufferNextRow[aGIndex + 3]) >> 2;
     249           0 :     averageB = (aSrcBuffer[aBIndex] + aSrcBuffer[aBIndex + 3] + aSrcBufferNextRow[aBIndex] + aSrcBufferNextRow[aBIndex + 3]) >> 2;
     250             : 
     251           0 :     aUBuffer[0] = RGBToU(averageR, averageG, averageB);
     252           0 :     aVBuffer[0] = RGBToV(averageR, averageG, averageB);
     253             : 
     254           0 :     aUBuffer += aUStep;
     255           0 :     aVBuffer += aVStep;
     256           0 :     aSrcBuffer += 3 * 2;
     257           0 :     aSrcBufferNextRow += 3 * 2;
     258             :   }
     259             : 
     260           0 :   if (aWidth & 1) {
     261           0 :     averageR = (aSrcBuffer[aRIndex] + aSrcBufferNextRow[aRIndex]) >> 1;
     262           0 :     averageG = (aSrcBuffer[aGIndex] + aSrcBufferNextRow[aGIndex]) >> 1;
     263           0 :     averageB = (aSrcBuffer[aBIndex] + aSrcBufferNextRow[aBIndex]) >> 1;
     264             : 
     265           0 :     aUBuffer[0] = RGBToU(averageR, averageG, averageB);
     266           0 :     aVBuffer[0] = RGBToV(averageR, averageG, averageB);
     267             :   }
     268           0 : }
     269             : 
     270             : template< int aRIndex, int aGIndex, int aBIndex>
     271             : static void
     272           0 : RGBAFamilyToY_Row(const uint8_t* aSrcBuffer, uint8_t* aYBuffer, int aWidth)
     273             : {
     274             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
     275             :   static_assert(aGIndex == 1, "Wrong G index.");
     276             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
     277             : 
     278           0 :   for (int j = 0; j < aWidth - 1; j += 2) {
     279           0 :     aYBuffer[0] = RGBToY(aSrcBuffer[aRIndex], aSrcBuffer[aGIndex], aSrcBuffer[aBIndex]);
     280           0 :     aYBuffer[1] = RGBToY(aSrcBuffer[aRIndex + 4], aSrcBuffer[aGIndex + 4], aSrcBuffer[aBIndex + 4]);
     281             : 
     282           0 :     aYBuffer += 2;
     283           0 :     aSrcBuffer += 4 * 2;
     284             :   }
     285             : 
     286           0 :   if (aWidth & 1) {
     287           0 :     aYBuffer[0] = RGBToY(aSrcBuffer[aRIndex], aSrcBuffer[aGIndex], aSrcBuffer[aBIndex]);
     288             :   }
     289           0 : }
     290             : 
     291             : template< int aRIndex, int aGIndex, int aBIndex, int aUStep, int aVStep>
     292             : static void
     293           0 : RGBAFamilyToUV_Row(const uint8_t* aSrcBuffer, int aSrcStride,
     294             :                    uint8_t* aUBuffer, uint8_t* aVBuffer, int aWidth)
     295             : {
     296             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
     297             :   static_assert(aGIndex == 1, "Wrong G index.");
     298             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
     299             : 
     300           0 :   uint8_t averageR = 0;
     301           0 :   uint8_t averageG = 0;
     302           0 :   uint8_t averageB = 0;
     303             : 
     304           0 :   const uint8_t* aSrcBufferNextRow = aSrcBuffer + aSrcStride;
     305           0 :   for (int j = 0; j < aWidth - 1; j += 2) {
     306           0 :     averageR = (aSrcBuffer[aRIndex] + aSrcBuffer[aRIndex + 4] + aSrcBufferNextRow[aRIndex] + aSrcBufferNextRow[aRIndex + 4]) >> 2;
     307           0 :     averageG = (aSrcBuffer[aGIndex] + aSrcBuffer[aGIndex + 4] + aSrcBufferNextRow[aGIndex] + aSrcBufferNextRow[aGIndex + 4]) >> 2;
     308           0 :     averageB = (aSrcBuffer[aBIndex] + aSrcBuffer[aBIndex + 4] + aSrcBufferNextRow[aBIndex] + aSrcBufferNextRow[aBIndex + 4]) >> 2;
     309             : 
     310           0 :     aUBuffer[0] = RGBToU(averageR, averageG, averageB);
     311           0 :     aVBuffer[0] = RGBToV(averageR, averageG, averageB);
     312             : 
     313           0 :     aUBuffer += aUStep;
     314           0 :     aVBuffer += aVStep;
     315           0 :     aSrcBuffer += 4 * 2;
     316           0 :     aSrcBufferNextRow += 4 * 2;
     317             :   }
     318             : 
     319           0 :   if (aWidth & 1) {
     320           0 :     averageR = (aSrcBuffer[aRIndex] + aSrcBufferNextRow[aRIndex]) >> 1;
     321           0 :     averageG = (aSrcBuffer[aGIndex] + aSrcBufferNextRow[aGIndex]) >> 1;
     322           0 :     averageB = (aSrcBuffer[aBIndex] + aSrcBufferNextRow[aBIndex]) >> 1;
     323             : 
     324           0 :     aUBuffer[0] = RGBToU(averageR, averageG, averageB);
     325           0 :     aVBuffer[0] = RGBToV(averageR, averageG, averageB);
     326             :   }
     327           0 : }
     328             : 
     329             : /*
     330             :  * RGB family -> RGBA family.
     331             :  */
     332             : int
     333           0 : RGB24ToRGBA32(const uint8_t* aSrcBuffer, int aSrcStride,
     334             :               uint8_t* aDstBuffer, int aDstStride,
     335             :               int aWidth, int aHeight)
     336             : {
     337             :   return RGBFamilyToRGBAFamily<0, 1, 2, 0, 1, 2, 3>(aSrcBuffer, aSrcStride,
     338             :                                                     aDstBuffer, aDstStride,
     339           0 :                                                     aWidth, aHeight);
     340             : }
     341             : 
     342             : int
     343           0 : BGR24ToRGBA32(const uint8_t* aSrcBuffer, int aSrcStride,
     344             :               uint8_t* aDstBuffer, int aDstStride,
     345             :               int aWidth, int aHeight)
     346             : {
     347             :   return RGBFamilyToRGBAFamily<2, 1, 0, 0, 1, 2, 3>(aSrcBuffer, aSrcStride,
     348             :                                                     aDstBuffer, aDstStride,
     349           0 :                                                     aWidth, aHeight);
     350             : }
     351             : 
     352             : int
     353           0 : RGB24ToBGRA32(const uint8_t* aSrcBuffer, int aSrcStride,
     354             :               uint8_t* aDstBuffer, int aDstStride,
     355             :               int aWidth, int aHeight)
     356             : {
     357             :   return RGBFamilyToRGBAFamily<0, 1, 2, 2, 1, 0, 3>(aSrcBuffer, aSrcStride,
     358             :                                                     aDstBuffer, aDstStride,
     359           0 :                                                     aWidth, aHeight);
     360             : }
     361             : 
     362             : int
     363           0 : BGR24ToBGRA32(const uint8_t* aSrcBuffer, int aSrcStride,
     364             :               uint8_t* aDstBuffer, int aDstStride,
     365             :               int aWidth, int aHeight)
     366             : {
     367             :   return RGBFamilyToRGBAFamily<2, 1, 0, 2, 1, 0, 3>(aSrcBuffer, aSrcStride,
     368             :                                                     aDstBuffer, aDstStride,
     369           0 :                                                     aWidth, aHeight);
     370             : }
     371             : 
     372             : /*
     373             :  * RGBA family -> RGB family.
     374             :  */
     375             : int
     376           0 : RGBA32ToRGB24(const uint8_t* aSrcBuffer, int aSrcStride,
     377             :               uint8_t* aDstBuffer, int aDstStride,
     378             :               int aWidth, int aHeight)
     379             : {
     380             :   return RGBAFamilyToRGBFamily<0, 1, 2, 0, 1, 2>(aSrcBuffer, aSrcStride,
     381             :                                                  aDstBuffer, aDstStride,
     382           0 :                                                  aWidth, aHeight);
     383             : }
     384             : 
     385             : int
     386           0 : BGRA32ToRGB24(const uint8_t* aSrcBuffer, int aSrcStride,
     387             :               uint8_t* aDstBuffer, int aDstStride,
     388             :               int aWidth, int aHeight)
     389             : {
     390             :   return RGBAFamilyToRGBFamily<2, 1, 0, 0, 1, 2>(aSrcBuffer, aSrcStride,
     391             :                                                  aDstBuffer, aDstStride,
     392           0 :                                                  aWidth, aHeight);
     393             : }
     394             : 
     395             : int
     396           0 : RGBA32ToBGR24(const uint8_t* aSrcBuffer, int aSrcStride,
     397             :               uint8_t* aDstBuffer, int aDstStride,
     398             :               int aWidth, int aHeight)
     399             : {
     400             :   return RGBAFamilyToRGBFamily<0, 1, 2, 2, 1, 0>(aSrcBuffer, aSrcStride,
     401             :                                                  aDstBuffer, aDstStride,
     402           0 :                                                  aWidth, aHeight);
     403             : }
     404             : 
     405             : int
     406           0 : BGRA32ToBGR24(const uint8_t* aSrcBuffer, int aSrcStride,
     407             :               uint8_t* aDstBuffer, int aDstStride,
     408             :               int aWidth, int aHeight)
     409             : {
     410             :   return RGBAFamilyToRGBFamily<2, 1, 0, 2, 1, 0>(aSrcBuffer, aSrcStride,
     411             :                                                  aDstBuffer, aDstStride,
     412           0 :                                                  aWidth, aHeight);
     413             : }
     414             : 
     415             : /*
     416             :  * Among RGB family.
     417             :  */
     418             : int
     419           0 : RGB24Copy(const uint8_t* aSrcBuffer, int aSrcStride,
     420             :           uint8_t* aDstBuffer, int aDstStride,
     421             :           int aWidth, int aHeight)
     422             : {
     423           0 :   MOZ_ASSERT(aSrcStride == aDstStride, "RGB24Copy: aSrcStride != aDstStride");
     424             : 
     425           0 :   const uint32_t length = aHeight * aDstStride;
     426           0 :   memcpy(aDstBuffer, aSrcBuffer, length);
     427           0 :   return 0;
     428             : }
     429             : 
     430             : int
     431           0 : RGB24ToBGR24(const uint8_t* aSrcBuffer, int aSrcStride,
     432             :              uint8_t* aDstBuffer, int aDstStride,
     433             :              int aWidth, int aHeight)
     434             : {
     435           0 :   for (int i = 0; i < aHeight; ++i) {
     436           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
     437           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     438             : 
     439           0 :     for (int j = 0; j < aWidth; ++j) {
     440           0 :       *(dstBuffer + 0) = *(srcBuffer + 2);
     441           0 :       *(dstBuffer + 1) = *(srcBuffer + 1);
     442           0 :       *(dstBuffer + 2) = *(srcBuffer + 0);
     443           0 :       srcBuffer += 3;
     444           0 :       dstBuffer += 3;
     445             :     }
     446             :   }
     447             : 
     448           0 :   return 0;
     449             : }
     450             : 
     451             : /*
     452             :  * YUV family -> RGB family.
     453             :  */
     454             : int
     455           0 : YUV444PToRGB24(const uint8_t* aYBuffer, int aYStride,
     456             :                const uint8_t* aUBuffer, int aUStride,
     457             :                const uint8_t* aVBuffer, int aVStride,
     458             :                uint8_t* aDstBuffer, int aDstStride,
     459             :                int aWidth, int aHeight)
     460             : {
     461           0 :   for (int i = 0; i < aHeight; ++i) {
     462           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     463           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * i;
     464           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * i;
     465           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     466             : 
     467             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 1, 2>(yBuffer,
     468             :                                                                  uBuffer,
     469             :                                                                  vBuffer,
     470             :                                                                  dstBuffer,
     471           0 :                                                                  aWidth);
     472             :   }
     473             : 
     474           0 :   return 0;
     475             : }
     476             : 
     477             : int
     478           0 : YUV422PToRGB24(const uint8_t* aYBuffer, int aYStride,
     479             :                const uint8_t* aUBuffer, int aUStride,
     480             :                const uint8_t* aVBuffer, int aVStride,
     481             :                uint8_t* aDstBuffer, int aDstStride,
     482             :                int aWidth, int aHeight)
     483             : {
     484           0 :   for (int i = 0; i < aHeight; ++i) {
     485           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     486           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * i;
     487           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * i;
     488           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     489             : 
     490             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 0, 0, 2, 1, 1, 0, 1, 2>(yBuffer,
     491             :                                                                  uBuffer,
     492             :                                                                  vBuffer,
     493             :                                                                  dstBuffer,
     494           0 :                                                                  aWidth);
     495             :   }
     496             : 
     497           0 :   return 0;
     498             : }
     499             : 
     500             : int
     501           0 : YUV420PToRGB24(const uint8_t* aYBuffer, int aYStride,
     502             :                const uint8_t* aUBuffer, int aUStride,
     503             :                const uint8_t* aVBuffer, int aVStride,
     504             :                uint8_t* aDstBuffer, int aDstStride,
     505             :                int aWidth, int aHeight)
     506             : {
     507           0 :   for (int i = 0; i < aHeight; ++i) {
     508           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     509           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
     510           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
     511           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     512             : 
     513             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 0, 0, 2, 1, 1, 0, 1, 2>(yBuffer,
     514             :                                                                  uBuffer,
     515             :                                                                  vBuffer,
     516             :                                                                  dstBuffer,
     517           0 :                                                                  aWidth);
     518             :   }
     519             : 
     520           0 :   return 0;
     521             : }
     522             : 
     523             : int
     524           0 : NV12ToRGB24(const uint8_t* aYBuffer, int aYStride,
     525             :             const uint8_t* aUVBuffer, int aUVStride,
     526             :             uint8_t* aDstBuffer, int aDstStride,
     527             :             int aWidth, int aHeight)
     528             : {
     529           0 :   for (int i = 0; i < aHeight; ++i) {
     530           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     531           0 :     const uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
     532           0 :     const uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
     533           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     534             : 
     535             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2>(yBuffer,
     536             :                                                                  uBuffer,
     537             :                                                                  vBuffer,
     538             :                                                                  dstBuffer,
     539           0 :                                                                  aWidth);
     540             :   }
     541             : 
     542           0 :   return 0;
     543             : }
     544             : 
     545             : int
     546           0 : NV21ToRGB24(const uint8_t* aYBuffer, int aYStride,
     547             :             const uint8_t* aVUBuffer, int aVUStride,
     548             :             uint8_t* aDstBuffer, int aDstStride,
     549             :             int aWidth, int aHeight)
     550             : {
     551           0 :   for (int i = 0; i < aHeight; ++i) {
     552           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     553           0 :     const uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
     554           0 :     const uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
     555           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     556             : 
     557             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2>(yBuffer,
     558             :                                                                  uBuffer,
     559             :                                                                  vBuffer,
     560             :                                                                  dstBuffer,
     561           0 :                                                                  aWidth);
     562             :   }
     563             : 
     564           0 :   return 0;
     565             : }
     566             : 
     567             : int
     568           0 : YUV444PToBGR24(const uint8_t* aYBuffer, int aYStride,
     569             :                const uint8_t* aUBuffer, int aUStride,
     570             :                const uint8_t* aVBuffer, int aVStride,
     571             :                uint8_t* aDstBuffer, int aDstStride,
     572             :                int aWidth, int aHeight)
     573             : {
     574           0 :   for (int i = 0; i < aHeight; ++i) {
     575           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     576           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * i;
     577           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * i;
     578           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     579             : 
     580             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 1, 0>(yBuffer,
     581             :                                                                  uBuffer,
     582             :                                                                  vBuffer,
     583             :                                                                  dstBuffer,
     584           0 :                                                                  aWidth);
     585             :   }
     586             : 
     587           0 :   return 0;
     588             : }
     589             : 
     590             : int
     591           0 : YUV422PToBGR24(const uint8_t* aYBuffer, int aYStride,
     592             :                const uint8_t* aUBuffer, int aUStride,
     593             :                const uint8_t* aVBuffer, int aVStride,
     594             :                uint8_t* aDstBuffer, int aDstStride,
     595             :                int aWidth, int aHeight)
     596             : {
     597           0 :   for (int i = 0; i < aHeight; ++i) {
     598           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     599           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * i;
     600           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * i;
     601           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     602             : 
     603             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 0, 0, 2, 1, 1, 2, 1, 0>(yBuffer,
     604             :                                                                  uBuffer,
     605             :                                                                  vBuffer,
     606             :                                                                  dstBuffer,
     607           0 :                                                                  aWidth);
     608             :   }
     609             : 
     610           0 :   return 0;
     611             : }
     612             : 
     613             : int
     614           0 : YUV420PToBGR24(const uint8_t* aYBuffer, int aYStride,
     615             :                const uint8_t* aUBuffer, int aUStride,
     616             :                const uint8_t* aVBuffer, int aVStride,
     617             :                uint8_t* aDstBuffer, int aDstStride,
     618             :                int aWidth, int aHeight)
     619             : {
     620           0 :   for (int i = 0; i < aHeight; ++i) {
     621           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     622           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
     623           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
     624           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     625             : 
     626             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 0, 0, 2, 1, 1, 2, 1, 0>(yBuffer,
     627             :                                                                  uBuffer,
     628             :                                                                  vBuffer,
     629             :                                                                  dstBuffer,
     630           0 :                                                                  aWidth);
     631             :   }
     632             : 
     633           0 :   return 0;
     634             : }
     635             : 
     636             : int
     637           0 : NV12ToBGR24(const uint8_t* aYBuffer, int aYStride,
     638             :             const uint8_t* aUVBuffer, int aUVStride,
     639             :             uint8_t* aDstBuffer, int aDstStride,
     640             :             int aWidth, int aHeight)
     641             : {
     642           0 :   for (int i = 0; i < aHeight; ++i) {
     643           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     644           0 :     const uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
     645           0 :     const uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
     646           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     647             : 
     648             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 0, 0, 2, 2, 2, 2, 1, 0>(yBuffer,
     649             :                                                                  uBuffer,
     650             :                                                                  vBuffer,
     651             :                                                                  dstBuffer,
     652           0 :                                                                  aWidth);
     653             :   }
     654             : 
     655           0 :   return 0;
     656             : }
     657             : 
     658             : int
     659           0 : NV21ToBGR24(const uint8_t* aYBuffer, int aYStride,
     660             :             const uint8_t* aVUBuffer, int aVUStride,
     661             :             uint8_t* aDstBuffer, int aDstStride,
     662             :             int aWidth, int aHeight)
     663             : {
     664           0 :   for (int i = 0; i < aHeight; ++i) {
     665           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     666           0 :     const uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
     667           0 :     const uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
     668           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     669             : 
     670             :     YUVFamilyToRGBFamily_Row<0, 0, 0, 1, 0, 0, 2, 2, 2, 2, 1, 0>(yBuffer,
     671             :                                                                  uBuffer,
     672             :                                                                  vBuffer,
     673             :                                                                  dstBuffer,
     674           0 :                                                                  aWidth);
     675             :   }
     676             : 
     677           0 :   return 0;
     678             : }
     679             : 
     680             : /*
     681             :  * YUV family -> RGBA family.
     682             :  */
     683             : int
     684           0 : YUV444PToRGBA32(const uint8_t* aYBuffer, int aYStride,
     685             :                 const uint8_t* aUBuffer, int aUStride,
     686             :                 const uint8_t* aVBuffer, int aVStride,
     687             :                 uint8_t* aDstBuffer, int aDstStride,
     688             :                 int aWidth, int aHeight)
     689             : {
     690           0 :   for (int i = 0; i < aHeight; ++i) {
     691           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     692           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * i;
     693           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * i;
     694           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     695             : 
     696             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 1, 1, 2, 2, 2, 0, 1, 2, 3>(yBuffer,
     697             :                                                                      uBuffer,
     698             :                                                                      vBuffer,
     699             :                                                                      dstBuffer,
     700           0 :                                                                      aWidth);
     701             :   }
     702             : 
     703           0 :   return 0;
     704             : }
     705             : 
     706             : int
     707           0 : YUV422PToRGBA32(const uint8_t* aYBuffer, int aYStride,
     708             :                 const uint8_t* aUBuffer, int aUStride,
     709             :                 const uint8_t* aVBuffer, int aVStride,
     710             :                 uint8_t* aDstBuffer, int aDstStride,
     711             :                 int aWidth, int aHeight)
     712             : {
     713           0 :   for (int i = 0; i < aHeight; ++i) {
     714           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     715           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * i;
     716           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * i;
     717           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     718             : 
     719             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 0, 0, 2, 1, 1, 0, 1, 2, 3>(yBuffer,
     720             :                                                                      uBuffer,
     721             :                                                                      vBuffer,
     722             :                                                                      dstBuffer,
     723           0 :                                                                      aWidth);
     724             :   }
     725             : 
     726           0 :   return 0;
     727             : }
     728             : 
     729             : int
     730           0 : YUV420PToRGBA32(const uint8_t* aYBuffer, int aYStride,
     731             :                 const uint8_t* aUBuffer, int aUStride,
     732             :                 const uint8_t* aVBuffer, int aVStride,
     733             :                 uint8_t* aDstBuffer, int aDstStride,
     734             :                 int aWidth, int aHeight)
     735             : {
     736           0 :   for (int i = 0; i < aHeight; ++i) {
     737           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     738           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
     739           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
     740           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     741             : 
     742             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 0, 0, 2, 1, 1, 0, 1, 2, 3>(yBuffer,
     743             :                                                                      uBuffer,
     744             :                                                                      vBuffer,
     745             :                                                                      dstBuffer,
     746           0 :                                                                      aWidth);
     747             :   }
     748             : 
     749           0 :   return 0;
     750             : }
     751             : 
     752             : int
     753           0 : NV12ToRGBA32(const uint8_t* aYBuffer, int aYStride,
     754             :              const uint8_t* aUVBuffer, int aUVStride,
     755             :              uint8_t* aDstBuffer, int aDstStride,
     756             :              int aWidth, int aHeight)
     757             : {
     758           0 :   for (int i = 0; i < aHeight; ++i) {
     759           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     760           0 :     const uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
     761           0 :     const uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
     762           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     763             : 
     764             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 3>(yBuffer,
     765             :                                                                      uBuffer,
     766             :                                                                      vBuffer,
     767             :                                                                      dstBuffer,
     768           0 :                                                                      aWidth);
     769             :   }
     770             : 
     771           0 :   return 0;
     772             : }
     773             : 
     774             : int
     775           0 : NV21ToRGBA32(const uint8_t* aYBuffer, int aYStride,
     776             :              const uint8_t* aVUBuffer, int aVUStride,
     777             :              uint8_t* aDstBuffer, int aDstStride,
     778             :              int aWidth, int aHeight)
     779             : {
     780           0 :   for (int i = 0; i < aHeight; ++i) {
     781           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     782           0 :     const uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
     783           0 :     const uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
     784           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     785             : 
     786             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 3>(yBuffer,
     787             :                                                                      uBuffer,
     788             :                                                                      vBuffer,
     789             :                                                                      dstBuffer,
     790           0 :                                                                      aWidth);
     791             :   }
     792             : 
     793           0 :   return 0;
     794             : }
     795             : 
     796             : int
     797           0 : YUV444PToBGRA32(const uint8_t* aYBuffer, int aYStride,
     798             :                 const uint8_t* aUBuffer, int aUStride,
     799             :                 const uint8_t* aVBuffer, int aVStride,
     800             :                 uint8_t* aDstBuffer, int aDstStride,
     801             :                 int aWidth, int aHeight)
     802             : {
     803           0 :   for (int i = 0; i < aHeight; ++i) {
     804           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     805           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * i;
     806           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * i;
     807           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     808             : 
     809             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 1, 0, 3>(yBuffer,
     810             :                                                                      uBuffer,
     811             :                                                                      vBuffer,
     812             :                                                                      dstBuffer,
     813           0 :                                                                      aWidth);
     814             :   }
     815             : 
     816           0 :   return 0;
     817             : }
     818             : 
     819             : int
     820           0 : YUV422PToBGRA32(const uint8_t* aYBuffer, int aYStride,
     821             :                 const uint8_t* aUBuffer, int aUStride,
     822             :                 const uint8_t* aVBuffer, int aVStride,
     823             :                 uint8_t* aDstBuffer, int aDstStride,
     824             :                 int aWidth, int aHeight)
     825             : {
     826           0 :   for (int i = 0; i < aHeight; ++i) {
     827           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     828           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * i;
     829           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * i;
     830           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     831             : 
     832             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 0, 0, 2, 1, 1, 2, 1, 0, 3>(yBuffer,
     833             :                                                                      uBuffer,
     834             :                                                                      vBuffer,
     835             :                                                                      dstBuffer,
     836           0 :                                                                      aWidth);
     837             :   }
     838             : 
     839           0 :   return 0;
     840             : }
     841             : 
     842             : int
     843           0 : YUV420PToBGRA32(const uint8_t* aYBuffer, int aYStride,
     844             :                 const uint8_t* aUBuffer, int aUStride,
     845             :                 const uint8_t* aVBuffer, int aVStride,
     846             :                 uint8_t* aDstBuffer, int aDstStride,
     847             :                 int aWidth, int aHeight)
     848             : {
     849           0 :   for (int i = 0; i < aHeight; ++i) {
     850           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     851           0 :     const uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
     852           0 :     const uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
     853           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     854             : 
     855             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 0, 0, 2, 1, 1, 2, 1, 0, 3>(yBuffer,
     856             :                                                                      uBuffer,
     857             :                                                                      vBuffer,
     858             :                                                                      dstBuffer,
     859           0 :                                                                      aWidth);
     860             :   }
     861             : 
     862           0 :   return 0;
     863             : }
     864             : 
     865             : int
     866           0 : NV12ToBGRA32(const uint8_t* aYBuffer, int aYStride,
     867             :              const uint8_t* aUVBuffer, int aUVStride,
     868             :              uint8_t* aDstBuffer, int aDstStride,
     869             :              int aWidth, int aHeight)
     870             : {
     871           0 :   for (int i = 0; i < aHeight; ++i) {
     872           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     873           0 :     const uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
     874           0 :     const uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
     875           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     876             : 
     877             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 0, 0, 2, 2, 2, 2, 1, 0, 3>(yBuffer,
     878             :                                                                      uBuffer,
     879             :                                                                      vBuffer,
     880             :                                                                      dstBuffer,
     881           0 :                                                                      aWidth);
     882             :   }
     883             : 
     884           0 :   return 0;
     885             : }
     886             : 
     887             : int
     888           0 : NV21ToBGRA32(const uint8_t* aYBuffer, int aYStride,
     889             :              const uint8_t* aVUBuffer, int aVUStride,
     890             :              uint8_t* aDstBuffer, int aDstStride,
     891             :              int aWidth, int aHeight)
     892             : {
     893           0 :   for (int i = 0; i < aHeight; ++i) {
     894           0 :     const uint8_t* yBuffer = aYBuffer + aYStride * i;
     895           0 :     const uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
     896           0 :     const uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
     897           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
     898             : 
     899             :     YUVFamilyToRGBAFamily_Row<0, 0, 0, 1, 0, 0, 2, 2, 2, 2, 1, 0, 3>(yBuffer,
     900             :                                                                      uBuffer,
     901             :                                                                      vBuffer,
     902             :                                                                      dstBuffer,
     903           0 :                                                                      aWidth);
     904             :   }
     905             : 
     906           0 :   return 0;
     907             : }
     908             : 
     909             : /*
     910             :  * RGB family -> YUV family.
     911             :  */
     912             : int
     913           0 : RGB24ToYUV444P(const uint8_t* aSrcBuffer, int aSrcStride,
     914             :                uint8_t* aYBuffer, int aYStride,
     915             :                uint8_t* aUBuffer, int aUStride,
     916             :                uint8_t* aVBuffer, int aVStride,
     917             :                int aWidth, int aHeight)
     918             : {
     919           0 :   for (int i = 0; i < aHeight; ++i) {
     920           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
     921           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
     922           0 :     uint8_t* uBuffer = aUBuffer + aUStride * i;
     923           0 :     uint8_t* vBuffer = aVBuffer + aVStride * i;
     924             : 
     925           0 :     for (int j = 0; j < aWidth; ++j) {
     926           0 :       yBuffer[0] = RGBToY(srcBuffer[0], srcBuffer[1], srcBuffer[2]);
     927           0 :       uBuffer[0] = RGBToU(srcBuffer[0], srcBuffer[1], srcBuffer[2]);
     928           0 :       vBuffer[0] = RGBToV(srcBuffer[0], srcBuffer[1], srcBuffer[2]);
     929             : 
     930           0 :       yBuffer += 1;
     931           0 :       uBuffer += 1;
     932           0 :       vBuffer += 1;
     933           0 :       srcBuffer += 3;
     934             :     }
     935             :   }
     936             : 
     937           0 :   return 0;
     938             : }
     939             : 
     940             : int
     941           0 : RGB24ToYUV422P(const uint8_t* aSrcBuffer, int aSrcStride,
     942             :                uint8_t* aYBuffer, int aYStride,
     943             :                uint8_t* aUBuffer, int aUStride,
     944             :                uint8_t* aVBuffer, int aVStride,
     945             :                int aWidth, int aHeight)
     946             : {
     947           0 :   for (int i = 0; i < aHeight; ++i) {
     948           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
     949           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
     950           0 :     uint8_t* uBuffer = aUBuffer + aUStride * i;
     951           0 :     uint8_t* vBuffer = aVBuffer + aVStride * i;
     952             : 
     953           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
     954             : 
     955             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
     956           0 :     RGBFamilyToUV_Row<0, 1, 2, 1, 1>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
     957             :   }
     958             : 
     959           0 :   return 0;
     960             : }
     961             : 
     962             : int
     963           0 : RGB24ToYUV420P(const uint8_t* aSrcBuffer, int aSrcStride,
     964             :                uint8_t* aYBuffer, int aYStride,
     965             :                uint8_t* aUBuffer, int aUStride,
     966             :                uint8_t* aVBuffer, int aVStride,
     967             :                int aWidth, int aHeight)
     968             : {
     969           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
     970           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
     971           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
     972           0 :     uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
     973           0 :     uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
     974             : 
     975           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
     976           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
     977           0 :     RGBFamilyToUV_Row<0, 1, 2, 1, 1>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
     978             :   }
     979             : 
     980           0 :   if (aHeight & 1) {
     981           0 :     const int i = aHeight - 1;
     982           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
     983           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
     984           0 :     uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
     985           0 :     uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
     986             : 
     987           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
     988             : 
     989             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
     990           0 :     RGBFamilyToUV_Row<0, 1, 2, 1, 1>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
     991             :   }
     992             : 
     993           0 :   return 0;
     994             : }
     995             : 
     996             : int
     997           0 : RGB24ToNV12(const uint8_t* aSrcBuffer, int aSrcStride,
     998             :             uint8_t* aYBuffer, int aYStride,
     999             :             uint8_t* aUVBuffer, int aUVStride,
    1000             :             int aWidth, int aHeight)
    1001             : {
    1002           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1003           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1004           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1005           0 :     uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
    1006           0 :     uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
    1007             : 
    1008           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1009           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1010           0 :     RGBFamilyToUV_Row<0, 1, 2, 2, 2>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1011             :   }
    1012             : 
    1013           0 :   if (aHeight & 1) {
    1014           0 :     const int i = aHeight - 1;
    1015           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1016           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1017           0 :     uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
    1018           0 :     uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
    1019             : 
    1020           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1021             : 
    1022             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1023           0 :     RGBFamilyToUV_Row<0, 1, 2, 2, 2>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1024             :   }
    1025             : 
    1026           0 :   return 0;
    1027             : }
    1028             : 
    1029             : int
    1030           0 : RGB24ToNV21(const uint8_t* aSrcBuffer, int aSrcStride,
    1031             :             uint8_t* aYBuffer, int aYStride,
    1032             :             uint8_t* aVUBuffer, int aVUStride,
    1033             :             int aWidth, int aHeight)
    1034             : {
    1035           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1036           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1037           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1038           0 :     uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
    1039           0 :     uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
    1040             : 
    1041           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1042           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1043           0 :     RGBFamilyToUV_Row<0, 1, 2, 2, 2>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1044             :   }
    1045             : 
    1046           0 :   if (aHeight & 1) {
    1047           0 :     const int i = aHeight - 1;
    1048           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1049           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1050           0 :     uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
    1051           0 :     uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
    1052             : 
    1053           0 :     RGBFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1054             : 
    1055             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1056           0 :     RGBFamilyToUV_Row<0, 1, 2, 2, 2>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1057             :   }
    1058             : 
    1059           0 :   return 0;
    1060             : }
    1061             : 
    1062             : int
    1063           0 : BGR24ToYUV444P(const uint8_t* aSrcBuffer, int aSrcStride,
    1064             :                uint8_t* aYBuffer, int aYStride,
    1065             :                uint8_t* aUBuffer, int aUStride,
    1066             :                uint8_t* aVBuffer, int aVStride,
    1067             :                int aWidth, int aHeight)
    1068             : {
    1069           0 :   for (int i = 0; i < aHeight; ++i) {
    1070           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1071           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1072           0 :     uint8_t* uBuffer = aUBuffer + aUStride * i;
    1073           0 :     uint8_t* vBuffer = aVBuffer + aVStride * i;
    1074             : 
    1075           0 :     for (int j = 0; j < aWidth; ++j) {
    1076           0 :       yBuffer[0] = RGBToY(srcBuffer[2], srcBuffer[1], srcBuffer[0]);
    1077           0 :       uBuffer[0] = RGBToU(srcBuffer[2], srcBuffer[1], srcBuffer[0]);
    1078           0 :       vBuffer[0] = RGBToV(srcBuffer[2], srcBuffer[1], srcBuffer[0]);
    1079             : 
    1080           0 :       yBuffer += 1;
    1081           0 :       uBuffer += 1;
    1082           0 :       vBuffer += 1;
    1083           0 :       srcBuffer += 3;
    1084             :     }
    1085             :   }
    1086             : 
    1087           0 :   return 0;
    1088             : }
    1089             : 
    1090             : int
    1091           0 : BGR24ToYUV422P(const uint8_t* aSrcBuffer, int aSrcStride,
    1092             :                uint8_t* aYBuffer, int aYStride,
    1093             :                uint8_t* aUBuffer, int aUStride,
    1094             :                uint8_t* aVBuffer, int aVStride,
    1095             :                int aWidth, int aHeight)
    1096             : {
    1097           0 :   for (int i = 0; i < aHeight; ++i) {
    1098           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1099           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1100           0 :     uint8_t* uBuffer = aUBuffer + aUStride * i;
    1101           0 :     uint8_t* vBuffer = aVBuffer + aVStride * i;
    1102             : 
    1103           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1104             : 
    1105             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1106           0 :     RGBFamilyToUV_Row<2, 1, 0, 1, 1>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1107             :   }
    1108             : 
    1109           0 :   return 0;
    1110             : }
    1111             : 
    1112             : int
    1113           0 : BGR24ToYUV420P(const uint8_t* aSrcBuffer, int aSrcStride,
    1114             :                uint8_t* aYBuffer, int aYStride,
    1115             :                uint8_t* aUBuffer, int aUStride,
    1116             :                uint8_t* aVBuffer, int aVStride,
    1117             :                int aWidth, int aHeight)
    1118             : {
    1119           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1120           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1121           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1122           0 :     uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
    1123           0 :     uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
    1124             : 
    1125           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1126           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1127           0 :     RGBFamilyToUV_Row<2, 1, 0, 1, 1>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1128             :   }
    1129             : 
    1130           0 :   if (aHeight & 1) {
    1131           0 :     const int i = aHeight - 1;
    1132           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1133           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1134           0 :     uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
    1135           0 :     uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
    1136             : 
    1137           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1138             : 
    1139             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1140           0 :     RGBFamilyToUV_Row<2, 1, 0, 1, 1>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1141             :   }
    1142             : 
    1143           0 :   return 0;
    1144             : }
    1145             : 
    1146             : int
    1147           0 : BGR24ToNV12(const uint8_t* aSrcBuffer, int aSrcStride,
    1148             :             uint8_t* aYBuffer, int aYStride,
    1149             :             uint8_t* aUVBuffer, int aUVStride,
    1150             :             int aWidth, int aHeight)
    1151             : {
    1152           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1153           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1154           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1155           0 :     uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
    1156           0 :     uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
    1157             : 
    1158           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1159           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1160           0 :     RGBFamilyToUV_Row<2, 1, 0, 2, 2>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1161             :   }
    1162             : 
    1163           0 :   if (aHeight & 1) {
    1164           0 :     const int i = aHeight - 1;
    1165           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1166           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1167           0 :     uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
    1168           0 :     uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
    1169             : 
    1170           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1171             : 
    1172             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1173           0 :     RGBFamilyToUV_Row<2, 1, 0, 2, 2>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1174             :   }
    1175             : 
    1176           0 :   return 0;
    1177             : }
    1178             : 
    1179             : int
    1180           0 : BGR24ToNV21(const uint8_t* aSrcBuffer, int aSrcStride,
    1181             :             uint8_t* aYBuffer, int aYStride,
    1182             :             uint8_t* aVUBuffer, int aVUStride,
    1183             :             int aWidth, int aHeight)
    1184             : {
    1185           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1186           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1187           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1188           0 :     uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
    1189           0 :     uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
    1190             : 
    1191           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1192           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1193           0 :     RGBFamilyToUV_Row<2, 1, 0, 2, 2>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1194             :   }
    1195             : 
    1196           0 :   if (aHeight & 1) {
    1197           0 :     const int i = aHeight - 1;
    1198           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1199           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1200           0 :     uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
    1201           0 :     uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
    1202             : 
    1203           0 :     RGBFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1204             : 
    1205             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1206           0 :     RGBFamilyToUV_Row<2, 1, 0, 2, 2>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1207             :   }
    1208             : 
    1209           0 :   return 0;
    1210             : }
    1211             : 
    1212             : /*
    1213             :  * RGBA family -> YUV family.
    1214             :  */
    1215             : int
    1216           0 : RGBA32ToYUV444P(const uint8_t* aSrcBuffer, int aSrcStride,
    1217             :                uint8_t* aYBuffer, int aYStride,
    1218             :                uint8_t* aUBuffer, int aUStride,
    1219             :                uint8_t* aVBuffer, int aVStride,
    1220             :                int aWidth, int aHeight)
    1221             : {
    1222           0 :   for (int i = 0; i < aHeight; ++i) {
    1223           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1224           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1225           0 :     uint8_t* uBuffer = aUBuffer + aUStride * i;
    1226           0 :     uint8_t* vBuffer = aVBuffer + aVStride * i;
    1227             : 
    1228           0 :     for (int j = 0; j < aWidth; ++j) {
    1229           0 :       yBuffer[0] = RGBToY(srcBuffer[0], srcBuffer[1], srcBuffer[2]);
    1230           0 :       uBuffer[0] = RGBToU(srcBuffer[0], srcBuffer[1], srcBuffer[2]);
    1231           0 :       vBuffer[0] = RGBToV(srcBuffer[0], srcBuffer[1], srcBuffer[2]);
    1232             : 
    1233           0 :       yBuffer += 1;
    1234           0 :       uBuffer += 1;
    1235           0 :       vBuffer += 1;
    1236           0 :       srcBuffer += 4;
    1237             :     }
    1238             :   }
    1239             : 
    1240           0 :   return 0;
    1241             : }
    1242             : 
    1243             : int
    1244           0 : RGBA32ToYUV422P(const uint8_t* aSrcBuffer, int aSrcStride,
    1245             :                uint8_t* aYBuffer, int aYStride,
    1246             :                uint8_t* aUBuffer, int aUStride,
    1247             :                uint8_t* aVBuffer, int aVStride,
    1248             :                int aWidth, int aHeight)
    1249             : {
    1250           0 :   for (int i = 0; i < aHeight; ++i) {
    1251           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1252           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1253           0 :     uint8_t* uBuffer = aUBuffer + aUStride * i;
    1254           0 :     uint8_t* vBuffer = aVBuffer + aVStride * i;
    1255             : 
    1256           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1257             : 
    1258             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1259           0 :     RGBAFamilyToUV_Row<0, 1, 2, 1, 1>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1260             :   }
    1261             : 
    1262           0 :   return 0;
    1263             : }
    1264             : 
    1265             : int
    1266           0 : RGBA32ToYUV420P(const uint8_t* aSrcBuffer, int aSrcStride,
    1267             :                uint8_t* aYBuffer, int aYStride,
    1268             :                uint8_t* aUBuffer, int aUStride,
    1269             :                uint8_t* aVBuffer, int aVStride,
    1270             :                int aWidth, int aHeight)
    1271             : {
    1272           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1273           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1274           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1275           0 :     uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
    1276           0 :     uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
    1277             : 
    1278           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1279           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1280           0 :     RGBAFamilyToUV_Row<0, 1, 2, 1, 1>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1281             :   }
    1282             : 
    1283           0 :   if (aHeight & 1) {
    1284           0 :     const int i = aHeight - 1;
    1285           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1286           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1287           0 :     uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
    1288           0 :     uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
    1289             : 
    1290           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1291             : 
    1292             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1293           0 :     RGBAFamilyToUV_Row<0, 1, 2, 1, 1>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1294             :   }
    1295             : 
    1296           0 :   return 0;
    1297             : }
    1298             : 
    1299             : int
    1300           0 : RGBA32ToNV12(const uint8_t* aSrcBuffer, int aSrcStride,
    1301             :             uint8_t* aYBuffer, int aYStride,
    1302             :             uint8_t* aUVBuffer, int aUVStride,
    1303             :             int aWidth, int aHeight)
    1304             : {
    1305           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1306           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1307           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1308           0 :     uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
    1309           0 :     uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
    1310             : 
    1311           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1312           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1313           0 :     RGBAFamilyToUV_Row<0, 1, 2, 2, 2>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1314             :   }
    1315             : 
    1316           0 :   if (aHeight & 1) {
    1317           0 :     const int i = aHeight - 1;
    1318           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1319           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1320           0 :     uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
    1321           0 :     uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
    1322             : 
    1323           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1324             : 
    1325             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1326           0 :     RGBAFamilyToUV_Row<0, 1, 2, 2, 2>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1327             :   }
    1328             : 
    1329           0 :   return 0;
    1330             : }
    1331             : 
    1332             : int
    1333           0 : RGBA32ToNV21(const uint8_t* aSrcBuffer, int aSrcStride,
    1334             :             uint8_t* aYBuffer, int aYStride,
    1335             :             uint8_t* aVUBuffer, int aVUStride,
    1336             :             int aWidth, int aHeight)
    1337             : {
    1338           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1339           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1340           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1341           0 :     uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
    1342           0 :     uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
    1343             : 
    1344           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1345           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1346           0 :     RGBAFamilyToUV_Row<0, 1, 2, 2, 2>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1347             :   }
    1348             : 
    1349           0 :   if (aHeight & 1) {
    1350           0 :     const int i = aHeight - 1;
    1351           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1352           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1353           0 :     uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
    1354           0 :     uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
    1355             : 
    1356           0 :     RGBAFamilyToY_Row<0, 1, 2>(srcBuffer, yBuffer, aWidth);
    1357             : 
    1358             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1359           0 :     RGBAFamilyToUV_Row<0, 1, 2, 2, 2>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1360             :   }
    1361             : 
    1362           0 :   return 0;
    1363             : }
    1364             : 
    1365             : int
    1366           0 : BGRA32ToYUV444P(const uint8_t* aSrcBuffer, int aSrcStride,
    1367             :                uint8_t* aYBuffer, int aYStride,
    1368             :                uint8_t* aUBuffer, int aUStride,
    1369             :                uint8_t* aVBuffer, int aVStride,
    1370             :                int aWidth, int aHeight)
    1371             : {
    1372           0 :   for (int i = 0; i < aHeight; ++i) {
    1373           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1374           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1375           0 :     uint8_t* uBuffer = aUBuffer + aUStride * i;
    1376           0 :     uint8_t* vBuffer = aVBuffer + aVStride * i;
    1377             : 
    1378           0 :     for (int j = 0; j < aWidth; ++j) {
    1379           0 :       yBuffer[0] = RGBToY(srcBuffer[2], srcBuffer[1], srcBuffer[0]);
    1380           0 :       uBuffer[0] = RGBToU(srcBuffer[2], srcBuffer[1], srcBuffer[0]);
    1381           0 :       vBuffer[0] = RGBToV(srcBuffer[2], srcBuffer[1], srcBuffer[0]);
    1382             : 
    1383           0 :       yBuffer += 1;
    1384           0 :       uBuffer += 1;
    1385           0 :       vBuffer += 1;
    1386           0 :       srcBuffer += 4;
    1387             :     }
    1388             :   }
    1389             : 
    1390           0 :   return 0;
    1391             : }
    1392             : 
    1393             : int
    1394           0 : BGRA32ToYUV422P(const uint8_t* aSrcBuffer, int aSrcStride,
    1395             :                uint8_t* aYBuffer, int aYStride,
    1396             :                uint8_t* aUBuffer, int aUStride,
    1397             :                uint8_t* aVBuffer, int aVStride,
    1398             :                int aWidth, int aHeight)
    1399             : {
    1400           0 :   for (int i = 0; i < aHeight; ++i) {
    1401           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1402           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1403           0 :     uint8_t* uBuffer = aUBuffer + aUStride * i;
    1404           0 :     uint8_t* vBuffer = aVBuffer + aVStride * i;
    1405             : 
    1406           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1407             : 
    1408             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1409           0 :     RGBAFamilyToUV_Row<2, 1, 0, 1, 1>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1410             :   }
    1411             : 
    1412           0 :   return 0;
    1413             : }
    1414             : 
    1415             : int
    1416           0 : BGRA32ToYUV420P(const uint8_t* aSrcBuffer, int aSrcStride,
    1417             :                uint8_t* aYBuffer, int aYStride,
    1418             :                uint8_t* aUBuffer, int aUStride,
    1419             :                uint8_t* aVBuffer, int aVStride,
    1420             :                int aWidth, int aHeight)
    1421             : {
    1422           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1423           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1424           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1425           0 :     uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
    1426           0 :     uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
    1427             : 
    1428           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1429           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1430           0 :     RGBAFamilyToUV_Row<2, 1, 0, 1, 1>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1431             :   }
    1432             : 
    1433           0 :   if (aHeight & 1) {
    1434           0 :     const int i = aHeight - 1;
    1435           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1436           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1437           0 :     uint8_t* uBuffer = aUBuffer + aUStride * (i / 2);
    1438           0 :     uint8_t* vBuffer = aVBuffer + aVStride * (i / 2);
    1439             : 
    1440           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1441             : 
    1442             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1443           0 :     RGBAFamilyToUV_Row<2, 1, 0, 1, 1>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1444             :   }
    1445             : 
    1446           0 :   return 0;
    1447             : }
    1448             : 
    1449             : int
    1450           0 : BGRA32ToNV12(const uint8_t* aSrcBuffer, int aSrcStride,
    1451             :             uint8_t* aYBuffer, int aYStride,
    1452             :             uint8_t* aUVBuffer, int aUVStride,
    1453             :             int aWidth, int aHeight)
    1454             : {
    1455           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1456           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1457           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1458           0 :     uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
    1459           0 :     uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
    1460             : 
    1461           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1462           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1463           0 :     RGBAFamilyToUV_Row<2, 1, 0, 2, 2>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1464             :   }
    1465             : 
    1466           0 :   if (aHeight & 1) {
    1467           0 :     const int i = aHeight - 1;
    1468           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1469           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1470           0 :     uint8_t* uBuffer = aUVBuffer + aUVStride * (i / 2);
    1471           0 :     uint8_t* vBuffer = aUVBuffer + aUVStride * (i / 2) + 1;
    1472             : 
    1473           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1474             : 
    1475             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1476           0 :     RGBAFamilyToUV_Row<2, 1, 0, 2, 2>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1477             :   }
    1478             : 
    1479           0 :   return 0;
    1480             : }
    1481             : 
    1482             : int
    1483           0 : BGRA32ToNV21(const uint8_t* aSrcBuffer, int aSrcStride,
    1484             :             uint8_t* aYBuffer, int aYStride,
    1485             :             uint8_t* aVUBuffer, int aVUStride,
    1486             :             int aWidth, int aHeight)
    1487             : {
    1488           0 :   for (int i = 0; i < aHeight - 1; i += 2) {
    1489           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1490           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1491           0 :     uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
    1492           0 :     uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
    1493             : 
    1494           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1495           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer + aSrcStride, yBuffer + aYStride, aWidth);
    1496           0 :     RGBAFamilyToUV_Row<2, 1, 0, 2, 2>(srcBuffer, aSrcStride, uBuffer, vBuffer, aWidth);
    1497             :   }
    1498             : 
    1499           0 :   if (aHeight & 1) {
    1500           0 :     const int i = aHeight - 1;
    1501           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1502           0 :     uint8_t* yBuffer = aYBuffer + aYStride * i;
    1503           0 :     uint8_t* uBuffer = aVUBuffer + aVUStride * (i / 2) + 1;
    1504           0 :     uint8_t* vBuffer = aVUBuffer + aVUStride * (i / 2);
    1505             : 
    1506           0 :     RGBAFamilyToY_Row<2, 1, 0>(srcBuffer, yBuffer, aWidth);
    1507             : 
    1508             :     // Pass 0 as the aSrcStride so we don't sample next row's RGB information.
    1509           0 :     RGBAFamilyToUV_Row<2, 1, 0, 2, 2>(srcBuffer, 0, uBuffer, vBuffer, aWidth);
    1510             :   }
    1511             : 
    1512           0 :   return 0;
    1513             : }
    1514             : 
    1515             : /*
    1516             :  * RGBA/RGB family -> HSV.
    1517             :  * Reference:
    1518             :  * (1) https://en.wikipedia.org/wiki/HSL_and_HSV
    1519             :  * (2) OpenCV implementation:
    1520             :  *     http://docs.opencv.org/3.1.0/de/d25/imgproc_color_conversions.html
    1521             :  */
    1522             : const float EPSILON = 1e-10f;
    1523             : 
    1524             : template<int aRIndex, int aGIndex, int aBIndex, int aSrcStep>
    1525             : int
    1526           0 : RGBFamilyToHSV(const uint8_t* aSrcBuffer, int aSrcStride,
    1527             :                float* aDstBuffer, int aDstStride,
    1528             :                int aWidth, int aHeight)
    1529             : {
    1530           0 :   for (int i = 0; i < aHeight; ++i) {
    1531           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1532           0 :     float* dstBuffer = (float*)((uint8_t*)(aDstBuffer) + aDstStride * i);
    1533             : 
    1534           0 :     for (int j = 0; j < aWidth; ++j) {
    1535           0 :       const float r = (float)(srcBuffer[aRIndex]) / 255.0f;
    1536           0 :       const float g = (float)(srcBuffer[aGIndex]) / 255.0f;
    1537           0 :       const float b = (float)(srcBuffer[aBIndex]) / 255.0f;
    1538           0 :       float& h = dstBuffer[0];
    1539           0 :       float& s = dstBuffer[1];
    1540           0 :       float& v = dstBuffer[2];
    1541             : 
    1542           0 :       float min = r;
    1543           0 :       if (g < min) min = g;
    1544           0 :       if (b < min) min = b;
    1545             : 
    1546           0 :       float max = r;
    1547           0 :       if (g > max) max = g;
    1548           0 :       if (b > max) max = b;
    1549             : 
    1550           0 :       const float diff = max - min + EPSILON; // Prevent dividing by zero.
    1551             : 
    1552             :       // Calculate v.
    1553           0 :       v = max;
    1554             : 
    1555             :       // Calculate s.
    1556           0 :       if (max == 0.0f) {
    1557           0 :         s = 0.0f;
    1558             :       } else {
    1559           0 :         s = diff / v;
    1560             :       }
    1561             : 
    1562             :       // Calculate h.
    1563           0 :       if (max == r) {
    1564           0 :         h = 60.0f * (g - b) / diff;
    1565           0 :       } else if (max == g) {
    1566           0 :         h = 60.0f * (b - r) / diff + 120.0f;
    1567           0 :       } else if (max == b) {
    1568           0 :         h = 60.0f * (r - g) / diff + 240.0f;
    1569             :       }
    1570             : 
    1571           0 :       if (h < 0.0f) {
    1572           0 :         h += 360.0f;
    1573             :       }
    1574             : 
    1575             :       // Step one pixel.
    1576           0 :       srcBuffer += aSrcStep;
    1577           0 :       dstBuffer += 3;
    1578             :     }
    1579             :   }
    1580             : 
    1581           0 :   return 0;
    1582             : }
    1583             : 
    1584             : static const int sector_data[][3]= {{0,3,1}, {2,0,1}, {1,0,3}, {1,2,0}, {3,1,0}, {0,1,2}};
    1585             : 
    1586             : // If the destination is a RGB24 or BGR24, set the aAIndex to be 0, 1 or 2,
    1587             : // so that the r, g or b value will be set to 255 first than to the right value.
    1588             : template<int aRIndex, int aGIndex, int aBIndex, int aAIndex, int aDstStep>
    1589             : int
    1590           0 : HSVToRGBAFamily(const float* aSrcBuffer, int aSrcStride,
    1591             :                 uint8_t* aDstBuffer, int aDstStride,
    1592             :                 int aWidth, int aHeight)
    1593             : {
    1594             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
    1595             :   static_assert(aGIndex == 1, "Wrong G index.");
    1596             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
    1597             :   static_assert(aAIndex == 0 || aAIndex == 1 || aAIndex == 2 || aAIndex == 3, "Wrong A index.");
    1598             : 
    1599           0 :   for (int i = 0; i < aHeight; ++i) {
    1600           0 :     const float* srcBuffer = (const float*)((const uint8_t*)(aSrcBuffer) + aSrcStride * i);
    1601           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
    1602             : 
    1603           0 :     for (int j = 0; j < aWidth; ++j) {
    1604           0 :       const float h = srcBuffer[0];
    1605           0 :       const float s = srcBuffer[1];
    1606           0 :       const float v = srcBuffer[2];
    1607             : 
    1608             :       // Calculate h-prime which should be in range [0, 6). -> h should be in
    1609             :       // range [0, 360).
    1610           0 :       float hPrime = h / 60.0f;
    1611           0 :       if (hPrime < 0.0f)
    1612           0 :           do hPrime += 6.0f; while (hPrime < 0.0f);
    1613           0 :       else if (hPrime >= 6.0f)
    1614           0 :           do hPrime -= 6.0f; while (hPrime >= 6.0f);
    1615           0 :       const int sector = floor(hPrime);
    1616           0 :       const float hMod1 = hPrime - sector;
    1617             : 
    1618             :       float values[4];
    1619           0 :       values[0] = v;
    1620           0 :       values[1] = v * (1.0f - s);
    1621           0 :       values[2] = v * (1.0f - s * hMod1);
    1622           0 :       values[3] = v * (1.0f - s * (1.0f - hMod1));
    1623             : 
    1624           0 :       dstBuffer[aAIndex] = 255;
    1625           0 :       dstBuffer[aRIndex] = Clamp(values[sector_data[sector][0]] * 255.0f);
    1626           0 :       dstBuffer[aGIndex] = Clamp(values[sector_data[sector][1]] * 255.0f);
    1627           0 :       dstBuffer[aBIndex] = Clamp(values[sector_data[sector][2]] * 255.0f);
    1628             : 
    1629             :       // Step one pixel.
    1630           0 :       srcBuffer += 3;
    1631           0 :       dstBuffer += aDstStep;
    1632             :     }
    1633             :   }
    1634             : 
    1635           0 :   return 0;
    1636             : }
    1637             : 
    1638             : int
    1639           0 : RGBA32ToHSV(const uint8_t* aSrcBuffer, int aSrcStride,
    1640             :             float* aDstBuffer, int aDstStride,
    1641             :             int aWidth, int aHeight)
    1642             : {
    1643             :   return RGBFamilyToHSV<0, 1, 2, 4>(aSrcBuffer, aSrcStride,
    1644             :                                     aDstBuffer, aDstStride,
    1645           0 :                                     aWidth, aHeight);
    1646             : }
    1647             : 
    1648             : int
    1649           0 : BGRA32ToHSV(const uint8_t* aSrcBuffer, int aSrcStride,
    1650             :             float* aDstBuffer, int aDstStride,
    1651             :             int aWidth, int aHeight)
    1652             : {
    1653             :   return RGBFamilyToHSV<2, 1, 0, 4>(aSrcBuffer, aSrcStride,
    1654             :                                     aDstBuffer, aDstStride,
    1655           0 :                                     aWidth, aHeight);
    1656             : }
    1657             : 
    1658             : int
    1659           0 : RGB24ToHSV(const uint8_t* aSrcBuffer, int aSrcStride,
    1660             :            float* aDstBuffer, int aDstStride,
    1661             :            int aWidth, int aHeight)
    1662             : {
    1663             :   return RGBFamilyToHSV<0, 1, 2, 3>(aSrcBuffer, aSrcStride,
    1664             :                                     aDstBuffer, aDstStride,
    1665           0 :                                     aWidth, aHeight);
    1666             : }
    1667             : 
    1668             : int
    1669           0 : BGR24ToHSV(const uint8_t* aSrcBuffer, int aSrcStride,
    1670             :            float* aDstBuffer, int aDstStride,
    1671             :            int aWidth, int aHeight)
    1672             : {
    1673             :   return RGBFamilyToHSV<2, 1, 0, 3>(aSrcBuffer, aSrcStride,
    1674             :                                     aDstBuffer, aDstStride,
    1675           0 :                                     aWidth, aHeight);
    1676             : }
    1677             : 
    1678             : int
    1679           0 : HSVToRGBA32(const float* aSrcBuffer, int aSrcStride,
    1680             :             uint8_t* aDstBuffer, int aDstStride,
    1681             :             int aWidth, int aHeight)
    1682             : {
    1683             :   return HSVToRGBAFamily<0, 1, 2, 3, 4>(aSrcBuffer, aSrcStride,
    1684             :                                         aDstBuffer, aDstStride,
    1685           0 :                                         aWidth, aHeight);
    1686             : }
    1687             : 
    1688             : int
    1689           0 : HSVToBGRA32(const float* aSrcBuffer, int aSrcStride,
    1690             :             uint8_t* aDstBuffer, int aDstStride,
    1691             :             int aWidth, int aHeight)
    1692             : {
    1693             :   return HSVToRGBAFamily<2, 1, 0, 3, 4>(aSrcBuffer, aSrcStride,
    1694             :                                         aDstBuffer, aDstStride,
    1695           0 :                                         aWidth, aHeight);
    1696             : }
    1697             : 
    1698             : int
    1699           0 : HSVToRGB24(const float* aSrcBuffer, int aSrcStride,
    1700             :            uint8_t* aDstBuffer, int aDstStride,
    1701             :            int aWidth, int aHeight)
    1702             : {
    1703             :   return HSVToRGBAFamily<0, 1, 2, 0, 3>(aSrcBuffer, aSrcStride,
    1704             :                                         aDstBuffer, aDstStride,
    1705           0 :                                         aWidth, aHeight);
    1706             : }
    1707             : 
    1708             : int
    1709           0 : HSVToBGR24(const float* aSrcBuffer, int aSrcStride,
    1710             :            uint8_t* aDstBuffer, int aDstStride,
    1711             :            int aWidth, int aHeight)
    1712             : {
    1713             :   return HSVToRGBAFamily<2, 1, 0, 0, 3>(aSrcBuffer, aSrcStride,
    1714             :                                         aDstBuffer, aDstStride,
    1715           0 :                                         aWidth, aHeight);
    1716             : }
    1717             : 
    1718             : /*
    1719             :  * RGBA/RGB family -> Lab.
    1720             :  * Reference:
    1721             :  * (1) https://en.wikipedia.org/wiki/SRGB
    1722             :  * (2) https://en.wikipedia.org/wiki/Lab_color_space
    1723             :  * (3) OpenCV implementation:
    1724             :  *     http://docs.opencv.org/3.1.0/de/d25/imgproc_color_conversions.html
    1725             :  */
    1726             : static const float sRGBToXYZ_D65[] = {0.412453f, 0.357580f, 0.180423f,
    1727             :                                       0.212671f, 0.715160f, 0.072169f,
    1728             :                                       0.019334f, 0.119193f, 0.950227f};
    1729             : static const float XYZTosRGB_D65[] = {3.240479f,  -1.53715f,  -0.498535f,
    1730             :                                       -0.969256f, 1.875991f,  0.041556f,
    1731             :                                       0.055648f,  -0.204043f, 1.057311f};
    1732             : static const float whitept_D65[] = {0.950456f, 1.0f, 1.088754f};
    1733             : static const float _magic = std::pow((6.0 / 29.0), 3.0); // should be around 0.008856.
    1734             : static const float _1_3 = 1.0f / 3.0f;
    1735             : static const float _a = std::pow((29.0 / 6.0), 2.0) / 3.0; // should be around 7.787.
    1736             : static const float _b = 16.0f / 116.0f; // should be around 0.1379.
    1737             : 
    1738             : template<int aRIndex, int aGIndex, int aBIndex, int aSrcStep>
    1739             : int
    1740           0 : RGBFamilyToLab(const uint8_t* aSrcBuffer, int aSrcStride,
    1741             :                float* aDstBuffer, int aDstStride,
    1742             :                int aWidth, int aHeight)
    1743             : {
    1744             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
    1745             :   static_assert(aGIndex == 1, "Wrong G index.");
    1746             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
    1747             : 
    1748           0 :   const float C0 = sRGBToXYZ_D65[0] / whitept_D65[0],
    1749           0 :               C1 = sRGBToXYZ_D65[1] / whitept_D65[0],
    1750           0 :               C2 = sRGBToXYZ_D65[2] / whitept_D65[0],
    1751           0 :               C3 = sRGBToXYZ_D65[3] / whitept_D65[1],
    1752           0 :               C4 = sRGBToXYZ_D65[4] / whitept_D65[1],
    1753           0 :               C5 = sRGBToXYZ_D65[5] / whitept_D65[1],
    1754           0 :               C6 = sRGBToXYZ_D65[6] / whitept_D65[2],
    1755           0 :               C7 = sRGBToXYZ_D65[7] / whitept_D65[2],
    1756           0 :               C8 = sRGBToXYZ_D65[8] / whitept_D65[2];
    1757             : 
    1758           0 :   for (int i = 0; i < aHeight; ++i) {
    1759           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1760           0 :     float* dstBuffer = (float*)((uint8_t*)(aDstBuffer) + aDstStride * i);
    1761             : 
    1762           0 :     for (int j = 0; j < aWidth; ++j) {
    1763           0 :       float r = (float)(srcBuffer[aRIndex]) / 255.0f;
    1764           0 :       float g = (float)(srcBuffer[aGIndex]) / 255.0f;
    1765           0 :       float b = (float)(srcBuffer[aBIndex]) / 255.0f;
    1766             : 
    1767             :       // gamma correction of sRGB
    1768           0 :       r = r <= 0.04045f ? r / 12.92f : std::pow((r + 0.055) / 1.055, 2.4);
    1769           0 :       g = g <= 0.04045f ? g / 12.92f : std::pow((g + 0.055) / 1.055, 2.4);
    1770           0 :       b = b <= 0.04045f ? b / 12.92f : std::pow((b + 0.055) / 1.055, 2.4);
    1771             : 
    1772           0 :       const float X = C0 * r + C1 * g + C2 * b;
    1773           0 :       const float Y = C3 * r + C4 * g + C5 * b;
    1774           0 :       const float Z = C6 * r + C7 * g + C8 * b;
    1775             : 
    1776           0 :       const float FX = X > _magic ? std::pow(X, _1_3) : (_a * X + _b);
    1777           0 :       const float FY = Y > _magic ? std::pow(Y, _1_3) : (_a * Y + _b);
    1778           0 :       const float FZ = Z > _magic ? std::pow(Z, _1_3) : (_a * Z + _b);
    1779             : 
    1780           0 :       dstBuffer[0] = 116.0f * FY - 16.0f;
    1781           0 :       dstBuffer[1] = 500.0f * (FX - FY);
    1782           0 :       dstBuffer[2] = 200.0f * (FY - FZ);
    1783             : 
    1784             :       // Step one pixel.
    1785           0 :       srcBuffer += aSrcStep;
    1786           0 :       dstBuffer += 3;
    1787             :     }
    1788             :   }
    1789           0 :   return 0;
    1790             : }
    1791             : 
    1792             : // If the destination is a RGB24 or BGR24, set the aAIndex to be 0, 1 or 2,
    1793             : // so that the r, g or b value will be set to 255 first than to the right value.
    1794             : template<int aRIndex, int aGIndex, int aBIndex, int aAIndex, int aDstStep>
    1795             : int
    1796           0 : LabToRGBAFamily(const float* aSrcBuffer, int aSrcStride,
    1797             :                 uint8_t* aDstBuffer, int aDstStride,
    1798             :                 int aWidth, int aHeight)
    1799             : {
    1800             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
    1801             :   static_assert(aGIndex == 1, "Wrong G index.");
    1802             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
    1803             :   static_assert(aAIndex == 0 || aAIndex == 1 || aAIndex == 2 || aAIndex == 3, "Wrong A index.");
    1804             : 
    1805           0 :   const float C0 = XYZTosRGB_D65[0] * whitept_D65[0],
    1806           0 :               C1 = XYZTosRGB_D65[1] * whitept_D65[1],
    1807           0 :               C2 = XYZTosRGB_D65[2] * whitept_D65[2],
    1808           0 :               C3 = XYZTosRGB_D65[3] * whitept_D65[0],
    1809           0 :               C4 = XYZTosRGB_D65[4] * whitept_D65[1],
    1810           0 :               C5 = XYZTosRGB_D65[5] * whitept_D65[2],
    1811           0 :               C6 = XYZTosRGB_D65[6] * whitept_D65[0],
    1812           0 :               C7 = XYZTosRGB_D65[7] * whitept_D65[1],
    1813           0 :               C8 = XYZTosRGB_D65[8] * whitept_D65[2];
    1814             : 
    1815           0 :   for (int i = 0; i < aHeight; ++i) {
    1816           0 :     const float* srcBuffer = (const float*)((const uint8_t*)(aSrcBuffer) + aSrcStride * i);
    1817           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
    1818             : 
    1819           0 :     for (int j = 0; j < aWidth; ++j) {
    1820           0 :       const float L = srcBuffer[0];
    1821           0 :       const float a = srcBuffer[1];
    1822           0 :       const float b = srcBuffer[2];
    1823             : 
    1824           0 :       const float FY = (L + 16.0f) / 116.0f;
    1825           0 :       const float FX = (a / 500.0f) + FY;
    1826           0 :       const float FZ = FY - (b / 200.0f);
    1827             : 
    1828           0 :       const float X = FX > 6.0f / 29.0f ? std::pow((double)FX, 3.0) : 3.0 * std::pow((6.0 / 29.0), 2.0) * (FX - (4.0 / 29.0));
    1829           0 :       const float Y = FY > 6.0f / 29.0f ? std::pow((double)FY, 3.0) : 3.0 * std::pow((6.0 / 29.0), 2.0) * (FY - (4.0 / 29.0));
    1830           0 :       const float Z = FZ > 6.0f / 29.0f ? std::pow((double)FZ, 3.0) : 3.0 * std::pow((6.0 / 29.0), 2.0) * (FZ - (4.0 / 29.0));
    1831             : 
    1832           0 :       const float r0 = C0 * X + C1 * Y + C2 * Z;
    1833           0 :       const float g0 = C3 * X + C4 * Y + C5 * Z;
    1834           0 :       const float b0 = C6 * X + C7 * Y + C8 * Z;
    1835             : 
    1836             :       // Apply gamma curve of sRGB to the linear rgb values.
    1837           0 :       dstBuffer[aAIndex] = 255;
    1838           0 :       dstBuffer[aRIndex] = Clamp((r0 <= 0.0031308f ? r0 * 12.92f : 1.055 * std::pow((double)r0, 1.0 / 2.4) - 0.055) * 255.0);
    1839           0 :       dstBuffer[aGIndex] = Clamp((g0 <= 0.0031308f ? g0 * 12.92f : 1.055 * std::pow((double)g0, 1.0 / 2.4) - 0.055) * 255.0);
    1840           0 :       dstBuffer[aBIndex] = Clamp((b0 <= 0.0031308f ? b0 * 12.92f : 1.055 * std::pow((double)b0, 1.0 / 2.4) - 0.055) * 255.0);
    1841             : 
    1842             :       // Step one pixel.
    1843           0 :       srcBuffer += 3;
    1844           0 :       dstBuffer += aDstStep;
    1845             :     }
    1846             :   }
    1847           0 :   return 0;
    1848             : }
    1849             : 
    1850             : int
    1851           0 : RGBA32ToLab(const uint8_t* aSrcBuffer, int aSrcStride,
    1852             :             float* aDstBuffer, int aDstStride,
    1853             :             int aWidth, int aHeight)
    1854             : {
    1855             :   return RGBFamilyToLab<0, 1, 2, 4>(aSrcBuffer, aSrcStride,
    1856             :                                     aDstBuffer, aDstStride,
    1857           0 :                                     aWidth, aHeight);
    1858             : }
    1859             : 
    1860             : int
    1861           0 : BGRA32ToLab(const uint8_t* aSrcBuffer, int aSrcStride,
    1862             :             float* aDstBuffer, int aDstStride,
    1863             :             int aWidth, int aHeight)
    1864             : {
    1865             :   return RGBFamilyToLab<2, 1, 0, 4>(aSrcBuffer, aSrcStride,
    1866             :                                     aDstBuffer, aDstStride,
    1867           0 :                                     aWidth, aHeight);
    1868             : }
    1869             : 
    1870             : int
    1871           0 : RGB24ToLab(const uint8_t* aSrcBuffer, int aSrcStride,
    1872             :            float* aDstBuffer, int aDstStride,
    1873             :            int aWidth, int aHeight)
    1874             : {
    1875             :   return RGBFamilyToLab<0, 1, 2, 3>(aSrcBuffer, aSrcStride,
    1876             :                                     aDstBuffer, aDstStride,
    1877           0 :                                     aWidth, aHeight);
    1878             : }
    1879             : 
    1880             : int
    1881           0 : BGR24ToLab(const uint8_t* aSrcBuffer, int aSrcStride,
    1882             :            float* aDstBuffer, int aDstStride,
    1883             :            int aWidth, int aHeight)
    1884             : {
    1885             :   return RGBFamilyToLab<2, 1, 0, 3>(aSrcBuffer, aSrcStride,
    1886             :                                     aDstBuffer, aDstStride,
    1887           0 :                                     aWidth, aHeight);
    1888             : }
    1889             : 
    1890             : int
    1891           0 : LabToRGBA32(const float* aSrcBuffer, int aSrcStride,
    1892             :             uint8_t* aDstBuffer, int aDstStride,
    1893             :             int aWidth, int aHeight)
    1894             : {
    1895             :   return LabToRGBAFamily<0, 1, 2, 3, 4>(aSrcBuffer, aSrcStride,
    1896             :                                         aDstBuffer, aDstStride,
    1897           0 :                                         aWidth, aHeight);
    1898             : }
    1899             : 
    1900             : int
    1901           0 : LabToBGRA32(const float* aSrcBuffer, int aSrcStride,
    1902             :             uint8_t* aDstBuffer, int aDstStride,
    1903             :             int aWidth, int aHeight)
    1904             : {
    1905             :   return LabToRGBAFamily<2, 1, 0, 3, 4>(aSrcBuffer, aSrcStride,
    1906             :                                         aDstBuffer, aDstStride,
    1907           0 :                                         aWidth, aHeight);
    1908             : }
    1909             : 
    1910             : int
    1911           0 : LabToRGB24(const float* aSrcBuffer, int aSrcStride,
    1912             :            uint8_t* aDstBuffer, int aDstStride,
    1913             :            int aWidth, int aHeight)
    1914             : {
    1915             :   return LabToRGBAFamily<0, 1, 2, 0, 3>(aSrcBuffer, aSrcStride,
    1916             :                                         aDstBuffer, aDstStride,
    1917           0 :                                         aWidth, aHeight);
    1918             : }
    1919             : 
    1920             : int
    1921           0 : LabToBGR24(const float* aSrcBuffer, int aSrcStride,
    1922             :            uint8_t* aDstBuffer, int aDstStride,
    1923             :            int aWidth, int aHeight)
    1924             : {
    1925             :   return LabToRGBAFamily<2, 1, 0, 0, 3>(aSrcBuffer, aSrcStride,
    1926             :                                         aDstBuffer, aDstStride,
    1927           0 :                                         aWidth, aHeight);
    1928             : }
    1929             : 
    1930             : /*
    1931             :  * RGBA/RGB family -> Gray8.
    1932             :  * Reference:
    1933             :  * (1) OpenCV implementation:
    1934             :  * http://docs.opencv.org/3.1.0/de/d25/imgproc_color_conversions.html
    1935             :  */
    1936             : template<int aRIndex, int aGIndex, int aBIndex, int aSrcStep>
    1937             : int
    1938           0 : RGBFamilyToGray8(const uint8_t* aSrcBuffer, int aSrcStride,
    1939             :                  uint8_t* aDstBuffer, int aDstStride,
    1940             :                  int aWidth, int aHeight)
    1941             : {
    1942             :   static_assert(aRIndex == 0 || aRIndex == 2, "Wrong R index.");
    1943             :   static_assert(aGIndex == 1, "Wrong G index.");
    1944             :   static_assert(aBIndex == 0 || aBIndex == 2, "Wrong B index.");
    1945             : 
    1946           0 :   for (int i = 0; i < aHeight; ++i) {
    1947           0 :     const uint8_t* srcBuffer = aSrcBuffer + aSrcStride * i;
    1948           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
    1949             : 
    1950           0 :     for (int j = 0; j < aWidth; ++j) {
    1951           0 :       dstBuffer[j] = 0.299 * srcBuffer[aRIndex] +
    1952           0 :                      0.587 * srcBuffer[aGIndex] +
    1953           0 :                      0.114 * srcBuffer[aBIndex];
    1954           0 :       srcBuffer += aSrcStep;
    1955             :     }
    1956             :   }
    1957             : 
    1958           0 :   return 0;
    1959             : }
    1960             : 
    1961             : int
    1962           0 : RGB24ToGray8(const uint8_t* aSrcBuffer, int aSrcStride,
    1963             :              uint8_t* aDstBuffer, int aDstStride,
    1964             :              int aWidth, int aHeight)
    1965             : {
    1966             :   return RGBFamilyToGray8<0, 1, 2, 3>(aSrcBuffer, aSrcStride,
    1967             :                                       aDstBuffer, aDstStride,
    1968           0 :                                       aWidth, aHeight);
    1969             : }
    1970             : 
    1971             : int
    1972           0 : BGR24ToGray8(const uint8_t* aSrcBuffer, int aSrcStride,
    1973             :              uint8_t* aDstBuffer, int aDstStride,
    1974             :              int aWidth, int aHeight)
    1975             : {
    1976             :   return RGBFamilyToGray8<2, 1, 0, 3>(aSrcBuffer, aSrcStride,
    1977             :                                       aDstBuffer, aDstStride,
    1978           0 :                                       aWidth, aHeight);
    1979             : }
    1980             : 
    1981             : int
    1982           0 : RGBA32ToGray8(const uint8_t* aSrcBuffer, int aSrcStride,
    1983             :               uint8_t* aDstBuffer, int aDstStride,
    1984             :               int aWidth, int aHeight)
    1985             : {
    1986             :   return RGBFamilyToGray8<0, 1, 2, 4>(aSrcBuffer, aSrcStride,
    1987             :                                       aDstBuffer, aDstStride,
    1988           0 :                                       aWidth, aHeight);
    1989             : }
    1990             : 
    1991             : int
    1992           0 : BGRA32ToGray8(const uint8_t* aSrcBuffer, int aSrcStride,
    1993             :               uint8_t* aDstBuffer, int aDstStride,
    1994             :               int aWidth, int aHeight)
    1995             : {
    1996             :   return RGBFamilyToGray8<2, 1, 0, 4>(aSrcBuffer, aSrcStride,
    1997             :                                       aDstBuffer, aDstStride,
    1998           0 :                                       aWidth, aHeight);
    1999             : }
    2000             : 
    2001             : /*
    2002             :  * YUV family -> Gray8.
    2003             :  * Reference:
    2004             :  * (1) OpenCV implementation:
    2005             :  * http://docs.opencv.org/3.1.0/de/d25/imgproc_color_conversions.html
    2006             :  */
    2007             : int
    2008           0 : YUVFamilyToGray8(const uint8_t* aSrcYBuffer, int aSrcYStride,
    2009             :                  uint8_t* aDstBuffer, int aDstStride,
    2010             :                  int aWidth, int aHeight)
    2011             : {
    2012           0 :   for (int i = 0; i < aHeight; ++i) {
    2013           0 :     const uint8_t* srcYBuffer = aSrcYBuffer + aSrcYStride * i;
    2014           0 :     uint8_t* dstBuffer = aDstBuffer + aDstStride * i;
    2015             : 
    2016           0 :     memcpy(dstBuffer, srcYBuffer, aDstStride);
    2017             :   }
    2018             : 
    2019           0 :   return 0;
    2020             : }
    2021             : 
    2022             : int
    2023           0 : YUV444PToGray8(const uint8_t* aYBuffer, int aYStride,
    2024             :                const uint8_t*, int,
    2025             :                const uint8_t*, int,
    2026             :                uint8_t* aDstBuffer, int aDstStride,
    2027             :                int aWidth, int aHeight)
    2028             : {
    2029             :   return YUVFamilyToGray8(aYBuffer, aYStride,
    2030             :                           aDstBuffer, aDstStride,
    2031           0 :                           aWidth, aHeight);
    2032             : }
    2033             : 
    2034             : int
    2035           0 : YUV422PToGray8(const uint8_t* aYBuffer, int aYStride,
    2036             :                const uint8_t*, int,
    2037             :                const uint8_t*, int,
    2038             :                uint8_t* aDstBuffer, int aDstStride,
    2039             :                int aWidth, int aHeight)
    2040             : {
    2041             :   return YUVFamilyToGray8(aYBuffer, aYStride,
    2042             :                           aDstBuffer, aDstStride,
    2043           0 :                           aWidth, aHeight);
    2044             : }
    2045             : 
    2046             : int
    2047           0 : YUV420PToGray8(const uint8_t* aYBuffer, int aYStride,
    2048             :                const uint8_t*, int,
    2049             :                const uint8_t*, int,
    2050             :                uint8_t* aDstBuffer, int aDstStride,
    2051             :                int aWidth, int aHeight)
    2052             : {
    2053             :   return YUVFamilyToGray8(aYBuffer, aYStride,
    2054             :                           aDstBuffer, aDstStride,
    2055           0 :                           aWidth, aHeight);
    2056             : }
    2057             : 
    2058             : int
    2059           0 : NV12ToGray8(const uint8_t* aYBuffer, int aYStride,
    2060             :             const uint8_t*, int,
    2061             :             uint8_t* aDstBuffer, int aDstStride,
    2062             :             int aWidth, int aHeight)
    2063             : {
    2064             :   return YUVFamilyToGray8(aYBuffer, aYStride,
    2065             :                           aDstBuffer, aDstStride,
    2066           0 :                           aWidth, aHeight);
    2067             : }
    2068             : 
    2069             : int
    2070           0 : NV21ToGray8(const uint8_t* aYBuffer, int aYStride,
    2071             :             const uint8_t*, int,
    2072             :             uint8_t* aDstBuffer, int aDstStride,
    2073             :             int aWidth, int aHeight)
    2074             : {
    2075             :   return YUVFamilyToGray8(aYBuffer, aYStride,
    2076             :                           aDstBuffer, aDstStride,
    2077           0 :                           aWidth, aHeight);
    2078             : }
    2079             : 
    2080             : } // namespace dom
    2081             : } // namespace mozilla

Generated by: LCOV version 1.13