summaryrefslogtreecommitdiff
path: root/doc/developer/reference-html/c1968.html
blob: ad12784dd08104078018f55d992b394357d88c08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML
><HEAD
><TITLE
>Dithering</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
REL="HOME"
TITLE="The Developer's Guide to Gutenprint"
HREF="book1.html"><LINK
REL="PREVIOUS"
TITLE="Weaving algorithms"
HREF="x1734.html"><LINK
REL="NEXT"
TITLE="GNU General Public License"
HREF="gpl.html"><META
http-equiv="Content-Type"
content="text/html; charset=UTF-8"></HEAD
><BODY
CLASS="chapter"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>The Developer's Guide to Gutenprint</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="x1734.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="gpl.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="chapter"
><H1
><A
NAME="AEN1968"
></A
>Chapter 7. Dithering</H1
><P
>&#13;    The dithering code in
    <TT
CLASS="filename"
>src/main/print-dither.c</TT
> attempts to
    reproduce various shades of gray (or all colors) from only a few
    different inks (black, cyan, magenta, yellow, and sometimes
    light cyan and light magenta).  The dots can't vary in darkness
    or size (except for certain special printers), and so we need to
    lay down a certain fraction of dots to represent each distinct
    level.
  </P
><P
>&#13;    This sounds straightforward; in practice, it isn't.  Completely
    random distribution of dots (simple probabilistic dithering)
    would create grainy clumps and light spots.  The smoothest
    pattern results from an equidistant spacing of dots.
    Approximating this requires sophisticated algorithms.  We have
    two dithering algorithms, an ordered dither algorithm that uses
    a grid (matrix) to decide whether to print, and a modified
    Floyd-Steinberg error diffusion algorithm that uses a grid in a
    slightly different way.
  </P
><P
>&#13;    We currently have three dithering functions:
  </P
><P
></P
><DIV
CLASS="variablelist"
><DL
><DT
><VAR
CLASS="literal"
>dither_fastblack</VAR
></DT
><DD
><P
>&#13;          This produces pure black or white from a pre-dithered
          input.  This is used for two purposes: for printing pure
          black and white very quickly (e.g. text), and for printing
          pre-screened monochrome output that was rasterized
          externally.
        </P
></DD
><DT
><VAR
CLASS="literal"
>dither_black</VAR
></DT
><DD
><P
>&#13;          This produces black from grayscale input.  The new
          dither_black can produce either a single or multiple
          levels of black, for printers supporting variable dot
          size.
        </P
></DD
><DT
><VAR
CLASS="literal"
>dither_cmyk</VAR
></DT
><DD
><P
>&#13;          This produces 3, 4, 5, 6, or 7 color output (CMY, CMYK,
          CcMmYK, CcMmYy, CcMmYyK, or any variants).  The new
          routine can handle single or multiple levels of each
          color.
        </P
></DD
></DL
></DIV
><P
>&#13;    There is a choice of dithering algorithms.  Four of them are
    based on a basic error diffusion, with a few tweaks of my own.
    The other one is ‘ordered’.  However, they all share
    the basic operation in common.  First, the algorithm picks what
    kind of dot (if there are multiple dot sizes and/or tones that
    may be picked) is the candidate to be printed.  This decision is
    made based on the darkness at the point being dithered.  Then,
    it decides whether the dot will be printed at all.  What this is
    based on depends upon which algorithm family we use.  This is
    all described in more detail below.
  </P
><P
>&#13;    Ordered dithering works by comparing the value at a given point
    with the value of a tiled matrix.  If the value at the point is
    greater than the value in the matrix, the dot is printed.  The
    matrix should consist of a set of evenly spaced points between 0
    and the upper limit.  The choice of matrix is very important for
    print quality.  A good dither matrix will emphasize high
    frequency components, which distributes dots evenly with a
    minimum of clumping.  The matrices used here are all simple
    matrices that are expanded recursively to create larger matrices
    with the same kind of even point distribution.  This is
    described below.
  </P
><P
>&#13;    Note that it is important to use different matrices for the two
    sub-operations, because otherwise the choice about whether to
    print and the choice of dot size will be correlated.  The usual
    result is that the print is either too dark or too light, but
    there can be other problems.
  </P
><P
>&#13;    Ordered dithering works quite well on single dot size, four
    color printers.  It has not been well tested on four color,
    variable dot size printers.  It should be avoided on six color
    printers.
  </P
