yuv2yuv.c
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:144k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. /*** #includes: ********************************************/
  36. #include "hxassert.h"
  37. #include "env.h"
  38. #include "yuv.h"    /* YUV-to-RGB conversion tables & macros */
  39. #include "clip.h"   /* macros for clipping & dithering */
  40. #include "hxassert.h"
  41. #include "colorlib.h"
  42. int PackedYUVMemcpyWithPitch( unsigned char *dest_ptr,
  43.                               int dest_width, int dest_height,
  44.                               int dest_pitch,
  45.                               int dest_x, int dest_y, int dest_dx, int dest_dy,
  46.                               unsigned char *src_ptr,
  47.                               int src_width, int src_height, int src_pitch,
  48.                               int src_x, int src_y, int src_dx, int src_dy);
  49. /*** YUV to YUV color converters: **************************/
  50. /*
  51.  * These functions were borrowed from our "old" color conversion library,
  52.  * and they do not support things like stretching or color adjustments.
  53.  * Given some more time this module should be completely rewritten.
  54.  *
  55.  ***************/
  56. static int YUY2toPlanarYUV(unsigned char *dY, unsigned char *dU, unsigned char *dV,
  57.                            int dest_width, int dest_height,
  58.                            int dyPitch, int duPitch, int dvPitch,
  59.                            int dest_x, int dest_y, int dest_dx, int dest_dy,
  60.                            unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  61.                            int src_x, int src_y, int src_dx, int src_dy);
  62. static int UYVYtoPlanarYUV(unsigned char *dY, unsigned char *dU, unsigned char *dV,
  63.                            int dest_width, int dest_height,
  64.                            int dyPitch, int duPitch, int dvPitch,
  65.                            int dest_x, int dest_y, int dest_dx, int dest_dy,
  66.                            unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  67.                            int src_x, int src_y, int src_dx, int src_dy);
  68. /*
  69.  * Checks format conversion parameters.
  70.  * Use:
  71.  *  int chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
  72.  *      int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  73.  *      unsigned char *src_ptr, int src_width, int src_height,
  74.  *      int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
  75.  *      int *p_scale_x, int *p_scale_y);
  76.  * Input:
  77.  *  dest_ptr - pointer to a destination buffer
  78.  *  dest_width, dest_height - width/height of the destination image (pixels)
  79.  *  dest_pitch - pitch of the dest. buffer (in bytes; <0 - if bottom up image)
  80.  *  dest_x, dest_y, dest_dx, dest_dy - destination rectangle (pixels)
  81.  *  src_ptr - pointer to an input image
  82.  *  src_width, src_height - width/height of the input image (pixels)
  83.  *  src_pitch - pitch of the source buffer (in bytes; <0 - if bottom up image)
  84.  *  src_x, src_y, src_dx, src_dy - source rectangle (pixels)
  85.  * Output:
  86.  *  p_scale_x, p_scale_y - scale factors for x,y axes
  87.  *      (currently only 1:1, and 2:1 scale factors are allowed)
  88.  * Returns:
  89.  *  0 - if success; -1 if failure.
  90.  */
  91. static int
  92. chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
  93.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  94.     unsigned char *src_ptr, int src_width, int src_height,
  95.     int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
  96.     int *p_scale_x, int *p_scale_y)
  97. {
  98.     /* alignments: */
  99.     if (((unsigned)dest_ptr & 3) || (dest_pitch & 3) ||
  100.         ((unsigned)src_ptr  & 3) || (src_pitch  & 3) ||
  101.     /* image sizes: */
  102.         dest_width <= 0 || dest_height <= 0 ||
  103.         src_width  <= 0 || src_height  <= 0 ||
  104.     /* rectangles: */
  105.         dest_x < 0 || dest_y < 0 || dest_dx <= 0 || dest_dy <= 0 ||
  106.         src_x  < 0 || src_y  < 0 || src_dx  <= 0 || src_dy  <= 0 ||
  107.     /* overlaps: */
  108.         dest_width < dest_x + dest_dx || dest_height < dest_y + dest_dy ||
  109.         src_width  < src_x  + src_dx  || src_height  < src_y  + src_dy)
  110.         goto fail;
  111.     /* scale factors: */
  112.     if (dest_dx == src_dx)          *p_scale_x = 1;
  113.     else if (dest_dx == 2 * src_dx) *p_scale_x = 2;
  114.     else goto fail;
  115.     if (dest_dy == src_dy)          *p_scale_y = 1;
  116.     else if (dest_dy == 2 * src_dy) *p_scale_y = 2;
  117.     else goto fail;
  118.     /* success: */
  119.     return 1;
  120.     /* failure: */
  121. fail:
  122.     return 0;
  123. }
  124. static int adjust_range (int *z1, int *dz1, int *z2, int *dz2, int inc2)
  125. {
  126.     /* skip odd start pixel: */
  127.     if (*z1 & 1) {
  128.         *z1 += 1;
  129.         *dz1 -= 1;
  130.         *z2 += inc2;
  131.         *dz2 -= inc2;
  132.     }
  133.     /* clip the range: */
  134.     if (*dz1 & 1) {
  135.         *dz1 -= 1;
  136.         *dz2 -= inc2;
  137.     }
  138.     return (*dz1 > 0 && *dz2 > 0);
  139. }
  140. /*** "from I420" converters: *******************************/
  141. /*
  142.  * I420toI420x() converter:
  143.  */
  144. int I420toI420x (unsigned char *dest_ptr, int dest_width, int dest_height,
  145.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  146.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  147.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  148.                  int src_x, int src_y, int src_dx, int src_dy)
  149. {
  150.     /* scale factors: */
  151.     int scale_x, scale_y;
  152. /* Chroma Shifting Allowed */
  153. int OddPattern;
  154.     /* check arguments: */
  155.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  156.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  157.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  158.         return -1;
  159.     /* remove odd destination pixels: */
  160.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  161.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  162.         return 0;
  163.     /* check if we have matching chroma components: */
  164.     //if ((src_x & 1) || (src_y & 1))
  165.     //   OddCrop= true;                          /* can't shift chromas */
  166. //else
  167. // OddCrop = false;
  168.     /* check if bottop-up images: */
  169.     if (dest_pitch <= 0 || yPitch <= 0)
  170.         return -1;                          /* not supported for this format */
  171.     /* check if 1:1 scale: */
  172.     if (scale_x == 1 && scale_y == 1) {
  173.         /* check if no color adjustmenst: */
  174.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  175.             /* no color adjustments: */
  176.             unsigned char *s, *d, *v, *s2, *v2;
  177.             int dest_uv_offs;
  178.             register int i,j;
  179.             /* copy Y plane: */
  180.             s = pY + src_x + src_y * yPitch;
  181.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  182.             for (i = 0; i < dest_dy; i ++) {
  183.                 memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  184.                 s += yPitch;
  185.                 d += dest_pitch;
  186.             }
  187.             /* get Cr/Cb offsets: */
  188.             dest_uv_offs = dest_height * dest_pitch / 4;
  189.             /* copy Cr/Cb planes: */
  190.             s = pU + src_x/2 + src_y/2 * uPitch;
  191.             v = pV + src_x/2 + src_y/2 * vPitch;
  192.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  193. // extremely cheap way to handle 1 pel cropping
  194. OddPattern = ((src_y & 1) << 1) | (src_x & 1);
  195.             for (i = 0; i < dest_dy/2; i++) 
  196. {
  197. if((i+1) < dest_dy/2) {
  198. s2 = s+uPitch;
  199. v2 = v+vPitch;
  200. } else {
  201. s2 = s;
  202. v2 = v;
  203. }
  204. /* convert pixels: */
  205. switch(OddPattern)
  206. {
  207. case(0):
  208. memcpy (d, s, dest_dx/2); /* Flawfinder: ignore */
  209. memcpy (d + dest_uv_offs, v, dest_dx/2); /* Flawfinder: ignore */
  210. //memcpy (d + dest_uv_offs, s + src_uv_offs, dest_dx/2);
  211. break;
  212. case(1):
  213. for (j = 0; j < dest_dx/2 -1; j ++) {
  214. d[j] = ((unsigned int)s[j] + (unsigned int)s[j+1] + 1)>>1;
  215. d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v[j+1] + 1)>>1;
  216. }
  217. d[j] = s[j];
  218. d[j + dest_uv_offs] = v[j];
  219. break;
  220. case(2):
  221. for (j = 0; j < dest_dx/2; j ++) {
  222. d[j] = (s[j] + s2[j] + 1)>>1;
  223. d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v2[j] + 1)>>1;
  224. }
  225. break;
  226. case(3):
  227. for (j = 0; j < dest_dx/2 -1; j ++) {
  228. d[j] = ((unsigned int)s[j] + (unsigned int)s[j+1] + (unsigned int)s2[j] + (unsigned int)s2[j+1] + 2)>>2;
  229. d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v[j+1] + (unsigned int)v2[j] + (unsigned int)v2[j+1] + 2)>>2;
  230. }
  231. d[j] = ((unsigned int)s[j]+ (unsigned int)s2[j] + 1)>>1;
  232. d[j + dest_uv_offs] = ((unsigned int)v[j] + (unsigned int)v2[j] + 1) >> 1;
  233. break;
  234. }
  235.                 s += uPitch;
  236.                 v += vPitch;
  237.                 d += (dest_pitch/2);
  238.             }
  239.         } else {
  240.             /* adjust colors: */
  241.             unsigned char *s, *d, *v, *s2, *v2;
  242.             int dest_uv_offs;
  243.             register int i, j;
  244.             /* convert Y plane: */
  245.             s = pY + src_x + src_y * yPitch;
  246.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  247.             for (i = 0; i < dest_dy; i ++) {
  248.                 /* convert pixels: */
  249.                 for (j = 0; j < dest_dx; j ++)
  250.                     d[j] = _yytab[s[j]];
  251.                 s += yPitch;
  252.                 d += dest_pitch;
  253.             }
  254.             /* get Cr/Cb offsets: */
  255.             dest_uv_offs = dest_height * dest_pitch / 4;
  256.             /* get chroma pointers: */
  257.             s = pU + src_x/2 + src_y/2 * uPitch;
  258.             v = pV + src_x/2 + src_y/2 * vPitch;
  259.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  260. OddPattern = ((src_y & 1) << 1) | (src_x & 1);
  261.             /* check if no hue adjustment: */
  262.             if (!is_alpha) {
  263.                 /* no chroma rotation: */
  264.                 for (i = 0; i < dest_dy/2; i ++) {
  265.                     if((i+1) < dest_dy/2) {
  266. s2 = s+uPitch;
  267. v2 = v+vPitch;
  268. } else {
  269. s2 = s;
  270. v2 = v;
  271. }
  272. /* convert pixels: */
  273. switch(OddPattern)
  274. {
  275. case(0):
  276. for (j = 0; j < dest_dx/2; j ++) {
  277. d[j] = _vvtab[s[j]];
  278. d[j + dest_uv_offs] = _uutab[v[j]];
  279. }
  280. break;
  281. case(1):
  282. for (j = 0; j < dest_dx/2 -1; j ++) {
  283. register unsigned int s1 = ((unsigned int)s[j] + (unsigned int)s[j+1] + 1)>>1;
  284. register unsigned int v1 = ((unsigned int)v[j] + (unsigned int)v[j+1] + 1)>>1;
  285. d[j] = _vvtab[s1];
  286. d[j + dest_uv_offs] = _uutab[v1];
  287. }
  288. d[j] = _vvtab[s[j]];
  289. d[j + dest_uv_offs] = _uutab[v[j]];
  290. break;
  291. case(2):
  292. for (j = 0; j < dest_dx/2; j ++) {
  293. register unsigned int s1 = ((unsigned int)s[j] + (unsigned int)s2[j] + 1)>>1;
  294. register unsigned int v1 = ((unsigned int)v[j] + (unsigned int)v2[j] + 1)>>1;
  295. d[j] = _vvtab[s1];
  296. d[j + dest_uv_offs] = _uutab[v1];
  297. }
  298. break;
  299. case(3):
  300. {
  301. register unsigned int s1, v1;
  302. for (j = 0; j < dest_dx/2 -1; j ++) {
  303. s1 = ((unsigned int)s[j] + (unsigned int)s[j+1] + (unsigned int)s2[j] + (unsigned int)s2[j+1] + 2)>>2;
  304. v1 = ((unsigned int)v[j] + (unsigned int)v[j+1] + (unsigned int)v2[j] + (unsigned int)v2[j+1] + 2)>>2; 
  305. d[j] = _vvtab[s1];
  306. d[j + dest_uv_offs] = _uutab[v1];
  307. }
  308. s1 =((unsigned int)s[j]+ (unsigned int)s2[j] + 1) >> 1;
  309. v1 = ((unsigned int)v[j] + (unsigned int)v2[j] + 1) >> 1;
  310. d[j] = _vvtab[s1];
  311. d[j + dest_uv_offs] = _uutab[v1];
  312. }
  313. break;
  314. }
  315.                     s += uPitch;
  316.                     v += vPitch;
  317.                     d += dest_pitch/2;
  318.                 }
  319.             } else {
  320.                 /* adjust hue: */
  321.                 for (i = 0; i < dest_dy/2; i ++) {
  322. if((i+1) < dest_dy/2) {
  323. s2 = s+uPitch;
  324. v2 = v+vPitch;
  325. } else {
  326. s2 = s;
  327. v2 = v;
  328. }
  329.                     /* convert pixels: */
  330.                     switch(OddPattern)
  331. {
  332. case(0):
  333. for (j = 0; j < dest_dx/2; j ++) {
  334. register unsigned v1 = v[j], u1 = s[j];
  335. d[j] = _CLIP(8,_vvtab[v1] + _vutab[u1]);
  336. d[j + dest_uv_offs] = _CLIP(8,_uutab[u1] + _uvtab[v1]);
  337. }
  338. break;
  339. case(1):
  340. {
  341. register unsigned s1, v1;
  342. for (j = 0; j < dest_dx/2 -1; j ++) {
  343. s1 = ((unsigned int)s[j] + (unsigned int)s[j+1] + 1)>>1;
  344. v1 = ((unsigned int)v[j] + (unsigned int)v[j+1] + 1)>>1;
  345. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  346. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  347. }
  348. v1 = v[j];
  349. s1 = s[j];
  350. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  351. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  352. }
  353. break;
  354. case(2):
  355. for (j = 0; j < dest_dx/2; j ++) {
  356. register unsigned s1 = ((unsigned int)s[j] + (unsigned int)s2[j] + 1)>>1;
  357. register unsigned v1 = ((unsigned int)v[j] + (unsigned int)v2[j] + 1)>>1;
  358. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  359. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  360. }
  361. break;
  362. case(3):
  363. {
  364. register unsigned s1, v1;
  365. for (j = 0; j < dest_dx/2 -1; j ++) {
  366. s1 =((unsigned int)s[j] + (unsigned int)s[j+1] + (unsigned int)s2[j] + (unsigned int)s2[j+1] + 2)>>2;
  367. v1 =((unsigned int)v[j] + (unsigned int)v[j+1] + (unsigned int)v2[j] + (unsigned int)v2[j+1] + 2)>>2;
  368. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  369. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  370. }
  371. s1 = ((unsigned int)s[j]+ (unsigned int)s2[j] + 1)>>1;
  372. v1 = ((unsigned int)v[j] + (unsigned int)v2[j] + 1) >> 1;
  373. d[j] = _CLIP(8,_vvtab[v1] + _vutab[s1]);
  374. d[j + dest_uv_offs] = _CLIP(8,_uutab[s1] + _uvtab[v1]);
  375. }
  376. break;
  377. }
  378.                     s += uPitch;
  379.                     v += vPitch;
  380.                     d += dest_pitch/2;
  381.                 }
  382.             }
  383.         }
  384.         return 0;
  385.     }
  386.     /* conversion is not supported */
  387.     return -1;
  388. }
  389. /*
  390.  * I420toI420() converter:
  391.  */
  392. int I420toI420 (unsigned char *dest_ptr, int dest_width, int dest_height,
  393.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  394.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  395.     int src_x, int src_y, int src_dx, int src_dy)
  396. {
  397. #if 1
  398.     unsigned char *pU = src_ptr+src_height*src_pitch,
  399.                   *pV = pU + src_height*src_pitch/4;
  400.     return I420toI420x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  401.                        src_ptr, pU, pV, 
  402.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  403.                        src_x, src_y, src_dx, src_dy);
  404.                     
  405. #else
  406.     /* scale factors: */
  407.     int scale_x, scale_y;
  408.     /* check arguments: */
  409.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  410.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  411.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  412.         return -1;
  413.     /* remove odd destination pixels: */
  414.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  415.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  416.         return 0;
  417.     /* check if we have matching chroma components: */
  418.     if ((src_x & 1) || (src_y & 1))
  419.         return -1;                          /* can't shift chromas */
  420.     /* check if bottop-up images: */
  421.     if (dest_pitch <= 0 || src_pitch <= 0)
  422.         return -1;                          /* not supported for this format */
  423.     /* check if 1:1 scale: */
  424.     if (scale_x == 1 && scale_y == 1) {
  425.         /* check if no color adjustmenst: */
  426.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  427.             /* no color adjustments: */
  428.             unsigned char *s, *d;
  429.             int src_uv_offs, dest_uv_offs;
  430.             register int i;
  431.             /* copy Y plane: */
  432.             s = src_ptr + src_x + src_y * src_pitch;
  433.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  434.             for (i = 0; i < dest_dy; i ++) {
  435.                 memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  436.                 s += src_pitch;
  437.                 d += dest_pitch;
  438.             }
  439.             /* get Cr/Cb offsets: */
  440.             src_uv_offs = src_height * src_pitch / 4;
  441.             dest_uv_offs = dest_height * dest_pitch / 4;
  442.             /* copy Cr/Cb planes: */
  443.             s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  444.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  445.             for (i = 0; i < dest_dy/2; i ++) {
  446.                 memcpy (d, s, dest_dx/2); /* Flawfinder: ignore */
  447.                 memcpy (d + dest_uv_offs, s + src_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  448.                 s += src_pitch/2;
  449.                 d += dest_pitch/2;
  450.             }
  451.         } else {
  452.             /* adjust colors: */
  453.             unsigned char *s, *d;
  454.             int src_uv_offs, dest_uv_offs;
  455.             register int i, j;
  456.             /* convert Y plane: */
  457.             s = src_ptr + src_x + src_y * src_pitch;
  458.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  459.             for (i = 0; i < dest_dy; i ++) {
  460.                 /* convert pixels: */
  461.                 for (j = 0; j < dest_dx; j ++)
  462.                     d[j] = _yytab[s[j]];
  463.                 s += src_pitch;
  464.                 d += dest_pitch;
  465.             }
  466.             /* get Cr/Cb offsets: */
  467.             src_uv_offs = src_height * src_pitch / 4;
  468.             dest_uv_offs = dest_height * dest_pitch / 4;
  469.             /* get chroma pointers: */
  470.             s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  471.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  472.             /* check if no hue adjustment: */
  473.             if (!is_alpha) {
  474.                 /* no chroma rotation: */
  475.                 for (i = 0; i < dest_dy/2; i ++) {
  476.                     /* convert pixels: */
  477.                     for (j = 0; j < dest_dx/2; j ++) {
  478.                         d[j] = _vvtab[s[j]];
  479.                         d[j + dest_uv_offs] = _uutab[s[j + src_uv_offs]];
  480.                     }
  481.                     s += src_pitch/2;
  482.                     d += dest_pitch/2;
  483.                 }
  484.             } else {
  485.                 /* adjust hue: */
  486.                 for (i = 0; i < dest_dy/2; i ++) {
  487.                     /* convert pixels: */
  488.                     for (j = 0; j < dest_dx/2; j ++) {
  489.                         register unsigned v = s[j], u = s[j + src_uv_offs];
  490.                         d[j] = _CLIP(8,_vvtab[v] + _vutab[u]);
  491.                         d[j + dest_uv_offs] = _CLIP(8,_uutab[u] + _uvtab[v]);
  492.                     }
  493.                     s += src_pitch/2;
  494.                     d += dest_pitch/2;
  495.                 }
  496.             }
  497.         }
  498.         return 0;
  499.     }
  500.     /* conversion is not supported */
  501.     return -1;
  502. #endif
  503. }
  504. int I420toYV12x (unsigned char *dest_ptr, int dest_width, int dest_height,
  505.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  506.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  507.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  508.                  int src_x, int src_y, int src_dx, int src_dy)
  509. {
  510.     /* scale factors: */
  511.     int scale_x, scale_y;
  512.     /* check arguments: */
  513.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  514.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  515.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  516.         return -1;
  517.     /* remove odd destination pixels: */
  518.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  519.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  520.         return 0;
  521.     /* check if we have matching chroma components: */
  522.     if ((src_x & 1) || (src_y & 1))
  523.         return -1;                          /* can't shift chromas */
  524.     /* check if bottop-up images: */
  525.     if (dest_pitch <= 0 || yPitch <= 0)
  526.         return -1;                          /* not supported for this format */
  527.     /* check if 1:1 scale: */
  528.     if (scale_x == 1 && scale_y == 1) {
  529.         /* check if no color adjustments: */
  530.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  531.             /* no color adjustments: */
  532.             unsigned char *sy, *su, *sv, *d;
  533.             int dest_uv_offs;
  534.             register int i;
  535.             /* copy Y plane: */
  536.             sy = pY + src_x + src_y * yPitch;
  537.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  538.             for (i = 0; i < dest_dy; i ++) {
  539.                 memcpy (d, sy, dest_dx); /* Flawfinder: ignore */
  540.                 sy += yPitch;
  541.                 d += dest_pitch;
  542.             }
  543.             /* get Cr/Cb offsets: */
  544.             dest_uv_offs = dest_height * dest_pitch / 4;
  545.             /* copy Cr/Cb planes: */
  546.             su = pU + src_x/2 + src_y/2 * uPitch;
  547.             sv = pV + src_x/2 + src_y/2 * vPitch;
  548.             
  549.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  550.             for (i = 0; i < dest_dy/2; i ++) {
  551.                 memcpy (d, sv, dest_dx/2); /* Flawfinder: ignore */
  552.                 memcpy (d + dest_uv_offs, su, dest_dx/2); /* Flawfinder: ignore */
  553.                 su += uPitch;
  554.                 sv += vPitch;
  555.                 d += dest_pitch/2;
  556.             }
  557.         } else {
  558.             /* adjust colors: */
  559.             unsigned char *sy, *su, *sv, *d;
  560.             int dest_uv_offs;
  561.             register int i, j;
  562.             /* convert Y plane: */
  563.             sy = pY + src_x + src_y * yPitch;
  564.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  565.             for (i = 0; i < dest_dy; i ++) {
  566.                 /* convert pixels: */
  567.                 for (j = 0; j < dest_dx; j ++)
  568.                     d[j] = _yytab[sy[j]];
  569.                 sy += yPitch;
  570.                 d += dest_pitch;
  571.             }
  572.             /* get Cr/Cb offsets: */
  573.             dest_uv_offs = dest_height * dest_pitch / 4;
  574.             /* get chroma pointers: */
  575.             su = pU + src_x/2 + src_y/2 * uPitch;
  576.             sv = pV + src_x/2 + src_y/2 * vPitch;
  577.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  578.             /* check if no hue adjustment: */
  579.             if (!is_alpha) {
  580.                 /* no chroma rotation: */
  581.                 for (i = 0; i < dest_dy/2; i ++) {
  582.                     /* convert pixels: */
  583.                     for (j = 0; j < dest_dx/2; j ++) {
  584.                         d[j] = _vvtab[sv[j]];
  585.                         d[j + dest_uv_offs] = _uutab[su[j]];
  586.                     }
  587.                     su += uPitch;
  588.                     sv += vPitch;
  589.                     d += dest_pitch/2;
  590.                 }
  591.             } else {
  592.                 /* adjust hue: */
  593.                 for (i = 0; i < dest_dy/2; i ++) {
  594.                     /* convert pixels: */
  595.                     for (j = 0; j < dest_dx/2; j ++) {
  596.                         register unsigned v = sv[j], u = su[j];
  597.                         d[j] = _CLIP(8,_vvtab[v] + _vutab[u]);
  598.                         d[j + dest_uv_offs] = _CLIP(8,_uutab[u] + _uvtab[v]);
  599.                     }
  600.                     su += uPitch;
  601.                     sv += vPitch;
  602.                     d += dest_pitch/2;
  603.                 }
  604.             }
  605.         }
  606.         return 0;
  607.     }
  608.     /* conversion is not supported */
  609.     return -1;
  610. }
  611. /*
  612.  * I420toYV12() converter:
  613.  */
  614. int I420toYV12 (unsigned char *dest_ptr, int dest_width, int dest_height,
  615.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  616.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  617.     int src_x, int src_y, int src_dx, int src_dy)
  618. {
  619. #if 1
  620.     unsigned char *pU = src_ptr+src_height*src_pitch,
  621.                   *pV = pU + src_height*src_pitch/4;
  622.     return I420toYV12x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  623.                        src_ptr, pU, pV, 
  624.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  625.                        src_x, src_y, src_dx, src_dy);
  626.                     
  627. #else
  628.     /* scale factors: */
  629.     int scale_x, scale_y;
  630.     /* check arguments: */
  631.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  632.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  633.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  634.         return -1;
  635.     /* remove odd destination pixels: */
  636.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  637.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  638.         return 0;
  639.     /* check if we have matching chroma components: */
  640.     if ((src_x & 1) || (src_y & 1))
  641.         return -1;                          /* can't shift chromas */
  642.     /* check if bottop-up images: */
  643.     if (dest_pitch <= 0 || src_pitch <= 0)
  644.         return -1;                          /* not supported for this format */
  645.     /* check if 1:1 scale: */
  646.     if (scale_x == 1 && scale_y == 1) {
  647.         /* check if no color adjustments: */
  648.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  649.             /* no color adjustments: */
  650.             unsigned char *s, *d;
  651.             int src_uv_offs, dest_uv_offs;
  652.             register int i;
  653.             /* copy Y plane: */
  654.             s = src_ptr + src_x + src_y * src_pitch;
  655.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  656.             for (i = 0; i < dest_dy; i ++) {
  657.                 memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  658.                 s += src_pitch;
  659.                 d += dest_pitch;
  660.             }
  661.             /* get Cr/Cb offsets: */
  662.             src_uv_offs = src_height * src_pitch / 4;
  663.             dest_uv_offs = dest_height * dest_pitch / 4;
  664.             /* copy Cr/Cb planes: */
  665.             s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  666.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  667.             for (i = 0; i < dest_dy/2; i ++) {
  668.                 memcpy (d, s + src_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  669.                 memcpy (d + dest_uv_offs, s, dest_dx/2); /* Flawfinder: ignore */
  670.                 s += src_pitch/2;
  671.                 d += dest_pitch/2;
  672.             }
  673.         } else {
  674.             /* adjust colors: */
  675.             unsigned char *s, *d;
  676.             int src_uv_offs, dest_uv_offs;
  677.             register int i, j;
  678.             /* convert Y plane: */
  679.             s = src_ptr + src_x + src_y * src_pitch;
  680.             d = dest_ptr + dest_x + dest_y * dest_pitch;
  681.             for (i = 0; i < dest_dy; i ++) {
  682.                 /* convert pixels: */
  683.                 for (j = 0; j < dest_dx; j ++)
  684.                     d[j] = _yytab[s[j]];
  685.                 s += src_pitch;
  686.                 d += dest_pitch;
  687.             }
  688.             /* get Cr/Cb offsets: */
  689.             src_uv_offs = src_height * src_pitch / 4;
  690.             dest_uv_offs = dest_height * dest_pitch / 4;
  691.             /* get chroma pointers: */
  692.             s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  693.             d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  694.             /* check if no hue adjustment: */
  695.             if (!is_alpha) {
  696.                 /* no chroma rotation: */
  697.                 for (i = 0; i < dest_dy/2; i ++) {
  698.                     /* convert pixels: */
  699.                     for (j = 0; j < dest_dx/2; j ++) {
  700.                         d[j] = _vvtab[s[j + src_uv_offs]];
  701.                         d[j + dest_uv_offs] = _uutab[s[j]];
  702.                     }
  703.                     s += src_pitch/2;
  704.                     d += dest_pitch/2;
  705.                 }
  706.             } else {
  707.                 /* adjust hue: */
  708.                 for (i = 0; i < dest_dy/2; i ++) {
  709.                     /* convert pixels: */
  710.                     for (j = 0; j < dest_dx/2; j ++) {
  711.                         register unsigned v = s[j + src_uv_offs], u = s[j];
  712.                         d[j] = _CLIP(8,_vvtab[v] + _vutab[u]);
  713.                         d[j + dest_uv_offs] = _CLIP(8,_uutab[u] + _uvtab[v]);
  714.                     }
  715.                     s += src_pitch/2;
  716.                     d += dest_pitch/2;
  717.                 }
  718.             }
  719.         }
  720.         return 0;
  721.     }
  722.     /* conversion is not supported */
  723.     return -1;
  724. #endif
  725. }
  726. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS)) && !defined(WINCE_EMULATOR)
  727. //Our MMX optimized YUY2 and UYVY to YUV converters.
  728. //No scaling supported yet.
  729. extern void YUY2ToPlanarYUV_MMX( unsigned char* d1,      
  730.                                  unsigned char* d2,      
  731.                                  unsigned char* du,      
  732.                                  unsigned char* dv,      
  733.                                  INT32          dyPitch, 
  734.                                  INT32          duPitch, 
  735.                                  INT32          dvPitch, 
  736.                                  INT32          dest_dx, 
  737.                                  INT32          dest_dy, 
  738.                                  unsigned char* s1,      
  739.                                  unsigned char* s2,      
  740.                                  INT32          src_pitch
  741.                                  );
  742. extern void UYVYToPlanarYUV_MMX( unsigned char* d1,      
  743.                                  unsigned char* d2,      
  744.                                  unsigned char* du,      
  745.                                  unsigned char* dv,      
  746.                                  INT32          dyPitch, 
  747.                                  INT32          duPitch, 
  748.                                  INT32          dvPitch, 
  749.                                  INT32          dest_dx, 
  750.                                  INT32          dest_dy, 
  751.                                  unsigned char* s1,      
  752.                                  unsigned char* s2,      
  753.                                  INT32          src_pitch
  754.                                  );
  755. extern  YUY2toUYVY_MMX( unsigned char* src,
  756.                         unsigned char* dest,
  757.                         ULONG32        dx
  758.                         );
  759. /* MMX version of I420toYUY2 converter: */
  760. extern void _MMX_lineI420toYUY2( unsigned char *sy,
  761.                                  unsigned char *su,
  762.                                  unsigned char *sv,
  763.                                  unsigned char *d,
  764.                                  int count
  765.                                  );
  766. /*  MMX version of I420toUYVY converter */
  767. extern void _MMX_lineI420toUYVY( unsigned char *sy,
  768.                                  unsigned char *su,
  769.                                  unsigned char *sv,
  770.                                  unsigned char *d,
  771.                                  int count
  772.                                  );
  773. #endif
  774. #ifdef _MACINTOSH
  775. #ifdef __cplusplus
  776. extern "C"
  777. #endif
  778. void
  779. AltiVec_lineI420toYUY2 (
  780. unsigned char *sy, 
  781. unsigned char *su, 
  782. unsigned char *sv,
  783. unsigned char *d,
  784. int dest_dx);
  785. #endif
  786. /*
  787.  * Combine 4 bytes in a register for fast transfer to
  788.  * the main memory:
  789.  */
  790. #if BYTE_ORDER == LITTLE_ENDIAN
  791. #define COMBINE(b0,b1,b2,b3)  
  792.     ((unsigned int)(b0) | ((unsigned int)(b1) << 8) | 
  793.     ((unsigned int)(b2) << 16) | ((unsigned int)(b3) << 24))
  794. #else /* BYTE_ORDER != LITTLE_ENDIAN */
  795. #define COMBINE(b0,b1,b2,b3)  
  796.     ((unsigned int)(b3) | ((unsigned int)(b2) << 8) | 
  797.     ((unsigned int)(b1) << 16) | ((unsigned int)(b0) << 24))
  798. #endif
  799. int I420toYUY2x (unsigned char *dest_ptr, int dest_width, int dest_height,
  800.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  801.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  802.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  803.                  int src_x, int src_y, int src_dx, int src_dy)
  804. {
  805.     /* scale factors: */
  806.     int scale_x, scale_y;
  807.     /* check arguments: */
  808.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  809.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  810.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  811.         return -1;
  812.     /* remove odd destination columns: */
  813.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x))
  814.         return 0;
  815.     /* check if we have misaligned input: */
  816.     if (src_x & 1)
  817.         return -1;                          /* can't shift chromas */
  818.     /* check if bottop-up images: */
  819.     if (dest_pitch < 0) dest_ptr -= (dest_height-1) * dest_pitch;
  820.     if (yPitch <= 0 ||
  821.         uPitch <= 0 ||
  822.         vPitch <= 0)
  823.         return -1;          /* not supported */
  824.     /* check if 1:1 scale: */
  825.     if (scale_x == 1 && scale_y == 1) {
  826.         /* check if no color adjustments: */
  827.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  828.             /* no color adjustments: */
  829.             unsigned char *sy, *sv, *su, *d;
  830.             register int i, j;
  831.             /* get pointers: */
  832.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  833.             su = pU + (src_x/2 + src_y/2 * uPitch);
  834.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  835.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  836. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS))  && !defined(WINCE_EMULATOR)
  837.             /* check if we can use MMX-optimized code here: */
  838.             if (_x86_MMX_Available)
  839.             {
  840.                 /* process top line (if chroma is not pairable): */
  841.                 if (dest_y & 1) {
  842.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  843.                     sy += yPitch;
  844.                     su += uPitch;
  845.                     sv += vPitch;
  846.                     d  += dest_pitch;
  847.                     dest_dy --;
  848.                 }
  849.                 /* the main loop (processes two lines a time): */
  850.                 for (i = 0; i < dest_dy/2; i ++) {
  851.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  852.                     sy += yPitch;
  853.                     d  += dest_pitch;
  854.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  855.                     sy += yPitch;
  856.                     su += uPitch;
  857.                     sv += vPitch;
  858.                     d  += dest_pitch;
  859.                 }
  860.                 /* process the last line (if dy is odd): */
  861.                 if (dest_dy & 1) {
  862.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  863.                 }
  864.                 /* end of MMX code */
  865. #if defined(_M_IX86) && !defined(WINCE_EMULATOR)                
  866.                 __asm emms
  867. #elif defined(_USE_MMX_BLENDERS) && !defined(WINCE_EMULATOR)
  868.                __asm__ __volatile__ ( "emms" );
  869. #endif                    
  870.             } else
  871. #endif
  872. #ifdef _MACINTOSH
  873.             /* check if we can use MMX-optimized code here: */
  874.             if (_AltiVec_Available)
  875.             {
  876.                 /* process top line (if chroma is not pairable): */
  877.                 if (dest_y & 1) {
  878.                     AltiVec_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  879.                     sy += yPitch;
  880.                     su += uPitch;
  881.                     sv += vPitch;
  882.                     d  += dest_pitch;
  883.                     dest_dy --;
  884.                 }
  885.                 /* the main loop (processes two lines a time): */
  886.                 for (i = 0; i < dest_dy/2; i ++) {
  887.                     AltiVec_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  888.                     sy += yPitch;
  889.                     d  += dest_pitch;
  890.                     AltiVec_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  891.                     sy += yPitch;
  892.                     su += uPitch;
  893.                     sv += vPitch;
  894.                     d  += dest_pitch;
  895.                 }
  896.                 /* process the last line (if dy is odd): */
  897.                 if (dest_dy & 1) {
  898.                     AltiVec_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  899.                 }
  900.                 /* end of MMX code */
  901.             } else
  902. #endif
  903.             /* a generic "C" version: */
  904.             {
  905.                 /* process top line (if chroma is not pairable): */
  906.                 if (dest_y & 1) {
  907.                     for (j = 0; j < dest_dx/2; j ++)
  908.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  909.                     sy += yPitch;
  910.                     su += uPitch;
  911.                     sv += vPitch;
  912.                     d  += dest_pitch;
  913.                     dest_dy --;
  914.                 }
  915.                 /* the main loop (processes two lines a time): */
  916.                 for (i = 0; i < dest_dy/2; i ++) {
  917.                     for (j = 0; j < dest_dx/2; j ++)
  918.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  919.                     sy += yPitch;
  920.                     d  += dest_pitch;
  921.                     for (j = 0; j < dest_dx/2; j ++)
  922.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  923.                     sy += yPitch;
  924.                     su += uPitch;
  925.                     sv += vPitch;
  926.                     d  += dest_pitch;
  927.                 }
  928.                 /* process the last line (if dy is odd): */
  929.                 if (dest_dy & 1) {
  930.                     for (j = 0; j < dest_dx/2; j ++)
  931.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  932.                 }
  933.             }
  934.         } else
  935.         /* check if no hue adjustment: */
  936.         if (!is_alpha) {
  937.             /* no chroma rotation: */
  938.             unsigned char *sy, *sv, *su, *d;
  939.             register int i, j;
  940.             /* get pointers: */
  941.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  942.             su = pU + (src_x/2 + src_y/2 * uPitch);
  943.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  944.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  945.             /* process top line (if chroma is not pairable): */
  946.             if (dest_y & 1) {
  947.                 for (j = 0; j < dest_dx/2; j ++)
  948.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  949.                 sy += yPitch;
  950.                 su += uPitch;
  951.                 sv += vPitch;
  952.                 d  += dest_pitch;
  953.                 dest_dy --;
  954.             }
  955.             /* the main loop (processes two lines a time): */
  956.             for (i = 0; i < dest_dy/2; i ++) {
  957.                 for (j = 0; j < dest_dx/2; j ++)
  958.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  959.                 sy += yPitch;
  960.                 d  += dest_pitch;
  961.                 for (j = 0; j < dest_dx/2; j ++)
  962.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  963.                 sy += yPitch;
  964.                 su += uPitch;
  965.                 sv += vPitch;
  966.                 d  += dest_pitch;
  967.             }
  968.             /* process the last line (if dy is odd): */
  969.             if (dest_dy & 1) {
  970.                 for (j = 0; j < dest_dx/2; j ++)
  971.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  972.             }
  973.         } else {
  974.             /* the most complex case (w. hue adjustment): */
  975.             unsigned char *sy, *sv, *su, *d;
  976.             register int i, j, u, v;
  977.             /* get pointers: */
  978.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  979.             su = pU + (src_x/2 + src_y/2 * uPitch);
  980.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  981.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  982.             /* process top line (if chroma is not pairable): */
  983.             if (dest_y & 1) {
  984.                 for (j = 0; j < dest_dx/2; j ++) {
  985.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  986.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  987.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  988.                 }
  989.                 sy += yPitch;
  990.                 su += uPitch;
  991.                 sv += vPitch;
  992.                 d  += dest_pitch;
  993.                 dest_dy --;
  994.             }
  995.             /* the main loop (processes two lines a time): */
  996.             for (i = 0; i < dest_dy/2; i ++) {
  997.                 for (j = 0; j < dest_dx/2; j ++) {
  998.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  999.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1000.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1001.                     *(unsigned int *)(d + j*4 + dest_pitch) = COMBINE(_yytab[sy[j*2 + yPitch]], u, _yytab[sy[j*2+1+yPitch]], v);
  1002.                 }
  1003.                 sy += yPitch*2;
  1004.                 su += uPitch;
  1005.                 sv += vPitch;
  1006.                 d  += dest_pitch*2;
  1007.             }
  1008.             /* process the last line (if dy is odd): */
  1009.             if (dest_dy & 1) {
  1010.                 for (j = 0; j < dest_dx/2; j ++) {
  1011.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1012.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1013.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1014.                 }
  1015.             }
  1016.         }
  1017.         return 0;
  1018.     }
  1019.     /* conversion is not supported */
  1020.     return -1;
  1021. }
  1022. /*
  1023.  * I420toYUY2() converter:
  1024.  */
  1025. int I420toYUY2 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1026.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1027.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1028.     int src_x, int src_y, int src_dx, int src_dy)
  1029. {
  1030. #if 1
  1031.     unsigned char *pU = src_ptr+src_height*src_pitch,
  1032.                   *pV = pU + src_height*src_pitch/4;
  1033.     return I420toYUY2x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1034.                        src_ptr, pU, pV, 
  1035.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1036.                        src_x, src_y, src_dx, src_dy);
  1037.                     
  1038. #else
  1039.     /* scale factors: */
  1040.     int scale_x, scale_y;
  1041.     /* check arguments: */
  1042.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1043.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1044.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1045.         return -1;
  1046.     /* remove odd destination columns: */
  1047.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x))
  1048.         return 0;
  1049.     /* check if we have misaligned input: */
  1050.     if (src_x & 1)
  1051.         return -1;                          /* can't shift chromas */
  1052.     /* check if bottop-up images: */
  1053.     if (dest_pitch < 0) dest_ptr -= (dest_height-1) * dest_pitch;
  1054.     if (src_pitch <= 0) return -1;          /* not supported */
  1055.     /* check if 1:1 scale: */
  1056.     if (scale_x == 1 && scale_y == 1) {
  1057.         /* check if no color adjustments: */
  1058.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  1059.             /* no color adjustments: */
  1060.             unsigned char *sy, *sv, *su, *d;
  1061.             register int i, j;
  1062.             /* get pointers: */
  1063.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1064.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  1065.             sv = su + src_height * src_pitch / 4;
  1066.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1067. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS)) && !defined(WINCE_EMULATOR)
  1068.             /* check if we can use MMX-optimized code here: */
  1069.             if (_x86_MMX_Available)
  1070.             {
  1071.                 /* process top line (if chroma is not pairable): */
  1072.                 if (dest_y & 1) {
  1073.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  1074.                     sy += src_pitch;
  1075.                     su += src_pitch/2;
  1076.                     sv += src_pitch/2;
  1077.                     d  += dest_pitch;
  1078.                     dest_dy --;
  1079.                 }
  1080.                 /* the main loop (processes two lines a time): */
  1081.                 for (i = 0; i < dest_dy/2; i ++) {
  1082.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  1083.                     sy += src_pitch;
  1084.                     d  += dest_pitch;
  1085.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  1086.                     sy += src_pitch;
  1087.                     su += src_pitch/2;
  1088.                     sv += src_pitch/2;
  1089.                     d  += dest_pitch;
  1090.                 }
  1091.                 /* process the last line (if dy is odd): */
  1092.                 if (dest_dy & 1) {
  1093.                     _MMX_lineI420toYUY2 (sy, su, sv, d, dest_dx);
  1094.                 }
  1095.                 /* end of MMX code */
  1096. #if defined(_M_IX86)  && !defined(WINCE_EMULATOR)                
  1097.                 __asm emms
  1098. #elif defined(_USE_MMX_BLENDERS) && !defined(WINCE_EMULATOR)
  1099.                 __asm__ __volatile__ ( "emms" );
  1100. #endif                    
  1101.             } else
  1102. #endif
  1103.             /* a generic "C" version: */
  1104.             {
  1105.                 /* process top line (if chroma is not pairable): */
  1106.                 if (dest_y & 1) {
  1107.                     for (j = 0; j < dest_dx/2; j ++)
  1108.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  1109.                     sy += src_pitch;
  1110.                     su += src_pitch/2;
  1111.                     sv += src_pitch/2;
  1112.                     d  += dest_pitch;
  1113.                     dest_dy --;
  1114.                 }
  1115.                 /* the main loop (processes two lines a time): */
  1116.                 for (i = 0; i < dest_dy/2; i ++) {
  1117.                     for (j = 0; j < dest_dx/2; j ++)
  1118.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  1119.                     sy += src_pitch;
  1120.                     d  += dest_pitch;
  1121.                     for (j = 0; j < dest_dx/2; j ++)
  1122.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  1123.                     sy += src_pitch;
  1124.                     su += src_pitch/2;
  1125.                     sv += src_pitch/2;
  1126.                     d  += dest_pitch;
  1127.                 }
  1128.                 /* process the last line (if dy is odd): */
  1129.                 if (dest_dy & 1) {
  1130.                     for (j = 0; j < dest_dx/2; j ++)
  1131.                         *(unsigned int *)(d + j*4) = COMBINE(sy[j*2], su[j], sy[j*2+1], sv[j]);
  1132.                 }
  1133.             }
  1134.         } else
  1135.         /* check if no hue adjustment: */
  1136.         if (!is_alpha) {
  1137.             /* no chroma rotation: */
  1138.             unsigned char *sy, *sv, *su, *d;
  1139.             register int i, j;
  1140.             /* get pointers: */
  1141.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1142.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  1143.             sv = su + src_height * src_pitch / 4;
  1144.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1145.             /* process top line (if chroma is not pairable): */
  1146.             if (dest_y & 1) {
  1147.                 for (j = 0; j < dest_dx/2; j ++)
  1148.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  1149.                 sy += src_pitch;
  1150.                 su += src_pitch/2;
  1151.                 sv += src_pitch/2;
  1152.                 d  += dest_pitch;
  1153.                 dest_dy --;
  1154.             }
  1155.             /* the main loop (processes two lines a time): */
  1156.             for (i = 0; i < dest_dy/2; i ++) {
  1157.                 for (j = 0; j < dest_dx/2; j ++)
  1158.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  1159.                 sy += src_pitch;
  1160.                 d  += dest_pitch;
  1161.                 for (j = 0; j < dest_dx/2; j ++)
  1162.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  1163.                 sy += src_pitch;
  1164.                 su += src_pitch/2;
  1165.                 sv += src_pitch/2;
  1166.                 d  += dest_pitch;
  1167.             }
  1168.             /* process the last line (if dy is odd): */
  1169.             if (dest_dy & 1) {
  1170.                 for (j = 0; j < dest_dx/2; j ++)
  1171.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], _uutab[su[j]], _yytab[sy[j*2+1]], _vvtab[sv[j]]);
  1172.             }
  1173.         } else {
  1174.             /* the most complex case (w. hue adjustment): */
  1175.             unsigned char *sy, *sv, *su, *d;
  1176.             register int i, j, u, v;
  1177.             /* get pointers: */
  1178.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1179.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch/2);
  1180.             sv = su + src_height * src_pitch / 4;
  1181.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1182.             /* process top line (if chroma is not pairable): */
  1183.             if (dest_y & 1) {
  1184.                 for (j = 0; j < dest_dx/2; j ++) {
  1185.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1186.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1187.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1188.                 }
  1189.                 sy += src_pitch;
  1190.                 su += src_pitch/2;
  1191.                 sv += src_pitch/2;
  1192.                 d  += dest_pitch;
  1193.                 dest_dy --;
  1194.             }
  1195.             /* the main loop (processes two lines a time): */
  1196.             for (i = 0; i < dest_dy/2; i ++) {
  1197.                 for (j = 0; j < dest_dx/2; j ++) {
  1198.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1199.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1200.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1201.                     *(unsigned int *)(d + j*4 + dest_pitch) = COMBINE(_yytab[sy[j*2 + src_pitch]], u, _yytab[sy[j*2+1+src_pitch]], v);
  1202.                 }
  1203.                 sy += src_pitch*2;
  1204.                 su += src_pitch/2;
  1205.                 sv += src_pitch/2;
  1206.                 d  += dest_pitch*2;
  1207.             }
  1208.             /* process the last line (if dy is odd): */
  1209.             if (dest_dy & 1) {
  1210.                 for (j = 0; j < dest_dx/2; j ++) {
  1211.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1212.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1213.                     *(unsigned int *)(d + j*4) = COMBINE(_yytab[sy[j*2]], u, _yytab[sy[j*2+1]], v);
  1214.                 }
  1215.             }
  1216.         }
  1217.         return 0;
  1218.     }
  1219.     /* conversion is not supported */
  1220.     return -1;
  1221. #endif //0
  1222. }
  1223. int I420toUYVYx (unsigned char *dest_ptr, int dest_width, int dest_height,
  1224.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1225.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1226.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1227.                  int src_x, int src_y, int src_dx, int src_dy)
  1228. {
  1229.     /* scale factors: */
  1230.     int scale_x, scale_y;
  1231.     /* check arguments: */
  1232.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1233.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  1234.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1235.         return -1;
  1236.     /* remove odd destination columns: */
  1237.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x))
  1238.         return 0;
  1239.     /* check if we have misaligned input: */
  1240.     if (src_x & 1)
  1241.         return -1;                          /* can't shift chromas */
  1242.     /* check if bottop-up images: */
  1243.     if (dest_pitch < 0) dest_ptr -= (dest_height-1) * dest_pitch;
  1244.     if (yPitch <= 0 ||
  1245.         uPitch <= 0 ||
  1246.         vPitch <= 0)
  1247.         return -1;          /* not supported */
  1248.     /* check if 1:1 scale: */
  1249.     if (scale_x == 1 && scale_y == 1) {
  1250.         /* check if no color adjustments: */
  1251.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  1252.             /* no color adjustments: */
  1253.             unsigned char *sy, *sv, *su, *d;
  1254.             register int i, j;
  1255.             /* get pointers: */
  1256.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  1257.             su = pU + (src_x/2 + src_y/2 * uPitch);
  1258.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  1259.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1260. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS)) && !defined(WINCE_EMULATOR)
  1261.             /* check if we can use MMX-optimized code here: */
  1262.             if (_x86_MMX_Available)
  1263.             {
  1264.                 /* process top line (if chroma is not pairable): */
  1265.                 if (dest_y & 1) {
  1266.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1267.                     sy += yPitch;
  1268.                     su += uPitch;
  1269.                     sv += vPitch;
  1270.                     d  += dest_pitch;
  1271.                     dest_dy --;
  1272.                 }
  1273.                 /* the main loop (processes two lines a time): */
  1274.                 for (i = 0; i < dest_dy/2; i ++) {
  1275.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1276.                     sy += yPitch;
  1277.                     d  += dest_pitch;
  1278.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1279.                     sy += yPitch;
  1280.                     su += uPitch;
  1281.                     sv += vPitch;
  1282.                     d  += dest_pitch;
  1283.                 }
  1284.                 /* process the last line (if dy is odd): */
  1285.                 if (dest_dy & 1) {
  1286.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1287.                 }
  1288.                 /* end of MMX code */
  1289. #if defined(_M_IX86) && !defined(WINCE_EMULATOR)                
  1290.                 __asm emms
  1291. #elif defined(_USE_MMX_BLENDERS) && !defined(WINCE_EMULATOR)
  1292.                 __asm__ __volatile__ ( "emms" );
  1293. #endif                    
  1294.             } else
  1295. #endif
  1296.             /* a generic "C" version: */
  1297.             {
  1298.                 /* process top line (if chroma is not pairable): */
  1299.                 if (dest_y & 1) {
  1300.                     for (j = 0; j < dest_dx/2; j ++)
  1301.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1302.                     sy += yPitch;
  1303.                     su += uPitch;
  1304.                     sv += vPitch;
  1305.                     d  += dest_pitch;
  1306.                     dest_dy --;
  1307.                 }
  1308.                 /* the main loop (processes two lines a time): */
  1309.                 for (i = 0; i < dest_dy/2; i ++) {
  1310.                     for (j = 0; j < dest_dx/2; j ++)
  1311.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1312.                     sy += yPitch;
  1313.                     d  += dest_pitch;
  1314.                     for (j = 0; j < dest_dx/2; j ++)
  1315.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1316.                     sy += yPitch;
  1317.                     su += uPitch;
  1318.                     sv += vPitch;
  1319.                     d  += dest_pitch;
  1320.                 }
  1321.                 /* process the last line (if dy is odd): */
  1322.                 if (dest_dy & 1) {
  1323.                     for (j = 0; j < dest_dx/2; j ++)
  1324.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1325.                 }
  1326.             }
  1327.         } else
  1328.         /* check if no hue adjustment: */
  1329.         if (!is_alpha) {
  1330.             /* no chroma rotation: */
  1331.             unsigned char *sy, *sv, *su, *d;
  1332.             register int i, j;
  1333.             /* get pointers: */
  1334.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  1335.             su = pU + (src_x/2 + src_y/2 * uPitch);
  1336.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  1337.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1338.             /* process top line (if chroma is not pairable): */
  1339.             if (dest_y & 1) {
  1340.                 for (j = 0; j < dest_dx/2; j ++)
  1341.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1342.                 sy += yPitch;
  1343.                 su += uPitch;
  1344.                 sv += vPitch;
  1345.                 d  += dest_pitch;
  1346.                 dest_dy --;
  1347.             }
  1348.             /* the main loop (processes two lines a time): */
  1349.             for (i = 0; i < dest_dy/2; i ++) {
  1350.                 for (j = 0; j < dest_dx/2; j ++)
  1351.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1352.                 sy += yPitch;
  1353.                 d  += dest_pitch;
  1354.                 for (j = 0; j < dest_dx/2; j ++)
  1355.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1356.                 sy += yPitch;
  1357.                 su += uPitch;
  1358.                 sv += vPitch;
  1359.                 d  += dest_pitch;
  1360.             }
  1361.             /* process the last line (if dy is odd): */
  1362.             if (dest_dy & 1) {
  1363.                 for (j = 0; j < dest_dx/2; j ++)
  1364.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1365.             }
  1366.         } else {
  1367.             /* the most complex case (w. hue adjustement): */
  1368.             unsigned char *sy, *sv, *su, *d;
  1369.             register int i, j, u, v;
  1370.             /* get pointers: */
  1371.             sy = pY + src_x + src_y * yPitch;           /* luma offset */
  1372.             su = pU + (src_x/2 + src_y/2 * uPitch);
  1373.             sv = pV + (src_x/2 + src_y/2 * vPitch);
  1374.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1375.             /* process top line (if chroma is not pairable): */
  1376.             if (dest_y & 1) {
  1377.                 for (j = 0; j < dest_dx/2; j ++) {
  1378.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1379.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1380.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1381.                 }
  1382.                 sy += yPitch;
  1383.                 su += uPitch;
  1384.                 sv += vPitch;
  1385.                 d  += dest_pitch;
  1386.                 dest_dy --;
  1387.             }
  1388.             /* the main loop (processes two lines a time): */
  1389.             for (i = 0; i < dest_dy/2; i ++) {
  1390.                 for (j = 0; j < dest_dx/2; j ++) {
  1391.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1392.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1393.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1394.                     *(unsigned int *)(d + j*4 + dest_pitch) = u | (_yytab[sy[j*2 + yPitch]] << 8) | (v << 16) | (_yytab[sy[j*2+1 + yPitch]] << 24);
  1395.                 }
  1396.                 sy += yPitch*2;
  1397.                 su += uPitch;
  1398.                 sv += vPitch;
  1399.                 d  += dest_pitch*2;
  1400.             }
  1401.             /* process the last line (if dy is odd): */
  1402.             if (dest_dy & 1) {
  1403.                 for (j = 0; j < dest_dx/2; j ++) {
  1404.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1405.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1406.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1407.                 }
  1408.             }
  1409.         }
  1410.         return 0;
  1411.     }
  1412.     /* conversion is not supported */
  1413.     return -1;
  1414. }
  1415. /*
  1416.  * I420toUYVY() converter:
  1417.  */
  1418. int I420toUYVY (unsigned char *dest_ptr, int dest_width, int dest_height,
  1419.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1420.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1421.     int src_x, int src_y, int src_dx, int src_dy)
  1422. {
  1423. #if 1
  1424.     unsigned char *pU = src_ptr+src_height*src_pitch,
  1425.                   *pV = pU + src_height*src_pitch/4;
  1426.     return I420toUYVYx(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1427.                        src_ptr, pU, pV, 
  1428.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1429.                        src_x, src_y, src_dx, src_dy);
  1430.                     
  1431. #else
  1432.     /* scale factors: */
  1433.     int scale_x, scale_y;
  1434.     /* check arguments: */
  1435.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1436.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1437.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1438.         return -1;
  1439.     /* remove odd destination columns: */
  1440.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x))
  1441.         return 0;
  1442.     /* check if we have misaligned input: */
  1443.     if (src_x & 1)
  1444.         return -1;                          /* can't shift chromas */
  1445.     /* check if bottop-up images: */
  1446.     if (dest_pitch < 0) dest_ptr -= (dest_height-1) * dest_pitch;
  1447.     if (src_pitch <= 0) return -1;          /* not supported */
  1448.     /* check if 1:1 scale: */
  1449.     if (scale_x == 1 && scale_y == 1) {
  1450.         /* check if no color adjustments: */
  1451.         if (!(is_alpha | is_beta | is_gamma | is_kappa)) {
  1452.             /* no color adjustments: */
  1453.             unsigned char *sy, *sv, *su, *d;
  1454.             register int i, j;
  1455.             /* get pointers: */
  1456.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1457.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  1458.             sv = su + src_height * src_pitch / 4;
  1459.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1460. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS))  && !defined(WINCE_EMULATOR)
  1461.             /* check if we can use MMX-optimized code here: */
  1462.             if (_x86_MMX_Available)
  1463.             {
  1464.                 /* process top line (if chroma is not pairable): */
  1465.                 if (dest_y & 1) {
  1466.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1467.                     sy += src_pitch;
  1468.                     su += src_pitch/2;
  1469.                     sv += src_pitch/2;
  1470.                     d  += dest_pitch;
  1471.                     dest_dy --;
  1472.                 }
  1473.                 /* the main loop (processes two lines a time): */
  1474.                 for (i = 0; i < dest_dy/2; i ++) {
  1475.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1476.                     sy += src_pitch;
  1477.                     d  += dest_pitch;
  1478.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1479.                     sy += src_pitch;
  1480.                     su += src_pitch/2;
  1481.                     sv += src_pitch/2;
  1482.                     d  += dest_pitch;
  1483.                 }
  1484.                 /* process the last line (if dy is odd): */
  1485.                 if (dest_dy & 1) {
  1486.                     _MMX_lineI420toUYVY (sy, su, sv, d, dest_dx);
  1487.                 }
  1488.                 /* end of MMX code */
  1489. #if defined(_M_IX86) && !defined(WINCE_EMULATOR)                
  1490.                 __asm emms
  1491. #elif defined(_USE_MMX_BLENDERS) && !defined(WINCE_EMULATOR)
  1492.                 __asm__ __volatile__ ( "emms" );
  1493. #endif                    
  1494.             } else
  1495. #endif
  1496.             /* a generic "C" version: */
  1497.             {
  1498.                 /* process top line (if chroma is not pairable): */
  1499.                 if (dest_y & 1) {
  1500.                     for (j = 0; j < dest_dx/2; j ++)
  1501.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1502.                     sy += src_pitch;
  1503.                     su += src_pitch/2;
  1504.                     sv += src_pitch/2;
  1505.                     d  += dest_pitch;
  1506.                     dest_dy --;
  1507.                 }
  1508.                 /* the main loop (processes two lines a time): */
  1509.                 for (i = 0; i < dest_dy/2; i ++) {
  1510.                     for (j = 0; j < dest_dx/2; j ++)
  1511.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1512.                     sy += src_pitch;
  1513.                     d  += dest_pitch;
  1514.                     for (j = 0; j < dest_dx/2; j ++)
  1515.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1516.                     sy += src_pitch;
  1517.                     su += src_pitch/2;
  1518.                     sv += src_pitch/2;
  1519.                     d  += dest_pitch;
  1520.                 }
  1521.                 /* process the last line (if dy is odd): */
  1522.                 if (dest_dy & 1) {
  1523.                     for (j = 0; j < dest_dx/2; j ++)
  1524.                         *(unsigned int *)(d + j*4) = su[j] | (sy[j*2] << 8) | (sv[j] << 16) | (sy[j*2+1] << 24);
  1525.                 }
  1526.             }
  1527.         } else
  1528.         /* check if no hue adjustment: */
  1529.         if (!is_alpha) {
  1530.             /* no chroma rotation: */
  1531.             unsigned char *sy, *sv, *su, *d;
  1532.             register int i, j;
  1533.             /* get pointers: */
  1534.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1535.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  1536.             sv = su + src_height * src_pitch / 4;
  1537.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1538.             /* process top line (if chroma is not pairable): */
  1539.             if (dest_y & 1) {
  1540.                 for (j = 0; j < dest_dx/2; j ++)
  1541.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1542.                 sy += src_pitch;
  1543.                 su += src_pitch/2;
  1544.                 sv += src_pitch/2;
  1545.                 d  += dest_pitch;
  1546.                 dest_dy --;
  1547.             }
  1548.             /* the main loop (processes two lines a time): */
  1549.             for (i = 0; i < dest_dy/2; i ++) {
  1550.                 for (j = 0; j < dest_dx/2; j ++)
  1551.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1552.                 sy += src_pitch;
  1553.                 d  += dest_pitch;
  1554.                 for (j = 0; j < dest_dx/2; j ++)
  1555.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1556.                 sy += src_pitch;
  1557.                 su += src_pitch/2;
  1558.                 sv += src_pitch/2;
  1559.                 d  += dest_pitch;
  1560.             }
  1561.             /* process the last line (if dy is odd): */
  1562.             if (dest_dy & 1) {
  1563.                 for (j = 0; j < dest_dx/2; j ++)
  1564.                     *(unsigned int *)(d + j*4) = _uutab[su[j]] | (_yytab[sy[j*2]] << 8) | (_vvtab[sv[j]] << 16) | (_yytab[sy[j*2+1]] << 24);
  1565.             }
  1566.         } else {
  1567.             /* the most complex case (w. hue adjustement): */
  1568.             unsigned char *sy, *sv, *su, *d;
  1569.             register int i, j, u, v;
  1570.             /* get pointers: */
  1571.             sy = src_ptr + src_x + src_y * src_pitch;           /* luma offset */
  1572.             su = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch/2);
  1573.             sv = su + src_height * src_pitch / 4;
  1574.             d  = dest_ptr + dest_x * 2 + dest_y * dest_pitch;   /* 2 bytes/pixel */
  1575.             /* process top line (if chroma is not pairable): */
  1576.             if (dest_y & 1) {
  1577.                 for (j = 0; j < dest_dx/2; j ++) {
  1578.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1579.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1580.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1581.                 }
  1582.                 sy += src_pitch;
  1583.                 su += src_pitch/2;
  1584.                 sv += src_pitch/2;
  1585.                 d  += dest_pitch;
  1586.                 dest_dy --;
  1587.             }
  1588.             /* the main loop (processes two lines a time): */
  1589.             for (i = 0; i < dest_dy/2; i ++) {
  1590.                 for (j = 0; j < dest_dx/2; j ++) {
  1591.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1592.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1593.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1594.                     *(unsigned int *)(d + j*4 + dest_pitch) = u | (_yytab[sy[j*2 + src_pitch]] << 8) | (v << 16) | (_yytab[sy[j*2+1 + src_pitch]] << 24);
  1595.                 }
  1596.                 sy += src_pitch*2;
  1597.                 su += src_pitch/2;
  1598.                 sv += src_pitch/2;
  1599.                 d  += dest_pitch*2;
  1600.             }
  1601.             /* process the last line (if dy is odd): */
  1602.             if (dest_dy & 1) {
  1603.                 for (j = 0; j < dest_dx/2; j ++) {
  1604.                     v = _CLIP(8,_vvtab[sv[j]] + _vutab[su[j]]);
  1605.                     u = _CLIP(8,_uutab[su[j]] + _uvtab[sv[j]]);
  1606.                     *(unsigned int *)(d + j*4) = u | (_yytab[sy[j*2]] << 8) | (v << 16) | (_yytab[sy[j*2+1]] << 24);
  1607.                 }
  1608.             }
  1609.         }
  1610.         return 0;
  1611.     }
  1612.     /* conversion is not supported */
  1613.     return -1;
  1614. #endif //0
  1615. }
  1616. /*** "to I420" converters: *********************************/
  1617. int YV12toI420x (unsigned char *dest_ptr, int dest_width, int dest_height,
  1618.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1619.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1620.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1621.                  int src_x, int src_y, int src_dx, int src_dy)
  1622. {
  1623.     /* scale factors: */
  1624.     int scale_x, scale_y;
  1625. /* Chroma Shifting Allowed */
  1626. int OddPattern;
  1627.     /* check arguments: */
  1628.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1629.         dest_x, dest_y, dest_dx, dest_dy, pY, src_width, src_height,
  1630.         yPitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1631.         return -1;
  1632.     /* remove odd destination pixels: */
  1633.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  1634.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  1635.         return 0;
  1636.     /* check if we have matching chroma components: */
  1637.     //if ((src_x & 1) || (src_y & 1))
  1638.     //    return -1;                          /* can't shift chromas */
  1639.     /* check if bottop-up images: */
  1640.     if (dest_pitch <= 0 || yPitch <= 0)
  1641.         return -1;                          /* not supported */
  1642. /*
  1643.  *  if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
  1644.  */
  1645.     {
  1646.         /* just move data in, no color adjustments: */
  1647.         unsigned char *sy, *su, *sv, *d, *su2, *sv2;
  1648.         int dest_uv_offs;
  1649.         register int i,j;
  1650.         /* copy Y plane: */
  1651.         sy = pY + src_x + src_y * yPitch;
  1652.         d = dest_ptr + dest_x + dest_y * dest_pitch;
  1653.         for (i = 0; i < dest_dy; i ++) {
  1654.             memcpy (d, sy, dest_dx); /* Flawfinder: ignore */
  1655.             sy += yPitch;
  1656.             d += dest_pitch;
  1657.         }
  1658.         /* get Cr/Cb offsets: */
  1659.         dest_uv_offs = dest_height * dest_pitch / 4;
  1660.         /* copy & flip Cr/Cb planes: */
  1661.         su = pU + src_x/2 + src_y/2 * uPitch;
  1662.         sv = pV + src_x/2 + src_y/2 * vPitch;
  1663.         d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  1664. OddPattern = ((src_y & 1) << 1) | (src_x & 1);
  1665. // extremely cheap way to handle 1 pel cropping
  1666.         for (i = 0; i < dest_dy/2; i ++) {
  1667. if((i+1) < dest_dy/2) {
  1668. su2 = su+uPitch;
  1669. sv2 = sv+vPitch;
  1670. } else {
  1671. su2 = su;
  1672. sv2 = sv;
  1673. }
  1674. /* convert pixels: */
  1675. switch(OddPattern)
  1676. {
  1677. case(0):
  1678. memcpy (d, su, dest_dx/2); /* Flawfinder: ignore */
  1679. memcpy (d + dest_uv_offs, sv, dest_dx/2); /* Flawfinder: ignore */
  1680. break;
  1681. case(1):
  1682. for (j = 0; j < dest_dx/2 -1; j ++) {
  1683. d[j] = ((unsigned int)su[j] + (unsigned int)su[j+1] + 1)>>1;
  1684. d[j + dest_uv_offs] = ((unsigned int)sv[j] + (unsigned int)sv[j+1] + 1)>>1;
  1685. }
  1686. d[j] = su[j];
  1687. d[j + dest_uv_offs] = sv[j];
  1688. break;
  1689. case(2):
  1690. for (j = 0; j < dest_dx/2; j ++) {
  1691. d[j] = ((unsigned int)su[j] + (unsigned int)su2[j] + 1)>>1;
  1692. d[j + dest_uv_offs] = ((unsigned int)sv[j] + (unsigned int)sv2[j] + 1)>>1;
  1693. }
  1694. break;
  1695. case(3):
  1696. for (j = 0; j < dest_dx/2 -1; j ++) {
  1697. d[j] = ((unsigned int)su[j] + (unsigned int)su[j+1] + (unsigned int)su2[j] + (unsigned int)su2[j+1] + 2)>>2;
  1698. d[j + dest_uv_offs] = ((unsigned int)sv[j] + (unsigned int)sv[j+1] + (unsigned int)sv2[j] + (unsigned int)sv2[j+1] + 2)>>2;
  1699. }
  1700. d[j] = ((unsigned int)su[j]+ (unsigned int)su2[j] + 1)>>1;
  1701. d[j + dest_uv_offs] = ((unsigned int)sv[j] + (unsigned int)sv2[j] + 1) >> 1;
  1702. break;
  1703. }
  1704. su += uPitch;
  1705. sv += vPitch;
  1706.             d += dest_pitch/2;
  1707.         }
  1708.     }
  1709. /*
  1710.  *  else {
  1711.  *      put all the color-dependent stuff here ...
  1712.  *  }
  1713.  */
  1714.     return 0;
  1715. }
  1716. int YV12toI420 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1717.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1718.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1719.     int src_x, int src_y, int src_dx, int src_dy)
  1720. {
  1721. #if 1
  1722.     unsigned char *pV = src_ptr+src_height*src_pitch,
  1723.                   *pU = pV + src_height*src_pitch/4;
  1724.     return YV12toI420x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1725.                        src_ptr, pU, pV, 
  1726.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1727.                        src_x, src_y, src_dx, src_dy);
  1728. #else    
  1729.     /* scale factors: */
  1730.     int scale_x, scale_y;
  1731.     /* check arguments: */
  1732.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1733.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1734.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1735.         return -1;
  1736.     /* remove odd destination pixels: */
  1737.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  1738.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  1739.         return 0;
  1740.     /* check if we have matching chroma components: */
  1741.     if ((src_x & 1) || (src_y & 1))
  1742.         return -1;                          /* can't shift chromas */
  1743.     /* check if bottop-up images: */
  1744.     if (dest_pitch <= 0 || src_pitch <= 0)
  1745.         return -1;                          /* not supported */
  1746. /*
  1747.  *  if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
  1748.  */
  1749.     {
  1750.         /* just move data in, no color adjustments: */
  1751.         unsigned char *s, *d;
  1752.         int src_uv_offs, dest_uv_offs;
  1753.         register int i;
  1754.         /* copy Y plane: */
  1755.         s = src_ptr + src_x + src_y * src_pitch;
  1756.         d = dest_ptr + dest_x + dest_y * dest_pitch;
  1757.         for (i = 0; i < dest_dy; i ++) {
  1758.             memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  1759.             s += src_pitch;
  1760.             d += dest_pitch;
  1761.         }
  1762.         /* get Cr/Cb offsets: */
  1763.         src_uv_offs = src_height * src_pitch / 4;
  1764.         dest_uv_offs = dest_height * dest_pitch / 4;
  1765.         /* copy & flip Cr/Cb planes: */
  1766.         s = (src_ptr + src_height * src_pitch) + src_x/2 + src_y/2 * src_pitch/2;
  1767.         d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  1768.         for (i = 0; i < dest_dy/2; i ++) {
  1769.             memcpy (d, s + src_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  1770.             memcpy (d + dest_uv_offs, s, dest_dx/2); /* Flawfinder: ignore */
  1771.             s += src_pitch/2;
  1772.             d += dest_pitch/2;
  1773.         }
  1774.     }
  1775. /*
  1776.  *  else {
  1777.  *      put all the color-dependent stuff here ...
  1778.  *  }
  1779.  */
  1780.     return 0;
  1781. #endif
  1782. }
  1783. int YV12toYV12x (unsigned char *dest_ptr, int dest_width, int dest_height,
  1784.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1785.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1786.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1787.                  int src_x, int src_y, int src_dx, int src_dy)
  1788. {
  1789.     return I420toYV12x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1790.                        pY, pU, pV, 
  1791.                        src_width, src_height, yPitch, uPitch, vPitch,
  1792.                        src_x, src_y, src_dx, src_dy);
  1793. }
  1794. int YV12toYV12 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1795.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1796.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1797.     int src_x, int src_y, int src_dx, int src_dy)
  1798. {
  1799.     unsigned char *pV = src_ptr+src_height*src_pitch,
  1800.                   *pU = pV + src_height*src_pitch/4;
  1801.     return I420toYV12x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1802.                        src_ptr, pU, pV, 
  1803.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1804.                        src_x, src_y, src_dx, src_dy);
  1805. }
  1806. int YV12toYUY2x (unsigned char *dest_ptr, int dest_width, int dest_height,
  1807.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1808.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1809.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1810.                  int src_x, int src_y, int src_dx, int src_dy)
  1811. {
  1812.     return I420toYUY2x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1813.                        pY, pU, pV, 
  1814.                        src_width, src_height, yPitch, uPitch, vPitch,
  1815.                        src_x, src_y, src_dx, src_dy);
  1816. }
  1817. int YV12toYUY2 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1818.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1819.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1820.     int src_x, int src_y, int src_dx, int src_dy)
  1821. {
  1822.     unsigned char *pV = src_ptr+src_height*src_pitch,
  1823.                   *pU = pV + src_height*src_pitch/4;
  1824.     return I420toYUY2x(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1825.                        src_ptr, pU, pV, 
  1826.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1827.                        src_x, src_y, src_dx, src_dy);
  1828. }
  1829. int YV12toUYVYx (unsigned char *dest_ptr, int dest_width, int dest_height,
  1830.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1831.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  1832.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  1833.                  int src_x, int src_y, int src_dx, int src_dy)
  1834. {
  1835.     return I420toUYVYx(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1836.                        pY, pU, pV, 
  1837.                        src_width, src_height, yPitch, uPitch, vPitch,
  1838.                        src_x, src_y, src_dx, src_dy);
  1839. }
  1840. int YV12toUYVY (unsigned char *dest_ptr, int dest_width, int dest_height,
  1841.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1842.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1843.     int src_x, int src_y, int src_dx, int src_dy)
  1844. {
  1845.     unsigned char *pV = src_ptr+src_height*src_pitch,
  1846.                   *pU = pV + src_height*src_pitch/4;
  1847.     return I420toUYVYx(dest_ptr, dest_width, dest_height, dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
  1848.                        src_ptr, pU, pV, 
  1849.                        src_width, src_height, src_pitch, src_pitch/2, src_pitch/2,
  1850.                        src_x, src_y, src_dx, src_dy);
  1851. }
  1852. static void lineYVU9toI420 (unsigned char *d, unsigned char *s, int x, int dx)
  1853. {
  1854.     register int i;
  1855.     /* first pixel: */
  1856. // extremely cheap way to handle 1 pel cropping
  1857.     switch(x&3)
  1858. {
  1859. case(0):
  1860. case(1):
  1861. break;    
  1862. case(2):
  1863.         d[0] = s[0];
  1864.         s += 1;
  1865.         d += 1;
  1866.         dx -= 2;
  1867. break;
  1868. case(3):
  1869. //d[0] = s[0];
  1870. s += 1;
  1871. //d += 1;
  1872.         //dx -= 2;
  1873. break;
  1874. }    
  1875.     /* the main loop: */
  1876.     for (i = 0; i < dx/4; i ++) {
  1877.         d[i*2] = s[i];
  1878.         d[i*2+1] = s[i];
  1879.     }
  1880.     /* last pixel: */
  1881.     if (dx & 2)
  1882.         d[dx/2] = s[dx/4];
  1883. }
  1884. #if 1
  1885. /*-----------------2/24/2002 2:01PM-----------------
  1886.  * fixes:
  1887.  *  - switched u and v pointers
  1888.  * --------------------------------------------------*/
  1889. int YVU9toI420 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1890.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1891.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1892.     int src_x, int src_y, int src_dx, int src_dy)
  1893. {
  1894.     /* scale factors: */
  1895.     int scale_x, scale_y;
  1896.     /* check arguments: */
  1897.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1898.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1899.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1900.         return -1;
  1901.     /* remove odd destination pixels: */
  1902.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  1903.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  1904.         return 0;
  1905.     /* check if we have matching chroma components: */
  1906.     //if ((src_x & 1) || (src_y & 1))
  1907.     //return -1;                          /* can't shift chromas */
  1908.     /* check if bottop-up images: */
  1909.     if (dest_pitch <= 0 || src_pitch <= 0)
  1910.         return -1;                          /* not supported */
  1911. /*
  1912.  *  if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
  1913.  */
  1914.     {
  1915.         /* no color adjustments: */
  1916.         unsigned char *s, *d;
  1917.         int src_uv_offs, dest_uv_offs;
  1918.         register int j;
  1919.         /* copy Y plane: */
  1920.         s = src_ptr + src_x + src_y * src_pitch;
  1921.         d = dest_ptr + dest_x + dest_y * dest_pitch;
  1922.         for (j = 0; j < dest_dy; j ++) {
  1923.             memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  1924.             s += src_pitch;
  1925.             d += dest_pitch;
  1926.         }
  1927.         /* get Cr/Cb offsets: */
  1928.         src_uv_offs = src_height * src_pitch / 16;
  1929.         dest_uv_offs = dest_height * dest_pitch / 4;
  1930.         /* get pointers: */
  1931.         s = (src_ptr + src_height * src_pitch) + src_x/4 + src_y/4 * src_pitch/4;
  1932.         d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  1933.         /* top lines: */
  1934. // extremely cheap way to handle 1 pel cropping
  1935.         switch(src_y & 3) 
  1936. {
  1937. case(2):
  1938. case(3):
  1939.             lineYVU9toI420 (d, s + src_uv_offs, src_x, dest_dx);   /* Cr */
  1940.             lineYVU9toI420 (d + dest_uv_offs, s, src_x, dest_dx);  /* Cb */
  1941.             s += src_pitch/4;
  1942.             d += dest_pitch/2;
  1943.             dest_dy -= 2;
  1944. break;
  1945. case(0):
  1946. case(1):
  1947. break;
  1948.         }
  1949.         /* the main loop (processes two lines a time): */
  1950.         for (j = 0; j < dest_dy/4; j ++) {
  1951.             lineYVU9toI420 (d, s + src_uv_offs, src_x, dest_dx);   /* Cr */
  1952.             memcpy (d + dest_pitch/2, d, dest_dx/2); /* Flawfinder: ignore */
  1953.             lineYVU9toI420 (d + dest_uv_offs, s, src_x, dest_dx);  /* Cb */
  1954.             memcpy (d + dest_pitch/2 + dest_uv_offs, d + dest_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  1955.             s += src_pitch/4;
  1956.             d += dest_pitch;
  1957.         }
  1958.         /* bottom lines: */
  1959.         if (dest_dy & 2) {
  1960.             lineYVU9toI420 (d, s + src_uv_offs, src_x, dest_dx);   /* Cr */
  1961.             lineYVU9toI420 (d + dest_uv_offs, s, src_x, dest_dx);  /* Cb */
  1962.         }
  1963.     }
  1964. /*
  1965.  *  else {
  1966.  *      put all the color-dependent stuff here ...
  1967.  *  }
  1968.  */
  1969.     return 0;
  1970. }
  1971. #else
  1972. int YVU9toI420 (unsigned char *dest_ptr, int dest_width, int dest_height,
  1973.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  1974.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  1975.     int src_x, int src_y, int src_dx, int src_dy)
  1976. {
  1977.     /* scale factors: */
  1978.     int scale_x, scale_y;
  1979.     /* check arguments: */
  1980.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  1981.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  1982.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  1983.         return -1;
  1984.     /* remove odd destination pixels: */
  1985.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  1986.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  1987.         return 0;
  1988.     /* check if we have matching chroma components: */
  1989.     if ((src_x & 1) || (src_y & 1))
  1990.         return -1;                          /* can't shift chromas */
  1991.     /* check if bottop-up images: */
  1992.     if (dest_pitch <= 0 || src_pitch <= 0)
  1993.         return -1;                          /* not supported */
  1994. /*
  1995.  *  if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
  1996.  */
  1997.     {
  1998.         /* no color adjustments: */
  1999.         unsigned char *s, *d;
  2000.         int src_uv_offs, dest_uv_offs;
  2001.         register int j;
  2002.         /* copy Y plane: */
  2003.         s = src_ptr + src_x + src_y * src_pitch;
  2004.         d = dest_ptr + dest_x + dest_y * dest_pitch;
  2005.         for (j = 0; j < dest_dy; j ++) {
  2006.             memcpy (d, s, dest_dx); /* Flawfinder: ignore */
  2007.             s += src_pitch;
  2008.             d += dest_pitch;
  2009.         }
  2010.         /* get Cr/Cb offsets: */
  2011.         src_uv_offs = src_height * src_pitch / 16;
  2012.         dest_uv_offs = dest_height * dest_pitch / 4;
  2013.         /* get pointers: */
  2014.         s = (src_ptr + src_height * src_pitch) + src_x/4 + src_y/4 * src_pitch/4;
  2015.         d = (dest_ptr + dest_height * dest_pitch) + dest_x/2 + dest_y/2 * dest_pitch/2;
  2016.         /* top lines: */
  2017.         if (src_y & 2) {
  2018.             lineYVU9toI420 (d, s, src_x, dest_dx);   /* Cr */
  2019.             lineYVU9toI420 (d + dest_uv_offs, s + src_uv_offs, src_x, dest_dx);  /* Cb */
  2020.             s += src_pitch/4;
  2021.             d += dest_pitch/2;
  2022.             dest_dy -= 2;
  2023.         }
  2024.         /* the main loop (processes two lines a time): */
  2025.         for (j = 0; j < dest_dy/4; j ++) {
  2026.             lineYVU9toI420 (d, s, src_x, dest_dx);   /* Cr */
  2027.             memcpy (d + dest_pitch/2, d, dest_dx/2); /* Flawfinder: ignore */
  2028.             lineYVU9toI420 (d + dest_uv_offs, s + src_uv_offs, src_x, dest_dx);  /* Cb */
  2029.             memcpy (d + dest_pitch/2 + dest_uv_offs, d + dest_uv_offs, dest_dx/2); /* Flawfinder: ignore */
  2030.             s += src_pitch/4;
  2031.             d += dest_pitch;
  2032.         }
  2033.         /* bottom lines: */
  2034.         if (dest_dy & 2) {
  2035.             lineYVU9toI420 (d, s, src_x, dest_dx);   /* Cr */
  2036.             lineYVU9toI420 (d + dest_uv_offs, s + src_uv_offs, src_x, dest_dx);  /* Cb */
  2037.         }
  2038.     }
  2039. /*
  2040.  *  else {
  2041.  *      put all the color-dependent stuff here ...
  2042.  *  }
  2043.  */
  2044.     return 0;
  2045. }
  2046. #endif /* YUV9 */
  2047. static int YUY2toPlanarYUV(unsigned char *dY, unsigned char *dU, unsigned char *dV,
  2048.                            int dest_width, int dest_height,
  2049.                            int dyPitch, int duPitch, int dvPitch,
  2050.                            int dest_x, int dest_y, int dest_dx, int dest_dy,
  2051.                            unsigned char *src_ptr,
  2052.                            int src_width, int src_height, int src_pitch,
  2053.                            int src_x, int src_y, int src_dx, int src_dy)
  2054. {
  2055.     /* scale factors: */
  2056.     int scale_x, scale_y;
  2057.     unsigned char *s1, *s2, *d1, *d2, *dv, *du;
  2058.     register int i, j;
  2059.     /* check arguments: */
  2060.     if (!chk_args (dY, dest_width, dest_height, dyPitch,
  2061.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  2062.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  2063.         return -1;
  2064.     /* remove odd destination pixels: */
  2065.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  2066.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  2067.         return 0;
  2068.     /* check if we have misaligned source: */
  2069.     if (src_x & 1)
  2070.         return -1; /* can't shift chromas */
  2071.     /* check if bottop-up images: */
  2072.     if (dyPitch <= 0)
  2073.         return -1;     /* not supported */
  2074.     if (src_pitch < 0)
  2075.         src_ptr -= (src_height-1) * src_pitch;
  2076.     /* just move data in, no color adjustments: */
  2077.     /* get pointers: */
  2078.     s1 = src_ptr + src_x * 2 + src_y * src_pitch;    /* 2 bytes/pixel */
  2079.     s2 = s1 + src_pitch;
  2080.     d1 = dY + dest_x + dest_y * dyPitch;   /* luma offsets  */
  2081.     d2 = d1 + dyPitch;
  2082.     
  2083.     du = dU + (dest_x/2 + dest_y/2 * duPitch);
  2084.     dv = dV + (dest_x/2 + dest_y/2 * dvPitch);
  2085. #if (defined(_M_IX86) || defined(_USE_MMX_BLENDERS)) && !defined(WINCE_EMULATOR)
  2086.     if (_x86_MMX_Available )
  2087.     {
  2088.         //Use our MMX versions.....
  2089.         HX_ASSERT( src_dx==dest_dx && src_dy==dest_dy );
  2090.         YUY2ToPlanarYUV_MMX( d1, d2, du, dv,
  2091.                              dyPitch, duPitch, dvPitch,
  2092.                              dest_dx, dest_dy, 
  2093.                              s1, s2, src_pitch
  2094.                              );
  2095.     }
  2096.     else
  2097. #endif    
  2098.     {
  2099.         /* the main loop (processes lines a time): */
  2100.         for (i = 0; i < dest_dy/2; i ++)
  2101.         {
  2102.             /* copy 2x2 pixels: */
  2103.             for (j = 0; j < dest_dx/2; j ++)
  2104.             {
  2105.                 /* copy luma components: */
  2106.                 d1[j*2]   = s1[j*4];
  2107.                 d1[j*2+1] = s1[j*4+2];
  2108.                 d2[j*2]   = s2[j*4];
  2109.                 d2[j*2+1] = s2[j*4+2];
  2110.                 
  2111.                 /* average chromas: */
  2112.                 du[j] = ((unsigned int) s1[j*4+1] + (unsigned int)s2[j*4+1]) >> 1;
  2113.                 dv[j] = ((unsigned int) s1[j*4+3] + (unsigned int)s2[j*4+3]) >> 1;
  2114.             }
  2115.             
  2116.             s1 += src_pitch*2;  s2 += src_pitch*2;
  2117.             d1 += dyPitch*2;    d2 += dyPitch*2;
  2118.             du += duPitch;      dv += dvPitch;
  2119.         }
  2120.     }
  2121.     return 0;
  2122. }
  2123. int YUY2toI420x (unsigned char *dest_ptr, int dest_width, int dest_height,
  2124.                  int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  2125.                  unsigned char *pY, unsigned char *pU, unsigned char *pV,
  2126.                  int src_width, int src_height, int yPitch, int uPitch, int vPitch,
  2127.                  int src_x, int src_y, int src_dx, int src_dy)
  2128. {
  2129.     // No need for seperate yuv pointers since yuy2 is packed
  2130.     return YUY2toI420(dest_ptr, dest_width, dest_height,
  2131.                       dest_pitch, dest_x, dest_y, dest_dx, dest_dy,  
  2132.                       pY, src_width, src_height, yPitch,
  2133.                       src_x, src_y, src_dx, src_dy);
  2134. }
  2135. /*
  2136.  * Mac YUVU/YVU2 formats: 
  2137.  * 8-bit 4:2:2 Component Y扖bCr format. 
  2138.  * Each 16 bit pixel is represented by an unsigned eight bit luminance 
  2139.  * component and two two抯 complement signed eight bit chroma components. 
  2140.  * Each pair of pixels shares a common set of chroma values. 
  2141.  * The components are ordered in memory; Y0, Cb, Y1, Cr. 
  2142.  * The luminance components have a range of [0, 255], 
  2143.  * the chroma values have a range of [-127, +127]. 
  2144.  * This format is equivalent to the 憏uv2