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

src/main/channel.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: channel.c,v 1.15 2004/07/24 02:07:21 rlk Exp $"
00003  *
00004  *   Dither routine entrypoints
00005  *
00006  *   Copyright 2003 Robert Krawitz (rlk@alum.mit.edu)
00007  *
00008  *   This program is free software; you can redistribute it and/or modify it
00009  *   under the terms of the GNU General Public License as published by the Free
00010  *   Software Foundation; either version 2 of the License, or (at your option)
00011  *   any later version.
00012  *
00013  *   This program is distributed in the hope that it will be useful, but
00014  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016  *   for more details.
00017  *
00018  *   You should have received a copy of the GNU General Public License
00019  *   along with this program; if not, write to the Free Software
00020  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021  *
00022  * Revision History:
00023  *
00024  *   See ChangeLog
00025  */
00026 
00027 #ifdef HAVE_CONFIG_H
00028 #include <config.h>
00029 #endif
00030 #include <gimp-print/gimp-print.h>
00031 #include "gimp-print-internal.h"
00032 #include <gimp-print/gimp-print-intl-internal.h>
00033 #ifdef HAVE_LIMITS_H
00034 #include <limits.h>
00035 #endif
00036 #include <math.h>
00037 #include <string.h>
00038 
00039 #ifdef __GNUC__
00040 #define inline __inline__
00041 #endif
00042 
00043 typedef struct
00044 {
00045   double value;
00046   double lower;
00047   double upper;
00048   double cutoff;
00049   unsigned short s_density;
00050 } stpi_subchannel_t;
00051 
00052 typedef struct
00053 {
00054   unsigned subchannel_count;
00055   stpi_subchannel_t *sc;
00056   unsigned short *lut;
00057 } stpi_channel_t;
00058 
00059 typedef struct
00060 {
00061   unsigned channel_count;
00062   unsigned total_channels;
00063   unsigned input_channels;
00064   size_t width;
00065   int initialized;
00066   unsigned ink_limit;
00067   unsigned max_density;
00068   stpi_channel_t *c;
00069   unsigned short *input_data;
00070   unsigned short *data;
00071   int black_channel;
00072 } stpi_channel_group_t;
00073 
00074 
00075 static void
00076 clear_a_channel(stpi_channel_group_t *cg, int channel)
00077 {
00078   if (channel < cg->channel_count)
00079     {
00080       STP_SAFE_FREE(cg->c[channel].sc);
00081       STP_SAFE_FREE(cg->c[channel].lut);
00082       cg->c[channel].subchannel_count = 0;
00083     }
00084 }
00085 
00086 static void
00087 stpi_channel_clear(void *vc)
00088 {
00089   stpi_channel_group_t *cg = (stpi_channel_group_t *) vc;
00090   int i;
00091   if (cg->channel_count > 0)
00092     for (i = 0; i < cg->channel_count; i++)
00093       clear_a_channel(cg, i);
00094   if (cg->data != cg->input_data)
00095     STP_SAFE_FREE(cg->data);
00096   STP_SAFE_FREE(cg->input_data);
00097   STP_SAFE_FREE(cg->c);
00098   cg->channel_count = 0;
00099   cg->total_channels = 0;
00100   cg->input_channels = 0;
00101   cg->initialized = 0;
00102 }
00103 
00104 void
00105 stp_channel_reset(stp_vars_t *v)
00106 {
00107   stpi_channel_group_t *cg =
00108     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00109   if (cg)
00110     stpi_channel_clear(cg);
00111 }
00112 
00113 void
00114 stp_channel_reset_channel(stp_vars_t *v, int channel)
00115 {
00116   stpi_channel_group_t *cg =
00117     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00118   if (cg)
00119     clear_a_channel(cg, channel);
00120 }
00121 
00122 static void
00123 stpi_channel_free(void *vc)
00124 {
00125   stpi_channel_clear(vc);
00126   stp_free(vc);
00127 }
00128 
00129 static stpi_subchannel_t *
00130 get_channel(stp_vars_t *v, unsigned channel, unsigned subchannel)
00131 {
00132   stpi_channel_group_t *cg =
00133     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00134   if (!cg)
00135     return NULL;
00136   if (channel >= cg->channel_count)
00137     return NULL;
00138   if (subchannel >= cg->c[channel].subchannel_count)
00139     return NULL;
00140   return &(cg->c[channel].sc[subchannel]);
00141 }
00142 
00143 void
00144 stp_channel_add(stp_vars_t *v, unsigned channel, unsigned subchannel,
00145                 double value)
00146 {
00147   stpi_channel_group_t *cg =
00148     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00149   stpi_channel_t *chan;
00150   if (!cg)
00151     {
00152       cg = stp_zalloc(sizeof(stpi_channel_group_t));
00153       cg->black_channel = -1;
00154       stp_allocate_component_data(v, "Channel", NULL, stpi_channel_free, cg);
00155     }
00156   if (channel >= cg->channel_count)
00157     {
00158       unsigned oc = cg->channel_count;
00159       cg->c = stp_realloc(cg->c, sizeof(stpi_channel_t) * (channel + 1));
00160       memset(cg->c + oc, 0, sizeof(stpi_channel_t) * (channel + 1 - oc));
00161       if (channel >= cg->channel_count)
00162         cg->channel_count = channel + 1;
00163     }
00164   chan = cg->c + channel;
00165   if (subchannel >= chan->subchannel_count)
00166     {
00167       unsigned oc = chan->subchannel_count;
00168       chan->sc =
00169         stp_realloc(chan->sc, sizeof(stpi_subchannel_t) * (subchannel + 1));
00170       (void) memset
00171         (chan->sc + oc, 0, sizeof(stpi_subchannel_t) * (subchannel + 1 - oc));
00172       chan->sc[subchannel].value = value;
00173       if (subchannel >= chan->subchannel_count)
00174         chan->subchannel_count = subchannel + 1;
00175     }
00176   chan->sc[subchannel].value = value;
00177   chan->sc[subchannel].s_density = 65535;
00178   chan->sc[subchannel].cutoff = 0.75;
00179 }
00180 
00181 void
00182 stp_channel_set_density_adjustment(stp_vars_t *v, int color, int subchannel,
00183                                    double adjustment)
00184 {
00185   stpi_subchannel_t *sch = get_channel(v, color, subchannel);
00186   if ((strcmp(stp_get_string_parameter(v, "STPIOutputType"), "Raw") == 0 &&
00187        strcmp(stp_get_string_parameter(v, "ColorCorrection"), "None") == 0) ||
00188       strcmp(stp_get_string_parameter(v, "ColorCorrection"), "Raw") == 0 ||
00189       strcmp(stp_get_string_parameter(v, "ColorCorrection"), "Predithered") == 0)
00190     {
00191       stp_dprintf(STP_DBG_INK, v,
00192                   "Ignoring channel_density channel %d subchannel %d adjustment %f\n",
00193                   color, subchannel, adjustment);
00194     }
00195   else
00196     {
00197       stp_dprintf(STP_DBG_INK, v,
00198                   "channel_density channel %d subchannel %d adjustment %f\n",
00199                   color, subchannel, adjustment);
00200       if (sch && adjustment >= 0 && adjustment <= 1)
00201         sch->s_density = adjustment * 65535;
00202     }
00203 }
00204 
00205 void
00206 stp_channel_set_ink_limit(stp_vars_t *v, double limit)
00207 {
00208   stpi_channel_group_t *cg =
00209     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00210   stp_dprintf(STP_DBG_INK, v, "ink_limit %f\n", limit);
00211   if (limit > 0)
00212     cg->ink_limit = 65535 * limit;
00213 }
00214 
00215 void
00216 stp_channel_set_black_channel(stp_vars_t *v, int channel)
00217 {
00218   stpi_channel_group_t *cg =
00219     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00220   stp_dprintf(STP_DBG_INK, v, "black_channel %d\n", channel);
00221   cg->black_channel = channel;
00222 }
00223 
00224 void
00225 stp_channel_set_cutoff_adjustment(stp_vars_t *v, int color, int subchannel,
00226                                   double adjustment)
00227 {
00228   stpi_subchannel_t *sch = get_channel(v, color, subchannel);
00229   stp_dprintf(STP_DBG_INK, v,
00230               "channel_cutoff channel %d subchannel %d adjustment %f\n",
00231               color, subchannel, adjustment);
00232   if (sch && adjustment >= 0)
00233     sch->cutoff = adjustment;
00234 }
00235 
00236 static int
00237 input_needs_splitting(const stp_vars_t *v)
00238 {
00239   const stpi_channel_group_t *cg =
00240     ((const stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00241 #if 1
00242   return cg->total_channels != cg->input_channels;
00243 #else
00244   int i;
00245   if (!cg || cg->channel_count <= 0)
00246     return 0;
00247   for (i = 0; i < cg->channel_count; i++)
00248     {
00249       if (cg->c[i].subchannel_count > 1)
00250         return 1;
00251     }
00252   return 0;
00253 #endif
00254 }
00255 
00256 void
00257 stp_channel_initialize(stp_vars_t *v, stp_image_t *image,
00258                        int input_channel_count)
00259 {
00260   stpi_channel_group_t *cg =
00261     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00262   int width = stp_image_width(image);
00263   int i, j, k;
00264   if (!cg)
00265     {
00266       cg = stp_zalloc(sizeof(stpi_channel_group_t));
00267       cg->black_channel = -1;
00268       stp_allocate_component_data(v, "Channel", NULL, stpi_channel_free, cg);
00269     }
00270   if (cg->initialized)
00271     return;
00272   cg->initialized = 1;
00273   cg->max_density = 0;
00274   if (cg->black_channel < -1 || cg->black_channel >= cg->channel_count)
00275     cg->black_channel = -1;
00276   for (i = 0; i < cg->channel_count; i++)
00277     {
00278       stpi_channel_t *c = &(cg->c[i]);
00279       int sc = c->subchannel_count;
00280       if (sc > 1)
00281         {
00282           int val = 0;
00283           int next_breakpoint;
00284           c->lut = stp_zalloc(sizeof(unsigned short) * sc * 65536);
00285           next_breakpoint = c->sc[0].value * 65535 * c->sc[0].cutoff;
00286           if (next_breakpoint > 65535)
00287             next_breakpoint = 65535;
00288           while (val <= next_breakpoint)
00289             {
00290               int value = (int) ((double) val / c->sc[0].value);
00291               c->lut[val * sc + sc - 1] = value;
00292               val++;
00293             }
00294 
00295           for (k = 0; k < sc - 1; k++)
00296             {
00297               double this_val = c->sc[k].value;
00298               double next_val = c->sc[k + 1].value;
00299               double this_cutoff = c->sc[k].cutoff;
00300               double next_cutoff = c->sc[k + 1].cutoff;
00301               int range;
00302               int base = val;
00303               double cutoff = sqrt(this_cutoff * next_cutoff);
00304               next_breakpoint = next_val * 65535 * cutoff;
00305               if (next_breakpoint > 65535)
00306                 next_breakpoint = 65535;
00307               range = next_breakpoint - val;
00308               while (val <= next_breakpoint)
00309                 {
00310                   double where = ((double) val - base) / (double) range;
00311                   double lower_val = base * (1.0 - where);
00312                   double lower_amount = lower_val / this_val;
00313                   double upper_amount = (val - lower_val) / next_val;
00314                   c->lut[val * sc + sc - k - 2] = upper_amount;
00315                   c->lut[val * sc + sc - k - 1] = lower_amount;
00316                   val++;
00317                 }
00318             }
00319           while (val <= 65535)
00320             {
00321               c->lut[val * sc] = val / c->sc[sc - 1].value;
00322               val++;
00323             }
00324         }
00325       cg->total_channels += c->subchannel_count;
00326       for (j = 0; j < c->subchannel_count; j++)
00327         cg->max_density += c->sc[j].s_density;
00328     }
00329   cg->input_channels = input_channel_count;
00330   cg->width = width;
00331   cg->data = stp_malloc(sizeof(unsigned short) * cg->total_channels * width);
00332   if (!input_needs_splitting(v))
00333     {
00334       cg->input_data = cg->data;
00335       return;
00336     }
00337   cg->input_data =
00338     stp_malloc(sizeof(unsigned short) * cg->input_channels * width);
00339 }
00340 
00341 static void
00342 clear_channel(unsigned short *data, unsigned width, unsigned depth)
00343 {
00344   int i;
00345   width *= depth;
00346   for (i = 0; i < width; i += depth)
00347     data[i] = 0;
00348 }
00349 
00350 static int
00351 scale_channel(unsigned short *data, unsigned width, unsigned depth,
00352               unsigned short density)
00353 {
00354   int i;
00355   int retval = 0;
00356   unsigned short previous_data = 0;
00357   unsigned short previous_value = 0;
00358   if (density > 65535)
00359     density = 65535;
00360   width *= depth;
00361   for (i = 0; i < width; i += depth)
00362     {
00363       if (data[i] == previous_data)
00364         data[i] = previous_value;
00365       else if (data[i] == (unsigned short) 65535)
00366         {
00367           data[i] = density;
00368           retval = 1;
00369         }
00370       else if (data[i] > 0)
00371         {
00372           unsigned short tval = (32767u + data[i] * density) / 65535u;
00373           previous_data = data[i];
00374           if (tval)
00375             retval = 1;
00376           previous_value = (unsigned short) tval;
00377           data[i] = (unsigned short) tval;
00378         }
00379     }
00380   return retval;
00381 }
00382 
00383 static int
00384 scan_channel(unsigned short *data, unsigned width, unsigned depth)
00385 {
00386   int i;
00387   width *= depth;
00388   for (i = 0; i < width; i += depth)
00389     {
00390       if (data[i])
00391         return 1;
00392     }
00393   return 0;
00394 }
00395 
00396 static inline unsigned
00397 ink_sum(const unsigned short *data, int total_channels)
00398 {
00399   int j;
00400   unsigned total_ink = 0;
00401   for (j = 0; j < total_channels; j++)
00402     total_ink += data[j];
00403   return total_ink;
00404 }
00405 
00406 static int
00407 limit_ink(const stp_vars_t *v)
00408 {
00409   int i;
00410   int retval = 0;
00411   stpi_channel_group_t *cg =
00412     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00413   unsigned short *ptr = cg->data;
00414   if (cg->ink_limit == 0 || cg->ink_limit >= cg->max_density)
00415     return 0;
00416   for (i = 0; i < cg->width; i++)
00417     {
00418       int total_ink = ink_sum(ptr, cg->total_channels);
00419       if (total_ink > cg->ink_limit) /* Need to limit ink? */
00420         {
00421           int j;
00422           /*
00423            * FIXME we probably should first try to convert light ink to dark
00424            */
00425           double ratio = (double) cg->ink_limit / (double) total_ink;
00426           for (j = 0; j < cg->total_channels; j++)
00427             ptr[j] *= ratio;
00428           retval = 1;
00429         }
00430       ptr += cg->total_channels;
00431    }
00432   return retval;
00433 }
00434 
00435 static inline int
00436 mem_eq(const unsigned short *i1, const unsigned short *i2, int count)
00437 {
00438   int i;
00439   for (i = 0; i < count; i++)
00440     if (i1[i] != i2[i])
00441       return 0;
00442   return 1;
00443 }
00444 
00445 void
00446 stp_channel_convert(const stp_vars_t *v, unsigned *zero_mask)
00447 {
00448   stpi_channel_group_t *cg =
00449     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00450   int i, j, k;
00451   int nz[STP_CHANNEL_LIMIT];
00452   int outbytes = cg->total_channels * sizeof(unsigned short);
00453   const unsigned short *input_cache = NULL;
00454   const unsigned short *output_cache = NULL;
00455   unsigned black_value = 0;
00456   unsigned l_val = 0;
00457   unsigned i_val = 0;
00458   unsigned o_val = 0;
00459   unsigned offset = 0;
00460   unsigned virtual_black = 0;
00461   memset(nz, 0, sizeof(nz));
00462   if (input_needs_splitting(v))
00463     {
00464       const unsigned short *input = cg->input_data;
00465       unsigned short *output = cg->data;
00466       const unsigned short *o_output;
00467       for (i = 0; i < cg->width; i++)
00468         {
00469           int zero_ptr = 0;
00470           if (input_cache && mem_eq(input_cache, input, cg->input_channels))
00471             {
00472               memcpy(output, output_cache, outbytes);
00473               input += cg->input_channels;
00474               output += cg->total_channels;
00475             }
00476           else
00477             {
00478               input_cache = input;
00479               black_value = 0;
00480               o_output = output;
00481               if (cg->black_channel >= 0)
00482                 black_value = input[cg->black_channel];
00483               virtual_black = 65535;
00484               for (j = 0; j < cg->channel_count; j++)
00485                 {
00486                   if (input[j] < virtual_black && j != cg->black_channel)
00487                     virtual_black = input[j];
00488                 }
00489               black_value += virtual_black / 4;
00490               for (j = 0; j < cg->channel_count; j++)
00491                 {
00492                   stpi_channel_t *c = &(cg->c[j]);
00493                   int s_count = c->subchannel_count;
00494                   if (s_count >= 1)
00495                     {
00496                       i_val = *input++;
00497                       if (i_val == 0)
00498                         {
00499                           for (k = 0; k < s_count; k++)
00500                             *(output++) = 0;
00501                         }
00502                       else if (s_count == 1)
00503                         {
00504                           if (c->sc[0].s_density < 65535)
00505                             i_val = i_val * c->sc[0].s_density / 65535;
00506                           nz[zero_ptr++] |= *(output++) = i_val;
00507                         }
00508                       else
00509                         {
00510                           l_val = i_val;
00511                           if (i_val > 0 && black_value &&
00512                               j != cg->black_channel)
00513                             {
00514                               l_val += black_value;
00515                               if (l_val > 65535)
00516                                 l_val = 65535;
00517                             }
00518                           offset = l_val * s_count;
00519                           for (k = 0; k < s_count; k++)
00520                             {
00521                               if (c->sc[k].s_density > 0)
00522                                 {
00523                                   o_val = c->lut[offset + k];
00524                                   if (i_val != l_val)
00525                                     o_val = o_val * i_val / l_val;
00526                                   if (c->sc[k].s_density < 65535)
00527                                     o_val = o_val * c->sc[k].s_density / 65535;
00528                                 }
00529                               else
00530                                 o_val = 0;
00531                               *output++ = o_val;
00532                               nz[zero_ptr++] |= o_val;
00533                             }
00534                         }
00535                     }
00536                 }
00537               output_cache = o_output;
00538             }
00539         }
00540       if (zero_mask)
00541         {
00542           *zero_mask = 0;
00543           for (i = 0; i < cg->total_channels; i++)
00544             if (!nz[i])
00545               *zero_mask |= 1 << i;
00546         }
00547     }
00548   else
00549     {
00550       int physical_channel = 0;
00551       if (zero_mask)
00552         *zero_mask = 0;
00553       for (i = 0; i < cg->channel_count; i++)
00554         {
00555           stpi_channel_t *ch = &(cg->c[i]);
00556           if (ch->subchannel_count > 0)
00557             for (j = 0; j < ch->subchannel_count; j++)
00558               {
00559                 stpi_subchannel_t *sch = &(ch->sc[j]);
00560                 unsigned density = sch->s_density;
00561                 unsigned short *output = cg->data + physical_channel;
00562                 if (density == 0)
00563                   {
00564                     clear_channel(output, cg->width, cg->total_channels);
00565                     if (zero_mask)
00566                       *zero_mask |= 1 << physical_channel;
00567                   }
00568                 else if (density != 65535)
00569                   {
00570                     if (scale_channel(output, cg->width, cg->total_channels,
00571                                       density) == 0)
00572                       if (zero_mask)
00573                         *zero_mask |= 1 << physical_channel;
00574                   }
00575                 else if (zero_mask)
00576                   {
00577                     if (scan_channel(output, cg->width, cg->total_channels) == 0)
00578                       *zero_mask |= 1 << physical_channel;
00579                   }
00580                 physical_channel++;
00581               }
00582         }
00583     }
00584   (void) limit_ink(v);
00585 }
00586 
00587 unsigned short *
00588 stp_channel_get_input(const stp_vars_t *v)
00589 {
00590   stpi_channel_group_t *cg =
00591     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00592   return (unsigned short *) cg->input_data;
00593 }
00594 
00595 unsigned short *
00596 stp_channel_get_output(const stp_vars_t *v)
00597 {
00598   stpi_channel_group_t *cg =
00599     ((stpi_channel_group_t *) stp_get_component_data(v, "Channel"));
00600   return cg->data;
00601 }

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