00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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 #include <string.h>
00035 #include "dither-impl.h"
00036 #include "dither-inlined-functions.h"
00037
00038
00039
00040
00041
00042
00043
00044 #define UPDATE_COLOR(color, dither) ( \
00045 ((dither) >= 0)? (color) + ((dither) >> 3) : (color) - ((-(dither)) >> 3))
00046
00047
00048
00049
00050
00051
00052
00053
00054 static inline int
00055 update_dither(stpi_dither_t *d, int channel, int width,
00056 int direction, int *error0, int *error1)
00057 {
00058 int r = CHANNEL(d, channel).v;
00059 int o = CHANNEL(d, channel).o;
00060 int tmp = r;
00061 int i, dist, dist1;
00062 int delta, delta1;
00063 int offset;
00064 if (tmp == 0)
00065 return error0[direction];
00066 if (tmp > 65535)
00067 tmp = 65535;
00068 if (d->spread >= 16 || o >= 2048)
00069 {
00070 tmp += tmp;
00071 tmp += tmp;
00072 error1[0] += tmp;
00073 return error0[direction] + tmp;
00074 }
00075 else
00076 {
00077 int tmpo = o << 5;
00078 offset = ((65535 - tmpo) >> d->spread) +
00079 ((tmp & d->spread_mask) > (tmpo & d->spread_mask));
00080 }
00081 switch (offset)
00082 {
00083 case 0:
00084 tmp += tmp;
00085 tmp += tmp;
00086 error1[0] += tmp;
00087 return error0[direction] + tmp;
00088 case 1:
00089 error1[-1] += tmp;
00090 error1[1] += tmp;
00091 tmp += tmp;
00092 error1[0] += tmp;
00093 tmp += tmp;
00094 return error0[direction] + tmp;
00095 default:
00096 tmp += tmp;
00097 tmp += tmp;
00098 dist = tmp / d->offset0_table[offset];
00099 dist1 = tmp / d->offset1_table[offset];
00100 delta = dist;
00101 delta1 = dist1;
00102 for (i = -offset; i; i++)
00103 {
00104 error1[i] += delta;
00105 error1[-i] += delta;
00106 error0[i] += delta1;
00107 error0[-i] += delta1;
00108 delta1 += dist1;
00109 delta += dist;
00110 }
00111 error1[0] += delta;
00112 return error0[direction];
00113 }
00114 }
00115
00116
00117
00118
00119
00120
00121
00122 static inline int
00123 print_color(const stpi_dither_t *d, stpi_dither_channel_t *dc, int x, int y,
00124 unsigned char bit, int length, int dontprint, int stpi_dither_type,
00125 const unsigned char *mask)
00126 {
00127 int base = dc->b;
00128 int density = dc->o;
00129 int adjusted = dc->v;
00130 unsigned randomizer = dc->randomizer;
00131 stp_dither_matrix_impl_t *pick_matrix = &(dc->pick);
00132 stp_dither_matrix_impl_t *dither_matrix = &(dc->dithermat);
00133 unsigned rangepoint = 32768;
00134 unsigned vmatrix;
00135 int i;
00136 int j;
00137 unsigned char *tptr;
00138 unsigned bits;
00139 unsigned v;
00140 int levels = dc->nlevels - 1;
00141 int dither_value = adjusted;
00142 stpi_ink_defn_t *lower;
00143 stpi_ink_defn_t *upper;
00144
00145 if (base <= 0 || density <= 0 ||
00146 (adjusted <= 0 && !(stpi_dither_type & D_ADAPTIVE_BASE)))
00147 return adjusted;
00148 if (density > 65535)
00149 density = 65535;
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 for (i = levels; i >= 0; i--)
00160 {
00161 stpi_dither_segment_t *dd = &(dc->ranges[i]);
00162
00163 if (density <= dd->lower->range)
00164 continue;
00165
00166
00167
00168
00169
00170
00171 if (stpi_dither_type & D_ADAPTIVE_BASE)
00172 {
00173 stpi_dither_type -= D_ADAPTIVE_BASE;
00174
00175 if (i < levels || base <= d->adaptive_limit)
00176 {
00177 stpi_dither_type = D_ORDERED;
00178 dither_value = base;
00179 }
00180 else if (adjusted <= 0)
00181 return adjusted;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 lower = dd->lower;
00194 upper = dd->upper;
00195
00196
00197
00198
00199
00200
00201 if (stpi_dither_type & D_ORDERED_BASE)
00202 {
00203 rangepoint = density - dd->lower->range;
00204 if (dd->range_span < 65535)
00205 rangepoint = rangepoint * 65535 / dd->range_span;
00206 vmatrix = 0;
00207 }
00208 else
00209 {
00210
00211
00212
00213
00214
00215
00216
00217 unsigned virtual_value;
00218 rangepoint = density - dd->lower->range;
00219 if (dd->range_span < 65535)
00220 rangepoint = rangepoint * 65535 / dd->range_span;
00221 if (dd->value_span == 0)
00222 virtual_value = upper->value;
00223 else
00224 virtual_value = (upper->value + lower->value) / 2;
00225
00226
00227
00228
00229 randomizer = 0;
00230 if (randomizer > 0)
00231 {
00232 if (base > d->d_cutoff)
00233 randomizer = 0;
00234 else if (base > d->d_cutoff / 2)
00235 randomizer = randomizer * 2 * (d->d_cutoff - base) / d->d_cutoff;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244 if (randomizer == 0)
00245 vmatrix = virtual_value / 2;
00246 else
00247 {
00248
00249
00250
00251
00252 vmatrix = ditherpoint(d, dither_matrix, x);
00253
00254
00255
00256
00257
00258
00259 vmatrix = vmatrix * virtual_value / 65535;
00260 if (randomizer != 65535)
00261 {
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 unsigned vbase = virtual_value * (65535u - randomizer) /
00272 131070u;
00273 vmatrix = vmatrix * randomizer / 65535;
00274 vmatrix += vbase;
00275 }
00276 }
00277 }
00278
00279
00280
00281
00282 if (dither_value > 0 && dither_value >= vmatrix)
00283 {
00284 stpi_ink_defn_t *subc;
00285
00286 if (dd->is_same_ink)
00287 subc = upper;
00288 else
00289 {
00290 if (rangepoint >= ditherpoint(d, pick_matrix, x))
00291 subc = upper;
00292 else
00293 subc = lower;
00294 }
00295 v = subc->value;
00296 if (!mask || (*(mask + d->ptr_offset) & bit))
00297 {
00298 if (dc->ptr)
00299 {
00300 tptr = dc->ptr + d->ptr_offset;
00301
00302
00303
00304
00305 if (dontprint < v)
00306 {
00307 bits = subc->bits;
00308 set_row_ends(dc, x);
00309 for (j = 1; j <= bits; j += j, tptr += length)
00310 {
00311 if (j & bits)
00312 tptr[0] |= bit;
00313 }
00314 }
00315 }
00316 }
00317 if (stpi_dither_type & D_ORDERED_BASE)
00318 {
00319 double adj = -(int) v;
00320 adj /= 2.0;
00321 adjusted = adj;
00322 }
00323 else
00324 {
00325 double adj = v;
00326 adjusted -= adj;
00327 }
00328 }
00329 return adjusted;
00330 }
00331 return adjusted;
00332 }
00333
00334 static int
00335 shared_ed_initializer(stpi_dither_t *d,
00336 int row,
00337 int duplicate_line,
00338 int zero_mask,
00339 int length,
00340 int direction,
00341 int ****error,
00342 int **ndither)
00343 {
00344 int i, j;
00345 for (i = 0; i < CHANNEL_COUNT(d); i++)
00346 CHANNEL(d, i).error_rows = 2;
00347 if (!duplicate_line)
00348 {
00349 if ((zero_mask & ((1 << CHANNEL_COUNT(d)) - 1)) !=
00350 ((1 << CHANNEL_COUNT(d)) - 1))
00351 d->last_line_was_empty = 0;
00352 else
00353 d->last_line_was_empty++;
00354 }
00355 else if (d->last_line_was_empty)
00356 d->last_line_was_empty++;
00357 if (d->last_line_was_empty >= 5)
00358 return 0;
00359 else if (d->last_line_was_empty == 4)
00360 {
00361 for (i = 0; i < CHANNEL_COUNT(d); i++)
00362 for (j = 0; j < d->error_rows; j++)
00363 memset(stpi_dither_get_errline(d, row + j, i), 0,
00364 d->dst_width * sizeof(int));
00365 return 0;
00366 }
00367 d->ptr_offset = (direction == 1) ? 0 : length - 1;
00368
00369 *error = stp_malloc(CHANNEL_COUNT(d) * sizeof(int **));
00370 *ndither = stp_malloc(CHANNEL_COUNT(d) * sizeof(int));
00371 for (i = 0; i < CHANNEL_COUNT(d); i++)
00372 {
00373 (*error)[i] = stp_malloc(d->error_rows * sizeof(int *));
00374 for (j = 0; j < d->error_rows; j++)
00375 {
00376 (*error)[i][j] = stpi_dither_get_errline(d, row + j, i);
00377 if (j == d->error_rows - 1)
00378 memset((*error)[i][j], 0, d->dst_width * sizeof(int));
00379 if (direction == -1)
00380 (*error)[i][j] += d->dst_width - 1;
00381 }
00382 (*ndither)[i] = (*error)[i][0][0];
00383 }
00384 return 1;
00385 }
00386
00387 static void
00388 shared_ed_deinitializer(stpi_dither_t *d,
00389 int ***error,
00390 int *ndither)
00391 {
00392 int i;
00393 for (i = 0; i < CHANNEL_COUNT(d); i++)
00394 {
00395 STP_SAFE_FREE(error[i]);
00396 }
00397 STP_SAFE_FREE(error);
00398 STP_SAFE_FREE(ndither);
00399 }
00400
00401 void
00402 stpi_dither_ed(stp_vars_t *v,
00403 int row,
00404 const unsigned short *raw,
00405 int duplicate_line,
00406 int zero_mask,
00407 const unsigned char *mask)
00408 {
00409 stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00410 int x,
00411 length;
00412 unsigned char bit;
00413 int i;
00414 int *ndither;
00415 int ***error;
00416
00417 int terminate;
00418 int direction = row & 1 ? 1 : -1;
00419 int xerror, xstep, xmod;
00420
00421 length = (d->dst_width + 7) / 8;
00422 if (d->stpi_dither_type & D_ADAPTIVE_BASE)
00423 for (i = 0; i < CHANNEL_COUNT(d); i++)
00424 if (CHANNEL(d, i).nlevels > 1)
00425 {
00426 stpi_dither_ordered(v, row, raw, duplicate_line, zero_mask, mask);
00427 return;
00428 }
00429 if (!shared_ed_initializer(d, row, duplicate_line, zero_mask, length,
00430 direction, &error, &ndither))
00431 return;
00432
00433 x = (direction == 1) ? 0 : d->dst_width - 1;
00434 bit = 1 << (7 - (x & 7));
00435 xstep = CHANNEL_COUNT(d) * (d->src_width / d->dst_width);
00436 xmod = d->src_width % d->dst_width;
00437 xerror = (xmod * x) % d->dst_width;
00438 terminate = (direction == 1) ? d->dst_width : -1;
00439
00440 if (direction == -1)
00441 raw += (CHANNEL_COUNT(d) * (d->src_width - 1));
00442
00443 for (; x != terminate; x += direction)
00444 {
00445 for (i = 0; i < CHANNEL_COUNT(d); i++)
00446 {
00447 if (CHANNEL(d, i).ptr)
00448 {
00449 CHANNEL(d, i).v = raw[i];
00450 CHANNEL(d, i).o = CHANNEL(d, i).v;
00451 CHANNEL(d, i).b = CHANNEL(d, i).v;
00452 CHANNEL(d, i).v = UPDATE_COLOR(CHANNEL(d, i).v, ndither[i]);
00453 CHANNEL(d, i).v = print_color(d, &(CHANNEL(d, i)), x, row, bit,
00454 length, 0, d->stpi_dither_type,
00455 mask);
00456 ndither[i] = update_dither(d, i, d->src_width,
00457 direction, error[i][0], error[i][1]);
00458 }
00459 }
00460 ADVANCE_BIDIRECTIONAL(d, bit, raw, direction, CHANNEL_COUNT(d), xerror,
00461 xstep, xmod, error, d->error_rows);
00462 }
00463 shared_ed_deinitializer(d, error, ndither);
00464 if (direction == -1)
00465 stpi_dither_reverse_row_ends(d);
00466 }