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

src/main/dither-inks.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: dither-inks.c,v 1.24 2004/05/07 19:20:30 rleigh Exp $"
00003  *
00004  *   Print plug-in driver utility functions for the GIMP.
00005  *
00006  *   Copyright 1997-2000 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 #ifdef HAVE_LIMITS_H
00035 #include <limits.h>
00036 #endif
00037 #include <math.h>
00038 #include <assert.h>
00039 #include <string.h>
00040 #include "dither-impl.h"
00041 
00042 int
00043 stpi_dither_translate_channel(stp_vars_t *v, unsigned channel,
00044                               unsigned subchannel)
00045 {
00046   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00047   unsigned chan_idx;
00048   if (!d)
00049     return -1;
00050   if (channel >= d->channel_count)
00051     return -1;
00052   if (subchannel >= d->subchannel_count[channel])
00053     return -1;
00054   chan_idx = d->channel_index[channel];
00055   return chan_idx + subchannel;
00056 }
00057 
00058 unsigned char *
00059 stp_dither_get_channel(stp_vars_t *v, unsigned channel, unsigned subchannel)
00060 {
00061   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00062   int place = stpi_dither_translate_channel(v, channel, subchannel);
00063   if (place >= 0)
00064     return d->channel[place].ptr;
00065   else
00066     return NULL;
00067 }
00068 
00069 static void
00070 insert_channel(stp_vars_t *v, stpi_dither_t *d, int channel)
00071 {
00072   unsigned oc = d->channel_count;
00073   int i;
00074   d->channel_index =
00075     stp_realloc (d->channel_index, sizeof(unsigned) * (channel + 1));
00076   d->subchannel_count =
00077     stp_realloc (d->subchannel_count, sizeof(unsigned) * (channel + 1));
00078   for (i = oc; i < channel + 1; i++)
00079     {
00080       if (oc == 0)
00081         d->channel_index[i] = 0;
00082       else
00083         d->channel_index[i] =
00084           d->channel_index[oc - 1] + d->subchannel_count[oc - 1];
00085       d->subchannel_count[i] = 0;
00086     }
00087   d->channel_count = channel + 1;
00088 }
00089 
00090 void
00091 stpi_dither_channel_destroy(stpi_dither_channel_t *channel)
00092 {
00093   int i;
00094   STP_SAFE_FREE(channel->ink_list);
00095   if (channel->errs)
00096     {
00097       for (i = 0; i < channel->error_rows; i++)
00098         STP_SAFE_FREE(channel->errs[i]);
00099       STP_SAFE_FREE(channel->errs);
00100     }
00101   STP_SAFE_FREE(channel->ranges);
00102   stp_dither_matrix_destroy(&(channel->pick));
00103   stp_dither_matrix_destroy(&(channel->dithermat));
00104 }  
00105 
00106 static void
00107 initialize_channel(stp_vars_t *v, int channel, int subchannel)
00108 {
00109   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00110   int idx = stpi_dither_translate_channel(v, channel, subchannel);
00111   stpi_dither_channel_t *dc = &(CHANNEL(d, idx));
00112   stp_shade_t shade;
00113   stp_dotsize_t dot;
00114   assert(idx >= 0);
00115   memset(dc, 0, sizeof(stpi_dither_channel_t));
00116   stp_dither_matrix_clone(&(d->dither_matrix), &(dc->dithermat), 0, 0);
00117   stp_dither_matrix_clone(&(d->transition_matrix), &(dc->pick), 0, 0);
00118   shade.dot_sizes = &dot;
00119   shade.value = 1.0;
00120   shade.numsizes = 1;
00121   dot.bit_pattern = 1;
00122   dot.value = 1.0;
00123   stp_dither_set_inks_full(v, channel, 1, &shade, 1.0, 1.0);
00124 }
00125 
00126 static void
00127 insert_subchannel(stp_vars_t *v, stpi_dither_t *d, int channel, int subchannel)
00128 {
00129   int i;
00130   unsigned oc = d->subchannel_count[channel];
00131   unsigned increment = subchannel - oc + 1;
00132   unsigned old_place = d->channel_index[channel] + oc;
00133   stpi_dither_channel_t *nc =
00134     stp_malloc(sizeof(stpi_dither_channel_t) *
00135                (d->total_channel_count + increment));
00136       
00137   if (d->channel)
00138     {
00139       /*
00140        * Copy the old channels, including all subchannels of the current
00141        * channel that already existed.
00142        */
00143       memcpy(nc, d->channel, sizeof(stpi_dither_channel_t) * old_place);
00144       if (old_place < d->total_channel_count)
00145         /*
00146          * If we're inserting a new subchannel in the middle somewhere,
00147          * we need to move everything else up
00148          */
00149         memcpy(nc + old_place + increment, d->channel + old_place,
00150                (sizeof(stpi_dither_channel_t) *
00151                 (d->total_channel_count - old_place)));
00152       stp_free(d->channel);
00153     }
00154   d->channel = nc;
00155   if (channel < d->channel_count - 1)
00156     /* Now fix up the subchannel offsets */
00157     for (i = channel + 1; i < d->channel_count; i++)
00158       d->channel_index[i] += increment;
00159   d->subchannel_count[channel] = subchannel + 1;
00160   d->total_channel_count += increment;
00161   for (i = oc; i < oc + increment; i++)
00162     initialize_channel(v, channel, i);
00163 }
00164 
00165 void
00166 stpi_dither_finalize(stp_vars_t *v)
00167 {
00168   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00169   if (!d->finalized)
00170     {
00171       int i;
00172       unsigned rc = 1 + (unsigned) ceil(sqrt(CHANNEL_COUNT(d)));
00173       unsigned x_n = d->dither_matrix.x_size / rc;
00174       unsigned y_n = d->dither_matrix.y_size / rc;
00175       for (i = 0; i < CHANNEL_COUNT(d); i++)
00176         {
00177           stpi_dither_channel_t *dc = &(CHANNEL(d, i));
00178           stp_dither_matrix_clone(&(d->dither_matrix), &(dc->dithermat),
00179                                    x_n * (i % rc), y_n * (i / rc));
00180           stp_dither_matrix_clone(&(d->dither_matrix), &(dc->pick),
00181                                    x_n * (i % rc), y_n * (i / rc));
00182         }
00183       d->finalized = 1;
00184     }
00185 }
00186 
00187 void
00188 stp_dither_add_channel(stp_vars_t *v, unsigned char *data,
00189                        unsigned channel, unsigned subchannel)
00190 {
00191   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00192   int idx;
00193   if (channel >= d->channel_count)
00194     insert_channel(v, d, channel);
00195   if (subchannel >= d->subchannel_count[channel])
00196     insert_subchannel(v, d, channel, subchannel);
00197   idx = stpi_dither_translate_channel(v, channel, subchannel);
00198   assert(idx >= 0);
00199   d->channel[idx].ptr = data;
00200 }
00201 
00202 static void
00203 stpi_dither_finalize_ranges(stp_vars_t *v, stpi_dither_channel_t *dc)
00204 {
00205   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00206   int i;
00207   unsigned lbit = dc->bit_max;
00208   dc->signif_bits = 0;
00209   while (lbit > 0)
00210     {
00211       dc->signif_bits++;
00212       lbit >>= 1;
00213     }
00214 
00215   for (i = 0; i < dc->nlevels; i++)
00216     {
00217       if (dc->ranges[i].lower->bits == dc->ranges[i].upper->bits)
00218         dc->ranges[i].is_same_ink = 1;
00219       else
00220         dc->ranges[i].is_same_ink = 0;
00221       if (dc->ranges[i].range_span > 0 && dc->ranges[i].value_span > 0)
00222         dc->ranges[i].is_equal = 0;
00223       else
00224         dc->ranges[i].is_equal = 1;
00225 
00226       stp_dprintf(STP_DBG_INK, v,
00227                   "    level %d value[0] %d value[1] %d range[0] %d range[1] %d\n",
00228                   i, dc->ranges[i].lower->value, dc->ranges[i].upper->value,
00229                   dc->ranges[i].lower->range, dc->ranges[i].upper->range);
00230       stp_dprintf(STP_DBG_INK, v,
00231                   "       bits[0] %d bits[1] %d\n",
00232                   dc->ranges[i].lower->bits, dc->ranges[i].upper->bits);
00233       stp_dprintf(STP_DBG_INK, v,
00234                   "       rangespan %d valuespan %d same_ink %d equal %d\n",
00235                   dc->ranges[i].range_span, dc->ranges[i].value_span,
00236                   dc->ranges[i].is_same_ink, dc->ranges[i].is_equal);
00237       if (i > 0 && dc->ranges[i].lower->range >= d->adaptive_limit)
00238         {
00239           d->adaptive_limit = dc->ranges[i].lower->range + 1;
00240           if (d->adaptive_limit > 65535)
00241             d->adaptive_limit = 65535;
00242           stp_dprintf(STP_DBG_INK, v, "Setting adaptive limit to %d\n",
00243                       d->adaptive_limit);
00244         }
00245     }
00246   for (i = 0; i <= dc->nlevels; i++)
00247     stp_dprintf(STP_DBG_INK, v,
00248                 "    ink_list[%d] range %d value %d bits %d\n",
00249                 i, dc->ink_list[i].range,
00250                 dc->ink_list[i].value, dc->ink_list[i].bits);
00251   if (dc->nlevels == 1 && dc->ranges[0].upper->bits == 1)
00252     dc->very_fast = 1;
00253   else
00254     dc->very_fast = 0;
00255 
00256   stp_dprintf(STP_DBG_INK, v,
00257               "  bit_max %d signif_bits %d\n", dc->bit_max, dc->signif_bits);
00258 }
00259 
00260 static void
00261 stpi_dither_set_ranges(stp_vars_t *v, int color, const stp_shade_t *shade,
00262                        double density, double darkness)
00263 {
00264   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00265   stpi_dither_channel_t *dc = &(CHANNEL(d, color));
00266   const stp_dotsize_t *ranges = shade->dot_sizes;
00267   int nlevels = shade->numsizes;
00268   int i;
00269 
00270   STP_SAFE_FREE(dc->ranges);
00271   STP_SAFE_FREE(dc->ink_list);
00272 
00273   dc->nlevels = nlevels > 1 ? nlevels + 1 : nlevels;
00274   dc->ranges = (stpi_dither_segment_t *)
00275     stp_zalloc(dc->nlevels * sizeof(stpi_dither_segment_t));
00276   dc->ink_list = (stpi_ink_defn_t *)
00277     stp_zalloc((dc->nlevels + 1) * sizeof(stpi_ink_defn_t));
00278   dc->bit_max = 0;
00279   dc->density = density * 65535;
00280   dc->darkness = darkness;
00281   stp_init_debug_messages(v);
00282   stp_dprintf(STP_DBG_INK, v,
00283               "stpi_dither_set_ranges channel %d nlevels %d density %f darkness %f\n",
00284               color, nlevels, density, darkness);
00285   for (i = 0; i < nlevels; i++)
00286     stp_dprintf(STP_DBG_INK, v,
00287                 "  level %d value %f pattern %x\n", i,
00288                 ranges[i].value, ranges[i].bit_pattern);
00289   dc->ranges[0].lower = &dc->ink_list[0];
00290   dc->ranges[0].upper = &dc->ink_list[1];
00291   dc->ink_list[0].range = 0;
00292   dc->ink_list[0].value = 0;
00293   dc->ink_list[0].bits = 0;
00294   if (nlevels == 1)
00295     dc->ink_list[1].range = 65535;
00296   else
00297     dc->ink_list[1].range = ranges[0].value * 65535.0 * density;
00298   if (dc->ink_list[1].range > 65535)
00299     dc->ink_list[1].range = 65535;
00300   dc->ink_list[1].value = ranges[0].value * 65535.0;
00301   if (dc->ink_list[1].value > 65535)
00302     dc->ink_list[1].value = 65535;
00303   dc->ink_list[1].bits = ranges[0].bit_pattern;
00304   if (ranges[0].bit_pattern > dc->bit_max)
00305     dc->bit_max = ranges[0].bit_pattern;
00306   dc->ranges[0].range_span = dc->ranges[0].upper->range;
00307   dc->ranges[0].value_span = dc->ranges[0].upper->value;
00308   if (dc->nlevels > 1)
00309     {
00310       for (i = 1; i < nlevels; i++)
00311         {
00312           int l = i + 1;
00313           dc->ranges[i].lower = &dc->ink_list[i];
00314           dc->ranges[i].upper = &dc->ink_list[l];
00315 
00316           dc->ink_list[l].range =
00317             (ranges[i].value + ranges[i].value) * 32768.0 * density;
00318           if (dc->ink_list[l].range > 65535)
00319             dc->ink_list[l].range = 65535;
00320           dc->ink_list[l].value = ranges[i].value * 65535.0;
00321           if (dc->ink_list[l].value > 65535)
00322             dc->ink_list[l].value = 65535;
00323           dc->ink_list[l].bits = ranges[i].bit_pattern;
00324           if (ranges[i].bit_pattern > dc->bit_max)
00325             dc->bit_max = ranges[i].bit_pattern;
00326           dc->ranges[i].range_span =
00327             dc->ink_list[l].range - dc->ink_list[i].range;
00328           dc->ranges[i].value_span =
00329             dc->ink_list[l].value - dc->ink_list[i].value;
00330         }
00331       dc->ranges[i].lower = &dc->ink_list[i];
00332       dc->ranges[i].upper = &dc->ink_list[i+1];
00333       dc->ink_list[i+1] = dc->ink_list[i];
00334       dc->ink_list[i+1].range = 65535;
00335       dc->ranges[i].range_span =
00336         dc->ink_list[i+1].range - dc->ink_list[i].range;
00337       dc->ranges[i].value_span =
00338         dc->ink_list[i+1].value - dc->ink_list[i].value;
00339     }
00340   stpi_dither_finalize_ranges(v, dc);
00341   stp_flush_debug_messages(v);
00342 }
00343 
00344 void
00345 stp_dither_set_inks_simple(stp_vars_t *v, int color, int nlevels,
00346                            const double *levels, double density,
00347                            double darkness)
00348 {
00349   stp_shade_t s;
00350   stp_dotsize_t *d = stp_malloc(nlevels * sizeof(stp_dotsize_t));
00351   int i;
00352   s.dot_sizes = d;
00353   s.value = 65535.0;
00354   s.numsizes = nlevels;
00355 
00356   for (i = 0; i < nlevels; i++)
00357     {
00358       d[i].bit_pattern = i + 1;
00359       d[i].value = levels[i];
00360     }
00361   stp_dither_set_inks_full(v, color, 1, &s, density, darkness);
00362   stp_free(d);
00363 }
00364 
00365 void
00366 stp_dither_set_inks_full(stp_vars_t *v, int color, int nshades,
00367                          const stp_shade_t *shades, double density,
00368                          double darkness)
00369 {
00370   int i;
00371   int idx;
00372   stpi_dither_channel_t *dc;
00373 
00374   stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00375 
00376   stp_channel_reset_channel(v, color);
00377 
00378   for (i = nshades - 1; i >= 0; i--)
00379     {
00380       int subchannel = nshades - i - 1;
00381       idx = stpi_dither_translate_channel(v, color, subchannel);
00382       assert(idx >= 0);
00383       dc = &(CHANNEL(d, idx));
00384 
00385       stp_channel_add(v, color, subchannel, shades[i].value);
00386       if (idx >= 0)
00387         stpi_dither_set_ranges(v, idx, &shades[i], density,
00388                                shades[i].value * darkness);
00389       stp_dprintf(STP_DBG_INK, v,
00390                   "  shade %d value %f\n",
00391                   i, shades[i].value);
00392     }
00393 }
00394 
00395 void
00396 stp_dither_set_inks(stp_vars_t *v, int color, double density, double darkness,
00397                     int nshades, const double *svalues,
00398                     int ndotsizes, const double *dvalues)
00399 {
00400   int i, j;
00401   stp_shade_t *shades = stp_malloc(sizeof(stp_shade_t) * nshades);
00402   stp_dotsize_t *dotsizes = stp_malloc(sizeof(stp_dotsize_t) * ndotsizes);
00403   j = 0;
00404   for (i = 0; i < ndotsizes; i++)
00405     {
00406       /* Skip over any zero-valued dot sizes */
00407       if (dvalues[i] > 0)
00408         {
00409           dotsizes[j].value = dvalues[i];
00410           dotsizes[j].bit_pattern = i + 1;
00411           j++;
00412         }
00413     }
00414   for (i = 0; i < nshades; i++)
00415     {
00416       shades[i].value = svalues[i];
00417       shades[i].numsizes = j;
00418       shades[i].dot_sizes = dotsizes;
00419     }
00420   stp_dither_set_inks_full(v, color, nshades, shades, density, darkness);
00421   stp_free(dotsizes);
00422   stp_free(shades);
00423 }

Generated on Wed Aug 25 07:56:13 2004 for libgimpprint API Reference by doxygen 1.3.6