home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Kasumi / source / pixel.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  23.7 KB  |  668 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Graphics support library
  3. //    Copyright (C) 1998-2007 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <vd2/system/math.h>
  20. #include <vd2/system/halffloat.h>
  21. #include <vd2/Kasumi/pixmap.h>
  22. #include <vd2/Kasumi/pixel.h>
  23.  
  24. uint32 VDPixmapSample(const VDPixmap& px, sint32 x, sint32 y) {
  25.     if (x >= px.w)
  26.         x = px.w - 1;
  27.     if (y >= px.h)
  28.         y = px.h - 1;
  29.     if (x < 0)
  30.         x = 0;
  31.     if (y < 0)
  32.         y = 0;
  33.  
  34.     switch(px.format) {
  35.     case nsVDPixmap::kPixFormat_Pal1:
  36.         {
  37.             uint8 idx = ((const uint8 *)px.data + px.pitch*y)[x >> 3];
  38.  
  39.             return px.palette[(idx >> (7 - (x & 7))) & 1];
  40.         }
  41.  
  42.     case nsVDPixmap::kPixFormat_Pal2:
  43.         {
  44.             uint8 idx = ((const uint8 *)px.data + px.pitch*y)[x >> 2];
  45.  
  46.             return px.palette[(idx >> (6 - (x & 3)*2)) & 3];
  47.         }
  48.  
  49.     case nsVDPixmap::kPixFormat_Pal4:
  50.         {
  51.             uint8 idx = ((const uint8 *)px.data + px.pitch*y)[x >> 1];
  52.  
  53.             if (!(x & 1))
  54.                 idx >>= 4;
  55.  
  56.             return px.palette[idx & 15];
  57.         }
  58.  
  59.     case nsVDPixmap::kPixFormat_Pal8:
  60.         {
  61.             uint8 idx = ((const uint8 *)px.data + px.pitch*y)[x];
  62.  
  63.             return px.palette[idx];
  64.         }
  65.  
  66.     case nsVDPixmap::kPixFormat_XRGB1555:
  67.         {
  68.             uint16 c = ((const uint16 *)((const uint8 *)px.data + px.pitch*y))[x];
  69.             uint32 r = c & 0x7c00;
  70.             uint32 g = c & 0x03e0;
  71.             uint32 b = c & 0x001f;
  72.             uint32 rgb = (r << 9) + (g << 6) + (b << 3);
  73.  
  74.             return rgb + ((rgb >> 5) & 0x070707);
  75.         }
  76.         break;
  77.  
  78.     case nsVDPixmap::kPixFormat_RGB565:
  79.         {
  80.             uint16 c = ((const uint16 *)((const uint8 *)px.data + px.pitch*y))[x];
  81.             uint32 r = c & 0xf800;
  82.             uint32 g = c & 0x07e0;
  83.             uint32 b = c & 0x001f;
  84.             uint32 rb = (r << 8) + (b << 3);
  85.  
  86.             return rb + ((rb >> 5) & 0x070007) + (g << 5) + ((g >> 1) & 0x0300);
  87.         }
  88.         break;
  89.  
  90.     case nsVDPixmap::kPixFormat_RGB888:
  91.         {
  92.             const uint8 *src = (const uint8 *)px.data + px.pitch*y + 3*x;
  93.             uint32 b = src[0];
  94.             uint32 g = src[1];
  95.             uint32 r = src[2];
  96.  
  97.             return (r << 16) + (g << 8) + b;
  98.         }
  99.         break;
  100.  
  101.     case nsVDPixmap::kPixFormat_XRGB8888:
  102.         return ((const uint32 *)((const uint8 *)px.data + px.pitch*y))[x];
  103.  
  104.     case nsVDPixmap::kPixFormat_Y8:
  105.         {
  106.             uint8 luma = ((const uint8 *)px.data + px.pitch*y)[x];
  107.  
  108.             return ((luma - 16)*255/219) * 0x010101;
  109.         }
  110.         break;
  111.  
  112.     case nsVDPixmap::kPixFormat_YUV444_Planar:
  113.         return VDConvertYCbCrToRGB(VDPixmapSample8(px.data, px.pitch, x, y), VDPixmapSample8(px.data2, px.pitch2, x, y), VDPixmapSample8(px.data3, px.pitch3, x, y));
  114.  
  115.     case nsVDPixmap::kPixFormat_YUV422_Planar:
  116.         {
  117.             sint32 u = (x << 7) + 128;
  118.             sint32 v = (y << 8);
  119.             uint32 w2 = px.w >> 1;
  120.             uint32 h2 = px.h;
  121.  
  122.             return VDConvertYCbCrToRGB(
  123.                         VDPixmapSample8(px.data, px.pitch, x, y),
  124.                         VDPixmapInterpolateSample8(px.data2, px.pitch2, w2, h2, u, v),
  125.                         VDPixmapInterpolateSample8(px.data3, px.pitch3, w2, h2, u, v));
  126.         }
  127.  
  128.     case nsVDPixmap::kPixFormat_YUV420_Planar:
  129.         {
  130.             sint32 u = (x << 7) + 128;
  131.             sint32 v = (y << 7);
  132.             uint32 w2 = px.w >> 1;
  133.             uint32 h2 = px.h >> 1;
  134.  
  135.             return VDConvertYCbCrToRGB(
  136.                         VDPixmapSample8(px.data, px.pitch, x, y),
  137.                         VDPixmapInterpolateSample8(px.data2, px.pitch2, w2, h2, u, v),
  138.                         VDPixmapInterpolateSample8(px.data3, px.pitch3, w2, h2, u, v));
  139.         }
  140.  
  141.     case nsVDPixmap::kPixFormat_YUV411_Planar:
  142.         {
  143.             sint32 u = (x << 6) + 128;
  144.             sint32 v = (y << 8);
  145.             uint32 w2 = px.w >> 2;
  146.             uint32 h2 = px.h;
  147.  
  148.             return VDConvertYCbCrToRGB(
  149.                         VDPixmapSample8(px.data, px.pitch, x, y),
  150.                         VDPixmapInterpolateSample8(px.data2, px.pitch2, w2, h2, u, v),
  151.                         VDPixmapInterpolateSample8(px.data3, px.pitch3, w2, h2, u, v));
  152.         }
  153.  
  154.     case nsVDPixmap::kPixFormat_YUV410_Planar:
  155.         {
  156.             sint32 u = (x << 6) + 128;
  157.             sint32 v = (y << 6);
  158.             uint32 w2 = px.w >> 2;
  159.             uint32 h2 = px.h >> 2;
  160.  
  161.             return VDConvertYCbCrToRGB(
  162.                         VDPixmapSample8(px.data, px.pitch, x, y),
  163.                         VDPixmapInterpolateSample8(px.data2, px.pitch2, w2, h2, u, v),
  164.                         VDPixmapInterpolateSample8(px.data3, px.pitch3, w2, h2, u, v));
  165.         }
  166.  
  167.     default:
  168.         return VDPixmapInterpolateSampleRGB24(px, (x << 8) + 128, (y << 8) + 128);
  169.     }
  170. }
  171.  
  172. uint8 VDPixmapInterpolateSample8(const void *data, ptrdiff_t pitch, uint32 w, uint32 h, sint32 x_256, sint32 y_256) {
  173.     // bias coordinates to integer
  174.     x_256 -= 128;
  175.     y_256 -= 128;
  176.  
  177.     // clamp coordinates
  178.     x_256 &= ~(x_256 >> 31);
  179.     y_256 &= ~(y_256 >> 31);
  180.  
  181.     uint32 w_256 = (w - 1) << 8;
  182.     uint32 h_256 = (h - 1) << 8;
  183.     x_256 ^= (x_256 ^ w_256) & ((x_256 - w_256) >> 31);
  184.     y_256 ^= (y_256 ^ h_256) & ((y_256 - h_256) >> 31);
  185.  
  186.     const uint8 *row0 = (const uint8 *)data + pitch * (y_256 >> 8);
  187.     const uint8 *row1 = row0;
  188.  
  189.     if ((uint32)y_256 < h_256)
  190.         row1 += pitch;
  191.  
  192.     ptrdiff_t xstep = (uint32)x_256 < w_256 ? 1 : 0;
  193.     sint32 xoffset = x_256 & 255;
  194.     sint32 yoffset = y_256 & 255;
  195.     sint32 p00 = row0[0];
  196.     sint32 p10 = row0[xstep];
  197.     sint32 p01 = row1[0];
  198.     sint32 p11 = row1[xstep];
  199.     sint32 p0 = (p00 << 8) + (p10 - p00)*xoffset;
  200.     sint32 p1 = (p01 << 8) + (p11 - p01)*xoffset;
  201.     sint32 p = ((p0 << 8) + (p1 - p0)*yoffset + 0x8000) >> 16;
  202.  
  203.     return (uint8)p;
  204. }
  205.  
  206. uint32 VDPixmapInterpolateSample8To24(const void *data, ptrdiff_t pitch, uint32 w, uint32 h, sint32 x_256, sint32 y_256) {
  207.     // bias coordinates to integer
  208.     x_256 -= 128;
  209.     y_256 -= 128;
  210.  
  211.     // clamp coordinates
  212.     x_256 &= ~(x_256 >> 31);
  213.     y_256 &= ~(y_256 >> 31);
  214.  
  215.     uint32 w_256 = (w - 1) << 8;
  216.     uint32 h_256 = (h - 1) << 8;
  217.     x_256 ^= (x_256 ^ w_256) & ((x_256 - w_256) >> 31);
  218.     y_256 ^= (y_256 ^ h_256) & ((y_256 - h_256) >> 31);
  219.  
  220.     const uint8 *row0 = (const uint8 *)data + pitch * (y_256 >> 8) + (x_256 >> 8);
  221.     const uint8 *row1 = row0;
  222.  
  223.     if ((uint32)y_256 < h_256)
  224.         row1 += pitch;
  225.  
  226.     ptrdiff_t xstep = (uint32)x_256 < w_256 ? 1 : 0;
  227.     sint32 xoffset = x_256 & 255;
  228.     sint32 yoffset = y_256 & 255;
  229.     sint32 p00 = row0[0];
  230.     sint32 p10 = row0[xstep];
  231.     sint32 p01 = row1[0];
  232.     sint32 p11 = row1[xstep];
  233.     sint32 p0 = (p00 << 8) + (p10 - p00)*xoffset;
  234.     sint32 p1 = (p01 << 8) + (p11 - p01)*xoffset;
  235.     sint32 p = (p0 << 8) + (p1 - p0)*yoffset;
  236.  
  237.     return p;
  238. }
  239.  
  240. uint32 VDPixmapInterpolateSample8x2To24(const void *data, ptrdiff_t pitch, uint32 w, uint32 h, sint32 x_256, sint32 y_256) {
  241.     // bias coordinates to integer
  242.     x_256 -= 128;
  243.     y_256 -= 128;
  244.  
  245.     // clamp coordinates
  246.     x_256 &= ~(x_256 >> 31);
  247.     y_256 &= ~(y_256 >> 31);
  248.  
  249.     uint32 w_256 = (w - 1) << 8;
  250.     uint32 h_256 = (h - 1) << 8;
  251.     x_256 ^= (x_256 ^ w_256) & ((x_256 - w_256) >> 31);
  252.     y_256 ^= (y_256 ^ h_256) & ((y_256 - h_256) >> 31);
  253.  
  254.     const uint8 *row0 = (const uint8 *)data + pitch * (y_256 >> 8) + (x_256 >> 8)*2;
  255.     const uint8 *row1 = row0;
  256.  
  257.     if ((uint32)y_256 < h_256)
  258.         row1 += pitch;
  259.  
  260.     ptrdiff_t xstep = (uint32)x_256 < w_256 ? 2 : 0;
  261.     sint32 xoffset = x_256 & 255;
  262.     sint32 yoffset = y_256 & 255;
  263.     sint32 p00 = row0[0];
  264.     sint32 p10 = row0[xstep];
  265.     sint32 p01 = row1[0];
  266.     sint32 p11 = row1[xstep];
  267.     sint32 p0 = (p00 << 8) + (p10 - p00)*xoffset;
  268.     sint32 p1 = (p01 << 8) + (p11 - p01)*xoffset;
  269.     sint32 p = (p0 << 8) + (p1 - p0)*yoffset;
  270.  
  271.     return p;
  272. }
  273.  
  274. uint32 VDPixmapInterpolateSample8x4To24(const void *data, ptrdiff_t pitch, uint32 w, uint32 h, sint32 x_256, sint32 y_256) {
  275.     // bias coordinates to integer
  276.     x_256 -= 128;
  277.     y_256 -= 128;
  278.  
  279.     // clamp coordinates
  280.     x_256 &= ~(x_256 >> 31);
  281.     y_256 &= ~(y_256 >> 31);
  282.  
  283.     uint32 w_256 = (w - 1) << 8;
  284.     uint32 h_256 = (h - 1) << 8;
  285.     x_256 ^= (x_256 ^ w_256) & ((x_256 - w_256) >> 31);
  286.     y_256 ^= (y_256 ^ h_256) & ((y_256 - h_256) >> 31);
  287.  
  288.     const uint8 *row0 = (const uint8 *)data + pitch * (y_256 >> 8) + (x_256 >> 8)*4;
  289.     const uint8 *row1 = row0;
  290.  
  291.     if ((uint32)y_256 < h_256)
  292.         row1 += pitch;
  293.  
  294.     ptrdiff_t xstep = (uint32)x_256 < w_256 ? 4 : 0;
  295.     sint32 xoffset = x_256 & 255;
  296.     sint32 yoffset = y_256 & 255;
  297.     sint32 p00 = row0[0];
  298.     sint32 p10 = row0[xstep];
  299.     sint32 p01 = row1[0];
  300.     sint32 p11 = row1[xstep];
  301.     sint32 p0 = (p00 << 8) + (p10 - p00)*xoffset;
  302.     sint32 p1 = (p01 << 8) + (p11 - p01)*xoffset;
  303.     sint32 p = (p0 << 8) + (p1 - p0)*yoffset;
  304.  
  305.     return p;
  306. }
  307.  
  308. float VDPixmapInterpolateSample16F(const void *data, ptrdiff_t pitch, uint32 w, uint32 h, sint32 x_256, sint32 y_256) {
  309.     // bias coordinates to integer
  310.     x_256 -= 128;
  311.     y_256 -= 128;
  312.  
  313.     // clamp coordinates
  314.     x_256 &= ~(x_256 >> 31);
  315.     y_256 &= ~(y_256 >> 31);
  316.  
  317.     uint32 w_256 = (w - 1) << 8;
  318.     uint32 h_256 = (h - 1) << 8;
  319.     x_256 ^= (x_256 ^ w_256) & ((x_256 - w_256) >> 31);
  320.     y_256 ^= (y_256 ^ h_256) & ((y_256 - h_256) >> 31);
  321.  
  322.     const uint16 *row0 = (const uint16 *)((const uint8 *)data + pitch * (y_256 >> 8) + (x_256 >> 8)*2);
  323.     const uint16 *row1 = row0;
  324.  
  325.     if ((uint32)y_256 < h_256)
  326.         row1 = (const uint16 *)((const char *)row1 + pitch);
  327.  
  328.     ptrdiff_t xstep = (uint32)x_256 < w_256 ? 1 : 0;
  329.     float xoffset = (float)(x_256 & 255) * (1.0f / 255.0f);
  330.     float yoffset = (float)(y_256 & 255) * (1.0f / 255.0f);
  331.  
  332.     float p00;
  333.     float p10;
  334.     float p01;
  335.     float p11;
  336.     VDConvertHalfToFloat(row0[0], &p00);
  337.     VDConvertHalfToFloat(row0[xstep], &p10);
  338.     VDConvertHalfToFloat(row1[0], &p01);
  339.     VDConvertHalfToFloat(row1[xstep], &p11);
  340.  
  341.     float p0 = p00 + (p10 - p00)*xoffset;
  342.     float p1 = p01 + (p11 - p01)*xoffset;
  343.  
  344.     return p0 + (p1 - p0)*yoffset;
  345. }
  346.  
  347. namespace {
  348.     uint32 Lerp8888(uint32 p0, uint32 p1, uint32 p2, uint32 p3, uint32 xf, uint32 yf) {
  349.         uint32 rb0 = p0 & 0x00ff00ff;
  350.         uint32 ag0 = p0 & 0xff00ff00;
  351.         uint32 rb1 = p1 & 0x00ff00ff;
  352.         uint32 ag1 = p1 & 0xff00ff00;
  353.         uint32 rb2 = p2 & 0x00ff00ff;
  354.         uint32 ag2 = p2 & 0xff00ff00;
  355.         uint32 rb3 = p3 & 0x00ff00ff;
  356.         uint32 ag3 = p3 & 0xff00ff00;
  357.  
  358.         uint32 rbt = (rb0 + (((       rb1 - rb0       )*xf + 0x00800080) >> 8)) & 0x00ff00ff;
  359.         uint32 agt = (ag0 + ((((ag1 >> 8) - (ag0 >> 8))*xf + 0x00800080)     )) & 0xff00ff00;
  360.         uint32 rbb = (rb2 + (((       rb3 - rb2       )*xf + 0x00800080) >> 8)) & 0x00ff00ff;
  361.         uint32 agb = (ag2 + ((((ag3 >> 8) - (ag2 >> 8))*xf + 0x00800080)     )) & 0xff00ff00;
  362.         uint32 rb  = (rbt + (((       rbb - rbt       )*yf + 0x00800080) >> 8)) & 0x00ff00ff;
  363.         uint32 ag  = (agt + ((((agb >> 8) - (agt >> 8))*yf + 0x00800080)     )) & 0xff00ff00;
  364.  
  365.         return rb + ag;
  366.     }
  367.  
  368.     uint32 InterpPlanarY8(const VDPixmap& px, sint32 x1, sint32 y1) {
  369.         sint32 y = VDPixmapInterpolateSample8To24(px.data, px.pitch, px.w, px.h, x1, y1);
  370.  
  371.         return VDClampedRoundFixedToUint8Fast((float)(y-0x100000) * (1.1643836f/65536.0f/255.0f))*0x010101;
  372.     }
  373.  
  374.     uint32 InterpPlanarYCC888(const VDPixmap& px, sint32 x1, sint32 y1, sint32 x23, sint32 y23, uint32 w23, uint32 h23) {
  375.         float y  = (float)(sint32)VDPixmapInterpolateSample8To24(px.data, px.pitch, px.w, px.h, x1, y1);
  376.         float cb = (float)(sint32)VDPixmapInterpolateSample8To24(px.data2, px.pitch2, w23, h23, x23, y23);
  377.         float cr = (float)(sint32)VDPixmapInterpolateSample8To24(px.data3, px.pitch3, w23, h23, x23, y23);
  378.  
  379.         //    !   1.1643836  - 5.599D-17    1.5960268  - 222.92157 !
  380.         //    !   1.1643836  - 0.3917623  - 0.8129676    135.57529 !
  381.         //    !   1.1643836    2.0172321  - 1.110D-16  - 276.83585 !
  382.         uint32 ir = VDClampedRoundFixedToUint8Fast((1.1643836f/65536.0f/255.0f)*y + (1.5960268f/65536.0f/255.0f)*cr - (222.92157f / 255.0f));
  383.         uint32 ig = VDClampedRoundFixedToUint8Fast((1.1643836f/65536.0f/255.0f)*y - (0.3917623f/65536.0f/255.0f)*cb - (0.8129676f/65536.0f/255.0f)*cr + (135.57529f / 255.0f));
  384.         uint32 ib = VDClampedRoundFixedToUint8Fast((1.1643836f/65536.0f/255.0f)*y + (2.0172321f/65536.0f/255.0f)*cb - (276.83585f / 255.0f));
  385.  
  386.         return (ir << 16) + (ig << 8) + ib;
  387.     }
  388.  
  389.     uint32 ConvertYCC72ToRGB24(sint32 iy, sint32 icb, sint32 icr) {
  390.         float y  = (float)iy;
  391.         float cb = (float)icb;
  392.         float cr = (float)icr;
  393.  
  394.         //    !   1.1643836  - 5.599D-17    1.5960268  - 222.92157 !
  395.         //    !   1.1643836  - 0.3917623  - 0.8129676    135.57529 !
  396.         //    !   1.1643836    2.0172321  - 1.110D-16  - 276.83585 !
  397.         uint32 ir = VDClampedRoundFixedToUint8Fast((1.1643836f/65536.0f/255.0f)*y + (1.5960268f/65536.0f/255.0f)*cr - (222.92157f / 255.0f));
  398.         uint32 ig = VDClampedRoundFixedToUint8Fast((1.1643836f/65536.0f/255.0f)*y - (0.3917623f/65536.0f/255.0f)*cb - (0.8129676f/65536.0f/255.0f)*cr + (135.57529f / 255.0f));
  399.         uint32 ib = VDClampedRoundFixedToUint8Fast((1.1643836f/65536.0f/255.0f)*y + (2.0172321f/65536.0f/255.0f)*cb - (276.83585f / 255.0f));
  400.  
  401.         return (ir << 16) + (ig << 8) + ib;
  402.     }
  403.  
  404.     uint32 ConvertYCC72ToRGB24_709(sint32 iy, sint32 icb, sint32 icr) {
  405.         float y  = (float)iy;
  406.         float cb = (float)icb;
  407.         float cr = (float)icr;
  408.  
  409.         //    !   1.1643836  - 2.932D-17    1.7927411  - 248.10099 !
  410.         //    !   1.1643836  - 0.2132486  - 0.5329093    76.87808  !
  411.         //    !   1.1643836    2.1124018  - 5.551D-17  - 289.01757 !
  412.         uint32 ir = VDClampedRoundFixedToUint8Fast((1.1643836f/65536.0f/255.0f)*y + (1.7927411f/65536.0f/255.0f)*cr - (248.10099f / 255.0f));
  413.         uint32 ig = VDClampedRoundFixedToUint8Fast((1.1643836f/65536.0f/255.0f)*y - (0.2132486f/65536.0f/255.0f)*cb - (0.5329093f/65536.0f/255.0f)*cr + (76.87808f / 255.0f));
  414.         uint32 ib = VDClampedRoundFixedToUint8Fast((1.1643836f/65536.0f/255.0f)*y + (2.1124018f/65536.0f/255.0f)*cb - (289.01757f / 255.0f));
  415.  
  416.         return (ir << 16) + (ig << 8) + ib;
  417.     }
  418.  
  419.     uint32 SampleV210_Y(const void *src, ptrdiff_t srcpitch, sint32 x, sint32 y, uint32 w, uint32 h) {
  420.         const uint32 *p = (const uint32 *)((const char *)src + srcpitch*y) + (x / 6)*4;
  421.  
  422.         switch((uint32)x % 6) {
  423.             default:
  424.             case 0:    return (p[0] >> 10) & 0x3ff;
  425.             case 1:    return (p[1] >>  0) & 0x3ff;
  426.             case 2:    return (p[1] >> 20) & 0x3ff;
  427.             case 3:    return (p[2] >> 10) & 0x3ff;
  428.             case 4:    return (p[3] >>  0) & 0x3ff;
  429.             case 5:    return (p[3] >> 20) & 0x3ff;
  430.         }
  431.     }
  432.  
  433.     uint32 SampleV210_Cb(const void *src, ptrdiff_t srcpitch, sint32 x, sint32 y, uint32 w, uint32 h) {
  434.         const uint32 *p = (const uint32 *)((const char *)src + srcpitch*y) + (x / 3)*4;
  435.  
  436.         switch((uint32)x % 3) {
  437.             default:
  438.             case 0:    return (p[0] >>  0) & 0x3ff;
  439.             case 1:    return (p[1] >> 10) & 0x3ff;
  440.             case 2:    return (p[2] >> 20) & 0x3ff;
  441.         }
  442.     }
  443.  
  444.     uint32 SampleV210_Cr(const void *src, ptrdiff_t srcpitch, sint32 x, sint32 y, uint32 w, uint32 h) {
  445.         const uint32 *p = (const uint32 *)((const char *)src + srcpitch*y) + (x / 3)*4;
  446.  
  447.         switch((uint32)x % 3) {
  448.             default:
  449.             case 0:    return (p[0] >> 20) & 0x3ff;
  450.             case 1:    return (p[2] >>  0) & 0x3ff;
  451.             case 2:    return (p[3] >> 10) & 0x3ff;
  452.         }
  453.     }
  454. }
  455.  
  456. uint32 VDPixmapInterpolateSampleRGB24(const VDPixmap& px, sint32 x_256, sint32 y_256) {
  457.     switch(px.format) {
  458.         case nsVDPixmap::kPixFormat_Pal1:
  459.         case nsVDPixmap::kPixFormat_Pal2:
  460.         case nsVDPixmap::kPixFormat_Pal4:
  461.         case nsVDPixmap::kPixFormat_Pal8:
  462.         case nsVDPixmap::kPixFormat_RGB565:
  463.         case nsVDPixmap::kPixFormat_RGB888:
  464.         case nsVDPixmap::kPixFormat_XRGB1555:
  465.         case nsVDPixmap::kPixFormat_XRGB8888:
  466.             {
  467.                 x_256 -= 128;
  468.                 y_256 -= 128;
  469.                 int ix = x_256 >> 8;
  470.                 int iy = y_256 >> 8;
  471.                 uint32 p0 = VDPixmapSample(px, ix, iy);
  472.                 uint32 p1 = VDPixmapSample(px, ix+1, iy);
  473.                 uint32 p2 = VDPixmapSample(px, ix, iy+1);
  474.                 uint32 p3 = VDPixmapSample(px, ix+1, iy+1);
  475.  
  476.                 return Lerp8888(p0, p1, p2, p3, x_256 & 255, y_256 & 255);
  477.             }
  478.             break;
  479.  
  480.         case nsVDPixmap::kPixFormat_Y8:
  481.             return InterpPlanarY8(px, x_256, y_256); 
  482.  
  483.         case nsVDPixmap::kPixFormat_YUV422_UYVY:
  484.             return ConvertYCC72ToRGB24(
  485.                     VDPixmapInterpolateSample8x2To24((const char *)px.data + 1, px.pitch, px.w, px.h, x_256, y_256),
  486.                     VDPixmapInterpolateSample8x4To24((const char *)px.data + 0, px.pitch, (px.w + 1) >> 1, px.h, (x_256 >> 1) + 128, y_256),
  487.                     VDPixmapInterpolateSample8x4To24((const char *)px.data + 2, px.pitch, (px.w + 1) >> 1, px.h, (x_256 >> 1) + 128, y_256)
  488.                 );
  489.  
  490.         case nsVDPixmap::kPixFormat_YUV422_YUYV:
  491.             return ConvertYCC72ToRGB24(
  492.                     VDPixmapInterpolateSample8x2To24((const char *)px.data + 0, px.pitch, px.w, px.h, x_256, y_256),
  493.                     VDPixmapInterpolateSample8x4To24((const char *)px.data + 1, px.pitch, (px.w + 1) >> 1, px.h, (x_256 >> 1) + 128, y_256),
  494.                     VDPixmapInterpolateSample8x4To24((const char *)px.data + 3, px.pitch, (px.w + 1) >> 1, px.h, (x_256 >> 1) + 128, y_256)
  495.                 );
  496.  
  497.         case nsVDPixmap::kPixFormat_YUV444_XVYU:
  498.             return ConvertYCC72ToRGB24(
  499.                     VDPixmapInterpolateSample8x4To24((const char *)px.data + 1, px.pitch, px.w, px.h, x_256, y_256),
  500.                     VDPixmapInterpolateSample8x4To24((const char *)px.data + 0, px.pitch, px.w, px.h, x_256, y_256),
  501.                     VDPixmapInterpolateSample8x4To24((const char *)px.data + 2, px.pitch, px.w, px.h, x_256, y_256)
  502.                 );
  503.  
  504.         case nsVDPixmap::kPixFormat_YUV422_UYVY_709:
  505.             return ConvertYCC72ToRGB24_709(
  506.                     VDPixmapInterpolateSample8x2To24((const char *)px.data + 1, px.pitch, px.w, px.h, x_256, y_256),
  507.                     VDPixmapInterpolateSample8x4To24((const char *)px.data + 0, px.pitch, (px.w + 1) >> 1, px.h, (x_256 >> 1) + 128, y_256),
  508.                     VDPixmapInterpolateSample8x4To24((const char *)px.data + 2, px.pitch, (px.w + 1) >> 1, px.h, (x_256 >> 1) + 128, y_256)
  509.                 );
  510.  
  511.         case nsVDPixmap::kPixFormat_YUV420_NV12:
  512.             return ConvertYCC72ToRGB24(
  513.                     VDPixmapInterpolateSample8To24(px.data, px.pitch, px.w, px.h, x_256, y_256),
  514.                     VDPixmapInterpolateSample8x2To24((const char *)px.data2 + 0, px.pitch2, (px.w + 1) >> 1, (px.h + 1) >> 1, (x_256 >> 1) + 128, y_256 >> 1),
  515.                     VDPixmapInterpolateSample8x2To24((const char *)px.data2 + 1, px.pitch2, (px.w + 1) >> 1, (px.h + 1) >> 1, (x_256 >> 1) + 128, y_256 >> 1)
  516.                 );
  517.  
  518.         case nsVDPixmap::kPixFormat_YUV444_Planar:
  519.             return InterpPlanarYCC888(px, x_256, y_256, x_256, y_256, px.w, px.h);
  520.  
  521.         case nsVDPixmap::kPixFormat_YUV422_Planar:
  522.             return InterpPlanarYCC888(px, x_256, y_256, (x_256 >> 1) + 128, y_256, (px.w + 1) >> 1, px.h);
  523.  
  524.         case nsVDPixmap::kPixFormat_YUV411_Planar:
  525.             return InterpPlanarYCC888(px, x_256, y_256, (x_256 >> 2) + 128, y_256, (px.w + 3) >> 2, px.h);
  526.  
  527.         case nsVDPixmap::kPixFormat_YUV420_Planar:
  528.             return InterpPlanarYCC888(px, x_256, y_256, (x_256 >> 1) + 128, y_256 >> 1, (px.w + 1) >> 1, (px.h + 1) >> 1);
  529.  
  530.         case nsVDPixmap::kPixFormat_YUV410_Planar:
  531.             return InterpPlanarYCC888(px, x_256, y_256, (x_256 >> 2) + 128, y_256 >> 2, (px.w + 3) >> 2, (px.h + 3) >> 2);
  532.  
  533.         case nsVDPixmap::kPixFormat_YUV420_Planar_Centered:
  534.             return InterpPlanarYCC888(px, x_256, y_256, x_256 >> 1, y_256 >> 1, (px.w + 1) >> 1, (px.h + 1) >> 1);
  535.  
  536.         case nsVDPixmap::kPixFormat_YUV422_Planar_Centered:
  537.             return InterpPlanarYCC888(px, x_256, y_256, x_256 >> 1, y_256, (px.w + 1) >> 1, px.h);
  538.  
  539.         case nsVDPixmap::kPixFormat_YUV422_Planar_16F:
  540.             {
  541.                 float y  = VDPixmapInterpolateSample16F(px.data, px.pitch, px.w, px.h, x_256, y_256);
  542.                 float cb = VDPixmapInterpolateSample16F(px.data2, px.pitch2, (px.w + 1) >> 1, px.h, (x_256 >> 1) + 128, y_256);
  543.                 float cr = VDPixmapInterpolateSample16F(px.data3, px.pitch3, (px.w + 1) >> 1, px.h, (x_256 >> 1) + 128, y_256);
  544.  
  545.                 uint32 ir = VDClampedRoundFixedToUint8Fast(1.1643836f*y + 1.5960268f*cr - (222.92157f / 255.0f));
  546.                 uint32 ig = VDClampedRoundFixedToUint8Fast(1.1643836f*y - 0.3917623f*cb - 0.8129676f*cr + (135.57529f / 255.0f));
  547.                 uint32 ib = VDClampedRoundFixedToUint8Fast(1.1643836f*y + 2.0172321f*cb - (276.83585f / 255.0f));
  548.  
  549.                 return (ir << 16) + (ig << 8) + ib;
  550.             }
  551.  
  552.         case nsVDPixmap::kPixFormat_YUV422_V210:
  553.             {
  554.                 sint32 luma_x = x_256 - 128;
  555.                 sint32 luma_y = y_256 - 128;
  556.  
  557.                 if (luma_x < 0)
  558.                     luma_x = 0;
  559.  
  560.                 if (luma_y < 0)
  561.                     luma_y = 0;
  562.  
  563.                 if (luma_x > (sint32)((px.w - 1) << 8))
  564.                     luma_x = (sint32)((px.w - 1) << 8);
  565.  
  566.                 if (luma_y > (sint32)((px.h - 1) << 8))
  567.                     luma_y = (sint32)((px.h - 1) << 8);
  568.  
  569.                 sint32 luma_ix = luma_x >> 8;
  570.                 sint32 luma_iy = luma_y >> 8;
  571.                 float luma_fx = (float)(luma_x & 255) * (1.0f / 255.0f);
  572.                 float luma_fy = (float)(luma_y & 255) * (1.0f / 255.0f);
  573.  
  574.                 float y0 = SampleV210_Y(px.data, px.pitch, luma_ix+0, luma_iy+0, px.w, px.h) * (1.0f / 1023.0f);
  575.                 float y1 = SampleV210_Y(px.data, px.pitch, luma_ix+1, luma_iy+0, px.w, px.h) * (1.0f / 1023.0f);
  576.                 float y2 = SampleV210_Y(px.data, px.pitch, luma_ix+0, luma_iy+1, px.w, px.h) * (1.0f / 1023.0f);
  577.                 float y3 = SampleV210_Y(px.data, px.pitch, luma_ix+1, luma_iy+1, px.w, px.h) * (1.0f / 1023.0f);
  578.                 float yt = y0 + (y1 - y0)*luma_fx;
  579.                 float yb = y2 + (y3 - y2)*luma_fx;
  580.                 float yr = yt + (yb - yt)*luma_fy;
  581.  
  582.                 uint32 chroma_w = (px.w + 1) >> 1;
  583.                 uint32 chroma_h = px.h;
  584.                 sint32 chroma_x = x_256 >> 1;
  585.                 sint32 chroma_y = y_256 - 128;
  586.  
  587.                 if (chroma_x < 0)
  588.                     chroma_x = 0;
  589.  
  590.                 if (chroma_y < 0)
  591.                     chroma_y = 0;
  592.  
  593.                 if (chroma_x > (sint32)((chroma_w - 1) << 8))
  594.                     chroma_x = (sint32)((chroma_w - 1) << 8);
  595.  
  596.                 if (chroma_y > (sint32)((chroma_h - 1) << 8))
  597.                     chroma_y = (sint32)((chroma_h - 1) << 8);
  598.  
  599.                 sint32 chroma_ix = chroma_x >> 8;
  600.                 sint32 chroma_iy = chroma_y >> 8;
  601.                 float chroma_fx = (float)(chroma_x & 255) * (1.0f / 255.0f);
  602.                 float chroma_fy = (float)(chroma_y & 255) * (1.0f / 255.0f);
  603.  
  604.                 float cb0 = SampleV210_Cb(px.data, px.pitch, chroma_ix+0, chroma_iy+0, px.w, px.h) * (1.0f / 1023.0f);
  605.                 float cb1 = SampleV210_Cb(px.data, px.pitch, chroma_ix+1, chroma_iy+0, px.w, px.h) * (1.0f / 1023.0f);
  606.                 float cb2 = SampleV210_Cb(px.data, px.pitch, chroma_ix+0, chroma_iy+1, px.w, px.h) * (1.0f / 1023.0f);
  607.                 float cb3 = SampleV210_Cb(px.data, px.pitch, chroma_ix+1, chroma_iy+1, px.w, px.h) * (1.0f / 1023.0f);
  608.                 float cbt = cb0 + (cb1 - cb0)*chroma_fx;
  609.                 float cbb = cb2 + (cb3 - cb2)*chroma_fx;
  610.                 float cbr = cbt + (cbb - cbt)*chroma_fy;
  611.  
  612.                 float cr0 = SampleV210_Cr(px.data, px.pitch, chroma_ix+0, chroma_iy+0, px.w, px.h) * (1.0f / 1023.0f);
  613.                 float cr1 = SampleV210_Cr(px.data, px.pitch, chroma_ix+1, chroma_iy+0, px.w, px.h) * (1.0f / 1023.0f);
  614.                 float cr2 = SampleV210_Cr(px.data, px.pitch, chroma_ix+0, chroma_iy+1, px.w, px.h) * (1.0f / 1023.0f);
  615.                 float cr3 = SampleV210_Cr(px.data, px.pitch, chroma_ix+1, chroma_iy+1, px.w, px.h) * (1.0f / 1023.0f);
  616.                 float crt = cr0 + (cr1 - cr0)*chroma_fx;
  617.                 float crb = cr2 + (cr3 - cr2)*chroma_fx;
  618.                 float crr = crt + (crb - crt)*chroma_fy;
  619.  
  620.                 uint32 ir = VDClampedRoundFixedToUint8Fast(1.1643836f*yr + 1.5960268f*crr - (222.92157f / 255.0f));
  621.                 uint32 ig = VDClampedRoundFixedToUint8Fast(1.1643836f*yr - 0.3917623f*cbr - 0.8129676f*crr + (135.57529f / 255.0f));
  622.                 uint32 ib = VDClampedRoundFixedToUint8Fast(1.1643836f*yr + 2.0172321f*cbr - (276.83585f / 255.0f));
  623.  
  624.                 return (ir << 16) + (ig << 8) + ib;
  625.             }
  626.             break;
  627.  
  628.         default:
  629.             return 0;
  630.     }
  631. }
  632.  
  633. uint32 VDConvertYCbCrToRGB(uint8 y0, uint8 cb0, uint8 cr0) {
  634.     sint32  y =  y0 -  16;
  635.     sint32 cb = cb0 - 128;
  636.     sint32 cr = cr0 - 128;
  637.  
  638.     sint32 y2 = y * 76309 + 0x8000;
  639.     sint32 r = y2 + cr * 104597;
  640.     sint32 g = y2 + cr * -53279 + cb * -25674;
  641.     sint32 b = y2 + cb * 132201;
  642.  
  643.     r &= ~(r >> 31);
  644.     g &= ~(g >> 31);
  645.     b &= ~(b >> 31);
  646.     r += (0xffffff - r) & ((0xffffff - r) >> 31);
  647.     g += (0xffffff - g) & ((0xffffff - g) >> 31);
  648.     b += (0xffffff - b) & ((0xffffff - b) >> 31);
  649.  
  650.     return (r & 0xff0000) + ((g & 0xff0000) >> 8) + (b >> 16);
  651. }
  652.  
  653. uint32 VDConvertRGBToYCbCr(uint32 c) {
  654.     return VDConvertRGBToYCbCr((uint8)(c >> 16), (uint8)(c >> 8), (uint8)c);
  655. }
  656.  
  657. uint32 VDConvertRGBToYCbCr(uint8 r8, uint8 g8, uint8 b8) {
  658.     sint32 r  = r8;
  659.     sint32 g  = g8;
  660.     sint32 b  = b8;
  661.     sint32 yt = 1052*r + 2065*g + 401*b;
  662.     sint32 y  = (yt + 0x10800) >> 4;
  663.     sint32 cr = (10507932*r - yt*2987 + 0x80800000U) >> 8;
  664.     sint32 cb = ( 8312025*b - yt*2363 + 0x80800000U) >> 24;
  665.  
  666.     return (uint8)cb + (y & 0xff00) + (cr&0xff0000);
  667. }
  668.