><P
>&#13;    Error diffusion works by taking the output error at a given
    pixel and “diffusing” it into surrounding pixels.
    Output error is the difference between the amount of ink output
    and the input level at each pixel.  For simple printers, with
    one or four ink colors and only one dot size, the amount of ink
    output is either 65536 (i. e. full output) or 0 (no output).
    The difference between this and the input level is the error.
    Normal error diffusion adds part of this error to the adjoining
    pixels in the next column and the next row (the algorithm simply
    scans each row in turn, never backing up).  The error adds up
    until it reaches a threshold (half of the full output level, or
    32768), at which point a dot is output, the output is subtracted
    from the current value, and the (now negative) error is diffused
    similarly.
  </P
><P
>&#13;    Error diffusion works quite well in general, but it tends to
    generate artifacts which usually appear as worm-like lines or
    areas of anomalous density.  I have devised some ways, as
    described below, of ameliorating these artifacts.
  </P
><P
>&#13;    There are two sub-classes of error diffusion that we use here,
    ‘random’ and ‘hybrid’.  One of the
    techniques that we use to ameliorate the artifacts is to use a
    fuzzy threshold rather than the hard threshold of half of the
    output level.  Random error diffusion uses a pseudo-random
    number to perturb the threshold, while hybrid error diffusion
    uses a matrix.  Hybrid error diffusion worked very poorly in
    3.1.3, and I couldn't figure out why until I found a bug.  It
    now works very well.
  </P
><P
>&#13;    There is one additional variant (on both sub-classes), called
    ‘adaptive hybrid’ and ‘adaptive random’.
    The adaptive variant takes advantage of the fact that the
    patterns that ordered dithering create are less visible at very
    low densities, while the artifacts created by error diffusion
    are more objectionable at low densities.  At low densities,
    therefore, it uses ordered dithering; at higher densities it
    uses error diffusion.
  </P
><P
>&#13;    Handling multiple output levels makes life a bit more
    complicated.  In principle, it shouldn't be much harder: simply
    figure out what the ratio between the available output levels is
    and have multiple thresholds.  In practice, getting these right
    involves a lot of trial and error.  The other thing that's
    important is to maximize the number of dots that have some ink.
    This will reduce the amount of speckling.  More on this later.
  </P
><P
>&#13;    The next question: how do we handle black when printing in
    color?  Black ink is much darker than colored inks.  It's
    possible to produce black by adding some mixture of cyan,
    magenta, and yellow—in principle.  In practice, the black
    really isn't very black, and different inks and different papers
    will produce different color casts.  However, by using CMY to
    produce gray, we can output a lot more dots!  This makes for a
    much smoother image.  What's more, one cyan, one magenta, and
    one yellow dot produce less darkness than one black dot, so
    we're outputting that many more dots.  Better yet, with 6 or 7
    color printers, we have to output even more light ink dots.  So
    Epson Stylus Photo printers can produce really smooth grays---if
    we do everything right.  The right idea is to use CMY at lower
    black levels, and gradually mix in black as the overall amount
    of ink increases, so the black dots don't really become visible
    within the ink mass.
  </P
><P
>&#13;    Variable dot sizes are handled by dividing the range between 0
    and 65536 into segments.  Each segment can either represent a
    range in which all of one kind of ink (color and/or dot size) is
    used, with varying amounts of ink, or a transition region
    between inks, in which equal numbers of dots are printed but the
    amount of each ink will be adjusted throughout the range.  Each
    range is represented by four numbers:
  </P
><P
></P
><UL
><LI
><P
>&#13;        Bottom of the range.
      </P
></LI
><LI
><P
>&#13;        Top of the range.
      </P
></LI
><LI
><P
>&#13;        Value of the lighter ink.
      </P
></LI
><LI
><P
>Value of the darker ink.
      </P
></LI
></UL
><P
>&#13;    In addition, the bit patterns and which type of ink are also
    represented, but they don't affect the actual algorithm.
  </P
><P
>&#13;    As mentioned above, the basic algorithm is the same whether we
    use ordered dither or error diffusion.  We perform the following
    steps on each color of each pixel:
  </P
><P
></P
><OL
TYPE="1"
><LI
><P
>&#13;        Compute the value of the particular color we're printing.
        This isn't usually the pure CMY value; it's adjusted to
        improve saturation and to limit the use of black in light
        toned regions (to avoid speckling).
      </P
