text: /*++
  
  Copyright (c) 1997-1999  Microsoft Corporation
  
  --*/
  
  // NTRAID#NTBUG9-576656-2002/03/14-yasuho-: Possible buffer overrun
  // NTRAID#NTBUG9-576658-2002/03/14-yasuho-: Possible divide by zero
  // NTRAID#NTBUG9-576661-2002/03/14-yasuho-: Remove the dead codes
  
  #include "pdev.h"
  #include "alpsres.h"
  #include "dither.h"
  #include "dtable.h"
  
  int Calc_degree(int x, int y);
  
  /*************************** Function Header *******************************
   *  bInitialDither
   *
   *  Pre-processing of dither tables.
   *
   * HISTORY:
   *  24 Jun 1996    -by-    Sueya Sugihara    [sueyas]
   *     Created.
   *
   ***************************************************************************/
  BOOL bInitialDither(
  PDEVOBJ     pdevobj)
  {
  
      PCURRENTSTATUS lpnp;
  
      lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
  
      // Already created the NewTable[][][] by dither.exe.
  
      if( lpnp->iTextQuality != CMDID_TEXTQUALITY_GRAY ){
  
      int B_LOW;
      int B_R;
      int UCR;
      int YUCR;
      int B_GEN;
      int i;
  //    FLOATOBJ  f1,f2;
      float  f1,f2;
  
      // initialize.
  
      if( lpnp->iTextQuality == CMDID_TEXTQUALITY_PHOTO ){
  
          B_LOW = 0;
          B_R   = 70;
          UCR   = 50;
          YUCR  = 4;
          B_GEN = 2;
  
      }else{
  
          B_LOW = 0;
          B_R   = 100;
          UCR   = 60;
          YUCR  = 4;
          B_GEN = 3;
      }
  
      // Create KuroTBL[] to get black from YMC.
  
      for( i=0; i< 256; i++){
  
          if( i < B_LOW )
  
          lpnp->KuroTBL[i] = 0;
  
          else{
  
          int       k;
  
          FLOATOBJ_SetLong(&f1, (i - B_LOW));
          FLOATOBJ_DivLong(&f1, (255 - B_LOW));
  
          f2 = f1;
  
          for(k=0; k<(B_GEN - 1); k++){
  
              FLOATOBJ_Mul(&f1, &f2);
  
          }
  
          FLOATOBJ_MulLong(&f1, 255);
  
          FLOATOBJ_MulLong(&f1, B_R);
  
          FLOATOBJ_DivLong(&f1, 100);
  
          FLOATOBJ_AddFloat(&f1,(FLOAT)0.5);
  
          lpnp->KuroTBL[i] = (unsigned char)FLOATOBJ_GetLong(&f1);
  
          }
  
      }
  
      // Create UcrTBL[] to reduce extracting black density from YMC
  
      for( i=0; i< 256; i++){
  
          if( i < B_LOW )
  
          lpnp->UcrTBL[i] = 0;
  
          else{
  
          FLOATOBJ_SetLong(&f1, (i - B_LOW));
  
          FLOATOBJ_MulLong(&f1, UCR);
  
          FLOATOBJ_DivLong(&f1, 100);
  
          lpnp->UcrTBL[i] = (unsigned char)FLOATOBJ_GetLong(&f1);
  
          }
      }
  
  
      lpnp->YellowUcr = (unsigned char)((unsigned int)(100 - YUCR) * 255 / 100);
  
      }
  
      return TRUE;
  }
  
  /*************************** Function Header *******************************
   *  bInitialColorConvert
   *
   *  Pre-processing of color conversion process.
   *
   * HISTORY:
   *  24 Jun 1996    -by-    Sueya Sugihara    [sueyas]
   *     Created.
   *
   ***************************************************************************/
  BOOL bInitialColorConvert(
  PDEVOBJ     pdevobj)
  {
  
      PCURRENTSTATUS lpnp;
      int            i;
      BYTE          *RedHosei;
      BYTE          *GreenHosei;
      BYTE          *BlueHosei;
  
      lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
  
      // Color definitions.
  
      lpnp->RGB_Rx = 6400;      // X value of Red 100% on monitor
      lpnp->RGB_Ry = 3300;      // Y value of Red 100% on monitor
      lpnp->RGB_Gx = 2900;      // X value of Green 100% on monitor
      lpnp->RGB_Gy = 6000;      // Y value of Green 100% on monitor
      lpnp->RGB_Bx = 1500;      // X value of Blue 100% on monitor
      lpnp->RGB_By =  600;      // Y value of Blue 100% on monitor
      lpnp->RGB_Wx = 3127;      // X value of White 100% on monitor
      lpnp->RGB_Wy = 3290;      // Y value of White 100% on monitor
  
      lpnp->CMY_Cx = 1726;      // X value of Cyan 100% on ribbon
      lpnp->CMY_Cy = 2248;      // Y value of Cyan 100% on ribbon
      lpnp->CMY_Mx = 3923;      // X value of Magenta 100% on ribbon
      lpnp->CMY_My = 2295;      // Y value of Magenta 100% on ribbon
      lpnp->CMY_Yx = 4600;      // X value of Yellow 100% on ribbon
      lpnp->CMY_Yy = 4600;      // Y value of Yellow 100% on ribbon
      lpnp->CMY_Rx = 6000;      // X value of Red (MY) 100% on ribbon
      lpnp->CMY_Ry = 3200;      // Y value of Red (MY) 100% on ribbon
      lpnp->CMY_Gx = 2362;      // X value of Green (CY) 100% on ribbon
      lpnp->CMY_Gy = 5024;      // Y value of Green (CY) 100% on ribbon
      lpnp->CMY_Bx = 2121;      // X value of Blue (CM) 100% on ribbon
      lpnp->CMY_By = 1552;      // Y value of Blue (CM) 100% on ribbon
      lpnp->CMY_Wx = 3148;      // X value of White on paper
      lpnp->CMY_Wy = 3317;      // Y value of White on paper
  
      lpnp->RedAdj     =   0;   // Param for density adjust
      lpnp->RedStart   =   0;   // Position of start for density adjust
      lpnp->GreenAdj   = 400;   // Param for density adjust
      lpnp->GreenStart =  50;   // Position of start for density adjust
      lpnp->BlueAdj    =   0;   // Param for density adjust
      lpnp->BlueStart  =   0;   // Position of start for density adjust
  
  
      // Calculation of density adjustment table.
  
      RedHosei = lpnp->RedHosei;
      GreenHosei = lpnp->GreenHosei;
      BlueHosei = lpnp->BlueHosei;
  
      for(i = 0; i < 256; i ++){
  
      RedHosei[i] = GreenHosei[i] = BlueHosei[i] = 0;
      }
  
      if( lpnp->RedAdj != 0 ){
  
      for(i = lpnp->RedStart; i < 255; i++)
  
          RedHosei[i] = (unsigned char)((255 - i) * (i - lpnp->RedStart) / lpnp->RedAdj);
  
      }
  
      if( lpnp->GreenAdj != 0 ){
  
      for(i = lpnp->GreenStart; i < 255; i++)
  
          GreenHosei[i] = (unsigned char)((255 - i) * (i - lpnp->GreenStart) / lpnp->GreenAdj);
  
      }
  
      if( lpnp->BlueAdj != 0 ){
  
      for(i = lpnp->BlueStart; i < 255; i++)
  
          BlueHosei[i] = (unsigned char)((255 - i) * (i - lpnp->BlueStart) / lpnp->BlueAdj);
  
      }
  
      // Calculation of color definition data.
  
      lpnp->RGB_Rx -= lpnp->RGB_Wx;        lpnp->RGB_Ry -= lpnp->RGB_Wy;
      lpnp->RGB_Gx -= lpnp->RGB_Wx;        lpnp->RGB_Gy -= lpnp->RGB_Wy;
      lpnp->RGB_Bx -= lpnp->RGB_Wx;        lpnp->RGB_By -= lpnp->RGB_Wy;
  
      lpnp->RGB_Cx = ( lpnp->RGB_Gx - lpnp->RGB_Bx ) / 2 + lpnp->RGB_Bx;
      lpnp->RGB_Cy = ( lpnp->RGB_Gy - lpnp->RGB_By ) / 2 + lpnp->RGB_By;
      lpnp->RGB_Mx = ( lpnp->RGB_Rx - lpnp->RGB_Bx ) / 2 + lpnp->RGB_Bx;
      lpnp->RGB_My = ( lpnp->RGB_Ry - lpnp->RGB_By ) / 2 + lpnp->RGB_By;
      lpnp->RGB_Yx = ( lpnp->RGB_Rx - lpnp->RGB_Gx ) / 2 + lpnp->RGB_Gx;
      lpnp->RGB_Yy = ( lpnp->RGB_Ry - lpnp->RGB_Gy ) / 2 + lpnp->RGB_Gy;
  
      lpnp->CMY_Cx -= lpnp->CMY_Wx;        lpnp->CMY_Cy -= lpnp->CMY_Wy;
      lpnp->CMY_Mx -= lpnp->CMY_Wx;        lpnp->CMY_My -= lpnp->CMY_Wy;
      lpnp->CMY_Yx -= lpnp->CMY_Wx;        lpnp->CMY_Yy -= lpnp->CMY_Wy;
      lpnp->CMY_Rx -= lpnp->CMY_Wx;        lpnp->CMY_Ry -= lpnp->CMY_Wy;
      lpnp->CMY_Gx -= lpnp->CMY_Wx;        lpnp->CMY_Gy -= lpnp->CMY_Wy;
      lpnp->CMY_Bx -= lpnp->CMY_Wx;        lpnp->CMY_By -= lpnp->CMY_Wy;
  
      // Calculation of data for color dimension judgement
  
      lpnp->CMY_Cd = Calc_degree( lpnp->CMY_Cx, lpnp->CMY_Cy );
      lpnp->CMY_Md = Calc_degree( lpnp->CMY_Mx, lpnp->CMY_My );
      lpnp->CMY_Yd = Calc_degree( lpnp->CMY_Yx, lpnp->CMY_Yy );
      lpnp->CMY_Rd = Calc_degree( lpnp->CMY_Rx, lpnp->CMY_Ry );
      lpnp->CMY_Gd = Calc_degree( lpnp->CMY_Gx, lpnp->CMY_Gy );
      lpnp->CMY_Bd = Calc_degree( lpnp->CMY_Bx, lpnp->CMY_By );
  
      return TRUE;
  }
  
  int Calc_degree( int x, int y)
  {
      register int    val;
  
      if( x == 0 ){
  
      if( y == 0 )
  
          val = 0;
  
      else if( y > 0 )
  
          val = 30000;
  
      else
  
          val = -30000;
  
      }else{
  
      val = y / x;
  
      if( val > 300 )
  
          val = 30000;
  
      else if( val < -300 )
  
          val = -30000;
  
      else
  
          val = (y * 100) / x;
  
      }
  
      return val;
  
  }
  
  
  // bOHPConvert() - No longer used.
  
  
  /*************************** Function Header *******************************
   *  bPhotoConvert
   *
   *  Convert RGB to CMYK for photo graphics.
   *
   *
   * HISTORY:
   *  24 Jun 1996    -by-    Sueya Sugihara    [sueyas]
   *     Created.
   *
   ***************************************************************************/
  BOOL bPhotoConvert(
  PDEVOBJ pdevobj,
  BYTE bRed,
  BYTE bGreen,
  BYTE bBlue,
  BYTE *ppy,
  BYTE *ppm,
  BYTE *ppc,
  BYTE *ppk)
  {
  
      int  k, w, pk, r, g, b;
      int  Est_x, Est_y;
      int  p1, p2;
      int  deg, area;
      register int  val_a, val_b, val_c, val_d;
      register int  val1,  val2;
      BYTE hosei;
      int  py, pm, pc;
      int  wx, wy;
      PCURRENTSTATUS lpnp;
  
      lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
  
      k = max( bRed, bGreen );
      k = max( k, bBlue );
  
      // Set black element
  
      pk = 255 - k;
  
      w = min( bRed, bGreen );
      w = min( w, bBlue );
  
      // Cut white element from each color
  
      r = bRed - w;
      g = bGreen - w;
      b = bBlue - w;
  
      // Get estimation for Est_x and Est_y
  
      if( r == 0 ){                       // G->C->B
  
      if(( g == 0 ) && ( b == 0 )){   // no color
  
          Est_x = 0;
          Est_y = 0;
  
      }
      else if( g >= b ){              // G->C dimension
  
          p1 = (lpnp->RGB_Gx * g) / 255;
          p2 = (lpnp->RGB_Cx * g) / 255;
          Est_x = ((p2 - p1) * b) / g + p1;
          p1 = (lpnp->RGB_Gy * g) / 255;
          p2 = (lpnp->RGB_Cy * g) / 255;
          Est_y = ((p2 - p1) * b) / g + p1;
  
      }
      else {                          // B->C dimension
  
          p1 = (lpnp->RGB_Bx * b) / 255;
          p2 = (lpnp->RGB_Cx * b) / 255;
          Est_x = ((p2 - p1) * g) / b + p1;
          p1 = (lpnp->RGB_By * b) / 255;
          p2 = (lpnp->RGB_Cy * b) / 255;
          Est_y = ((p2 - p1) * g) / b + p1;
  
      }
  
      }
      else if( g == 0 ){                  // B->M->R
  
      if( b >= r ){                   // B->M dimension
  
          p1 = (lpnp->RGB_Bx * b) / 255;
          p2 = (lpnp->RGB_Mx * b) / 255;
          Est_x = ((p2 - p1) * r) / b + p1;
          p1 = (lpnp->RGB_By * b) / 255;
          p2 = (lpnp->RGB_My * b) / 255;
          Est_y = ((p2 - p1) * r) / b + p1;
  
      }
      else{                           // R->M dimension
  
          p1 = (lpnp->RGB_Rx * r) / 255;
          p2 = (lpnp->RGB_Mx * r) / 255;
          Est_x = ((p2 - p1) * b) / r + p1;
          p1 = (lpnp->RGB_Ry * r) / 255;
          p2 = (lpnp->RGB_My * r) / 255;
          Est_y = ((p2 - p1) * b) / r + p1;
  
      }
  
      }
      else{                               // G->Y->R
  
      if( g >= r ){                   // G->Y dimension
  
          p1 = (lpnp->RGB_Gx * g) / 255;
          p2 = (lpnp->RGB_Yx * g) / 255;
          Est_x = ((p2 - p1) * r) / g + p1;
          p1 = (lpnp->RGB_Gy * g) / 255;
          p2 = (lpnp->RGB_Yy * g) / 255;
          Est_y = ((p2 - p1) * r) / g + p1;
  
      }
      else{                           // R->Y dimension
  
          p1 = (lpnp->RGB_Rx * r) / 255;
          p2 = (lpnp->RGB_Yx * r) / 255;
          Est_x = ((p2 - p1) * g) / r + p1;
          p1 = (lpnp->RGB_Ry * r) / 255;
          p2 = (lpnp->RGB_Yy * r) / 255;
          Est_y = ((p2 - p1) * g) / r + p1;
  
      }
  
      }
  
      // Convert origin of Est_x and Est_y to paper color
  
      wx = lpnp->RGB_Wx ? lpnp->RGB_Wx : 1;
      wy = lpnp->RGB_Wy ? lpnp->RGB_Wy : 1;
  
      Est_x += lpnp->RGB_Wx;
      Est_y += lpnp->RGB_Wy;
      Est_x = Est_x * lpnp->CMY_Wx / wx;
      Est_y = Est_y * lpnp->CMY_Wy / wy;
      Est_x -= lpnp->CMY_Wx;
      Est_y -= lpnp->CMY_Wy;
  
      pc = pm = py = 0;
  
      if( !((Est_x == 0) && (Est_y == 0)) ){
  
      // Get deg on CMY color dimension from Est_x and Est_y
  
      if( Est_x == 0 ){
  
          if( Est_y > 0 )
  
          deg = 30000;
  
          else
  
          deg = -30000;
  
      }
      else{
  
          deg = Est_y / Est_x;
  
          if( deg > 300 )
  
          deg = 30000;
  
          else if( deg  < -300 )
  
          deg = -30000;
  
          else
  
          deg = ( Est_y * 100 ) / Est_x;
  
      }
  
  
      if( Est_x >= 0 ){
  
          if( deg <= lpnp->CMY_Md )       // M->B dimension
  
          area = 1;
  
          else if( deg <= lpnp->CMY_Rd )  // M->R dimension
  
          area = 2;
  
          else if( deg <= lpnp->CMY_Yd )  // Y->R dimension
  
          area = 3;
  
          else                            // Y->G dimension
  
          area = 4;
  
      }
      else{
  
          if( deg <= lpnp->CMY_Gd )       // Y->G dimension
  
          area = 4;
  
          else if( deg <= lpnp->CMY_Cd )  // C->G dimension
  
          area = 5;
  
          else if( deg <= lpnp->CMY_Bd )  // C->B dimension
  
          area = 6;
  
          else                            // M->B dimension
  
          area = 1;
  
      }
  
      switch ( area ){
  
      case 1:                             // M->B dimension
  
          val_a = lpnp->CMY_Bx - lpnp->CMY_Mx;
          val_b = lpnp->CMY_By - lpnp->CMY_My;
          val_c = lpnp->CMY_Mx;
          val_d = lpnp->CMY_My;
  
          val1 = val_b * val_c - val_a * val_d;
          val2 = ( val_b * Est_x - val_a * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          pm = val2 / val1;
  
          if( pm < 0 )
          pm = 0;
  
          val1 = val_a * val_d - val_b * val_c;
          val2 = ( val_d * Est_x - val_c * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          pc = val2 / val1;
  
          if( pc < 0 )
          pc = 0;
  
          if( pc > 255 )
          pc = 255;
  
          hosei = lpnp->BlueHosei[pc];
  
          pc += hosei;
          pm += hosei;
  
          if( pc > 255 )
          pc = 255;
  
          if( pm > 255 )
          pm = 255;
  
          break;
  
      case 2:                             // M->R dimension
  
          val_a = lpnp->CMY_Rx - lpnp->CMY_Mx;
          val_b = lpnp->CMY_Ry - lpnp->CMY_My;
          val_c = lpnp->CMY_Mx;
          val_d = lpnp->CMY_My;
  
          val1 = val_b * val_c - val_a * val_d;
          val2 = ( val_b * Est_x - val_a * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          pm = val2 / val1;
  
          if( pm < 0 )
          pm = 0;
  
          val1 = val_a * val_d - val_b * val_c;
          val2 = ( val_d * Est_x - val_c * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          py = val2 / val1;
  
          if( py < 0 )
          py = 0;
  
          if( py > 255 )
          py = 255;
  
          hosei = lpnp->RedHosei[py];
  
          py += hosei;
          pm += hosei;
  
          if( pm > 255 )
          pm = 255;
  
          if( py > 255 )
          py = 255;
  
          break;
  
      case 3:                             // Y->R dimension
  
          val_a = lpnp->CMY_Rx - lpnp->CMY_Yx;
          val_b = lpnp->CMY_Ry - lpnp->CMY_Yy;
          val_c = lpnp->CMY_Yx;
          val_d = lpnp->CMY_Yy;
  
          val1 = val_b * val_c - val_a * val_d;
          val2 = ( val_b * Est_x - val_a * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          py = val2 / val1;
  
          if( py < 0 )
          py = 0;
  
          val1 = val_a * val_d - val_b * val_c;
          val2 = ( val_d * Est_x - val_c * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          pm = val2 / val1;
  
          if( pm < 0 )
          pm = 0;
  
          if( pm > 255 )
          pm = 255;
  
          hosei = lpnp->RedHosei[pm];
  
          py += hosei;
          pm += hosei;
  
          if( pm > 255 )
          pm = 255;
  
          if( py > 255 )
          py = 255;
  
          break;
  
      case 4:                             // Y->G dimension
  
          val_a = lpnp->CMY_Gx - lpnp->CMY_Yx;
          val_b = lpnp->CMY_Gy - lpnp->CMY_Yy;
          val_c = lpnp->CMY_Yx;
          val_d = lpnp->CMY_Yy;
  
          val1 = val_b * val_c - val_a * val_d;
          val2 = ( val_b * Est_x - val_a * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          py = val2 / val1;
  
          if( py < 0 )
          py = 0;
  
          val1 = val_a * val_d - val_b * val_c;
          val2 = ( val_d * Est_x - val_c * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          pc = val2 / val1;
  
          if( pc < 0 )
          pc = 0;
  
          if( pc > 255 )
          pc = 255;
  
          hosei = lpnp->GreenHosei[pc];
  
          py += hosei;
          pc += hosei;
  
          if( pc > 255 )
          pc = 255;
  
          if( py > 255 )
          py = 255;
  
          break;
  
      case 5:                             // C->G dimension
  
          val_a = lpnp->CMY_Gx - lpnp->CMY_Cx;
          val_b = lpnp->CMY_Gy - lpnp->CMY_Cy;
          val_c = lpnp->CMY_Cx;
          val_d = lpnp->CMY_Cy;
  
          val1 = val_b * val_c - val_a * val_d;
          val2 = ( val_b * Est_x - val_a * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          pc = val2 / val1;
  
          if( pc < 0 )
          pc = 0;
  
          val1 = val_a * val_d - val_b * val_c;
          val2 = ( val_d * Est_x - val_c * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          py = val2 / val1;
  
          if( py < 0 )
          py = 0;
  
          if( py > 255 )
          py = 255;
  
          // Dwnsity adjustment for green
          hosei = lpnp->GreenHosei[py];
  
          py += hosei;
          pc += hosei;
  
          if( pc > 255 )
          pc = 255;
  
          if( py > 255 )
          py = 255;
  
          break;
  
      case 6:                             // C->B dimension
  
          val_a = lpnp->CMY_Bx - lpnp->CMY_Cx;
          val_b = lpnp->CMY_By - lpnp->CMY_Cy;
          val_c = lpnp->CMY_Cx;
          val_d = lpnp->CMY_Cy;
  
          val1 = val_b * val_c - val_a * val_d;
          val2 = ( val_b * Est_x - val_a * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          pc = val2 / val1;
  
          if( pc < 0 )
          pc = 0;
  
          val1 = val_a * val_d - val_b * val_c;
          val2 = ( val_d * Est_x - val_c * Est_y ) * 255;
  
          val1 = val1 ? val1 : 1;
  
          pm = val2 / val1;
  
          if( pm < 0 )
          pm = 0;
  
          if( pm > 255 )
          pm = 255;
  
          hosei = lpnp->BlueHosei[pm];
  
          pc += hosei;
          pm += hosei;
  
          if( pc > 255 )
          pc = 255;
  
          if( pm > 255 )
          pm = 255;
  
      } // switch area
  
      }
  
      // Add pk to color
  
      k = pc;
  
      if( k < pm )
      k = pm;
  
      if( k < py )
      k = py;
  
      r = ( pk  + k > 255) ? 255 - k : pk;
  
      pk -= r;
      pc += r;
      pm += r;
      py += r;
  
  
      // Extract K and adjust to other color for its extracting value
  
      if (bPlaneSendOrderCMYK(lpnp)) {
  
      int min_p;
      BYTE ucr_sub, ucr_div;
  
      min_p = min( py, pm );
      min_p = min( min_p, pc );
  
  #ifdef BLACK_RIBBON_HACK
      if( min_p == 255 ){
          pk = 255;
          pc = pm = py = 0;
      }
      else{
  #endif // BLACK_RIBBOM_HACK
  
      pk += lpnp->KuroTBL[min_p];
      pk = ( pk > 255 ) ? 255 : pk;
  
      ucr_sub = lpnp->UcrTBL[min_p];
      ucr_div = 255 - ucr_sub;
  
      ucr_div = ucr_div ? ucr_div : 1;
  
      py = (BYTE)((UINT)(py - ucr_sub) * lpnp->YellowUcr / ucr_div);
      pm = (BYTE)((UINT)(pm - ucr_sub) * 255 / ucr_div);
      pc = (BYTE)((UINT)(pc - ucr_sub) * 255 / ucr_div);
  
  #ifdef BLACK_RIBBON_HACK
      }
  #endif // BLACK_RIBBON_HACK
  
      }
  
      py = 255 - py;
      pm = 255 - pm;
      pc = 255 - pc;
      pk = 255 - pk;
  
      *ppy = (BYTE)py;
      *ppm = (BYTE)pm;
      *ppc = (BYTE)pc;
      *ppk = (BYTE)pk;
  
      return TRUE;
  }
  /*************************** Function Header *******************************
   *  bBusinessConvert
   *
   *  Convert RGB to CMYK for business graphics.
   *
   *
   * HISTORY:
   *  24 Jun 1996    -by-    Sueya Sugihara    [sueyas]
   *     Created.
   *
   ***************************************************************************/
  BOOL bBusinessConvert(
  PDEVOBJ pdevobj,
  BYTE bRed,
  BYTE bGreen,
  BYTE bBlue,
  BYTE *ppy,
  BYTE *ppm,
  BYTE *ppc,
  BYTE *ppk)
  {
      int    py, pm, pc, pk;
      int    min_p;
      BYTE   ucr_sub, ucr_div;
      PCURRENTSTATUS lpnp;
  
      lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
  
      // Simple convert RGB to CMY
  
      py = 255 - bBlue;
      pm = 255 - bGreen;
      pc = 255 - bRed;
      pk = 0;
  
      // Extract K and adjust to other color for its extracting value
  
      // Extract pk from py, pm and pc by using followings, and erase black element.
  
      // When this media is 3 plane type, we do not extract black.
  
      if (bPlaneSendOrderCMYK(lpnp)) {
  
      min_p = min( py, pm );
      min_p = min( min_p, pc );
  
  #ifdef BLACK_RIBBON_HACK
      if( min_p == 255 ){
          pk = 255;
          pc = pm = py = 0;
      }
      else{
  #endif // BLACK_RIBBON_HACK
  
      pk = lpnp->KuroTBL[min_p];
  
      ucr_sub = lpnp->UcrTBL[min_p];
  
      ucr_div = 255 - ucr_sub;
  
      ucr_div = ucr_div ? ucr_div : 1;
  
      py = (BYTE)((UINT)(py - ucr_sub) * lpnp->YellowUcr / ucr_div);
      pm = (BYTE)((UINT)(pm - ucr_sub) * 255 / ucr_div);
      pc = (BYTE)((UINT)(pc - ucr_sub) * 255 / ucr_div);
  
  #ifdef BLACK_RIBBON_HACK
      }
  #endif // BLACK_RIBBON_HACK
  
      }
  
      py = 255 - py;
      pm = 255 - pm;
      pc = 255 - pc;
      pk = 255 - pk;
  
      *ppy = (BYTE)py;
      *ppm = (BYTE)pm;
      *ppc = (BYTE)pc;
      *ppk = (BYTE)pk;
  
      return TRUE;
  }
  
  /*************************** Function Header *******************************
   *  bCharacterConvert
   *
   *  Convert RGB to CMYK for character graphics.
   *
   *
   * HISTORY:
   *  24 Jun 1996    -by-    Sueya Sugihara    [sueyas]
   *     Created.
   *
   ***************************************************************************/
  BOOL bCharacterConvert(
  PDEVOBJ pdevobj,
  BYTE bRed,
  BYTE bGreen,
  BYTE bBlue,
  BYTE *ppy,
  BYTE *ppm,
  BYTE *ppc,
  BYTE *ppk)
  {
      int    py, pm, pc, pk;
      int    min_p;
      BYTE   ucr_sub, ucr_div;
      PCURRENTSTATUS lpnp;
  
      lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
  
      // Simple convert RGB to CMY
  
      py = 255 - bBlue;
      pm = 255 - bGreen;
      pc = 255 - bRed;
      pk = 0;
  
      // Extract K and adjust to other color for its extracting value
  
      // Extract pk from py, pm and pc by using followings, and erase black element.
  
      // When this media is 3 plane type, we do not extract black.
  
      if (bPlaneSendOrderCMYK(lpnp)) {
  
      min_p = min( py, pm );
      min_p = min( min_p, pc );
  
      if( min_p == 255 ){
  
          pk = 255;
          pc = pm = py = 0;
  
      }
      else{
  
          pk = lpnp->KuroTBL[min_p];
  
          ucr_sub = lpnp->UcrTBL[min_p];
  
          ucr_div = 255 - ucr_sub;
  
          ucr_div = ucr_div ? ucr_div : 1;
  
          py = (BYTE)((UINT)(py - ucr_sub) * lpnp->YellowUcr / ucr_div);
          pm = (BYTE)((UINT)(pm - ucr_sub) * 255 / ucr_div);
          pc = (BYTE)((UINT)(pc - ucr_sub) * 255 / ucr_div);
  
      }
      }
  
      py = 255 - py;
      pm = 255 - pm;
      pc = 255 - pc;
      pk = 255 - pk;
  
      *ppy = (BYTE)py;
      *ppm = (BYTE)pm;
      *ppc = (BYTE)pc;
      *ppk = (BYTE)pk;
  
      return TRUE;
  }
  /*************************** Function Header *******************************
   *  bMonoConvert
   *
   *  Convert RGB to Grayscale.
   *
   *
   * HISTORY:
   *  24 Jun 1996    -by-    Sueya Sugihara    [sueyas]
   *     Created.
   *
   ***************************************************************************/
  BOOL bMonoConvert(
  PDEVOBJ pdevobj,
  BYTE bRed,
  BYTE bGreen,
  BYTE bBlue,
  BYTE *ppk)
  {
      int    mono;
  
      mono = ( 30 * bRed + 59 * bGreen + 11 * bBlue ) / 100;
  
      *ppk = 0xff - (BYTE)( mono & 0xff );
  
  
      return TRUE;
  
  }
  
  
  /*************************** Function Header *******************************
   *  cVDColorDither
   *
   *  VD Color Dither processing
   *
   *
   * HISTORY:
   *  11 Jan 1999    -by-    Yoshitaka Oku    [yoshitao]
   *     Created.
   *
   *    BYTE Color : Plane Color <Yellow, Cyan, Magenta, Black>
   *    BYTE c     : oliginal tone of the pixel
   *    int  x     : X position of the pixel
   *    int  y     : Y position of the pixel
   *
   ***************************************************************************/
  cVDColorDither(
  BYTE Color,
  BYTE c,
  int  x,
  int  y)
  {
      int   m, n;
      short Base;
      BYTE  Tone;
      BYTE  C_Thresh, Thresh;
      short AdjustedColor;
      BYTE  TempTone;
      BYTE  BaseTone;
  
      switch (Color) {
          case Yellow:
              Base = 112;
              m = n = 12;
              break;
  
          case Cyan:
          case Magenta:
              Base = 208;
              m = n = 40;
              break;
  
          case Black:
              Base = 96;
              m = n = 24;
              break;
          default:
              Color = Black;
              Base = 96;
              m = n = 24;
              break;
      }
  
      Tone = 0;                   /* Clear Tone value */
      c = VD_ColorAdjustTable[Color][c];  /* Convert orignal color */ 
      if (c != 0) {
          C_Thresh = (VD_DitherTable[Color][y % m][x % n]);
          if ( C_Thresh < 16 )
              Thresh = 1;
          else {
              C_Thresh -= 16;
              Thresh = (C_Thresh >> 2) + 1;
          }
          AdjustedColor = VD_ExpandValueTable[Color][c] - 1;
          if ( AdjustedColor < Base )
              TempTone = ( AdjustedColor >> 4 ) + 1;
          else {
              AdjustedColor -= Base;
              TempTone = ( AdjustedColor >> 2 ) + ( Base >> 4 ) + 1;
          }
          if (TempTone >= 232) TempTone = 232-1;
          BaseTone = VD_ToneOptimaizeTable[Color][TempTone].base;
          if ( BaseTone > Thresh ) {
              Tone = 15;
          } else {
              if ( BaseTone == Thresh ) {
                  if ( BaseTone == 1 )  {
                      if (( AdjustedColor & 0x0f ) >= C_Thresh )
                          Tone = VD_ToneOptimaizeTable[Color][(( AdjustedColor >> 4) & 0x0f )+ 1 ].offset;
                      else
                          Tone = VD_ToneOptimaizeTable[Color][( AdjustedColor >> 4) & 0x0f ].offset ;	
                  } else {
                      if ((AdjustedColor & 0x03) >= (C_Thresh & 0x03))
                          Tone = VD_ToneOptimaizeTable[Color][TempTone].offset;
                      else {
                          if (TempTone < 1) TempTone = 1;
                          if (VD_ToneOptimaizeTable[Color][TempTone -1].base == BaseTone)
                              Tone = VD_ToneOptimaizeTable[Color][TempTone -1].offset;
                      }
                  }
              }
          }
      }
      return (Tone);
  }
  
  
  
  
  
  /*************************** Function Header *******************************
   *  bDitherProcess
   *
   *  Dither processing
   *
   *
   * HISTORY:
   *  24 Jun 1996    -by-    Sueya Sugihara    [sueyas]
   *     Created.
   *
   ***************************************************************************/
  BOOL bDitherProcess(
  PDEVOBJ pdevobj,
  int  x,
  BYTE py,
  BYTE pm,
  BYTE pc,
  BYTE pk,
  BYTE *pby,
  BYTE *pbm,
  BYTE *pbc,
  BYTE *pbk)
  {
  
      PCURRENTSTATUS lpnp;
      BYTE           rm;
  
      lpnp = (PCURRENTSTATUS)MINIDEV_DATA(pdevobj);
  
  
      if( lpnp->iDither == DITHER_VD ){
  
      // Yellow
      *pby = (BYTE)cVDColorDither(Yellow, (BYTE)(255 - py), x, lpnp->y);
  
      // Magenta
      *pbm = (BYTE)cVDColorDither(Magenta, (BYTE)(255 - pm), x, lpnp->y);
  
      // Cyan
      *pbc = (BYTE)cVDColorDither(Cyan, (BYTE)(255 - pc), x, lpnp->y);
  
      // Black
      *pbk = (BYTE)cVDColorDither(Black, (BYTE)(255 - pk), x, lpnp->y);
  
      }else if( lpnp->iDither == DITHER_DYE ){
  
      rm = DYE_NewTable[lpnp->y % DYE_MaxY][x % DYE_MaxX];
  
      // Yellow
      *pby = ( (255 - py) / kToneLevel ) + ( ( ( (255 - py) % kToneLevel ) > rm ) ? 1 : 0 );
  
      // Magenta
      *pbm = ( (255 - pm) / kToneLevel ) + ( ( ( (255 - pm) % kToneLevel ) > rm ) ? 1 : 0 );
  
      // Cyan
      *pbc = ( (255 - pc) / kToneLevel ) + ( ( ( (255 - pc) % kToneLevel ) > rm ) ? 1 : 0 );
  
      // Black
      *pbk = 0;
  
      }else if( lpnp->iDither == DITHER_HIGH ){
  
      // Yellow
      rm = H_NewTable[Yellow][lpnp->y % H_MaxY[Yellow]][x % H_MaxX[Yellow]];
  
      *pby = ( py <= rm ) ? 1 : 0;
  
      // Magenta
      rm = H_NewTable[Magenta][lpnp->y % H_MaxY[Magenta]][x % H_MaxX[Magenta]];
  
      *pbm = ( pm <= rm ) ? 1 : 0;
  
      // Cyan
      rm = H_NewTable[Cyan][lpnp->y % H_MaxY[Cyan]][x % H_MaxX[Cyan]];
  
      *pbc = ( pc <= rm ) ? 1 : 0;
  
      // Black
      rm = H_NewTable[Black][lpnp->y % H_MaxY[Black]][x % H_MaxX[Black]];
  
      if( lpnp->iTextQuality == CMDID_TEXTQUALITY_PHOTO )
          *pbk = ( pk < rm ) ? 1 : 0;
      else
          *pbk = ( pk <= rm ) ? 1 : 0;
  
      }else if( lpnp->iDither == DITHER_LOW ){
  
      // Yellow
      rm = L_NewTable[Yellow][lpnp->y % L_MaxY[Yellow]][x % L_MaxX[Yellow]];
  
      *pby = ( py <= rm ) ? 1 : 0;
  
      // Magenta
      rm = L_NewTable[Magenta][lpnp->y % L_MaxY[Magenta]][x % L_MaxX[Magenta]];
  
      *pbm = ( pm <= rm ) ? 1 : 0;
  
      // Cyan
      rm = L_NewTable[Cyan][lpnp->y % L_MaxY[Cyan]][x % L_MaxX[Cyan]];
  
      *pbc = ( pc <= rm ) ? 1 : 0;
  
      // Black
      rm = L_NewTable[Black][lpnp->y % L_MaxY[Black]][x % L_MaxX[Black]];
  
      if( lpnp->iTextQuality == CMDID_TEXTQUALITY_PHOTO )
          *pbk = ( pk < rm ) ? 1 : 0;
      else
          *pbk = ( pk <= rm ) ? 1 : 0;
  
      }else{ // DITHER_HIGH_DIV2
  
      // Yellow
      rm = H_NewTable[Yellow][(lpnp->y/2) % H_MaxY[Yellow]][(x/2) % H_MaxX[Yellow]];
  
      *pby = ( py <= rm ) ? 1 : 0;
  
      // Magenta
      rm = H_NewTable[Magenta][(lpnp->y/2) % H_MaxY[Magenta]][(x/2) % H_MaxX[Magenta]];
  
      *pbm = ( pm <= rm ) ? 1 : 0;
  
      // Cyan
      rm = H_NewTable[Cyan][(lpnp->y/2) % H_MaxY[Cyan]][(x/2) % H_MaxX[Cyan]];
  
      *pbc = ( pc <= rm ) ? 1 : 0;
  
      // Black
      rm = H_NewTable[Black][(lpnp->y/2) % H_MaxY[Black]][(x/2) % H_MaxX[Black]];
  
      if( lpnp->iTextQuality == CMDID_TEXTQUALITY_PHOTO )
          *pbk = ( pk < rm ) ? 1 : 0;
      else
          *pbk = ( pk <= rm ) ? 1 : 0;
      }
  
  
      return TRUE;
  }
  
  
  