libgimpprint API Reference: src/main/dither-ordered.c Source File

Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

# src/main/dither-ordered.c

Go to the documentation of this file.

    00001 /*
    00002  * "$Id: dither-ordered_8c-source.html,v 1.1.1.2 2004/12/22 23:48:58 jlovell Exp $"
    00003  *
    00004  *   Ordered dither algorithm
    00005  *
    00006  *   Copyright 1997-2003 Michael Sweet (mike@easysw.com) and
    00007  *      Robert Krawitz (rlk@alum.mit.edu)
    00008  *
    00009  *   This program is free software; you can redistribute it and/or modify it
    00010  *   under the terms of the GNU General Public License as published by the Free
    00011  *   Software Foundation; either version 2 of the License, or (at your option)
    00012  *   any later version.
    00013  *
    00014  *   This program is distributed in the hope that it will be useful, but
    00015  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    00016  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    00017  *   for more details.
    00018  *
    00019  *   You should have received a copy of the GNU General Public License
    00020  *   along with this program; if not, write to the Free Software
    00021  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    00022  *
    00023  * Revision History:
    00024  *
    00025  *   See ChangeLog
    00026  */
    00027
    00028 #ifdef HAVE_CONFIG_H
    00029 #include <config.h>
    00030 #endif
    00031 #include <gimp-print/gimp-print.h>
    00032 #include "gimp-print-internal.h"
    00033 #include <gimp-print/gimp-print-intl-internal.h>
    00034 #include "dither-impl.h"
    00035 #include "dither-inlined-functions.h"
    00036
    00037 static inline void
    00038 print_color_ordered(const stpi_dither_t *d, stpi_dither_channel_t *dc, int val,
    00039                     int x, int y, unsigned char bit, int length)
    00040 {
    00041   int i;
    00042   int j;
    00043   unsigned bits;
    00044   int levels = dc->nlevels - 1;
    00045
    00046   /*
    00047    * Look for the appropriate range into which the input value falls.
    00048    * Notice that we use the input, not the error, to decide what dot type
    00049    * to print (if any).  We actually use the "density" input to permit
    00050    * the caller to use something other that simply the input value, if it's
    00051    * desired to use some function of overall density, rather than just
    00052    * this color's input, for this purpose.
    00053    */
    00054   for (i = levels; i >= 0; i--)
    00055     {
    00056       stpi_dither_segment_t *dd = &(dc->ranges[i]);
    00057
    00058       if (val > dd->lower->value)
    00059         {
    00060           /*
    00061            * Where are we within the range.
    00062            */
    00063
    00064           unsigned rangepoint = val - dd->lower->value;
    00065           if (dd->value_span < 65535)
    00066             rangepoint = rangepoint * 65535 / dd->value_span;
    00067
    00068           if (rangepoint >= ditherpoint(d, &(dc->dithermat), x))
    00069             bits = dd->upper->bits;
    00070           else
    00071             bits = dd->lower->bits;
    00072
    00073           if (bits)
    00074             {
    00075               unsigned char *tptr = dc->ptr + d->ptr_offset;
    00076
    00077               /*
    00078                * Lay down all of the bits in the pixel.
    00079                */
    00080               set_row_ends(dc, x);
    00081               for (j = 1; j <= bits; j += j, tptr += length)
    00082                 {
    00083                   if (j & bits)
    00084                     tptr[0] |= bit;
    00085                 }
    00086
    00087             }
    00088           return;
    00089         }
    00090     }
    00091 }
    00092
    00093
    00094 void
    00095 stpi_dither_ordered(stp_vars_t *v,
    00096                     int row,
    00097                     const unsigned short *raw,
    00098                     int duplicate_line,
    00099                     int zero_mask,
    00100                     const unsigned char *mask)
    00101 {
    00102   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
    00103   int           x,
    00104                 length;
    00105   unsigned char bit;
    00106   int i;
    00107   int one_bit_only = 1;
    00108
    00109   int xerror, xstep, xmod;
    00110
    00111   if ((zero_mask & ((1 << CHANNEL_COUNT(d)) - 1)) ==
    00112       ((1 << CHANNEL_COUNT(d)) - 1))
    00113     return;
    00114
    00115   length = (d->dst_width + 7) / 8;
    00116
    00117   bit = 128;
    00118   xstep  = CHANNEL_COUNT(d) * (d->src_width / d->dst_width);
    00119   xmod   = d->src_width % d->dst_width;
    00120   xerror = 0;
    00121
    00122   for (i = 0; i < CHANNEL_COUNT(d); i++)
    00123     {
    00124       stpi_dither_channel_t *dc = &(CHANNEL(d, i));
    00125       if (dc->nlevels != 1 || dc->ranges[0].upper->bits != 1)
    00126         one_bit_only = 0;
    00127     }
    00128
    00129   if (one_bit_only)
    00130     {
    00131       for (x = 0; x < d->dst_width; x ++)
    00132         {
    00133           if (!mask || (*(mask + d->ptr_offset) & bit))
    00134             {
    00135               for (i = 0; i < CHANNEL_COUNT(d); i++)
    00136                 {
    00137                   if (raw[i] &&
    00138                       raw[i] >= ditherpoint(d, &(CHANNEL(d, i).dithermat), x))
    00139                     {
    00140                       set_row_ends(&(CHANNEL(d, i)), x);
    00141                       CHANNEL(d, i).ptr[d->ptr_offset] |= bit;
    00142                     }
    00143                 }
    00144             }
    00145           ADVANCE_UNIDIRECTIONAL(d, bit, raw, CHANNEL_COUNT(d),
    00146                                  xerror, xstep, xmod);
    00147         }
    00148     }
    00149   else
    00150     {
    00151       for (x = 0; x != d->dst_width; x ++)
    00152         {
    00153           if (!mask || (*(mask + d->ptr_offset) & bit))
    00154             {
    00155               for (i = 0; i < CHANNEL_COUNT(d); i++)
    00156                 {
    00157                   if (CHANNEL(d, i).ptr && raw[i])
    00158                     print_color_ordered(d, &(CHANNEL(d, i)), raw[i], x, row,
    00159                                         bit, length);
    00160                 }
    00161             }
    00162           ADVANCE_UNIDIRECTIONAL(d, bit, raw, CHANNEL_COUNT(d), xerror,
    00163                                  xstep, xmod);
    00164         }
    00165     }
    00166 }