></LI
><LI
><P
>&#13;        Find the range containing this value.
      </P
></LI
><LI
><P
>&#13;        Compute where this value lies within the range.  We scale
        the endpoints between 0 and 65536 for this purpose.  So for
        example, if the bottom of the range is 10,000 and the top of
        the range is 20,000, and the value is 12,500, we're 1/4 of
        the way between the bottom and the top of the range, so our
        scale point is 16384.
      </P
></LI
><LI
><P
>&#13;        Compute the “virtual value”.  The virtual value
        is the distance between the value of the lighter and the
        value of the darker ink.  So if the value of the light ink
        is 32768 and the dark ink is 65536, we compute a virtual
        value scaled appropriately between these two values, which
        is 40960 in this case.
      </P
></LI
><LI
><P
>&#13;        Using either error diffusion or ordered dither, the standard
        threshold is 1/2 of the value (20480 in this case).  Using
        ordered dither, we want to compute a value between 0 and
        40960 that we will compare the input value against to decide
        whether to print.  Using pure error diffusion, we would
        compare the accumulated error against 20480 to decide
        whether to print.  In practice, we use the same matrix
        method to decide whether to print.  The correct amount of
        ink will be printed this way, but we minimize the squiggly
        lines characteristic of error diffusion by dithering the
        threshold in this fashion.  A future enhancement will allow
        us to control the amount of dithering applied to the
        threshold.
      </P
></LI
></OL
><P
>&#13;    The matrices were generated by Thomas Tonino
    <CODE
CLASS="email"
>&#60;<A
HREF="mailto:ttonino@bio.vu.nl"
>ttonino@bio.vu.nl</A
>&#62;</CODE
> with an algorithm of his
    devising.  The algorithm is designed to maximize the spacing
    between dots at any given density by searching the matrix for
    holes and placing a dot in the largest available hole.  It
    requires careful selection of initial points to achieve good
    results, and is very time consuming.  For best results, a
    different matrix must be used for modes with 2:1 aspect ratio
    (e.g. 1440×720) than for 1:1 (e. g. 720×720).  It is
    essential with any of these matrices that every point be used.
    Skipping points generates low-frequency noise.
  </P
><P
>&#13;    It's essential to use different matrices for deciding whether to
    print and for deciding what color (dark or light) to print.
    This should be obvious; the decision about whether to print at
    all should be as independent as possible from the decision about
    what color to print, because any bias will result in excess
    light or dark ink being printed, shifting the tonal balance.  We
    actually use the same matrices, but we shift them vertically and
    horizontally.  Assuming that the matrices are not
    self-correlated, this will yield good results.
  </P
><P
>&#13;    The ranges are computed from a list of ink values (between 0 and
    1 for each possible combination of dot size and ink tone, where
    the value represents the darkness of the ink) and the desired
    maximum density of the ink.  This is done in dither_set_ranges,
    and needs more documentation.
  </P
><P
>&#13;    I stated earlier that I've tweaked the basic error diffusion
    algorithm.  Here's what I've done to improve it:
  </P
><P
></P
><UL
><LI
><P
>&#13;        We use a variable threshold to decide when to print, as
        discussed above.  This does two things for us: it reduces
        the slightly squiggly diagonal lines that are the mark of
        error diffusion; and it allows us to lay down some ink even
        in very light areas near the edge of the image.  The
        squiggly lines that error diffusion algorithms tend to
        generate are caused by the gradual accumulation of error.
        This error is partially added horizontally and partially
        vertically.  The horizontal accumulation results in a dot
        eventually being printed.  The vertical accumulation results
        in a dot getting laid down in roughly the same horizontal
        position in the next row.  The diagonal squigglies result
        from the error being added to pixels one forward and one
        below the current pixel; these lines slope from the top
        right to the bottom left of the image.
      </P
><P
>&#13;        Error diffusion also results in pale areas being completely
        white near the top left of the image (the origin of the
        printing coordinates).  This is because enough error has to
        accumulate for anything at all to get printed.  In very pale
        areas it takes quite a long time to build up anything
        printable at all; this results in the bare spots.
      </P
