libgimpprint API Reference: src/main/channel.c Source File

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_8c-source.html,v 1.1.1.2 2004/12/22 23:48:56 jlovell 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 }