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 = ˙ 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