><P
>&#13;        Randomizing the threshold somewhat breaks up the diagonals
        to some degree by randomizing the exact location that the
        accumulated output crosses the threshold.  It reduces the
        false white areas by allowing some dots to be printed even
        when the accumulated output level is very low.  It doesn't
        result in excess ink because the full output level is still
        subtracted and diffused.
      </P
><P
>&#13;        Excessive randomization leads to blobs at high densities.
        Therefore, as the density increases, the degree of
        randomization decreases.
      </P
></LI
><LI
><P
>&#13;        Alternating scan direction between rows (first row is
        scanned left to right, second is scanned right to left, and
        so on).  This also helps break up white areas, and it also
        seems to break up squigglies a bit.  Furthermore, it
        eliminates directional biases in the horizontal direction.
        This isn't necessary for ordered dither, but it doesn't hurt
        either.
      </P
></LI
><LI
><P
>&#13;        Diffusing the error into more pixels.  Instead of diffusing
        the entire error into (X+1, Y) and (X, Y+1), we diffuse it
        into (X+1, Y), (X+K, Y+1), (X, Y+1), (X-K, Y+1) where K
        depends upon the output level (it never exceeds about 10
        dots, and is greater at higher output levels).  This really
        reduces squigglies and graininess.  The amount of this
        spread can be controlled; for line art, it should be less
        than for photographs (of course, line art doesn't usually
        contain much light color, but the <SPAN
CLASS="emphasis"
><I
CLASS="emphasis"
>error</I
></SPAN
>
        value can be small in places!)  In addition to requiring
        more computation, a wide ink spread results in patterning at
        high dot densities (note that the dot density can be high
        even in fairly pale regions if multiple dot sizes are in
        use).
      </P
></LI
><LI
><P
>&#13;        Don't lay down any colored ink if we're laying down black
        ink.  There's no point; the colored ink won't show.  We
        still pretend that we did for purposes of error diffusion
        (otherwise excessive error will build up, and will take a
        long time to clear, resulting in heavy bleeding of ink into
        surrounding areas, which is very ugly indeed), but we don't
        bother wasting the ink.  How well this will do with variable
        dot size remains to be seen.
      </P
></LI
><LI
><P
>&#13;        Oversampling.  This is how to print 1440×720 with Epson
        Stylus printers.  Printing full density at 1440×720 will
        result in excess ink being laid down.  The trick is to print
        only every other dot.  We still compute the error as though we
        printed every dot.  It turns out that randomizing which dots
        are printed results in very speckled output.  This can be
        taken too far; oversampling at 1440×1440 or
        1440×2880 virtual resolution results in other problems.
        However, at present 1440×1440 (which is more accurately
        called "1440×720 enhanced", as the Epson printers cannot
        print 1440 rows per inch) does quite well, although it's slow.
      </P
></LI
></UL
><P
>&#13;    What about multiple output levels?  For 6 and 7 color printers,
    simply using different threshold levels has a problem: the pale
    inks have trouble being seen when a lot of darker ink is being
    printed.  So rather than just using the output level of the
    particular color to decide which ink to print, we look at the
    total density (sum of all output levels).  If the density's high
    enough, we prefer to use the dark ink.  Speckling is less
    visible when there's a lot of ink, anyway.  I haven't yet
    figured out what to do for multiple levels of one color.
  </P
><P
>&#13;    You'll note that I haven't quoted a single source on color or
    printing theory.  I simply did all of this empirically.
  </P
><P
>&#13;    There are various other tricks to reduce speckling.  One that
    I've seen is to reduce the amount of ink printed in regions
    where one color (particularly cyan, which is perceived as the
    darkest) is very pale.  This does reduce speckling all right,
    but it also results in strange tonal curves and weird (to my
    eye) colors.
  </P
><P
>&#13;    Before any dither routine is used,
    <CODE
CLASS="function"
>init_dither</CODE
> must be called.  This takes
    three arguments: the input width (number of pixels in the
    input), the output width (number of pixels in the output), and a
    <SPAN
CLASS="type"
>stp_vars_t</SPAN
> structure containing the parameters for
    the print job.
  </P
><P
>&#13;    <CODE
CLASS="function"
>init_dither</CODE
> returns a pointer to an opaque
    object representing the dither.  This object is passed as the first
    argument to all of the dither-related routines.
  </P
