home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / jpeg / jdcolor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  17.8 KB  |  600 lines

  1. /*
  2.  * jdcolor.c
  3.  *
  4.  * This file contains an Optimized Routine for YCbCr->RGB Color Space Conversion
  5.  *
  6.  * Copyright (C) 1991-1996, Thomas G. Lane.
  7.  * This file is part of the Independent JPEG Group's software.
  8.  * For conditions of distribution and use, see the accompanying README file.
  9.  *
  10.  * This file contains output colorspace conversion routines.
  11.  *
  12.  */
  13.  
  14.  
  15. #define JPEG_INTERNALS
  16. #include "jinclude.h"
  17. #include "jpeglib.h"
  18. #include "xp_core.h"
  19.  
  20. /* Private subobject */
  21.  
  22. typedef struct {
  23.   struct jpeg_color_deconverter pub; /* public fields */
  24.  
  25.   /* Private state for YCC->RGB conversion */
  26.   int * Cr_r_tab;        /* => table for Cr to R conversion */
  27.   int * Cb_b_tab;        /* => table for Cb to B conversion */
  28.   INT32 * Cr_g_tab;        /* => table for Cr to G conversion */
  29.   INT32 * Cb_g_tab;        /* => table for Cb to G conversion */
  30. } my_color_deconverter;
  31.  
  32. typedef my_color_deconverter * my_cconvert_ptr;
  33.  
  34.  
  35. #ifdef XP_WIN32
  36. /* Info Added for MMX(TM) Technology Optimization */
  37. extern void MMXYCbCr2RGB(
  38.   int columns,      
  39.   unsigned char *inY,
  40.   unsigned char *inU,
  41.   unsigned char *inV,
  42.   unsigned char *outRGB);
  43. /*
  44.  These constants correspond to CCIR 601-1
  45.  R = [256*Y + 359*(Cr-128)] / 256
  46.  G = [256*Y - 88*(Cb-128) - 183*(Cr-128)] / 256
  47.  B = [256*Y + 454*(Cb-128)] / 256
  48. Conventional floating point equations:
  49.     R = Y + 1.40200 * Cr
  50.     G = Y - 0.34414 * Cb - 0.71414 * Cr
  51.     B = Y + 1.77200 * Cb
  52. */
  53. /*Ry=0100 Ru=0000 Rv=0167*/
  54. /*Gy=0100 Gu=FFA8 Gv=FF49*/
  55. /*By=0100 Bu=01C6 Bv=0000*/
  56. /* constants for YCbCr->RGB and YCbCrA->RGBA*/
  57. static __int64 const_0        = 0x0000000000000000;
  58. static __int64 const_sub128    = 0x0080008000800080;
  59. static __int64 const_VUmul    = 0xFF49FFA8FF49FFA8;
  60. static __int64 const_YVmul    = 0x0100016701000167;
  61. static __int64 const_YUmul    = 0x010001C6010001C6;
  62. static __int64 mask_highd    = 0xFFFFFFFF00000000;
  63. static __int64 const_invert    = 0x00FFFFFF00FFFFFF;
  64.  
  65. /* End of added info */
  66. #endif
  67.  
  68. /**************** YCbCr -> RGB conversion: most common case **************/
  69.  
  70. /*
  71.  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
  72.  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
  73.  * The conversion equations to be implemented are therefore
  74.  *    R = Y                + 1.40200 * Cr
  75.  *    G = Y - 0.34414 * Cb - 0.71414 * Cr
  76.  *    B = Y + 1.77200 * Cb
  77.  * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
  78.  * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
  79.  *
  80.  * To avoid floating-point arithmetic, we represent the fractional constants
  81.  * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
  82.  * the products by 2^16, with appropriate rounding, to get the correct answer.
  83.  * Notice that Y, being an integral input, does not contribute any fraction
  84.  * so it need not participate in the rounding.
  85.  *
  86.  * For even more speed, we avoid doing any multiplications in the inner loop
  87.  * by precalculating the constants times Cb and Cr for all possible values.
  88.  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
  89.  * for 12-bit samples it is still acceptable.  It's not very reasonable for
  90.  * 16-bit samples, but if you want lossless storage you shouldn't be changing
  91.  * colorspace anyway.
  92.  * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
  93.  * values for the G calculation are left scaled up, since we must add them
  94.  * together before rounding.
  95.  */
  96.  
  97. #define SCALEBITS    16    /* speediest right-shift on some machines */
  98. #define ONE_HALF    ((INT32) 1 << (SCALEBITS-1))
  99. #define FIX(x)        ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
  100.  
  101.  
  102. /*
  103.  * Initialize tables for YCC->RGB colorspace conversion.
  104.  */
  105.  
  106. LOCAL void
  107. build_ycc_rgb_table (j_decompress_ptr cinfo)
  108. {
  109.   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
  110.   int i;
  111.   INT32 x;
  112.   SHIFT_TEMPS
  113.  
  114.   cconvert->Cr_r_tab = (int *)
  115.     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  116.                 (MAXJSAMPLE+1) * SIZEOF(int));
  117.   cconvert->Cb_b_tab = (int *)
  118.     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  119.                 (MAXJSAMPLE+1) * SIZEOF(int));
  120.   cconvert->Cr_g_tab = (INT32 *)
  121.     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  122.                 (MAXJSAMPLE+1) * SIZEOF(INT32));
  123.   cconvert->Cb_g_tab = (INT32 *)
  124.     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  125.                 (MAXJSAMPLE+1) * SIZEOF(INT32));
  126.  
  127.   for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
  128.     /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
  129.     /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
  130.     /* Cr=>R value is nearest int to 1.40200 * x */
  131.     cconvert->Cr_r_tab[i] = (int)
  132.             RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
  133.     /* Cb=>B value is nearest int to 1.77200 * x */
  134.     cconvert->Cb_b_tab[i] = (int)
  135.             RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
  136.     /* Cr=>G value is scaled-up -0.71414 * x */
  137.     cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
  138.     /* Cb=>G value is scaled-up -0.34414 * x */
  139.     /* We also add in ONE_HALF so that need not do it in inner loop */
  140.     cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
  141.   }
  142. }
  143.  
  144.  
  145. /*
  146.  * Convert some rows of samples to the output colorspace.
  147.  *
  148.  * Note that we change from noninterleaved, one-plane-per-component format
  149.  * to interleaved-pixel format.  The output buffer is therefore three times
  150.  * as wide as the input buffer.
  151.  * A starting row offset is provided only for the input buffer.  The caller
  152.  * can easily adjust the passed output_buf value to accommodate any row
  153.  * offset required on that side.
  154.  */
  155.  
  156. METHODDEF void
  157. ycc_rgb_convert (j_decompress_ptr cinfo,
  158.          JSAMPIMAGE input_buf, JDIMENSION input_row,
  159.          JSAMPARRAY output_buf, int num_rows)
  160. {
  161.   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
  162.   register int y, cb, cr;
  163.   register JSAMPROW outptr;
  164.   register JSAMPROW inptr0, inptr1, inptr2;
  165.   register JDIMENSION col;
  166.   JDIMENSION num_cols = cinfo->output_width;
  167. #ifdef XP_WIN32
  168. /* Alignment variables - CRK */
  169. /* JDIMENSION tail_cols = num_cols&7; */
  170.  
  171.   JDIMENSION mmx_cols=num_cols&~7;
  172. #endif
  173.  
  174.   /* copy these pointers into registers if possible */
  175.   register JSAMPLE * range_limit = cinfo->sample_range_limit;
  176.   register int * Crrtab = cconvert->Cr_r_tab;
  177.   register int * Cbbtab = cconvert->Cb_b_tab;
  178.   register INT32 * Crgtab = cconvert->Cr_g_tab;
  179.   register INT32 * Cbgtab = cconvert->Cb_g_tab;
  180.   SHIFT_TEMPS
  181.  
  182. #ifdef XP_WIN32
  183.   if(MMXAvailable) { //MMX Code - CRK
  184.     while (--num_rows >= 0) {
  185.         inptr0 = input_buf[0][input_row];
  186.         inptr1 = input_buf[1][input_row];
  187.         inptr2 = input_buf[2][input_row];
  188.         input_row++;
  189.         outptr = *output_buf++;
  190.         MMXYCbCr2RGB(mmx_cols, inptr0, inptr1, inptr2, outptr);
  191.         
  192.         outptr += 3*mmx_cols;
  193.         for (col = mmx_cols; col < num_cols; col++) {
  194.           y  = GETJSAMPLE(inptr0[col]);
  195.           cb = GETJSAMPLE(inptr1[col]);
  196.           cr = GETJSAMPLE(inptr2[col]);
  197.           /* Range-limiting is essential due to noise introduced by DCT losses. */
  198.           outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
  199.           outptr[RGB_GREEN] = range_limit[y +
  200.                       ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
  201.                              SCALEBITS))];
  202.           outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
  203.           outptr += RGB_PIXELSIZE;
  204.         }
  205.     }
  206.     __asm emms    
  207.   }
  208.   else
  209.     {
  210. #endif
  211.     while    (--num_rows >= 0) {
  212.         inptr0 = input_buf[0][input_row];
  213.         inptr1 = input_buf[1][input_row];
  214.         inptr2 = input_buf[2][input_row];
  215.         input_row++;
  216.         outptr = *output_buf++;
  217.  
  218.         for (col = 0; col < num_cols; col++) {
  219.           y  = GETJSAMPLE(inptr0[col]);
  220.           cb = GETJSAMPLE(inptr1[col]);
  221.           cr = GETJSAMPLE(inptr2[col]);
  222.           /* Range-limiting is essential due to noise introduced by DCT losses. */
  223.           outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
  224.           outptr[RGB_GREEN] = range_limit[y +
  225.                       ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
  226.                              SCALEBITS))];
  227.           outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
  228.           outptr += RGB_PIXELSIZE;
  229.         }    
  230.     }
  231. #ifdef XP_WIN32
  232.   }
  233. #endif
  234. }
  235.  
  236.  
  237.  
  238.  
  239. /**************** Cases other than YCbCr -> RGB **************/
  240.  
  241.  
  242. /*
  243.  * Color conversion for no colorspace change: just copy the data,
  244.  * converting from separate-planes to interleaved representation.
  245.  */
  246.  
  247. METHODDEF void
  248. null_convert (j_decompress_ptr cinfo,
  249.           JSAMPIMAGE input_buf, JDIMENSION input_row,
  250.           JSAMPARRAY output_buf, int num_rows)
  251. {
  252.   register JSAMPROW inptr, outptr;
  253.   register JDIMENSION count;
  254.   register int num_components = cinfo->num_components;
  255.   JDIMENSION num_cols = cinfo->output_width;
  256.   int ci;
  257.  
  258.   while (--num_rows >= 0) {
  259.     for (ci = 0; ci < num_components; ci++) {
  260.       inptr = input_buf[ci][input_row];
  261.       outptr = output_buf[0] + ci;
  262.       for (count = num_cols; count > 0; count--) {
  263.     *outptr = *inptr++;    /* needn't bother with GETJSAMPLE() here */
  264.     outptr += num_components;
  265.       }
  266.     }
  267.     input_row++;
  268.     output_buf++;
  269.   }
  270. }
  271.  
  272.  
  273.  
  274. /*
  275.  * Color conversion for grayscale: just copy the data.
  276.  * This also works for YCbCr -> grayscale conversion, in which
  277.  * we just copy the Y (luminance) component and ignore chrominance.
  278.  */
  279.  
  280. METHODDEF void
  281. grayscale_convert (j_decompress_ptr cinfo,
  282.            JSAMPIMAGE input_buf, JDIMENSION input_row,
  283.            JSAMPARRAY output_buf, int num_rows)
  284. {
  285.   jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
  286.             num_rows, cinfo->output_width);
  287. }
  288.  
  289.  
  290. /*
  291.  * Adobe-style YCCK->CMYK conversion.
  292.  * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
  293.  * conversion as above, while passing K (black) unchanged.
  294.  * We assume build_ycc_rgb_table has been called.
  295.  */
  296.  
  297. METHODDEF void
  298. ycck_cmyk_convert (j_decompress_ptr cinfo,
  299.            JSAMPIMAGE input_buf, JDIMENSION input_row,
  300.            JSAMPARRAY output_buf, int num_rows)
  301. {
  302.   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
  303.   register int y, cb, cr;
  304.   register JSAMPROW outptr;
  305.   register JSAMPROW inptr0, inptr1, inptr2, inptr3;
  306.   register JDIMENSION col;
  307.   JDIMENSION num_cols = cinfo->output_width;
  308.   /* copy these pointers into registers if possible */
  309.   register JSAMPLE * range_limit = cinfo->sample_range_limit;
  310.   register int * Crrtab = cconvert->Cr_r_tab;
  311.   register int * Cbbtab = cconvert->Cb_b_tab;
  312.   register INT32 * Crgtab = cconvert->Cr_g_tab;
  313.   register INT32 * Cbgtab = cconvert->Cb_g_tab;
  314.   SHIFT_TEMPS
  315.  
  316.   while (--num_rows >= 0) {
  317.     inptr0 = input_buf[0][input_row];
  318.     inptr1 = input_buf[1][input_row];
  319.     inptr2 = input_buf[2][input_row];
  320.     inptr3 = input_buf[3][input_row];
  321.     input_row++;
  322.     outptr = *output_buf++;
  323.     for (col = 0; col < num_cols; col++) {
  324.       y  = GETJSAMPLE(inptr0[col]);
  325.       cb = GETJSAMPLE(inptr1[col]);
  326.       cr = GETJSAMPLE(inptr2[col]);
  327.       /* Range-limiting is essential due to noise introduced by DCT losses. */
  328.       outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])];    /* red */
  329.       outptr[1] = range_limit[MAXJSAMPLE - (y +            /* green */
  330.                   ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
  331.                          SCALEBITS)))];
  332.       outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])];    /* blue */
  333.       /* K passes through unchanged */
  334.       outptr[3] = inptr3[col];    /* don't need GETJSAMPLE here */
  335.       outptr += 4;
  336.     }
  337.   }
  338. }
  339.  
  340.  
  341. /*
  342.  * Empty method for start_pass.
  343.  */
  344.  
  345. METHODDEF void
  346. start_pass_dcolor (j_decompress_ptr cinfo)
  347. {
  348.   /* no work needed */
  349. }
  350.  
  351.  
  352. /*
  353.  * Module initialization routine for output colorspace conversion.
  354.  */
  355.  
  356. GLOBAL void
  357. jinit_color_deconverter (j_decompress_ptr cinfo)
  358. {
  359.   my_cconvert_ptr cconvert;
  360.   int ci;
  361.  
  362.   cconvert = (my_cconvert_ptr)
  363.     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  364.                 SIZEOF(my_color_deconverter));
  365.   cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
  366.   cconvert->pub.start_pass = start_pass_dcolor;
  367.  
  368.   /* Make sure num_components agrees with jpeg_color_space */
  369.   switch (cinfo->jpeg_color_space) {
  370.   case JCS_GRAYSCALE:
  371.     if (cinfo->num_components != 1)
  372.       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
  373.     break;
  374.  
  375.   case JCS_RGB:
  376.   case JCS_YCbCr:
  377.     if (cinfo->num_components != 3)
  378.       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
  379.     break;
  380.  
  381.   case JCS_CMYK:
  382.   case JCS_YCCK:
  383.     if (cinfo->num_components != 4)
  384.       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
  385.     break;
  386.  
  387.   default:            /* JCS_UNKNOWN can be anything */
  388.     if (cinfo->num_components < 1)
  389.       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
  390.     break;
  391.   }
  392.  
  393.   /* Set out_color_components and conversion method based on requested space.
  394.    * Also clear the component_needed flags for any unused components,
  395.    * so that earlier pipeline stages can avoid useless computation.
  396.    */
  397.  
  398.   switch (cinfo->out_color_space) {
  399.   case JCS_GRAYSCALE:
  400.     cinfo->out_color_components = 1;
  401.     if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
  402.     cinfo->jpeg_color_space == JCS_YCbCr) {
  403.       cconvert->pub.color_convert = grayscale_convert;
  404.       /* For color->grayscale conversion, only the Y (0) component is needed */
  405.       for (ci = 1; ci < cinfo->num_components; ci++)
  406.     cinfo->comp_info[ci].component_needed = FALSE;
  407.     } else
  408.       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
  409.     break;
  410.  
  411.   case JCS_RGB:
  412.     cinfo->out_color_components = RGB_PIXELSIZE;
  413.     if (cinfo->jpeg_color_space == JCS_YCbCr) {
  414.       cconvert->pub.color_convert = ycc_rgb_convert;
  415.       build_ycc_rgb_table(cinfo);
  416.     } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
  417.       cconvert->pub.color_convert = null_convert;
  418.     } else
  419.       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
  420.     break;
  421.  
  422.   case JCS_CMYK:
  423.     cinfo->out_color_components = 4;
  424.     if (cinfo->jpeg_color_space == JCS_YCCK) {
  425.       cconvert->pub.color_convert = ycck_cmyk_convert;
  426.       build_ycc_rgb_table(cinfo);
  427.     } else if (cinfo->jpeg_color_space == JCS_CMYK) {
  428.       cconvert->pub.color_convert = null_convert;
  429.     } else
  430.       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
  431.     break;
  432.  
  433.   default:
  434.     /* Permit null conversion to same output space */
  435.     if (cinfo->out_color_space == cinfo->jpeg_color_space) {
  436.       cinfo->out_color_components = cinfo->num_components;
  437.       cconvert->pub.color_convert = null_convert;
  438.     } else            /* unsupported non-null conversion */
  439.       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
  440.     break;
  441.   }
  442.  
  443.   if (cinfo->quantize_colors)
  444.     cinfo->output_components = 1; /* single colormapped output component */
  445.   else
  446.     cinfo->output_components = cinfo->out_color_components;
  447. }
  448.  
  449.  
  450. #ifdef XP_WIN32
  451. //  MMX(tm) technology assembly code additions begin here
  452. void MMXYCbCr2RGB( 
  453.   int columns,      
  454.   unsigned char *inY,
  455.   unsigned char *inU,
  456.   unsigned char *inV,
  457.   unsigned char *outRGB)
  458. {
  459.  
  460. //;  This program will compile with Microsoft Visual C++ 4.1 or greater.
  461. //;  Use the /GM compile switch to allow the compilation of MMX(tm) Technology 
  462. //;  instructions as inline assembly
  463.  
  464.   __asm {
  465.     // Initialize all the pointers, loop variables
  466.     mov        eax, inY
  467.     mov        ecx, inV
  468.  
  469.     mov        edi, columns
  470.     mov        ebx, inU
  471.  
  472.     shr        edi, 2                ; number of loops = cols/4 
  473.     mov        edx, outRGB
  474.  
  475.     // Main Loop to process 12 bytes
  476. YUVtoRGB:
  477.     movd    mm0, [eax]            ; 0/0/0/0/Y3/Y2/Y1/Y0
  478.     pxor    mm7, mm7            ; use mm7 as const_0 to achieve better pairing at start
  479.  
  480.     movd    mm2, [ebx]            ; 0/0/0/0/U3/U2/U1/U0
  481.     punpcklbw    mm0, mm7        ; Y3/Y2/Y1/Y0
  482.  
  483.     movd    mm3, [ecx]            ; 0/0/0/0/V3/V2/V1/V0
  484.     punpcklbw    mm2, mm7        ; U3/U2/U1/U0
  485.     
  486.     psubsw    mm2, const_sub128    ; U3'/U2'/U1'/U0'
  487.     punpcklbw    mm3, mm7        ; V3/V2/V1/V0
  488.  
  489.     psubsw    mm3, const_sub128    ; V3'/V2'/V1'/V0'
  490.     movq    mm4, mm2
  491.     
  492.     punpcklwd    mm2, mm3        ; V1'/U1'/V0'/U0'
  493.     movq    mm1, mm0            
  494.  
  495.     pmaddwd    mm2, const_VUmul    ; gvV1'+guU1'/gvV0'+guU0'
  496.     psllw    mm1, 8                ; Y3*256/Y2*256/Y1*256/Y0*256
  497.  
  498.     movq    mm6, mm1
  499.     punpcklwd    mm1, mm7        ; Y1*256/Y0*256
  500.     
  501.     punpckhwd    mm6, mm7        ; Y3*256/Y2*256
  502.     movq    mm5, mm4
  503.  
  504.     punpckhwd    mm5, mm3        ; V3'/U3'/V2'/U2'
  505.     paddd    mm2, mm1            ; G1*256/G0*256        (mm1 free)
  506.  
  507.     pmaddwd    mm5, const_VUmul    ; gvV3'+guU3'/gvV2'+guU2'
  508.     movq    mm1, mm3            ;        (using mm1)    
  509.     
  510.     punpcklwd    mm3, mm0        ; Y1/V1'/Y0/V0'
  511.     movq    mm7, mm4            ; This wipes out the zero constant
  512.     
  513.     pmaddwd    mm3, const_YVmul    ; ryY1+rvV1'/ryY0+rvV0'
  514.     psrad    mm2, 8                ; G1/G0
  515.  
  516.     paddd    mm5, mm6            ; G3*256/G2*256        (mm6 free)
  517.     punpcklwd    mm4, mm0        ; Y1/U1'/Y0/U0'
  518.  
  519.     pmaddwd    mm4, const_YUmul    ; // "byY1+buU1'/byY0'+buU0'"
  520.     psrad    mm5, 8                ; G3/G2
  521.  
  522.     psrad    mm3, 8                ; R1/R0
  523.  
  524.     punpckhwd    mm7 , mm0        ; Y3/U3'/Y2/U2'
  525.     
  526.     psrad    mm4, 8                ; B1/B0
  527.     movq    mm6, mm3
  528.  
  529.     pmaddwd    mm7, const_YUmul    ; // "byY3+buU3'/byY2'+buU2'"
  530.     punpckhwd    mm1, mm0        ; Y3/V3'/Y2/V2'        
  531.     
  532.     pmaddwd    mm1, const_YVmul    ; ryY3+rvV3'/ryY2+rvV2'
  533.     punpckldq    mm3, mm2        ; G0/R0
  534.  
  535.     punpckhdq    mm6, mm2        ; G1/R1            (mm2 free)
  536.     movq    mm0, mm4
  537.  
  538.     psrad    mm7, 8                ; B3/B2
  539.     
  540.     punpckldq    mm4, const_0    ; 0/B0
  541.  
  542.     punpckhdq    mm0, const_0    ; 0/B1
  543.  
  544.     psrad    mm1, 8                ; R3/R2
  545.  
  546.     packssdw    mm3, mm4        ; 0/B0/G0/R0    (mm4 free)
  547.     movq    mm2, mm1
  548.  
  549.     packssdw    mm6, mm0        ; 0/B1/G1/R1    (mm0 free)
  550.  
  551.     packuswb mm3, mm6            ; 0/B1/G1/R1/0/B0/G0/R0  (mm6 free)
  552.  
  553.     punpckldq    mm2, mm5        ; G2/R2
  554.     movq    mm4, mm7
  555.  
  556.     punpckhdq    mm1, mm5        ; G3/R3 (mm5 done)
  557.  
  558.     punpckldq    mm7, const_0    ; 0/B2        (change this line for alpha code)
  559.  
  560.     punpckhdq    mm4, const_0    ; 0/B3        (change this line for alpha code)
  561.  
  562.     movq        mm0, mm3        
  563.     packssdw    mm2, mm7        ; 0/B2/G2/R2
  564.  
  565.     pand        mm3, mask_highd    ; 0/B1/G1/R1/0/0/0/0
  566.     packssdw    mm1, mm4        ; 0/B3/G3/R3
  567.  
  568.     psrlq        mm3, 8            ; 0/0/B1/G1/R1/0/0/0
  569.     add            edx, 12
  570.  
  571.     por            mm0, mm3        ; 0/0/?/?/R1/B0/G0/R0 
  572.     packuswb    mm2, mm1        ; 0/B3/G3/R3/0/B2/G2/R2
  573.  
  574.     psrlq        mm3, 32            ; 0/0/0/0/0/0/B1/G1
  575.     add            eax, 4
  576.  
  577.     movd        [edx][-12], mm0        ; correct for add        
  578.     punpcklwd    mm3, mm2        ; 0/B2/0/0/G2/R2/B1/G1
  579.  
  580.     psrlq        mm2, 24            ; 0/0/0/0/B3/G3/R3/0
  581.     add            ecx, 4
  582.  
  583.     movd        [edx][-8], mm3    ; correct for previous add
  584.     psrlq        mm3, 48            ; 0/0/0/0/0/0/0/B2
  585.     
  586.     por            mm2, mm3        ; 0/0/0/0/B3/G3/R3/0
  587.     add            ebx, 4
  588.  
  589.     movd        [edx][-4], mm2    ; correct for previous add
  590.  
  591.     dec            edi
  592.     jnz            YUVtoRGB        ; Do 12 more bytes if not zero
  593.  
  594.     //emms       // "commented out since it is done at the end of the caller's loop"
  595.   } // end of __asm
  596. }
  597.  
  598. #endif
  599.  
  600.