yuv.h revision 0406ce1417f76f2034833414dcecc9f56253640c
1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2010 Google Inc. All Rights Reserved.
29aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//
30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license
40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source
50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found
60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may
70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree.
89aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// -----------------------------------------------------------------------------
99aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//
10a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// inline YUV<->RGB conversion function
119aea642eefa7a641ab8b89d953251939221d2719Eric Hassold//
121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// More information at: http://en.wikipedia.org/wiki/YCbCr
141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// We use 16bit fixed point operations for RGB->YUV conversion.
181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//
191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// For the Y'CbCr to RGB conversion, the BT.601 specification reads:
201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//   R = 1.164 * (Y-16) + 1.596 * (V-128)
211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//   G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128)
221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//   B = 1.164 * (Y-16)                   + 2.018 * (U-128)
231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// where Y is in the [16,235] range, and U/V in the [16,240] range.
240406ce1417f76f2034833414dcecc9f56253640cVikas Arora// In the table-lookup version (WEBP_YUV_USE_TABLE), the common factor
250406ce1417f76f2034833414dcecc9f56253640cVikas Arora// "1.164 * (Y-16)" can be handled as an offset in the VP8kClip[] table.
260406ce1417f76f2034833414dcecc9f56253640cVikas Arora// So in this case the formulae should be read as:
271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//   R = 1.164 * [Y + 1.371 * (V-128)                  ] - 18.624
281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//   G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624
291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//   B = 1.164 * [Y                   + 1.733 * (U-128)] - 18.624
301e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// once factorized. Here too, 16bit fixed precision is used.
311e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//
329aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Author: Skal (pascal.massimino@gmail.com)
339aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
34a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifndef WEBP_DSP_YUV_H_
35a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define WEBP_DSP_YUV_H_
369aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
37a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../dec/decode_vp8.h"
389aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
390406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Define the following to use the LUT-based code:
400406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define WEBP_YUV_USE_TABLE
410406ce1417f76f2034833414dcecc9f56253640cVikas Arora
421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#if defined(WEBP_EXPERIMENTAL_FEATURES)
431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Do NOT activate this feature for real compression. This is only experimental!
441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace.
451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// This colorspace is close to Rec.601's Y'CbCr model with the notable
461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// difference of allowing larger range for luma/chroma.
471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its
481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// #define USE_YUVj
501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif
5188fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora
52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// YUV -> RGB conversion
54a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
559aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#if defined(__cplusplus) || defined(c_plusplus)
569aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern "C" {
579aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#endif
589aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
599aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldenum { YUV_FIX = 16,                // fixed-point precision
600406ce1417f76f2034833414dcecc9f56253640cVikas Arora       YUV_HALF = 1 << (YUV_FIX - 1),
610406ce1417f76f2034833414dcecc9f56253640cVikas Arora       YUV_MASK = (256 << YUV_FIX) - 1,
629aea642eefa7a641ab8b89d953251939221d2719Eric Hassold       YUV_RANGE_MIN = -227,        // min value of r/g/b output
639aea642eefa7a641ab8b89d953251939221d2719Eric Hassold       YUV_RANGE_MAX = 256 + 226    // max value of r/g/b output
649aea642eefa7a641ab8b89d953251939221d2719Eric Hassold};
650406ce1417f76f2034833414dcecc9f56253640cVikas Arora
660406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef WEBP_YUV_USE_TABLE
670406ce1417f76f2034833414dcecc9f56253640cVikas Arora
689aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern int16_t VP8kVToR[256], VP8kUToB[256];
699aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern int32_t VP8kVToG[256], VP8kUToG[256];
709aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
71466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroraextern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN];
729aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
74a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                    uint8_t* const rgb) {
759aea642eefa7a641ab8b89d953251939221d2719Eric Hassold  const int r_off = VP8kVToR[v];
769aea642eefa7a641ab8b89d953251939221d2719Eric Hassold  const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
779aea642eefa7a641ab8b89d953251939221d2719Eric Hassold  const int b_off = VP8kUToB[u];
789aea642eefa7a641ab8b89d953251939221d2719Eric Hassold  rgb[0] = VP8kClip[y + r_off - YUV_RANGE_MIN];
799aea642eefa7a641ab8b89d953251939221d2719Eric Hassold  rgb[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
809aea642eefa7a641ab8b89d953251939221d2719Eric Hassold  rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN];
819aea642eefa7a641ab8b89d953251939221d2719Eric Hassold}
829aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
830406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
840406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                    uint8_t* const bgr) {
850406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int r_off = VP8kVToR[v];
860406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
870406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int b_off = VP8kUToB[u];
880406ce1417f76f2034833414dcecc9f56253640cVikas Arora  bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN];
890406ce1417f76f2034833414dcecc9f56253640cVikas Arora  bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
900406ce1417f76f2034833414dcecc9f56253640cVikas Arora  bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN];
910406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
920406ce1417f76f2034833414dcecc9f56253640cVikas Arora
93a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
94a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                       uint8_t* const rgb) {
95466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  const int r_off = VP8kVToR[v];
96466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
97466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  const int b_off = VP8kUToB[u];
981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const uint8_t rg = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) |
991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora                      (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5));
1001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const uint8_t gb = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) |
1011e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora                      (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3));
1021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef WEBP_SWAP_16BIT_CSP
1031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  rgb[0] = gb;
1041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  rgb[1] = rg;
10588fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora#else
1061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  rgb[0] = rg;
1071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  rgb[1] = gb;
10888fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora#endif
109466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
110466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
112466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora                                         uint8_t* const argb) {
113466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  const int r_off = VP8kVToR[v];
114466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
115466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  const int b_off = VP8kUToB[u];
1161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const uint8_t rg = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) |
1171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora                      VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]);
1181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const uint8_t ba = (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4) | 0x0f;
1191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef WEBP_SWAP_16BIT_CSP
1201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  argb[0] = ba;
1211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  argb[1] = rg;
12288fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora#else
1231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  argb[0] = rg;
1241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  argb[1] = ba;
12588fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora#endif
1269aea642eefa7a641ab8b89d953251939221d2719Eric Hassold}
1279aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
1280406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else   // Table-free version (slower on x86)
1290406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1300406ce1417f76f2034833414dcecc9f56253640cVikas Arora// These constants are 16b fixed-point version of ITU-R BT.601 constants
1310406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kYScale 76309      // 1.164 = 255 / 219
1320406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kVToR   104597     // 1.596 = 255 / 112 * 0.701
1330406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kUToG   25674      // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587
1340406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kVToG   53278      // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587
1350406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kUToB   132201     // 2.018 = 255 / 112 * 0.886
1360406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kRCst (-kYScale * 16 - kVToR * 128 + YUV_HALF)
1370406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kGCst (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF)
1380406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kBCst (-kYScale * 16 - kUToB * 128 + YUV_HALF)
1390406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1400406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE uint8_t VP8Clip8(int v) {
1410406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> YUV_FIX)
1420406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                : (v < 0) ? 0u : 255u;
1430406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1440406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1450406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE uint8_t VP8ClipN(int v, int N) {  // clip to N bits
1460406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> (YUV_FIX + (8 - N)))
1470406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                : (v < 0) ? 0u : (255u >> (8 - N));
1480406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1490406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1500406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE int VP8YUVToR(int y, int v) {
1510406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return kYScale * y + kVToR * v + kRCst;
1520406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1530406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1540406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE int VP8YUVToG(int y, int u, int v) {
1550406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return kYScale * y - kUToG * u - kVToG * v + kGCst;
1560406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1570406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1580406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE int VP8YUVToB(int y, int u) {
1590406ce1417f76f2034833414dcecc9f56253640cVikas Arora  return kYScale * y  + kUToB * u + kBCst;
1600406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1610406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1620406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
1630406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                    uint8_t* const rgb) {
1640406ce1417f76f2034833414dcecc9f56253640cVikas Arora  rgb[0] = VP8Clip8(VP8YUVToR(y, v));
1650406ce1417f76f2034833414dcecc9f56253640cVikas Arora  rgb[1] = VP8Clip8(VP8YUVToG(y, u, v));
1660406ce1417f76f2034833414dcecc9f56253640cVikas Arora  rgb[2] = VP8Clip8(VP8YUVToB(y, u));
1670406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1680406ce1417f76f2034833414dcecc9f56253640cVikas Arora
169a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
170a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                    uint8_t* const bgr) {
1710406ce1417f76f2034833414dcecc9f56253640cVikas Arora  bgr[0] = VP8Clip8(VP8YUVToB(y, u));
1720406ce1417f76f2034833414dcecc9f56253640cVikas Arora  bgr[1] = VP8Clip8(VP8YUVToG(y, u, v));
1730406ce1417f76f2034833414dcecc9f56253640cVikas Arora  bgr[2] = VP8Clip8(VP8YUVToR(y, v));
1740406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1750406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1760406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
1770406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                       uint8_t* const rgb) {
1780406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int r = VP8Clip8(VP8YUVToR(y, u));
1790406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int g = VP8ClipN(VP8YUVToG(y, u, v), 6);
1800406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int b = VP8ClipN(VP8YUVToB(y, v), 5);
1810406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint8_t rg = (r & 0xf8) | (g >> 3);
1820406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint8_t gb = (g << 5) | b;
1830406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef WEBP_SWAP_16BIT_CSP
1840406ce1417f76f2034833414dcecc9f56253640cVikas Arora  rgb[0] = gb;
1850406ce1417f76f2034833414dcecc9f56253640cVikas Arora  rgb[1] = rg;
1860406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else
1870406ce1417f76f2034833414dcecc9f56253640cVikas Arora  rgb[0] = rg;
1880406ce1417f76f2034833414dcecc9f56253640cVikas Arora  rgb[1] = gb;
1890406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif
1900406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
1910406ce1417f76f2034833414dcecc9f56253640cVikas Arora
1920406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
1930406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                         uint8_t* const argb) {
1940406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int r = VP8Clip8(VP8YUVToR(y, u));
1950406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int g = VP8ClipN(VP8YUVToG(y, u, v), 4);
1960406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const int b = VP8Clip8(VP8YUVToB(y, v));
1970406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint8_t rg = (r & 0xf0) | g;
1980406ce1417f76f2034833414dcecc9f56253640cVikas Arora  const uint8_t ba = b | 0x0f;   // overwrite the lower 4 bits
1990406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef WEBP_SWAP_16BIT_CSP
2000406ce1417f76f2034833414dcecc9f56253640cVikas Arora  argb[0] = ba;
2010406ce1417f76f2034833414dcecc9f56253640cVikas Arora  argb[1] = rg;
2020406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else
2030406ce1417f76f2034833414dcecc9f56253640cVikas Arora  argb[0] = rg;
2040406ce1417f76f2034833414dcecc9f56253640cVikas Arora  argb[1] = ba;
2050406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif
2060406ce1417f76f2034833414dcecc9f56253640cVikas Arora}
2070406ce1417f76f2034833414dcecc9f56253640cVikas Arora
2080406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif  // WEBP_YUV_USE_TABLE
2090406ce1417f76f2034833414dcecc9f56253640cVikas Arora
2100406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
2110406ce1417f76f2034833414dcecc9f56253640cVikas Arora                                     uint8_t* const argb) {
2120406ce1417f76f2034833414dcecc9f56253640cVikas Arora  argb[0] = 0xff;
2130406ce1417f76f2034833414dcecc9f56253640cVikas Arora  VP8YuvToRgb(y, u, v, argb + 1);
2149aea642eefa7a641ab8b89d953251939221d2719Eric Hassold}
2159aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
216a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v,
217a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                     uint8_t* const bgra) {
2189aea642eefa7a641ab8b89d953251939221d2719Eric Hassold  VP8YuvToBgr(y, u, v, bgra);
2199aea642eefa7a641ab8b89d953251939221d2719Eric Hassold  bgra[3] = 0xff;
2209aea642eefa7a641ab8b89d953251939221d2719Eric Hassold}
2219aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
222a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v,
223a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                                     uint8_t* const rgba) {
224466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  VP8YuvToRgb(y, u, v, rgba);
225466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  rgba[3] = 0xff;
226466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
227466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
2289aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Must be called before everything, to initialize the tables.
22903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Aroravoid VP8YUVInit(void);
2309aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
231a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
232a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// RGB -> YUV conversion
233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int VP8ClipUV(int v) {
2351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2);
2361e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255;
237a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
2391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifndef USE_YUVj
2401e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
241a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int VP8RGBToY(int r, int g, int b) {
242a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX);
243a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  const int luma = 16839 * r + 33059 * g + 6420 * b;
244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return (luma + kRound) >> YUV_FIX;  // no need to clip
245a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
246a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int VP8RGBToU(int r, int g, int b) {
2481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const int u = -9719 * r - 19081 * g + 28800 * b;
2491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return VP8ClipUV(u);
2501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora}
2511e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
2521e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE int VP8RGBToV(int r, int g, int b) {
2531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const int v = +28800 * r - 24116 * g - 4684 * b;
2541e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return VP8ClipUV(v);
2551e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora}
2561e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
2571e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#else
2581e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
2591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// This JPEG-YUV colorspace, only for comparison!
2601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// These are also 16-bit precision coefficients from Rec.601, but with full
2611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// [0..255] output range.
2621e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE int VP8RGBToY(int r, int g, int b) {
2631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const int kRound = (1 << (YUV_FIX - 1));
2641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const int luma = 19595 * r + 38470 * g + 7471 * b;
2651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return (luma + kRound) >> YUV_FIX;  // no need to clip
2661e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora}
2671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
2681e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE int VP8RGBToU(int r, int g, int b) {
2691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const int u = -11058 * r - 21710 * g + 32768 * b;
2701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return VP8ClipUV(u);
271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int VP8RGBToV(int r, int g, int b) {
2741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  const int v = 32768 * r - 27439 * g - 5329 * b;
2751e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora  return VP8ClipUV(v);
276a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
2781e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif    // USE_YUVj
2791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora
2809aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#if defined(__cplusplus) || defined(c_plusplus)
2819aea642eefa7a641ab8b89d953251939221d2719Eric Hassold}    // extern "C"
2829aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#endif
2839aea642eefa7a641ab8b89d953251939221d2719Eric Hassold
284a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif  /* WEBP_DSP_YUV_H_ */
285