><P
>&#13;    After a page is fully dithered, <CODE
CLASS="function"
>free_dither</CODE
>
    must be called to free the dither object and perform any
    cleanup.  In the future, this may do more (such as flush
    output).  This arrangement permits using these routines with
    programs that create multiple output pages, such as GhostScript.
  </P
><P
>&#13;    The dithering routines themselves have a number of control knobs
    that control internal aspects of the dithering process.  These
    knobs are accessible via a number of functions that can be
    called after <CODE
CLASS="function"
>init_dither</CODE
>.
  </P
><P
></P
><UL
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_density</CODE
> takes a double
        between 0 and 1 representing the desired ink density for
        printing solid colors.  This is used in a number of places
        in the dithering routine to make decisions.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_black_density</CODE
> takes a double
        between 0 and 1 representing the desired ink density for
        printing black ink in color printing.  This is used to
        balance black against color ink.  By default, this is equal
        to the density set by
        <CODE
CLASS="function"
>dither_set_density</CODE
>.  By setting it
        higher, more black ink will be printed.  For example, if the
        base density is .4 and the black density is .8, twice as
        much black ink will be printed as would otherwise be called
        for.
      </P
><P
>&#13;        This is not used when printing in monochrome.  When printing
        monochrome, the base density
        (<CODE
CLASS="function"
>dither_set_density</CODE
>) should be adjusted
        appropriately.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_ink_budget</CODE
> takes an unsigned
        number representing the most ink that may be deposited at a
        given point.  This number is arbitrary; the limit is
        computed by summing the size of each ink dot, which is
        supplied as a parameter in
        <CODE
CLASS="function"
>dither_set_X_ranges</CODE
>.  By default, there
        is no limit.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_black_lower</CODE
> takes a double
        that should be between 0 and 1 that represents the lowest
        density level at which black ink will start to mix in with
        colored ink to generate grays.  The lower this is, the less
        density is required to use black ink.  Setting this too low
        will result in speckling from black dots, particularly on 6
        and 7 color printers.  Setting this too high will make it
        hard to get satisfactory black or may result in sharp
        transition between blended colors and black.  Default:
        0.0468.
      </P
><P
>&#13;        It is important to note that since the density scale is
        never linear (and since this value is adjusted via other
        things happening during the dithering process) that this
        does not mean that 95% gray will use any black ink.  At this
        setting, there will be no black ink used until about 50%
        gray.
      </P
><P
>&#13;        This only applies to color mode.
        </P
><P
>&#13;        This value should be set lower for printers capable of
        variable dot size, since more dots can be laid down close to
        each other.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_black_upper</CODE
> takes a double
        that should be between 0 and 1 that represents the highest
        density level at which colored inks will be mixed to create
        gray.  Setting this too low will result in speckly dark
        grays because there is not enough ink to fill all the holes,
        or sharp transition between blended colors and black if it
        is too close to the value of
        <CODE
CLASS="function"
>dither_set_black_upper</CODE
> Setting this too
        high will result in poor black and dark tone quality.
        Default: 0.5.  This results in 10% and darker grays being
        printed with essentially all black.
      </P
><P
>&#13;        This only applies to color mode.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_black_levels</CODE
> takes three
        doubles that represent the amount of cyan, magenta, and
        yellow respectively that are blended to create gray.  The
        defaults are 1.0 for each, which is probably too low for
        most printers.  These values are adjusted to create a good
        gray balance.  Setting these too low will result in pale
        light and midtone grays, with a sharp transition to darker
        tones as black mixes in.  Setting them too high will result
        in overly dark grays and use of too much ink, possibly
        creating bleed-through.
      </P
><P
>&#13;        This only applies to color mode.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_randomizers</CODE
> takes four
        integer values representing the degree of randomness used
        for cyan, magenta, yellow, and black.  This is used to allow
        some printing to take place in pale areas.  Zero is the most
        random; greater than 8 or so gives very little randomness at
        all.  Defaults are 0 for cyan, magenta, and yellow, and 4
        for black.  Setting the value for black too low will result
        in black speckling in pale areas.  Setting values too high
        will result in pale areas getting no ink at all.
      </P
><P
>&#13;        This currently only applies to single dot size in color and
        black.  It should be extended to operate in variable dot
        size mode, although actually applying it correctly will be
        tricky.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_ink_darkness</CODE
