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
00029 #ifdef HAVE_CONFIG_H
00030 #include <config.h>
00031 #endif
00032 #include <gimp-print/gimp-print.h>
00033 #include "gimp-print-internal.h"
00034 #include <gimp-print/gimp-print-intl-internal.h>
00035 #include <string.h>
00036 #include <math.h>
00037 #include <limits.h>
00038 #include "dither-impl.h"
00039 #include "dither-inlined-functions.h"
00040
00041 typedef struct
00042 {
00043 int dx;
00044 int dy;
00045 int r_sq;
00046 } distance_t;
00047
00048 typedef struct
00049 {
00050 int d2x;
00051 int d2y;
00052 distance_t d_sq;
00053 int aspect;
00054 int unitone_aspect;
00055 int physical_aspect;
00056 int diff_factor;
00057 stpi_dither_channel_t *dummy_channel;
00058 } eventone_t;
00059
00060 typedef struct shade_segment
00061 {
00062 distance_t dis;
00063 distance_t *et_dis;
00064 stpi_ink_defn_t lower;
00065 stpi_ink_defn_t upper;
00066 int share_this_channel;
00067 } shade_distance_t;
00068
00069
00070 #define EVEN_C1 256
00071 #define EVEN_C2 (EVEN_C1 * sqrt(3.0) / 2.0)
00072 #define UNITONE_C1 16384
00073 #define UNITONE_C2 (UNITONE_C1 * sqrt(3.0) / 2.0)
00074
00075 static void
00076 free_eventone_data(stpi_dither_t *d)
00077 {
00078 int i;
00079 eventone_t *et = (eventone_t *) (d->aux_data);
00080 for (i = 0; i < CHANNEL_COUNT(d); i++)
00081 {
00082 if (CHANNEL(d, i).aux_data)
00083 {
00084 shade_distance_t *shade = (shade_distance_t *) CHANNEL(d,i).aux_data;
00085 STP_SAFE_FREE(shade->et_dis);
00086 STP_SAFE_FREE(CHANNEL(d, i).aux_data);
00087 }
00088 }
00089 if (et->dummy_channel) {
00090 stpi_dither_channel_t *dc = et->dummy_channel;
00091 shade_distance_t *shade = (shade_distance_t *) dc->aux_data;
00092 STP_SAFE_FREE(shade->et_dis);
00093 STP_SAFE_FREE(dc->aux_data);
00094 stpi_dither_channel_destroy(dc);
00095 STP_SAFE_FREE(et->dummy_channel);
00096 }
00097 STP_SAFE_FREE(et);
00098 }
00099
00100 static void
00101 et_setup(stpi_dither_t *d)
00102 {
00103 int size = 2 * MAX_SPREAD + ((d->dst_width + 7) & ~7);
00104 static const int diff_factors[] = {1, 10, 16, 23, 32};
00105 eventone_t *et = stp_zalloc(sizeof(eventone_t));
00106 int xa, ya;
00107 int i;
00108 for (i = 0; i < CHANNEL_COUNT(d); i++) {
00109 CHANNEL(d, i).error_rows = 1;
00110 CHANNEL(d, i).errs = stp_zalloc(1 * sizeof(int *));
00111 CHANNEL(d, i).errs[0] = stp_zalloc(size * sizeof(int));
00112 }
00113 if (d->stpi_dither_type & D_UNITONE) {
00114 stpi_dither_channel_t *dc = stp_zalloc(sizeof(stpi_dither_channel_t));
00115 stp_dither_matrix_clone(&(d->dither_matrix), &(dc->dithermat), 0, 0);
00116 stp_dither_matrix_clone(&(d->transition_matrix), &(dc->pick), 0, 0);
00117 dc->error_rows = 1;
00118 dc->errs = stp_zalloc(1 * sizeof(int *));
00119 dc->errs[0] = stp_zalloc(size * sizeof(int));
00120 et->dummy_channel = dc;
00121 }
00122
00123 xa = d->x_aspect / d->y_aspect;
00124 if (xa == 0)
00125 xa = 1;
00126 et->d_sq.dx = xa * xa;
00127 et->d2x = 2 * et->d_sq.dx;
00128
00129 ya = d->y_aspect / d->x_aspect;
00130 if (ya == 0)
00131 ya = 1;
00132 et->d_sq.dy = ya * ya;
00133 et->d2y = 2 * et->d_sq.dy;
00134
00135 et->aspect = EVEN_C2 / (xa * ya);
00136 et->unitone_aspect = UNITONE_C2 / (xa * ya);
00137 et->d_sq.r_sq = 0;
00138
00139 for (i = 0; i < CHANNEL_COUNT(d); i++) {
00140 int x;
00141 shade_distance_t *shade = stp_zalloc(sizeof(shade_distance_t));
00142 shade->dis = et->d_sq;
00143 shade->et_dis = stp_malloc(sizeof(distance_t) * d->dst_width);
00144 if (CHANNEL(d, i).darkness > .1)
00145 shade->share_this_channel = 1;
00146 else
00147 shade->share_this_channel = 0;
00148 for (x = 0; x < d->dst_width; x++) {
00149 shade->et_dis[x] = et->d_sq;
00150 }
00151 CHANNEL(d, i).aux_data = shade;
00152 }
00153 if (et->dummy_channel) {
00154 int x;
00155 shade_distance_t *shade = stp_zalloc(sizeof(shade_distance_t));
00156 shade->dis = et->d_sq;
00157 shade->et_dis = stp_malloc(sizeof(distance_t) * d->dst_width);
00158 for (x = 0; x < d->dst_width; x++) {
00159 shade->et_dis[x] = et->d_sq;
00160 }
00161 et->dummy_channel->aux_data = shade;
00162 }
00163
00164 et->physical_aspect = d->y_aspect / d->x_aspect;
00165 if (et->physical_aspect >= 4)
00166 et->physical_aspect = 4;
00167 else if (et->physical_aspect >= 2)
00168 et->physical_aspect = 2;
00169 else et->physical_aspect = 1;
00170
00171 et->diff_factor = diff_factors[et->physical_aspect];
00172
00173 d->aux_data = et;
00174 d->aux_freefunc = free_eventone_data;
00175 }
00176
00177 static int
00178 et_initializer(stpi_dither_t *d, int duplicate_line, int zero_mask)
00179 {
00180 int i;
00181 eventone_t *et;
00182 if (!d->aux_data)
00183 et_setup(d);
00184
00185 et = (eventone_t *) (d->aux_data);
00186 if (!duplicate_line) {
00187 if ((zero_mask & ((1 << CHANNEL_COUNT(d)) - 1)) !=
00188 ((1 << CHANNEL_COUNT(d)) - 1)) {
00189 d->last_line_was_empty = 0;
00190 } else {
00191 d->last_line_was_empty++;
00192 }
00193 } else if (d->last_line_was_empty) {
00194 d->last_line_was_empty++;
00195 }
00196
00197 if (d->last_line_was_empty >= 5) {
00198 return 0;
00199 } else if (d->last_line_was_empty == 4) {
00200 if (et->dummy_channel) {
00201 memset(et->dummy_channel->errs[0], 0, d->dst_width * sizeof(int));
00202 }
00203 for (i = 0; i < CHANNEL_COUNT(d); i++)
00204 memset(CHANNEL(d, i).errs[0], 0, d->dst_width * sizeof(int));
00205 return 0;
00206 }
00207 for (i = 0; i < CHANNEL_COUNT(d); i++)
00208 CHANNEL(d, i).v = 0;
00209 if (et->dummy_channel)
00210 et->dummy_channel->v = 0;
00211 return 1;
00212 }
00213
00214 static inline void
00215 advance_eventone_pre(shade_distance_t *sp, eventone_t *et, int x)
00216 {
00217 distance_t *etd = &sp->et_dis[x];
00218 int t = sp->dis.r_sq + sp->dis.dx;
00219 if (t <= etd->r_sq) {
00220 sp->dis.r_sq = t;
00221 sp->dis.dx += et->d2x;
00222 } else {
00223 sp->dis = *etd;
00224 }
00225 }
00226
00227 static inline void
00228 eventone_update(stpi_dither_channel_t *dc, eventone_t *et,
00229 int x, int direction)
00230 {
00231 shade_distance_t *sp = (shade_distance_t *) dc->aux_data;
00232 distance_t *etd = &sp->et_dis[x];
00233 int t = etd->r_sq + etd->dy;
00234 int u = sp->dis.r_sq + sp->dis.dy;
00235 if (u < t) {
00236 t = u;
00237 etd->dx = sp->dis.dx;
00238 etd->dy = sp->dis.dy;
00239 }
00240 etd->dy += et->d2y;
00241
00242 if (t > 65535) {
00243 t = 65535;
00244 }
00245 etd->r_sq = t;
00246 }
00247
00248 static inline void
00249 diffuse_error(stpi_dither_channel_t *dc, eventone_t *et, int x, int direction)
00250 {
00251
00252
00253
00254
00255
00256
00257 #if 0
00258
00259 int frac_2 = dc->v + dc->v;
00260 int frac_3 = frac_2 + dc->v;
00261 dc->errs[0][x + MAX_SPREAD] = frac_3;
00262 dc->errs[0][x + MAX_SPREAD - direction] += frac_2;
00263 dc->v -= (frac_2 + frac_3) / 16;
00264 #else
00265 dc->errs[0][x + MAX_SPREAD] = dc->v * 3;
00266 dc->errs[0][x + MAX_SPREAD - direction] += dc->v * 5;
00267 dc->errs[0][x + MAX_SPREAD - (direction * 2)] += dc->v * 1;
00268 dc->v -= dc->v * 9 / 16;
00269 #endif
00270 }
00271
00272 static inline int
00273 eventone_adjust(stpi_dither_channel_t *dc, eventone_t *et, int dither_point,
00274 unsigned int desired)
00275 {
00276 if (dither_point <= 0)
00277 return 0;
00278 else if (dither_point >= 65535)
00279 return 65535;
00280 if (desired == 0) {
00281 dither_point = 0;
00282 } else {
00283 shade_distance_t *shade = (shade_distance_t *) dc->aux_data;
00284 dither_point += shade->dis.r_sq * et->aspect - (EVEN_C1 * 65535) / desired;
00285 if (dither_point > 65535)
00286 dither_point = 65535;
00287 else if (dither_point < 0)
00288 dither_point = 0;
00289 }
00290 return dither_point;
00291 }
00292
00293 static inline int
00294 unitone_adjust(stpi_dither_channel_t *dc, eventone_t *et,
00295 int dither_point, unsigned int desired)
00296 {
00297 if (dither_point <= 0)
00298 return INT_MIN;
00299 else if (dither_point >= 65535)
00300 return dither_point;
00301 if (desired == 0) {
00302 dither_point = INT_MIN;
00303 } else {
00304 shade_distance_t *shade = (shade_distance_t *) dc->aux_data;
00305 dither_point += shade->dis.r_sq * et->unitone_aspect -
00306 (UNITONE_C1 * 65535u) / desired;
00307 }
00308 return dither_point;
00309 }
00310
00311
00312 static inline void
00313 find_segment(stpi_dither_channel_t *dc, unsigned inkval,
00314 stpi_ink_defn_t *lower, stpi_ink_defn_t *upper)
00315 {
00316 lower->range = 0;
00317 lower->bits = 0;
00318
00319 if (dc->nlevels == 1)
00320 {
00321 upper->bits = dc->ink_list[1].bits;
00322 upper->range = dc->ink_list[1].value;
00323 }
00324 else
00325 {
00326 int i;
00327 stpi_ink_defn_t *ip;
00328
00329 for (i=0, ip = dc->ink_list; i < dc->nlevels - 1; i++, ip++) {
00330 if (ip->value > inkval)
00331 break;
00332 lower->bits = ip->bits;
00333 lower->range = ip->value;
00334 }
00335
00336 upper->bits = ip->bits;
00337 upper->range = ip->value;
00338 }
00339 }
00340
00341 static inline int
00342 find_segment_and_ditherpoint(stpi_dither_channel_t *dc, unsigned inkval,
00343 stpi_ink_defn_t *lower, stpi_ink_defn_t *upper)
00344 {
00345 find_segment(dc, inkval, lower, upper);
00346 if (inkval <= lower->range)
00347 return 0;
00348 else if (inkval >= upper->range)
00349 return 65535;
00350 else
00351 return (65535u * (inkval - lower->range)) / (upper->range - lower->range);
00352 }
00353
00354 static inline void
00355 print_ink(stpi_dither_t *d, unsigned char *tptr, const stpi_ink_defn_t *ink,
00356 unsigned char bit, int length)
00357 {
00358 int j;
00359
00360 if (tptr != 0)
00361 {
00362 tptr += d->ptr_offset;
00363 switch(ink->bits)
00364 {
00365 case 1:
00366 tptr[0] |= bit;
00367 return;
00368 case 2:
00369 tptr[length] |= bit;
00370 return;
00371 case 3:
00372 tptr[0] |= bit;
00373 tptr[length] |= bit;
00374 return;
00375 default:
00376 for (j=1; j <= ink->bits; j+=j, tptr += length) {
00377 if (j & ink->bits)
00378 *tptr |= bit;
00379 }
00380 return;
00381 }
00382 }
00383 }
00384
00385 void
00386 stpi_dither_et(stp_vars_t *v,
00387 int row,
00388 const unsigned short *raw,
00389 int duplicate_line,
00390 int zero_mask,
00391 const unsigned char *mask)
00392 {
00393 stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00394 eventone_t *et;
00395
00396 int x,
00397 length;
00398 unsigned char bit;
00399 int i;
00400
00401 int terminate;
00402 int direction;
00403 int xerror, xstep, xmod;
00404 int channel_count = CHANNEL_COUNT(d);
00405
00406 if (!et_initializer(d, duplicate_line, zero_mask))
00407 return;
00408
00409 et = (eventone_t *) d->aux_data;
00410
00411 length = (d->dst_width + 7) / 8;
00412
00413 if (row & 1) {
00414 direction = 1;
00415 x = 0;
00416 terminate = d->dst_width;
00417 d->ptr_offset = 0;
00418 } else {
00419 direction = -1;
00420 x = d->dst_width - 1;
00421 terminate = -1;
00422 d->ptr_offset = length - 1;
00423 raw += channel_count * (d->src_width - 1);
00424 }
00425 bit = 1 << (7 - (x & 7));
00426 xstep = channel_count * (d->src_width / d->dst_width);
00427 xmod = d->src_width % d->dst_width;
00428 xerror = (xmod * x) % d->dst_width;
00429
00430 for (; x != terminate; x += direction) {
00431
00432 int point_error = 0;
00433 int comparison = 32768;
00434
00435 if (d->stpi_dither_type & D_ORDERED_BASE)
00436 comparison += (ditherpoint(d, &(d->dither_matrix), x) / 16) - 2048;
00437
00438 for (i=0; i < channel_count; i++) {
00439 if (CHANNEL(d, i).ptr)
00440 {
00441 int inkspot;
00442 int range_point;
00443 stpi_dither_channel_t *dc = &CHANNEL(d, i);
00444 shade_distance_t *sp = (shade_distance_t *) dc->aux_data;
00445 stpi_ink_defn_t *inkp;
00446 stpi_ink_defn_t lower, upper;
00447
00448 advance_eventone_pre(sp, et, x);
00449
00450
00451
00452
00453
00454
00455
00456 range_point =
00457 find_segment_and_ditherpoint(dc, raw[i], &lower, &upper);
00458
00459
00460 dc->v += 2 * range_point + (dc->errs[0][x + MAX_SPREAD] + 8) / 16;
00461 inkspot = dc->v - range_point;
00462
00463 point_error += eventone_adjust(dc, et, inkspot, range_point);
00464
00465
00466 inkp = &lower;
00467 if (point_error >= comparison) {
00468 point_error -= 65535;
00469 inkp = &upper;
00470 dc->v -= 131070;
00471 sp->dis = et->d_sq;
00472 }
00473
00474
00475 if (inkp->bits) {
00476 if (!mask || (*(mask + d->ptr_offset) & bit)) {
00477 set_row_ends(dc, x);
00478
00479
00480 print_ink(d, dc->ptr, inkp, bit, length);
00481 }
00482 }
00483
00484
00485 eventone_update(dc, et, x, direction);
00486 diffuse_error(dc, et, x, direction);
00487 }
00488 }
00489 if (direction == 1)
00490 ADVANCE_UNIDIRECTIONAL(d, bit, raw, channel_count, xerror, xstep, xmod);
00491 else
00492 ADVANCE_REVERSE(d, bit, raw, channel_count, xerror, xstep, xmod);
00493 }
00494 if (direction == -1)
00495 stpi_dither_reverse_row_ends(d);
00496 }
00497
00498 void
00499 stpi_dither_ut(stp_vars_t *v,
00500 int row,
00501 const unsigned short *raw,
00502 int duplicate_line,
00503 int zero_mask,
00504 const unsigned char *mask)
00505 {
00506 stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither");
00507 eventone_t *et;
00508
00509 int x,
00510 length;
00511 unsigned char bit;
00512 int i;
00513
00514 int terminate;
00515 int direction;
00516 int xerror, xstep, xmod;
00517 int channel_count = CHANNEL_COUNT(d);
00518 stpi_dither_channel_t *ddc;
00519
00520 if (channel_count == 1) {
00521 stpi_dither_et(v, row, raw, duplicate_line, zero_mask, mask);
00522 return;
00523 }
00524
00525 if (!et_initializer(d, duplicate_line, zero_mask))
00526 return;
00527
00528 et = (eventone_t *) d->aux_data;
00529 ddc = et->dummy_channel;
00530
00531 length = (d->dst_width + 7) / 8;
00532
00533 if (row & 1) {
00534 direction = 1;
00535 x = 0;
00536 terminate = d->dst_width;
00537 d->ptr_offset = 0;
00538 } else {
00539 direction = -1;
00540 x = d->dst_width - 1;
00541 terminate = -1;
00542 d->ptr_offset = length - 1;
00543 raw += channel_count * (d->src_width - 1);
00544 }
00545 bit = 1 << (7 - (x & 7));
00546 xstep = channel_count * (d->src_width / d->dst_width);
00547 xmod = d->src_width % d->dst_width;
00548 xerror = (xmod * x) % d->dst_width;
00549
00550 for (; x != terminate; x += direction) {
00551
00552 shade_distance_t *ssp = (shade_distance_t *) ddc->aux_data;
00553 int point_error = 0;
00554 int total_error = 0;
00555 int channels_to_print = 0;
00556 int print_all_channels = 0;
00557 int maximum_value = 0;
00558 int comparison = 32768;
00559 stpi_dither_channel_t *best_channel = NULL;
00560 stpi_dither_channel_t *second_best_channel = NULL;
00561 int best_channel_value = INT_MIN;
00562 int second_best_channel_value = INT_MIN;
00563 int random_value = ditherpoint(d, &(d->dither_matrix), x);
00564
00565 if (d->stpi_dither_type & D_ORDERED_BASE)
00566 comparison += (random_value / 16) - 2048;
00567
00568
00569 ddc->b = 0;
00570 advance_eventone_pre(ssp, et, x);
00571
00572 for (i=0; i < channel_count; i++) {
00573 stpi_dither_channel_t *dc = &CHANNEL(d, i);
00574 if (dc->ptr) {
00575 shade_distance_t *sp = (shade_distance_t *) dc->aux_data;
00576
00577 advance_eventone_pre(sp, et, x);
00578
00579
00580
00581
00582
00583
00584
00585 dc->b = find_segment_and_ditherpoint(dc, raw[i],
00586 &(sp->lower), &(sp->upper));
00587 if (sp->share_this_channel) {
00588 if (dc->b > maximum_value)
00589 maximum_value = dc->b;
00590 ddc->b += dc->b;
00591 }
00592
00593 dc->v += 2 * dc->b + (dc->errs[0][x + MAX_SPREAD] + 8) / 16;
00594 dc->o = unitone_adjust(dc, et, dc->v - dc->b, dc->b);
00595 }
00596 }
00597
00598 #if 0
00599 if ((2 * (ddc->b - maximum_value)) < (3 * maximum_value))
00600 print_all_channels = 1;
00601 #endif
00602
00603 if (ddc->b > 131070)
00604 print_all_channels = 1;
00605 else if (ddc->b > 65535) {
00606 ddc->b -= 65535;
00607 channels_to_print = 1;
00608 }
00609
00610 if (ddc->b > 65535) {
00611 ddc->b = 65535;
00612 }
00613
00614 ddc->v += 2 * ddc->b + (ddc->errs[0][x + MAX_SPREAD] + 8) / 16;
00615 total_error += eventone_adjust(ddc, et, ddc->v - ddc->b, ddc->b);
00616 if (total_error >= comparison) {
00617 channels_to_print += 1;
00618 }
00619
00620 if (!print_all_channels) {
00621 for (i=0; i < channel_count; i++) {
00622 stpi_dither_channel_t *dc = &CHANNEL(d, i);
00623 shade_distance_t *sp = (shade_distance_t *) dc->aux_data;
00624
00625 if (dc->ptr) {
00626
00627 if (sp->share_this_channel) {
00628 if (dc->o > best_channel_value) {
00629 second_best_channel = best_channel;
00630 best_channel = dc;
00631 second_best_channel_value = best_channel_value;
00632 if (dc->o >= 32768)
00633 best_channel_value = INT_MAX;
00634 else
00635 best_channel_value = dc->o;
00636 } else if (dc->o > second_best_channel_value) {
00637 second_best_channel = dc;
00638 if (dc->o >= 32768)
00639 second_best_channel_value = INT_MAX;
00640 else
00641 second_best_channel_value = dc->o;
00642 }
00643 }
00644 }
00645 }
00646 }
00647
00648 for (i=0; i < channel_count; i++) {
00649 stpi_dither_channel_t *dc = &CHANNEL(d, i);
00650 if (dc->ptr) {
00651
00652
00653 shade_distance_t *sp = (shade_distance_t *) dc->aux_data;
00654 stpi_ink_defn_t *inkp = &(sp->lower);
00655
00656 if (dc->o < 0)
00657 dc->o = 0;
00658 else if (dc->o > 65535)
00659 dc->o = 65535;
00660 if (print_all_channels || !sp->share_this_channel) {
00661 point_error += dc->o;
00662 if (point_error >= comparison) {
00663 point_error -= 65535;
00664 inkp = &(sp->upper);
00665 dc->v -= 131070;
00666 sp->dis = et->d_sq;
00667 }
00668 } else if ((channels_to_print >= 1 && best_channel == dc) ||
00669 (channels_to_print >= 2 && second_best_channel == dc)) {
00670 inkp = &(sp->upper);
00671 dc->v -= 131070;
00672 sp->dis = et->d_sq;
00673 }
00674 if (inkp->bits) {
00675 if (!mask || (*(mask + d->ptr_offset) & bit)) {
00676 set_row_ends(dc, x);
00677
00678
00679 print_ink(d, dc->ptr, inkp, bit, length);
00680 }
00681 }
00682 }
00683 }
00684 if (total_error >= comparison) {
00685 ddc->v -= 131070;
00686 total_error -= 65535;
00687 ssp->dis = et->d_sq;
00688 }
00689
00690 eventone_update(ddc, et, x, direction);
00691 diffuse_error(ddc, et, x, direction);
00692 for (i=0; i < channel_count; i++) {
00693 stpi_dither_channel_t *dc = &CHANNEL(d, i);
00694 if (dc->ptr) {
00695
00696
00697 eventone_update(dc, et, x, direction);
00698 diffuse_error(dc, et, x, direction);
00699 }
00700 }
00701
00702
00703 if (direction == 1)
00704 ADVANCE_UNIDIRECTIONAL(d, bit, raw, channel_count, xerror, xstep, xmod);
00705 else
00706 ADVANCE_REVERSE(d, bit, raw, channel_count, xerror, xstep, xmod);
00707 }
00708 if (direction == -1)
00709 stpi_dither_reverse_row_ends(d);
00710 }