Logo Search packages:      
Sourcecode: lexmark7000linux version File versions

dither.c

/*
 * $Id: dither.c,v 1.2 1999/03/28 09:42:22 henryk Exp $
 * dither.c - just ripped from GIMP's print-util.c
 * 
 * "Id: print-util.c,v 1.10 1998/05/17 07:16:49 yosh Exp "
 *
 *   Print plug-in driver utility functions for the GIMP.
 *
 *   Copyright 1997-1998 Michael Sweet (mike@easysw.com)
 *   dither_black()       - Dither grayscale pixels to black.
 *   dither_cmyk()        - Dither RGB pixels to cyan, magenta, yellow, and
 *                          black.
 *   gray_to_gray()       - Convert grayscale image data to grayscale.
 *   indexed_to_gray()    - Convert indexed image data to grayscale.
 *   indexed_to_rgb()     - Convert indexed image data to RGB.
 *   rgb_to_gray()        - Convert RGB image data to grayscale.
 *   rgb_to_rgb()         - Convert RGB image data to RGB.
 *   default_media_size() - Return the size of a default page size.
 */

#include "dither.h"

/* #include "print.h" */
/*
 * RGB to grayscale luminance constants...
 */

#define LUM_RED         31
#define LUM_GREEN 61
#define LUM_BLUE  8


/*
 * Error buffer for dither functions.  This needs to be at least 14xMAXDPI
 * (currently 720) to avoid problems...
 */

int   error[2][4][14*720+1] =
      {
        { { 0 }, { 0 }, { 0 } , { 0 } },
        { { 0 }, { 0 }, { 0 } , { 0 } }
      };


/*
 * 'dither_black()' - Dither grayscale pixels to black.
 */

void
dither_black(guchar        *gray,   /* I - Grayscale pixels */
             int           row,           /* I - Current Y coordinate */
             int           src_width,     /* I - Width of input row */
             int           dst_width,     /* I - Width of output row */
             unsigned char *black)  /* O - Black bitmap pixels */
{
  int       x,          /* Current X coordinate */
            xerror,           /* X error count */
            xstep,            /* X step */
            xmod,       /* X error modulus */
            length;           /* Length of output bitmap in bytes */
  unsigned char   bit,        /* Current bit */
            *kptr;            /* Current black pixel */
  int       k,          /* Current black error */
            ditherk,    /* Next error value in buffer */
            *kerror0,   /* Pointer to current error row */
            *kerror1;   /* Pointer to next error row */
  int       ditherbit;  /* Random dithering bitmask */


  xstep  = src_width / dst_width;
  xmod   = src_width % dst_width;
  length = (dst_width + 7) / 8;

  kerror0 = error[row & 1][3];
  kerror1 = error[1 - (row & 1)][3];

  memset(black, 0, length);

  for (x = 0, bit = 128, kptr = black, xerror = 0,
           ditherbit = rand(), ditherk = *kerror0;
       x < dst_width;
       x ++, kerror0 ++, kerror1 ++)
  {
    k = 255 - *gray + ditherk / 8;

    if (k > 127)
    {
      *kptr |= bit;
      k -= 255;
    };

    if (ditherbit & bit)
    {
      kerror1[0] = 5 * k;
      ditherk    = kerror0[1] + 3 * k;
    }
    else
    {
      kerror1[0] = 3 * k;
      ditherk    = kerror0[1] + 5 * k;
    };

    if (bit == 1)
    {
      kptr ++;
      bit       = 128;
      ditherbit = rand();
    }
    else
      bit >>= 1;

    gray   += xstep;
    xerror += xmod;
    if (xerror >= dst_width)
    {
      xerror -= dst_width;
      gray   ++;
    };
  };
}


/*
 * 'dither_cmyk()' - Dither RGB pixels to cyan, magenta, yellow, and black.
 */

