1/*
2 * "$Id: dither-inks.c,v 1.27 2010/08/04 00:33:56 rlk Exp $"
3 *
4 *   Print plug-in driver utility functions for the GIMP.
5 *
6 *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
7 *	Robert Krawitz (rlk@alum.mit.edu)
8 *
9 *   This program is free software; you can redistribute it and/or modify it
10 *   under the terms of the GNU General Public License as published by the Free
11 *   Software Foundation; either version 2 of the License, or (at your option)
12 *   any later version.
13 *
14 *   This program is distributed in the hope that it will be useful, but
15 *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 *   for more details.
18 *
19 *   You should have received a copy of the GNU General Public License
20 *   along with this program; if not, write to the Free Software
21 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 * Revision History:
24 *
25 *   See ChangeLog
26 */
27
28#ifdef HAVE_CONFIG_H
29#include <config.h>
30#endif
31#include <gutenprint/gutenprint.h>
32#include "gutenprint-internal.h"
33#include <gutenprint/gutenprint-intl-internal.h>
34#ifdef HAVE_LIMITS_H
35#include <limits.h>
36#endif
37#include <math.h>
38#include <string.h>
39#include "dither-impl.h"
40
41int
42stpi_dither_translate_channel(stp_vars_t *v, unsigned channel,
43			      unsigned subchannel)
44{
45  stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
46  unsigned chan_idx;
47  if (!d)
48    return -1;
49  if (channel >= d->channel_count)
50    return -1;
51  if (subchannel >= d->subchannel_count[channel])
52    return -1;
53  chan_idx = d->channel_index[channel];
54  return chan_idx + subchannel;
55}
56
57unsigned char *
58stp_dither_get_channel(stp_vars_t *v, unsigned channel, unsigned subchannel)
59{
60  stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
61  int place = stpi_dither_translate_channel(v, channel, subchannel);
62  if (place >= 0)
63    return d->channel[place].ptr;
64  else
65    return NULL;
66}
67
68static void
69insert_channel(stp_vars_t *v, stpi_dither_t *d, int channel)
70{
71  unsigned oc = d->channel_count;
72  int i;
73  d->channel_index =
74    stp_realloc (d->channel_index, sizeof(unsigned) * (channel + 1));
75  d->subchannel_count =
76    stp_realloc (d->subchannel_count, sizeof(unsigned) * (channel + 1));
77  for (i = oc; i < channel + 1; i++)
78    {
79      if (oc == 0)
80	d->channel_index[i] = 0;
81      else
82	d->channel_index[i] =
83	  d->channel_index[oc - 1] + d->subchannel_count[oc - 1];
84      d->subchannel_count[i] = 0;
85    }
86  d->channel_count = channel + 1;
87}
88
89void
90stpi_dither_channel_destroy(stpi_dither_channel_t *channel)
91{
92  int i;
93  STP_SAFE_FREE(channel->ink_list);
94  if (channel->errs)
95    {
96      for (i = 0; i < channel->error_rows; i++)
97	STP_SAFE_FREE(channel->errs[i]);
98      STP_SAFE_FREE(channel->errs);
99    }
100  STP_SAFE_FREE(channel->ranges);
101  stp_dither_matrix_destroy(&(channel->pick));
102  stp_dither_matrix_destroy(&(channel->dithermat));
103}
104
105static void
106initialize_channel(stp_vars_t *v, int channel, int subchannel)
107{
108  stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
109  int idx = stpi_dither_translate_channel(v, channel, subchannel);
110  stpi_dither_channel_t *dc = &(CHANNEL(d, idx));
111  stp_shade_t shade;
112  stp_dotsize_t dot;
113  STPI_ASSERT(idx >= 0, NULL);
114  memset(dc, 0, sizeof(stpi_dither_channel_t));
115  stp_dither_matrix_clone(&(d->dither_matrix), &(dc->dithermat), 0, 0);
116  shade.dot_sizes = &dot;
117  shade.value = 1.0;
118  shade.numsizes = 1;
119  dot.bit_pattern = 1;
120  dot.value = 1.0;
121  stp_dither_set_inks_full(v, channel, 1, &shade, 1.0, 1.0);
122}
123
124static void
125insert_subchannel(stp_vars_t *v, stpi_dither_t *d, int channel, int subchannel)
126{
127  int i;
128  unsigned oc = d->subchannel_count[channel];
129  unsigned increment = subchannel - oc + 1;
130  unsigned old_place = d->channel_index[channel] + oc;
131  stpi_dither_channel_t *nc =
132    stp_malloc(sizeof(stpi_dither_channel_t) *
133	       (d->total_channel_count + increment));
134
135  if (d->channel)
136    {
137      /*
138       * Copy the old channels, including all subchannels of the current
139       * channel that already existed.
140       */
141      memcpy(nc, d->channel, sizeof(stpi_dither_channel_t) * old_place);
142      if (old_place < d->total_channel_count)
143	/*
144	 * If we're inserting a new subchannel in the middle somewhere,
145	 * we need to move everything else up
146	 */
147	memcpy(nc + old_place + increment, d->channel + old_place,
148	       (sizeof(stpi_dither_channel_t) *
149		(d->total_channel_count - old_place)));
150      stp_free(d->channel);
151    }
152  d->channel = nc;
153  if (channel < d->channel_count - 1)
154    /* Now fix up the subchannel offsets */
155    for (i = channel + 1; i < d->channel_count; i++)
156      d->channel_index[i] += increment;
157  d->subchannel_count[channel] = subchannel + 1;
158  d->total_channel_count += increment;
159  for (i = oc; i < oc + increment; i++)
160    initialize_channel(v, channel, i);
161}
162
163void
164stpi_dither_finalize(stp_vars_t *v)
165{
166  stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
167  if (!d->finalized)
168    {
169      int i;
170      unsigned rc = 1 + (unsigned) ceil(sqrt(CHANNEL_COUNT(d)));
171      unsigned x_n = d->dither_matrix.x_size / rc;
172      unsigned y_n = d->dither_matrix.y_size / rc;
173      for (i = 0; i < CHANNEL_COUNT(d); i++)
174	{
175	  stpi_dither_channel_t *dc = &(CHANNEL(d, i));
176	  stp_dither_matrix_clone(&(d->dither_matrix), &(dc->dithermat),
177				   x_n * (i % rc), y_n * (i / rc));
178	  stp_dither_matrix_clone(&(d->dither_matrix), &(dc->pick),
179				   x_n * (i % rc), y_n * (i / rc));
180	}
181      d->finalized = 1;
182    }
183}
184
185void
186stp_dither_add_channel(stp_vars_t *v, unsigned char *data,
187		       unsigned channel, unsigned subchannel)
188{
189  stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
190  int idx;
191  if (channel >= d->channel_count)
192    insert_channel(v, d, channel);
193  if (subchannel >= d->subchannel_count[channel])
194    insert_subchannel(v, d, channel, subchannel);
195  idx = stpi_dither_translate_channel(v, channel, subchannel);
196  STPI_ASSERT(idx >= 0, NULL);
197  d->channel[idx].ptr = data;
198}
199
200static void
201stpi_dither_finalize_ranges(stp_vars_t *v, stpi_dither_channel_t *dc)
202{
203  stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
204  int i;
205  unsigned lbit = dc->bit_max;
206  dc->signif_bits = 0;
207  while (lbit > 0)
208    {
209      dc->signif_bits++;
210      lbit >>= 1;
211    }
212
213  for (i = 0; i < dc->nlevels; i++)
214    {
215      if (dc->ranges[i].lower->bits == dc->ranges[i].upper->bits)
216	dc->ranges[i].is_same_ink = 1;
217      else
218	dc->ranges[i].is_same_ink = 0;
219      if (dc->ranges[i].range_span > 0 && dc->ranges[i].value_span > 0)
220	dc->ranges[i].is_equal = 0;
221      else
222	dc->ranges[i].is_equal = 1;
223
224      stp_dprintf(STP_DBG_INK, v,
225		  "    level %d value[0] %d value[1] %d range[0] %d range[1] %d\n",
226		  i, dc->ranges[i].lower->value, dc->ranges[i].upper->value,
227		  dc->ranges[i].lower->range, dc->ranges[i].upper->range);
228      stp_dprintf(STP_DBG_INK, v,
229		  "       bits[0] %d bits[1] %d\n",
230		  dc->ranges[i].lower->bits, dc->ranges[i].upper->bits);
231      stp_dprintf(STP_DBG_INK, v,
232		  "       rangespan %d valuespan %d same_ink %d equal %d\n",
233		  dc->ranges[i].range_span, dc->ranges[i].value_span,
234		  dc->ranges[i].is_same_ink, dc->ranges[i].is_equal);
235      if (i > 0 && dc->ranges[i].lower->range >= d->adaptive_limit)
236	{
237	  d->adaptive_limit = dc->ranges[i].lower->range + 1;
238	  if (d->adaptive_limit > 65535)
239	    d->adaptive_limit = 65535;
240	  stp_dprintf(STP_DBG_INK, v, "Setting adaptive limit to %d\n",
241		      d->adaptive_limit);
242	}
243    }
244  for (i = 0; i <= dc->nlevels; i++)
245    stp_dprintf(STP_DBG_INK, v,
246		"    ink_list[%d] range %d value %d bits %d\n",
247		i, dc->ink_list[i].range,
248		dc->ink_list[i].value, dc->ink_list[i].bits);
249  if (dc->nlevels == 1 && dc->ranges[0].upper->bits == 1)
250    dc->very_fast = 1;
251  else
252    dc->very_fast = 0;
253
254  stp_dprintf(STP_DBG_INK, v,
255	      "  bit_max %d signif_bits %d\n", dc->bit_max, dc->signif_bits);
256}
257
258static void
259stpi_dither_set_ranges(stp_vars_t *v, int color, const stp_shade_t *shade,
260		       double density, double darkness)
261{
262  stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
263  stpi_dither_channel_t *dc = &(CHANNEL(d, color));
264  const stp_dotsize_t *ranges = shade->dot_sizes;
265  int nlevels = shade->numsizes;
266  int i;
267
268  STP_SAFE_FREE(dc->ranges);
269  STP_SAFE_FREE(dc->ink_list);
270
271  dc->nlevels = nlevels > 1 ? nlevels + 1 : nlevels;
272  dc->ranges = (stpi_dither_segment_t *)
273    stp_zalloc(dc->nlevels * sizeof(stpi_dither_segment_t));
274  dc->ink_list = (stpi_ink_defn_t *)
275    stp_zalloc((dc->nlevels + 1) * sizeof(stpi_ink_defn_t));
276  dc->bit_max = 0;
277  dc->density = density * 65535;
278  dc->darkness = darkness;
279  stp_init_debug_messages(v);
280  stp_dprintf(STP_DBG_INK, v,
281	      "stpi_dither_set_ranges channel %d nlevels %d density %f darkness %f\n",
282	      color, nlevels, density, darkness);
283  for (i = 0; i < nlevels; i++)
284    stp_dprintf(STP_DBG_INK, v,
285		"  level %d value %f pattern %x\n", i,
286		ranges[i].value, ranges[i].bit_pattern);
287  dc->ranges[0].lower = &dc->ink_list[0];
288  dc->ranges[0].upper = &dc->ink_list[1];
289  dc->ink_list[0].range = 0;
290  dc->ink_list[0].value = 0;
291  dc->ink_list[0].bits = 0;
292  if (nlevels == 1)
293    dc->ink_list[1].range = 65535;
294  else
295    dc->ink_list[1].range = ranges[0].value * 65535.0 * density;
296  if (dc->ink_list[1].range > 65535)
297    dc->ink_list[1].range = 65535;
298  dc->ink_list[1].value = ranges[0].value * 65535.0;
299  if (dc->ink_list[1].value > 65535)
300    dc->ink_list[1].value = 65535;
301  dc->ink_list[1].bits = ranges[0].bit_pattern;
302  if (ranges[0].bit_pattern > dc->bit_max)
303    dc->bit_max = ranges[0].bit_pattern;
304  dc->ranges[0].range_span = dc->ranges[0].upper->range;
305  dc->ranges[0].value_span = dc->ranges[0].upper->value;
306  if (dc->nlevels > 1)
307    {
308      for (i = 1; i < nlevels; i++)
309	{
310	  int l = i + 1;
311	  dc->ranges[i].lower = &dc->ink_list[i];
312	  dc->ranges[i].upper = &dc->ink_list[l];
313
314	  dc->ink_list[l].range =
315	    (ranges[i].value + ranges[i].value) * 32768.0 * density;
316	  if (dc->ink_list[l].range > 65535)
317	    dc->ink_list[l].range = 65535;
318	  dc->ink_list[l].value = ranges[i].value * 65535.0;
319	  if (dc->ink_list[l].value > 65535)
320	    dc->ink_list[l].value = 65535;
321	  dc->ink_list[l].bits = ranges[i].bit_pattern;
322	  if (ranges[i].bit_pattern > dc->bit_max)
323	    dc->bit_max = ranges[i].bit_pattern;
324	  dc->ranges[i].range_span =
325	    dc->ink_list[l].range - dc->ink_list[i].range;
326	  dc->ranges[i].value_span =
327	    dc->ink_list[l].value - dc->ink_list[i].value;
328	}
329      dc->ranges[i].lower = &dc->ink_list[i];
330      dc->ranges[i].upper = &dc->ink_list[i+1];
331      dc->ink_list[i+1] = dc->ink_list[i];
332      dc->ink_list[i+1].range = 65535;
333      dc->ranges[i].range_span =
334	dc->ink_list[i+1].range - dc->ink_list[i].range;
335      dc->ranges[i].value_span =
336	dc->ink_list[i+1].value - dc->ink_list[i].value;
337    }
338  stpi_dither_finalize_ranges(v, dc);
339  stp_flush_debug_messages(v);
340}
341
342void
343stp_dither_set_inks_simple(stp_vars_t *v, int color, int nlevels,
344			   const double *levels, double density,
345			   double darkness)
346{
347  stp_shade_t s;
348  stp_dotsize_t *d = stp_malloc(nlevels * sizeof(stp_dotsize_t));
349  int i;
350  s.dot_sizes = d;
351  s.value = 65535.0;
352  s.numsizes = nlevels;
353
354  for (i = 0; i < nlevels; i++)
355    {
356      d[i].bit_pattern = i + 1;
357      d[i].value = levels[i];
358    }
359  stp_dither_set_inks_full(v, color, 1, &s, density, darkness);
360  stp_free(d);
361}
362
363void
364stp_dither_set_inks_full(stp_vars_t *v, int color, int nshades,
365			 const stp_shade_t *shades, double density,
366			 double darkness)
367{
368  int i;
369  int idx;
370  stpi_dither_channel_t *dc;
371
372  stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
373
374  stp_channel_reset_channel(v, color);
375
376  for (i = nshades - 1; i >= 0; i--)
377    {
378      int subchannel = nshades - i - 1;
379      idx = stpi_dither_translate_channel(v, color, subchannel);
380      STPI_ASSERT(idx >= 0, NULL);
381      dc = &(CHANNEL(d, idx));
382
383      stp_channel_add(v, color, subchannel, shades[i].value);
384      if (idx >= 0)
385	stpi_dither_set_ranges(v, idx, &shades[i], density,
386			       shades[i].value * darkness);
387      stp_dprintf(STP_DBG_INK, v,
388		  "  shade %d value %f\n",
389		  i, shades[i].value);
390    }
391}
392
393void
394stp_dither_set_inks(stp_vars_t *v, int color, double density, double darkness,
395		    int nshades, const double *svalues,
396		    int ndotsizes, const double *dvalues)
397{
398  int i, j;
399  stp_shade_t *shades = stp_malloc(sizeof(stp_shade_t) * nshades);
400  stp_dotsize_t *dotsizes = stp_malloc(sizeof(stp_dotsize_t) * ndotsizes);
401  j = 0;
402  for (i = 0; i < ndotsizes; i++)
403    {
404      /* Skip over any zero-valued dot sizes */
405      if (dvalues[i] > 0)
406	{
407	  dotsizes[j].value = dvalues[i];
408	  dotsizes[j].bit_pattern = i + 1;
409	  j++;
410	}
411    }
412  for (i = 0; i < nshades; i++)
413    {
414      shades[i].value = svalues[i];
415      shades[i].numsizes = j;
416      shades[i].dot_sizes = dotsizes;
417    }
418  stp_dither_set_inks_full(v, color, nshades, shades, density, darkness);
419  stp_free(dotsizes);
420  stp_free(shades);
421}
422