> takes three
        doubles representing the contribution to perceived darkness
        of cyan, magenta, and yellow.  This is used to help decide
        when to switch between light and dark inks in 6 and 7 color
        printers (with light cyan, light magenta, and possibly light
        yellow).  Setting these too low will result in too much
        light ink being laid down, creating flat spots in the
        darkness curves and bleed-through.  Setting them too high
        will result in dark ink being used in pale areas, creating
        speckle.  The defaults are .4 for cyan, .3 for magenta, and
        .2 for yellow.  Dark cyan will show against yellow much more
        than dark magenta will show against cyan, since the cyan
        appears much darker than the yellow.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_light_inks</CODE
> takes three
        doubles between 0 and 1 representing the ratio in darkness
        between the light and dark versions of the inks.  Setting
        these too low will result in too much dark ink being used in
        pale areas, creating speckling, while setting them too high
        will result in very smooth texture but too much use of light
        ink, resulting in flat spots in the density curves and ink
        bleed-through.  There are no defaults.  Any light ink
        specified as zero indicates that there is no light ink for
        that color.
      </P
><P
>&#13;        This only applies to 6 and 7 color printers in single dot
        size color mode, and only to those inks which have light
        versions (usually cyan and magenta).
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_ink_spread</CODE
> takes a small
        integer representing the amount of ink spread in the dither.
        Larger numbers mean less spread.  Larger values are
        appropriate for line art and solid tones; they will yield
        sharper transitions but more dither artifacts.  Smaller
        values are more appropriate for photos.  They will reduce
        resolution and sharpness but reduce dither artifacts up to a
        point.  A value of 16 or higher implies minimum ink spread
        at any resolution no matter what the overdensity.  A value
        of 14 is typical for photos on single dot size, 6 color
        printers.  For 4 color printers, subtract 1 (more spread;
        the dots are farther apart).  For variable dot size
        printers, add 1 (more small dots are printed; less spread is
        desirable).
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_adaptive_divisor</CODE
> takes a
        float representing the transition point between error
        diffusion and ordered dither if adaptive dithering is used.
        The float is a fraction of the printing density.  For
        example, if you wish the transition to be at 1/4 of the
        maximum density (which works well on simple 4-color
        printers), you would pass .25 here.  With six colors and/or
        with multiple dot sizes, the values should be set lower.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_transition</CODE
> takes a float
        representing the exponent of the transition curve between
        light and dark inks/dot sizes.  A value less than 1 (typical
        when using error diffusion) mixes in less dark ink/small
        dots at lower ends of the range, to reduce speckling.  When
        using ordered dithering, this must be set to 1.
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_X_ranges_simple</CODE
>
        (<VAR
CLASS="literal"
>X</VAR
> = <VAR
CLASS="literal"
>c</VAR
>,
        <VAR
CLASS="literal"
>m</VAR
>, <VAR
CLASS="literal"
>y</VAR
> or
        <VAR
CLASS="literal"
>k</VAR
>) describes the ink choices available
        for each color.  This is useful in typical cases where a
        four color printer with variable dot sizes is in use.  It is
        passed an array of doubles between (0, 1] representing the
        relative darkness of each dot size.  The dot sizes are
        assigned bit patterns (and ink quantities, see
        <CODE
CLASS="function"
>dither_set_ink_budget</CODE
> above) from 1 to
        the number of levels.  This also requires a density, which
        is the desired density for this color.  This density need
        not equal the density specified in
        <CODE
CLASS="function"
>dither_set_density</CODE
>.  Setting it lower
        will tend to print more dark ink (because the curves are
        calculated for this color assuming a lower density than is
        actually supplied).
      </P
></LI
><LI
><P
>&#13;        <CODE
CLASS="function"
>dither_set_X_ranges</CODE
>
        (<VAR
CLASS="literal"
>X</VAR
> = <VAR
CLASS="literal"
>c</VAR
>,
        <VAR
CLASS="literal"
>m</VAR
>, <VAR
CLASS="literal"
>y</VAR
> or
        <VAR
CLASS="literal"
>k</VAR
>) describes in a more general way the
        ink choices available for each color.  For each possible ink
        choice, a bit pattern, dot size, value (i. e. relative
        darkness), and whether the ink is the dark or light variant
        ink is specified.
      </P
></LI
></UL
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="x1734.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="book1.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="gpl.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Weaving algorithms</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
>&nbsp;</TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>GNU General Public License</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>