void
dither_cmyk(guchar        *rgb,           /* I - RGB pixels */
            int           row,            /* I - Current Y coordinate */
            int           src_width,      /* I - Width of input row */
            int           dst_width,      /* I - Width of output rows */
            unsigned char *cyan,    /* O - Cyan bitmap pixels */
            unsigned char *magenta, /* O - Magenta bitmap pixels */
            unsigned char *yellow,  /* O - Yellow bitmap pixels */
            unsigned char *black)   /* O - Black bitmap pixels */
{
  int       x,          /* Current X coordinate */
            xerror,           /* X error count */
            xstep,            /* X step */
            xmod,       /* X error modulus */
            length;           /* Length of output bitmap in bytes */
  int       c, m, y, k, /* CMYK values */
            divk,       /* Inverse of K */
            diff;       /* Average color difference */
  unsigned char   bit,        /* Current bit */
            *cptr,            /* Current cyan pixel */
            *mptr,            /* Current magenta pixel */
            *yptr,            /* Current yellow pixel */
            *kptr;            /* Current black pixel */
  int       ditherc,    /* Next error value in buffer */
            *cerror0,   /* Pointer to current error row */
            *cerror1;   /* Pointer to next error row */
  int       dithery,    /* Next error value in buffer */
            *yerror0,   /* Pointer to current error row */
            *yerror1;   /* Pointer to next error row */
  int       ditherm,    /* Next error value in buffer */
            *merror0,   /* Pointer to current error row */
            *merror1;   /* Pointer to next error row */
  int       ditherk,    /* Next error value in buffer */
            *kerror0,   /* Pointer to current error row */
            *kerror1;   /* Pointer to next error row */
  int       ditherbit;  /* Random dither bitmask */


  xstep  = 3 * (src_width / dst_width);
  xmod   = src_width % dst_width;
  length = (dst_width + 7) / 8;

  cerror0 = error[row & 1][0];
  cerror1 = error[1 - (row & 1)][0];

  merror0 = error[row & 1][1];
  merror1 = error[1 - (row & 1)][1];

  yerror0 = error[row & 1][2];
  yerror1 = error[1 - (row & 1)][2];

  kerror0 = error[row & 1][3];
  kerror1 = error[1 - (row & 1)][3];

  memset(cyan, 0, length);
  memset(magenta, 0, length);
  memset(yellow, 0, length);
  if (black != NULL)
    memset(black, 0, length);

  for (x = 0, bit = 128, cptr = cyan, mptr = magenta, yptr = yellow,
           kptr = black, xerror = 0, ditherbit = rand(), ditherc = cerror0[0],
           ditherm = merror0[0], dithery = yerror0[0], ditherk = kerror0[0];
       x < dst_width;
       x ++, cerror0 ++, cerror1 ++, merror0 ++, merror1 ++, yerror0 ++,
           yerror1 ++, kerror0 ++, kerror1 ++)
  {
   /*
    * First compute the standard CMYK separation color values...
    */

    c = 255 - rgb[0];
    m = 255 - rgb[1];
    y = 255 - rgb[2];
    k = MIN(c, MIN(m, y));

    if (black != NULL)
    {
     /*
      * Since we're printing black, adjust the black level based upon
      * the amount of color in the pixel (colorful pixels get less black)...
      */

      diff = 255 - (abs(c - m) + abs(c - y) + abs(m - y)) / 3;
      diff = diff * diff * diff / 65025; /* diff = diff^3 */
      k    = diff * k / 255;
      divk = 255 - k;
      
      if (divk == 0)
        c = m = y = 0;  /* Grayscale */
      else
      {
       /*
        * Full color; update the CMY values for the black value and reduce
        * CMY as necessary to give better blues, greens, and reds... :)
        */

        c  = (255 - rgb[1] / 4) * (c - k) / divk;
        m  = (255 - rgb[2] / 4) * (m - k) / divk;
        y  = (255 - rgb[0] / 4) * (y - k) / divk;
      };

      k += ditherk / 8;
      if (k > 127)
      {
      *kptr |= bit;
      k -= 255;
      };

      if (ditherbit & bit)
      {
      kerror1[0] = 5 * k;
      ditherk    = kerror0[1] + 3 * k;
      }
      else
      {
      kerror1[0] = 3 * k;
      ditherk    = kerror0[1] + 5 * k;
      };

      if (bit == 1)
        kptr ++;
    }
    else
    {
     /*
      * We're not printing black, but let's adjust the CMY levels to produce
      * better reds, greens, and blues...
      */

      c  = (255 - rgb[1] / 4) * (c - k) / 255 + k;
      m  = (255 - rgb[2] / 4) * (m - k) / 255 + k;
      y  = (255 - rgb[0] / 4) * (y - k) / 255 + k;
    };

    c += ditherc / 8;
    if (c > 127)
    {
      *cptr |= bit;
      c -= 255;
    };

    if (ditherbit & bit)
    {
      cerror1[0] = 5 * c;
      ditherc    = cerror0[1] + 3 * c;
    }
    else
    {
      cerror1[0] = 3 * c;
      ditherc    = cerror0[1] + 5 * c;
    };

    m += ditherm / 8;
    if (m > 127)
    {
      *mptr |= bit;
      m -= 255;
    };

    if (ditherbit & bit)
    {
      merror1[0] = 5 * m;
      ditherm    = merror0[1] + 3 * m;
    }
    else
    {
      merror1[0] = 3 * m;
      ditherm    = merror0[1] + 5 * m;
    };

    y += dithery / 8;
    if (y > 127)
    {
      *yptr |= bit;
      y -= 255;
    };

    if (ditherbit & bit)
    {
      yerror1[0] = 5 * y;
      dithery    = yerror0[1] + 3 * y;
    }
    else
    {
      yerror1[0] = 3 * y;
      dithery    = yerror0[1] + 5 * y;
    };

    if (bit == 1)
    {
      cptr ++;
      mptr ++;
      yptr ++;
      bit       = 128;
      ditherbit = rand();
    }
    else
      bit >>= 1;

    rgb    += xstep;
    xerror += xmod;
    if (xerror >= dst_width)
    {
      xerror -= dst_width;
      rgb    += 3;
    };
  };
}



Generated by  Doxygen 1.6.0   Back to index