Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals  

src/main/dither-ed.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: dither-ed.c,v 1.17 2004/05/07 19:20:29 rleigh Exp $"
00003  *
00004  *   Error diffusion and closely related adaptive hybrid 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 <string.h>
00035 #include "dither-impl.h"
00036 #include "dither-inlined-functions.h"
00037 
00038 /*
00039  * Add the error to the input value.  Notice that we micro-optimize this
00040  * to save a division when appropriate.  This has yielded measurable
00041  * improvement -- rlk 20030119
00042  */
00043 
00044 #define UPDATE_COLOR(color, dither) (                                      \
00045 ((dither) >= 0)? (color) + ((dither) >> 3) : (color) - ((-(dither)) >> 3))
00046 
00047 /*
00048  * For Floyd-Steinberg, distribute the error residual.  We spread the
00049  * error to nearby points, spreading more broadly in lighter regions to
00050  * achieve more uniform distribution of color.  The actual distribution
00051  * is a triangular function.
00052  */
00053 
00054 static inline int
00055 update_dither(stpi_dither_t *d, int channel, int width,
00056               int direction, int *error0, int *error1)
00057 {
00058   int r = CHANNEL(d, channel).v;
00059   int o = CHANNEL(d, channel).o;
00060   int tmp = r;
00061   int i, dist, dist1;
00062   int delta, delta1;
00063   int offset;
00064   if (tmp == 0)
00065     return error0[direction];
00066   if (tmp > 65535)
00067     tmp = 65535;
00068   if (d->spread >= 16 || o >= 2048)
00069     {
00070       tmp += tmp;
00071       tmp += tmp;
00072       error1[0] += tmp;
00073       return error0[direction] + tmp;
00074     }
00075   else
00076     {
00077       int tmpo = o << 5;
00078       offset = ((65535 - tmpo) >> d->spread) +
00079         ((tmp & d->spread_mask) > (tmpo & d->spread_mask));
00080     }
00081   switch (offset)
00082     {
00083     case 0:
00084       tmp += tmp;
00085       tmp += tmp;
00086       error1[0] += tmp;
00087       return error0[direction] + tmp;
00088     case 1:
00089       error1[-1] += tmp;
00090       error1[1] += tmp;
00091       tmp += tmp;
00092       error1[0] += tmp;
00093       tmp += tmp;
00094       return error0[direction] + tmp;
00095     default:
00096       tmp += tmp;
00097       tmp += tmp;
00098       dist = tmp / d->offset0_table[offset];
00099       dist1 = tmp / d->offset1_table[offset];
00100       delta = dist;
00101       delta1 = dist1;
00102       for (i = -offset; i; i++)
00103         {
00104           error1[i] += delta;
00105           error1[-i] += delta;
00106           error0[i] += delta1;
00107           error0[-i] += delta1;
00108           delta1 += dist1;
00109           delta += dist;
00110         }
00111       error1[0] += delta;
00112       return error0[direction];
00113     }
00114 }
00115 
00116 
00117 /*
00118  * Print a single dot.  This routine has become awfully complicated
00119  * awfully fast!
00120  */
00121 
00122 static inline int
00123 print_color(const stpi_dither_t *d, stpi_dither_channel_t *dc, int x, int y,
00124             unsigned char bit, int length, int dontprint, int stpi_dither_type,
00125             const unsigned char *mask)
00126 {
00127   int base = dc->b;
00128   int density = dc->o;
00129   int adjusted = dc->v;
00130   unsigned randomizer = dc->randomizer;
00131   stp_dither_matrix_impl_t *pick_matrix = &(dc->pick);
00132   stp_dither_matrix_impl_t *dither_matrix = &(dc->dithermat);
00133   unsigned rangepoint = 32768;
00134   unsigned vmatrix;
00135   int i;
00136   int j;
00137   unsigned char *tptr;
00138   unsigned bits;
00139   unsigned v;
00140   int levels = dc->nlevels - 1;
00141   int dither_value = adjusted;
00142   stpi_ink_defn_t *lower;
00143   stpi_ink_defn_t *upper;
00144 
00145   if (base <= 0 || density <= 0 ||
00146       (adjusted <= 0 && !(stpi_dither_type & D_ADAPTIVE_BASE)))
00147     return adjusted;
00148   if (density > 65535)
00149     density = 65535;
00150 
00151   /*
00152    * Look for the appropriate range into which the input value falls.
00153    * Notice that we use the input, not the error, to decide what dot type
00154    * to print (if any).  We actually use the "density" input to permit
00155    * the caller to use something other that simply the input value, if it's
00156    * desired to use some function of overall density, rather than just
00157    * this color's input, for this purpose.
00158    */
00159   for (i = levels; i >= 0; i--)
00160     {
00161       stpi_dither_segment_t *dd = &(dc->ranges[i]);
00162 
00163       if (density <= dd->lower->range)
00164         continue;
00165 
00166       /*
00167        * If we're using an adaptive dithering method, decide whether
00168        * to use the Floyd-Steinberg or the ordered method based on the
00169        * input value.
00170        */
00171       if (stpi_dither_type & D_ADAPTIVE_BASE)
00172         {
00173           stpi_dither_type -= D_ADAPTIVE_BASE;
00174 
00175           if (i < levels || base <= d->adaptive_limit)
00176             {
00177               stpi_dither_type = D_ORDERED;
00178               dither_value = base;
00179             }
00180           else if (adjusted <= 0)
00181             return adjusted;
00182         }
00183       /*
00184        * Where are we within the range.  If we're going to print at
00185        * all, this determines the probability of printing the darker
00186        * vs. the lighter ink.  If the inks are identical (same value
00187        * and darkness), it doesn't matter.
00188        *
00189        * We scale the input linearly against the top and bottom of the
00190        * range.
00191        */
00192 
00193       lower = dd->lower;
00194       upper = dd->upper;
00195 
00196       /*
00197        * Reduce the randomness as the base value increases, to get
00198        * smoother output in the midtones.  Idea suggested by
00199        * Thomas Tonino.
00200        */
00201       if (stpi_dither_type & D_ORDERED_BASE)
00202         {
00203           rangepoint = density - dd->lower->range;
00204           if (dd->range_span < 65535)
00205             rangepoint = rangepoint * 65535 / dd->range_span;
00206           vmatrix = 0;
00207         }
00208       else
00209         {
00210 
00211           /*
00212            * Compute the virtual dot size that we're going to print.
00213            * This is somewhere between the two candidate dot sizes.
00214            * This is scaled between the high and low value.
00215            */
00216 
00217           unsigned virtual_value;
00218           rangepoint = density - dd->lower->range;
00219           if (dd->range_span < 65535)
00220             rangepoint = rangepoint * 65535 / dd->range_span;
00221           if (dd->value_span == 0)
00222             virtual_value = upper->value;
00223           else /* if (dd->range_span == 0) */
00224             virtual_value = (upper->value + lower->value) / 2;
00225           /*
00226             else
00227             virtual_value = lower->value + (dd->value_span * rangepoint / 65535);
00228           */
00229           randomizer = 0;
00230           if (randomizer > 0)
00231             {
00232               if (base > d->d_cutoff)
00233                 randomizer = 0;
00234               else if (base > d->d_cutoff / 2)
00235                 randomizer = randomizer * 2 * (d->d_cutoff - base) / d->d_cutoff;
00236             }
00237 
00238           /*
00239            * Compute the comparison value to decide whether to print at
00240            * all.  If there is no randomness, simply divide the virtual
00241            * dotsize by 2 to get standard "pure" Floyd-Steinberg (or "pure"
00242            * matrix dithering, which degenerates to a threshold).
00243            */
00244           if (randomizer == 0)
00245             vmatrix = virtual_value / 2;
00246           else
00247             {
00248               /*
00249                * First, compute a value between 0 and 65535 that will be
00250                * scaled to produce an offset from the desired threshold.
00251                */
00252               vmatrix = ditherpoint(d, dither_matrix, x);
00253               /*
00254                * Now, scale the virtual dot size appropriately.  Note that
00255                * we'll get something evenly distributed between 0 and
00256                * the virtual dot size, centered on the dot size / 2,
00257                * which is the normal threshold value.
00258                */
00259               vmatrix = vmatrix * virtual_value / 65535;
00260               if (randomizer != 65535)
00261                 {
00262                   /*
00263                    * We want vmatrix to be scaled between 0 and
00264                    * virtual_value when randomizer is 65535 (fully random).
00265                    * When it's less, we want it to scale through part of
00266                    * that range. In all cases, it should center around
00267                    * virtual_value / 2.
00268                    *
00269                    * vbase is the bottom of the scaling range.
00270                    */
00271                   unsigned vbase = virtual_value * (65535u - randomizer) /
00272                     131070u;
00273                   vmatrix = vmatrix * randomizer / 65535;
00274                   vmatrix += vbase;
00275                 }
00276             } /* randomizer != 0 */
00277         }
00278       /*
00279        * After all that, printing is almost an afterthought.
00280        * Pick the actual dot size (using a matrix here) and print it.
00281        */
00282       if (dither_value > 0 && dither_value >= vmatrix)
00283         {
00284           stpi_ink_defn_t *subc;
00285 
00286           if (dd->is_same_ink)
00287             subc = upper;
00288           else
00289             {
00290               if (rangepoint >= ditherpoint(d, pick_matrix, x))
00291                 subc = upper;
00292               else
00293                 subc = lower;
00294             }
00295           v = subc->value;
00296           if (!mask || (*(mask + d->ptr_offset) & bit))
00297             {
00298               if (dc->ptr)
00299                 {
00300                   tptr = dc->ptr + d->ptr_offset;
00301 
00302                   /*
00303                    * Lay down all of the bits in the pixel.
00304                    */
00305                   if (dontprint < v)
00306                     {
00307                       bits = subc->bits;
00308                       set_row_ends(dc, x);
00309                       for (j = 1; j <= bits; j += j, tptr += length)
00310                         {
00311                           if (j & bits)
00312                             tptr[0] |= bit;
00313                         }
00314                     }
00315                 }
00316             }
00317           if (stpi_dither_type & D_ORDERED_BASE)
00318             {
00319               double adj = -(int) v;
00320               adj /= 2.0;
00321               adjusted = adj;
00322             }
00323           else
00324             {
00325               double adj = v;
00326               adjusted -= adj;
00327             }
00328         }
00329       return adjusted;
00330     }
00331   return adjusted;
00332 }
00333 
00334 static int
00335 shared_ed_initializer(stpi_dither_t *d,
00336                       int row,
00337                       int duplicate_line,
00338                       int zero_mask,
00339                       int length,
00340                       int direction,
00341                       int ****error,
00342                       int **ndither)
00343 {
00344   int i, j;
00345   for (i = 0; i < CHANNEL_COUNT(d); i++)
00346     CHANNEL(d, i).error_rows = 2;
00347   if (!duplicate_line)
00348     {
00349       if ((zero_mask & ((1 << CHANNEL_COUNT(d)) - 1)) !=
00350           ((1 << CHANNEL_COUNT(d)) - 1))
00351         d->last_line_was_empty = 0;
00352       else
00353         d->last_line_was_empty++;
00354     }
00355   else if (d->last_line_was_empty)
00356     d->last_line_was_empty++;
00357   if (d->last_line_was_empty >= 5)
00358     return 0;
00359   else if (d->last_line_was_empty == 4)
00360     {
00361       for (i = 0; i < CHANNEL_COUNT(d); i++)
00362         for (j = 0; j < d->error_rows; j++)
00363           memset(stpi_dither_get_errline(d, row + j, i), 0,
00364                  d->dst_width * sizeof(int));
00365       return 0;
00366     }
00367   d->ptr_offset = (direction == 1) ? 0 : length - 1;
00368 
00369   *error = stp_malloc(CHANNEL_COUNT(d) * sizeof(int **));
00370   *ndither = stp_malloc(CHANNEL_COUNT(d) * sizeof(int));
00371   for (i = 0; i < CHANNEL_COUNT(d); i++)
00372     {
00373       (*error)[i] = stp_malloc(d->error_rows * sizeof(int *));
00374       for (j = 0; j < d->error_rows; j++)
00375         {
00376           (*error)[i][j] = stpi_dither_get_errline(d, row + j, i);
00377           if (j == d->error_rows - 1)
00378             memset((*error)[i][j], 0, d->dst_width * sizeof(int));
00379           if (direction == -1)
00380             (*error)[i][j] += d->dst_width - 1;
00381         }
00382       (*ndither)[i] = (*error)[i][0][0];
00383     }
00384   return 1;
00385 }
00386 
00387 static void
00388 shared_ed_deinitializer(stpi_dither_t *d,
00389                         int ***error,
00390                         int *ndither)
00391 {
00392   int i;
00393   for (i = 0; i < CHANNEL_COUNT(d); i++)
00394     {
00395       STP_SAFE_FREE(error[i]);
00396     }
00397   STP_SAFE_FREE(error);
00398   STP_SAFE_FREE(ndither);
00399 }
00400 
00401 void
00402 stpi_dither_ed(stp_vars_t *v,
00403                int row,
00404                const unsigned short *raw,
00405                int duplicate_line,
00406                int zero_mask,
00407                const unsigned char *mask)
00408 {
00409   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00410   int           x,
00411                 length;
00412   unsigned char bit;
00413   int           i;
00414   int           *ndither;
00415   int           ***error;
00416 
00417   int           terminate;
00418   int           direction = row & 1 ? 1 : -1;
00419   int xerror, xstep, xmod;
00420 
00421   length = (d->dst_width + 7) / 8;
00422   if (d->stpi_dither_type & D_ADAPTIVE_BASE)
00423     for (i = 0; i < CHANNEL_COUNT(d); i++)
00424       if (CHANNEL(d, i).nlevels > 1)
00425         {
00426           stpi_dither_ordered(v, row, raw, duplicate_line, zero_mask, mask);
00427           return;
00428         }
00429   if (!shared_ed_initializer(d, row, duplicate_line, zero_mask, length,
00430                              direction, &error, &ndither))
00431     return;
00432 
00433   x = (direction == 1) ? 0 : d->dst_width - 1;
00434   bit = 1 << (7 - (x & 7));
00435   xstep  = CHANNEL_COUNT(d) * (d->src_width / d->dst_width);
00436   xmod   = d->src_width % d->dst_width;
00437   xerror = (xmod * x) % d->dst_width;
00438   terminate = (direction == 1) ? d->dst_width : -1;
00439 
00440   if (direction == -1)
00441     raw += (CHANNEL_COUNT(d) * (d->src_width - 1));
00442 
00443   for (; x != terminate; x += direction)
00444     {
00445       for (i = 0; i < CHANNEL_COUNT(d); i++)
00446         {
00447           if (CHANNEL(d, i).ptr)
00448             {
00449               CHANNEL(d, i).v = raw[i];
00450               CHANNEL(d, i).o = CHANNEL(d, i).v;
00451               CHANNEL(d, i).b = CHANNEL(d, i).v;
00452               CHANNEL(d, i).v = UPDATE_COLOR(CHANNEL(d, i).v, ndither[i]);
00453               CHANNEL(d, i).v = print_color(d, &(CHANNEL(d, i)), x, row, bit,
00454                                             length, 0, d->stpi_dither_type,
00455                                             mask);
00456               ndither[i] = update_dither(d, i, d->src_width,
00457                                          direction, error[i][0], error[i][1]);
00458             }
00459         }
00460       ADVANCE_BIDIRECTIONAL(d, bit, raw, direction, CHANNEL_COUNT(d), xerror,
00461                             xstep, xmod, error, d->error_rows);
00462     }
00463   shared_ed_deinitializer(d, error, ndither);
00464   if (direction == -1)
00465     stpi_dither_reverse_row_ends(d);
00466 }

Generated on Wed May 12 20:21:28 2004 for libgimpprint API Reference by doxygen1.2.17