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

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

# src/main/dither-ed.c

Go to the documentation of this file.

    00001 /*
    00002  * "$Id: dither-ed_8c-source.html,v 1.1.1.2 2004/12/22 23:48:57 jlovell 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 }