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
|
<chapter>
<title>Adding a new printer</title>
<para>
This chapter covers adding a new ESCP/2, PCL, or Canon printer.
Writing a new driver module is not covered.
</para>
<para>
The three steps to adding a printer are:
<orderedlist>
<listitem>
<para>
Add an entry to <filename>printers.xml</filename>.
</para>
</listitem>
<listitem>
<para>
Add the appropriate code and data to the appropriate
driver module.
</para>
</listitem>
<listitem>
<para>
Tune the printer.
</para>
</listitem>
</orderedlist>
</para>
<para>
Printer information is stored in two places: in
<filename>printers.xml</filename> (which contains the list of
printer models available to the the upper-level application),
and in the appropriate driver file
(<filename>print-escp2.c</filename>,
<filename>print-pcl.c</filename>, or
<filename>print-canon.c</filename>).
</para>
<sect1>
<title><filename>printers.xml</filename></title>
<para>
<filename>printers.xml</filename> is an XML file that contains
very simple printer definitions. A schema may be used to
validate the XML (<filename>src/main/gutenprint.xsd</filename>).
This is an example definition:
</para>
<informalexample>
<programlisting><printer name="EPSON Stylus Color 1500" driver="escp2-1500">
<color value="true"/>
<model value="2"/>
<gamma value="0.597"/>
<density value="1.0"/>
</printer></programlisting>
</informalexample>
<para>
There are other tags that may be present. The only ones that
are mandatory are <literal><printer></literal>,
<literal><color></literal> and
<literal><model></literal>. The other optional parameters
(<literal><gamma></literal> and
<literal><density></literal> in this case) can be used to
adjust control settings. This is probably not the right place
for them; the printer drivers themselves should contain this
information. There's probably no good reason for anything but
gamma and density to be in here. Gamma refers to the printer's
gamma factor; density is the desired base ink density for the
printer. The Epson driver contains the density information for
each printer at each resolution internally. An even better
driver would adjust density and possibly even gamma for paper
type. All the more reason not to have that information here.
</para>
<para>
If you really are curious about what tags are permitted, please
see the schema. These are the definitions of the tags that do
matter:
</para>
<variablelist>
<title>printdef XML elements</title>
<varlistentry>
<term><literal><family></literal></term>
<listitem>
<para>
This defines what driver module this printer uses. The
attribute <literal>name</literal> is the name of the
family driver to associate the printers with, for example
<literal>escp2</literal>, <literal>pcl</literal>,
<literal>canon</literal>, <literal>ps</literal> or
<literal>raw</literal>. This tag may only contain
<literal><printer></literal> elements.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal><printer></literal></term>
<listitem>
<para>
This starts the definition of a printer. It must contain
the attributes <literal>name</literal> and
<literal>driver</literal>. <literal>name</literal> should
be is the full name of the printer, and must be human
readable. <literal>driver</literal> should consist of
alphanumerics and hyphens, and be fairly short.
<literal>name</literal> is what will appear in the
user-visible listing of printers, and may be translated
into the user's language, while <literal>driver</literal>
is what is actually used to key into the list of printers.
It is legal to have multiple printers with the same driver
name.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal><color></literal></term>
<listitem>
<para>
This tag may not contain any content, but the
<literal>value</literal> attribute may be set to
<literal>true</literal> or <literal>false</literal>. This
indicates that this printer is capable of color, or is not
capable of color respectively.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal><model></literal></term>
<listitem>
<para>
This defines a model number. This tag may not contain any
content, but the <literal>value</literal> attribute may be
set to a positive integer. This is passed into the
driver, which may do whatever it cares to with
it—index into a table, compute on, or whatever.
This need not be unique.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect1>
<sect1>
<title>The driver file</title>
<para>
Adding a new printer to a driver module
<filename>print-canon.c</filename>,
<filename>print-escp2.c</filename>,
<filename>print-lexmark.c</filename>, or
<filename>print-pcl.c</filename> or
(<filename>print-ps.c</filename> is really ad hoc) requires a
bit more planning. Each driver is somewhat different, but they
all generally have a vector of printer definitions, and the code
does some special casing based on particular printer
capabilities. The PCL and Canon drivers are quite similar; the
Canon driver was actually cribbed from the PCL driver, but it
then returned the favor.
</para>
<para>
The Epson driver is a little bit different. Canon and PCL
printers have some amount of intelligence; a lot of them have
specific ink options, and know about specific paper sizes and
types, and must be told the right thing. Epson printers have
somewhat less intelligence and will more or less do exactly what
the host tells it to do in a fairly regular fashion. I actually
prefer this; it isn't materially more work for the host to
compute things like exact paper sizes and such, it allows a lot
more tweaking, and it may be why Epson has been more open with
information—the communication protocol doesn't really
contain very much IP, so they have less reason to keep it
secret.
</para>
<para>
The sections about PCL and Canon printers need completing.
</para>
<sect2>
<title>Epson inkjet printers</title>
<para>
The <varname>model_capabilities</varname> vector in
<filename>print-escp2.c</filename> contains one entry for each
defined printer model. The <literal>model</literal> parameter
in <filename>printers.xml</filename> is an index into this
table.
</para>
<para>
In general, the new printers have fewer eccentricities than
the older printers. That doesn't mean they're simpler, just
that they're more consistent.
</para>
<para>
<type>escp2_printer_t</type> is a C struct defined as follows:
</para>
<informalexample>
<programlisting>typedef struct escp2_printer
{
model_cap_t flags; /* Bitmask of flags, see below */
/*****************************************************************************/
int nozzles; /* Number of nozzles per color */
int min_nozzles; /* Minimum number of nozzles per color */
int nozzle_separation; /* Separation between rows, in 1/360" */
int black_nozzles; /* Number of black nozzles (may be extra) */
int min_black_nozzles; /* # of black nozzles (may be extra) */
int black_nozzle_separation; /* Separation between rows */
/*****************************************************************************/
int xres; /* Normal distance between dots in */
/* softweave mode (inverse inches) */
int enhanced_xres; /* Distance between dots in highest */
/* quality modes */
int base_separation; /* Basic unit of row separation */
int base_resolution; /* Base hardware spacing (above this */
/* always requires multiple passes) */
int enhanced_resolution;/* Above this we use the */
/* enhanced_xres rather than xres */
int resolution_scale; /* Scaling factor for ESC(D command */
int max_black_resolution; /* Above this resolution, we */
/* must use color parameters */
/* rather than (faster) black */
/* only parameters*/
int max_hres;
int max_vres;
int min_hres;
int min_vres;
/*****************************************************************************/
int max_paper_width; /* Maximum paper width, in points */
int max_paper_height; /* Maximum paper height, in points */
int min_paper_width; /* Maximum paper width, in points */
int min_paper_height; /* Maximum paper height, in points */
/* Softweave: */
int left_margin; /* Left margin, points */
int right_margin; /* Right margin, points */
int top_margin; /* Absolute top margin, points */
int bottom_margin; /* Absolute bottom margin, points */
/* "Micro"weave: */
int m_left_margin; /* Left margin, points */
int m_right_margin; /* Right margin, points */
int m_top_margin; /* Absolute top margin, points */
int m_bottom_margin; /* Absolute bottom margin, points */
/*****************************************************************************/
int extra_feed; /* Extra distance the paper can be spaced */
/* beyond the bottom margin, in 1/360". */
/* (maximum useful value is */
/* nozzles * nozzle_separation) */
int separation_rows; /* Some printers require funky spacing */
/* arguments in microweave mode. */
int pseudo_separation_rows;/* Some printers require funky */
/* spacing arguments in softweave mode */
int zero_margin_offset; /* Offset to use to achieve */
/* zero-margin printing */
/*****************************************************************************/
/* The stylus 480 and 580 have an unusual arrangement of
color jets that need special handling */
const int *head_offset;
int initial_vertical_offset;
int black_initial_vertical_offset;
/*****************************************************************************/
const int *dot_sizes; /* Vector of dot sizes for resolutions */
const double *densities; /* List of densities for each printer */
const escp2_variable_inklist_t *inks; /* Choices of inks for this printer */
/*****************************************************************************/
const double *lum_adjustment;
const double *hue_adjustment;
const double *sat_adjustment;
const paperlist_t *paperlist;
} escp2_printer_t;</programlisting>
</informalexample>
<para>
The printer definition block is divided into 8 sections.
The first section is a set of miscellaneous printer options.
These are described in the code, and will not be discussed
further here.
</para>
<para>
The second section describes the number of nozzles and the
separation between nozzles in base units. The base unit is
1/360" for all currently supported printers, but future
printers may support a smaller base unit.
</para>
<para>
Many printers have more black nozzles than nozzles of other
colors, and when used in black and white mode, it's possible
to use these extra nozzles, which speeds up printing. As an
example, a printer that is specified to have 48 cyan, magenta,
and yellow nozzles, and 144 black nozzles, can use all 144
black nozzles when printing black ink only. When printing in
color, only 48 nozzles of each color (including black) can be
used.
</para>
<para>
Most printers can print using either the number of nozzles
available or any smaller number. Some printers require that
all of the nozzles be used. Those printers will set
<varname>min_nozzles</varname> and/or
<varname>min_black_nozzles</varname> to the same value as
<varname>nozzles</varname> and/or
<varname>black_nozzles</varname>.
</para>
<para>
The third section defines basic units of measure for the
printer, including the standard separation between dots, the
base nozzle separation, and the minimum and maximum printing
resolutions the printer supports. Most of these are fairly
self-explanatory, but some are not obvious.
</para>
<para>
Most Epson printers, other than the high-end Stylus Pro
models, cannot print dots spaced more closely than 1/360" or
1/720" apart (this is the setting for <varname>xres</varname>.
This is true even for printers that support resolutions of
1440 or 2880 DPI. In these cases, the data must be printed in
2, 4, or 8 passes. While the printer can position the head to
a resolution of 1/1440" or 1/2880", the head cannot deposit
ink that frequently.
</para>
<para>
Some printers can only print in their very best quality (using
the smallest dots available) printing at a lower resolution.
For example, the Stylus Photo EX can normally print with a dot
spacing of 1/720". The smallest dot size cannot be printed
with a dot spacing of less than 1/360", however. In this
case, we use <varname>enhanced_xres</varname> to specify the
resolution to be used in this enhanced mode, and
<varname>enhanced_resolution</varname> to specify the printing
resolution above which we use the
<varname>enhanced_xres</varname>.
</para>
<para>
The <varname>resolution_scale</varname> command is used to
specify scaling factors for the dot separation on newer
printers. It should always be 14400 with current printers.
</para>
<para>
The fourth section specifies the minimum and maximum paper
sizes, and the margins. Some printers allow use of narrower
margins when softweave is used; both sets of margins are
specified.
</para>
<para>
There is a convenient <function>INCH</function> macro defined
to make specification of the
<varname>max_paper_width</varname> and
<varname>max_paper_height</varname> more legible. It
multiplies <constant>72</constant> by the provided expression
to get the appropriate number of points. For example, to
specify 8.5", <literal>INCH(17/2)</literal> expands to
<literal>(72 * 17/2)</literal>, which is evaluated left to
right, and hence generates the correct value.
</para>
<para>
The fifth section specifies some miscellaneous values that are
required for certain printers. For most printers, the correct
values are <constant>1</constant> for
<varname>separation_rows</varname> and <constant>0</constant>
for the others. Very, very few printers require (or allow)
<varname>separation_rows</varname> to be anything but
<constant>1</constant> and
<varname>pseudo_separation_rows</varname> other than
<constant>0</constant>. The Stylus Color 1520, Stylus Color
800, Stylus Color 850, and (strangely enough to my mind, since
it's a newer printer) Stylus Color 660 seem to be the only
exceptions.
</para>
<para>
<varname>zero_margin_offset</varname> is used to specify an
additional negative horizontal offset required to print to the
edges of the paper on newer Stylus Photo printers. These must
be determined empirically; good starting values are
<constant>100</constant> for 1440 DPI and
<constant>50</constant> for 2880 DPI printers. The goal is to
print to the edge of the page, but not over it.
</para>
<para>
The sixth section specifies head offsets for printers that do
not have the color jets aligned. Certain printers, such as
the Stylus Color 480, have an unusual head arrangement whereby
instead of all of the colors being aligned vertically, the
nozzles are configured in groups. These printers are easy to
determine; if the normal head offset of zero for each color is
used, the printing will be vertically out of alignment. Most
of these printers require specification of a negative offset
for printing to the top edge of the paper; typically these
printers do not require such an offset when printing black
only.
</para>
<para>
The seventh section specifies the most difficult values to
tune, the dot sizes, printing densities, and ink values (for
variable dot size enabled printers). These will be described
in detail below.
</para>
<para>
The last section specifies luminosity, hue, and saturation
adjustment vectors for the printer, and the paper definitions.
These are used to adjust the color in
<emphasis>Photograph</emphasis> and <emphasis>Solid
Colors</emphasis> output modes. These are each vectors of 48
(actually 49, as the first value must be duplicated) doubles
that remap the luminosity, hue, and saturation respectively.
The hue is calculated, and the value used to interpolate
between the two closest points in each vector.
</para>
<para>
The paper definitions is a set of paper definitions. The
paper definition contains the name of the paper type, special
settings that are required for printers to process the paper
correctly, and a set of adjustment values. These are not
currently discussed here.
</para>
<para>
The lists of dot sizes and densities contain values for 13
printing modes: 120/180 DPI using printer weaving (single row;
incorrectly referred to as “microweave”) and
“soft” weaving (the driver determines the exact
pattern of dot layout), 360 DPI microweave and softweave,
720×360 DPI microweave and softweave, 720 DPI microweave
and softweave, 1440×720 microweave and softweave,
2880×720 microweave and softweave, and 2880×1440
softweave only. Printer weaving is referred to as
“microweave” for historical reasons.
</para>
<para>
For the dot sizes, the value for each element in the vector
selects the dot size to be used when printing at this (or
similar) resolution. The dot sizes are determined by
consulting the programming manual for the printer and
experimenting as described below. Current Epson printers
always use dot sizes less than <constant>16</constant>
(<constant>0x10</constant>), to indicate single dot size (each
dot is represented by 1 bit, and it's either printed or not),
and dot sizes of <constant>16</constant> or greater to
indicate variable dot size (each dot is represented by 2 bits,
and it can either be not printed or take on 2 or 3 values,
representing the relative size of the printed dot). Variable
dot sizes permit the use of very small dots (which would be
too small to fill the page and produce solid black) in light
areas, while allowing the page to be filled with larger dots
in darker areas.
</para>
<para>
Even single dot size printers can usually produce dots of
different sizes; it's just illegal to actually try to switch
dot size during a page. These dots are also much bigger than
those used in true variable dot size printing.
</para>
<para>
A dot size of <constant>-1</constant> indicates that this
resolution is illegal for the printer in question. Any
resolutions that would use this dot size will not be presented
to the user. A dot size of <constant>-2</constant> indicates
that this resolution is legal, but that the driver is not to
attempt to set any dot size. Some very old printers do not
support the command to set the dot size.
</para>
<para>
Most printers support a dot size of <constant>0</constant> as
a mode-specific default, but it's often a bigger dot than
necessary. Printers usually also support some dot sizes
between <constant>1</constant> and <constant>3</constant>.
Usually <constant>1</constant> is the right dot size for 720
and 1440 DPI printing, and <constant>3</constant> works best
at 360 DPI.
</para>
<para>
Variable dot size printers usually support 2 or 3 sets of
variable dot sizes. Older printers based on a 6 picolitre
drop (the 480, 720, 740, 750, 900, and 1200) support two: mode
16 (0x10 in hexadecimal) for normal variable dots at 1440 or
720 DPI, and mode 17 (0x10) for special larger dots at 360
DPI. Newer printers based on 4 picolitre drops normally
support three sizes: <constant>0x10</constant> for 4 pl base
drops, <constant>0x11</constant> for 6 pl base drops, and
<constant>0x12</constant> for special large drops. On these
printers, <constant>0x10</constant> usually works best at
1440×720 and <constant>0x11</constant> works best at
720×720. Unfortunately, <constant>0x10</constant>
doesn't seem to generate quite enough density at
720×720, because if it did the output would be very
smooth. Perhaps it's possible to tweak things…
</para>
<para>
The list of densities is a list of base density values for all
of the above listed modes. “Density” refers to
the amount of ink deposited when a solid color (or solid
black) is printed. So if the density is
<constant>0.5</constant>, solid black actually prints only
half the possible dots. “Base density” refers to
the fact that the density value can be scaled in the GUI or on
the Ghostscript command line. The density value specified
(which is not made visible to the user) is multiplied by the
base density to obtain the effective density value. All other
things (such as ink drop size) remaining the same, doubling
the resolution requires halving the base density. The base
density in the density vector may exceed
<constant>1</constant>, as many paper types require lower
density than the base driver. The driver ensures that the
actual density never exceeds <constant>1</constant>.
</para>
<para>
Tuning the density should be done on high quality paper
(usually glossy photo paper). The goal is to find the lowest
density value that results in solid black (no visible gaps
under a fairly high power magnifying glass or loupe). If an
appropriate density value is found for 720 DPI, it could be
divided by 2 for 1440×720, by 4 for 2880×720, and
by 8 for 2880×1440.
</para>
<para>
However, for printers that offer a choice of dot size, this
may not be the best strategy. The best choice for dot size is
the smallest dot size that allows choosing a density value not
greater than <constant>1</constant> that gives full coverage.
This dot size may be different for different resolutions.
Tuning variable dot size printers is more complicated; the
process is described below.
</para>
<para>
The last member is a pointer to a structure containing a list
of ink values for variable dot size (or 6 color) inks. We
model variable dot size inks as producing a certain
“value” of ink for each available dot size, where
the largest dot size has a value of <constant>1</constant>.
6-color inks are handled similarly; the light cyan and light
magenta inks are treated as a fractional ink value. The
combination of variable dot size and 6 color inks, of course,
just creates that many more different ink choices.
</para>
<para>
This structure is actually rather complicated; it contains
entries for each combination of physical printer resolution
(180, 360, 720, and 1440 DPI), ink colors (4, 6, and 7), and
single and variable dot sizes (since some printer modes can't
handle variable dot size inks). Since there's so much data,
it's actually a somewhat deeply nested structure.
</para>
<itemizedlist>
<listitem>
<para>
An <type>escp2_printer_t</type> contains a pointer
(essentially, a reference rather than a copy) to an
<type>escp2_variable_inklist_t</type>.
</para>
</listitem>
<listitem>
<para>
An <type>escp2_variable_inklist_t</type> contains pointers
to <type>escp2_variable_inkset_t</type> structures. There
is one such pointer for each combination of resolution,
dot type, and ink colors as described above. Yes, this is
rather inflexible.
</para>
</listitem>
<listitem>
<para>
An <type>escp2_variable_inkset_t</type> contains pointers
to <type>escp2_variable_ink_t</type> structures. There is
one such pointer for each of the four colors (C, M, Y, and
K).
</para>
</listitem>
<listitem>
<para>
An <type>escp2_variable_ink_t</type> contains a pointer to
the actual list of ink values
(<type>simple_dither_range_t</type>), the number of ink
values, and a density value to be used for computing the
transitions. This density value is actually a scaling
value; it is multiplied by the effective density to
compute the density to be used for computing the
transitions. Normally, this value is
<constant>1</constant>, but in some cases it may be
possible to get smoother results with a different value
(in particular, the single dot size 6-color inks work best
with the effective density scaled to
<constant>.75</constant> for this purpose). A lower
density lowers the transition points, which results in
more ink being deposited.
</para>
</listitem>
<listitem>
<para>
A <type>simple_dither_range_t</type> is a structure containing four values:
<itemizedlist>
<listitem>
<para>
The value of the particular ink
</para>
</listitem>
<listitem>
<para>
The bit pattern used to represent the ink
</para>
</listitem>
<listitem>
<para>
Whether the ink is light (0) or dark (1), for inks
with light and dark variants
</para>
</listitem>
<listitem>
<para>
The relative amount of ink actually deposited by
this dot (not currently used for much; it can be
used for ink reduction purposes, to reduce the
amount of ink deposited on the paper).
</para>
</listitem>
</itemizedlist>
</para>
<para>
These things are interesting as arrays. From an array of
<type>simple_dither_range_t</type>'s, the dither code
computes transition values that it looks up at run time to
decide what ink to print, as well as whether to print at
all.
</para>
</listitem>
</itemizedlist>
<para>
<emphasis>Really</emphasis> confused now? Yup. You'll
probably find it easier to simply read the code.
</para>
</sect2>
<sect2>
<title>Tuning the printer</title>
<para>
Now, how do you use all this to tune a printer? There are a
number of ways to do it; this one is my personal favorite.
</para>
<para>
There's a file named <filename>test/cyan-sweep.tif</filename>.
This consists of a thin bar of cyan sweeping from white to
almost pure cyan, and from pure cyan to black. The first
thing to do is to pick the appropriate
<type>simple_dither_range_t</type> (or create a whole new
<type>escp2_variable_inklist_t</type>) and comment out all but
the darkest ink (this means you'll be using the largest dots
of dark ink). At 8.5" width (the width of a letter-size piece
of paper), the bar will be 1/8" high. Printing it on wider or
narrower paper will change the height accordingly. Print it
width-wise across a piece of photo quality paper in line art
mode using ordered or adaptive hybrid dither. Do not use
photographic mode; the colors in photographic mode vary
non-linearly depending upon the presence of the three color
components, while in line art mode the colors are much purer.
Make sure that all the color adjustments are set to defaults
(1.0). Use the highest quality version of the print mode
you're testing to reduce banding and other artifacts. This is
much easier to do with the Gimp than with Ghostscript.
</para>
<para>
At this stage, you want to look for four things:
<orderedlist>
<listitem>
<para>
The black near the center of the line is solid, but not
more so than that.
</para>
</listitem>
<listitem>
<para>
The cyan immediately to the left of the black is
<emphasis>almost</emphasis> solid.
</para>
</listitem>
<listitem>
<para>
The dark cyan at the far right of the page is solid, but
not more so. You can try tuning the density so that it
isn't quite solid, then nudging up the density until it
is.
</para>
</listitem>
<listitem>
<para>
Both sweeps sweep smoothly from light to dark. In
particular, the dark half of the bar shouldn't visibly
change color; it should go smoothly from cyan to black.
</para>
</listitem>
</orderedlist>
</para>
<para>
Repeat this stage until you have everything just right. Use
the positioning entry boxes in the dialog to position each bar
exactly 1/8" further down the page. Adjacent bars will be
touching.
</para>
<para>
The next step is to uncomment out the second darkest dot size.
If you're using variable dots, use the second largest dot size
of the dark ink rather than the largest dot size of the light
ink. This will give you two inks.
</para>
<para>
When you recompile the plugin, you simply need to copy the new
executable into the correct place. You do not need to exit
and restart the Gimp.
</para>
<para>
Print another bar adjacent to the first one. Your goal is to
match the bar using a single dot size as closely as possible.
You'll find that the dark region of the bar shouldn't change
to any great degree, but the light half probably will. If the
lighter part of the light half is too dark, you need to
increase the value of the smaller dot; if it's too light, you
need to decrease the value. The reasoning is that if the
value is too low, the ink isn't being given enough credit for
its contribution to the darkness of the ink, and vice versa.
Repeat until you have a good match. Make sure you let the ink
dry fully, which will take a few minutes. Wet ink will look
too dark. Don't look at the paper too closely; hold it at a
distance. The extra graininess of the largest dot size will
probably make it look lighter than it should; if you hold it
far enough away so that you can't see the dots, you'll get a
more accurate picture of what's going on.
</para>
<para>
After you have what looks like a good match, print another bar
using only the largest dot size (or dark ink, for single dot
size 6-color printers). You want to ensure that the bars
touching each other look identical, or as close as possible to
it; your eye won't give you a good reading if the bars are
separated from each other. You'll probably have to repeat the
procedure.
</para>
<para>
The next step is to comment out all but the largest and
third-largest dot size, and repeat the procedure. When they
match, use all three dot sizes of dark ink. Again, the goal
is to match the single dot size.
</para>
<para>
You'll probably find the match is imperfect. Now you have to
figure out what region isn't right, which takes some
experimentation. Even small adjustments can make a noticeable
difference in what you see. At this stage, it's very
important to hold the page far enough from your eye; when you
use all three dot sizes, the texture will be much more even,
which sometimes makes it look darker and sometimes lighter.
</para>
<para>
After this is calibrated, it's time to calibrate the light ink
against the dark ink. To do this, comment out all but the
large dot version of the two inks, and repeat the procedure.
This is trickier, because the hues of the inks might not be
quite identical. Look at the dark half of the bar as well as
the light half to see that the hue really doesn't change as
you sweep from cyan to black. Sometimes it's easier to judge
that way. You may find that it looks blotchy, in which case
you should switch from ordered dither to adaptive hybrid.
</para>
<para>
After you have the light and dark inks calibrated against each
other, it's time to add everything back in. Usually you don't
want to use the largest dot size of light ink. These dots
will be much larger than the small dots of dark ink, but
they'll still be lighter. This will cause problems when
printing mixed colors, since you'll be depositing more ink on
lighter regions of the page, and you'll probably get strange
color casts that you can't get rid of in neutral tones. I
normally use only the smallest one or two dot sizes of light
ink.
</para>
<para>
After you've tweaked everything, print the color bar with
saturation set to zero. This will print neutral tones using
color inks. Your goal here is to look for neutral tonality.
If you're using a 6-color printer and get a yellow cast, it
means that the values for your light inks are too high
(remember, that means they're getting too much credit, so
you're not depositing enough cyan and magenta ink, and the
yellow dominates). If you get a bluish or bluish-purple cast,
your light inks are too low (you're not giving them enough
credit, so too much cyan and magenta is deposited, which
overwhelms the yellow). Make sure you do this on very white,
very high grade inkjet paper that's designed for
1440×720 DPI or higher; otherwise the ink will spread on
contact and you'll get values that aren't really true for high
grade paper. You can, of course, calibrate for low grade
paper if that's what you're going to use, but that shouldn't
be put into the distribution.
</para>
<para>
You can also fully desaturate this bar inside the Gimp and
print it as monochrome (don't print the cyan as monochrome;
the driver does funny things with luminance), for comparison.
You'll find it very hard to get rid of all color casts.
</para>
<para>
There are other ways of tuning printers, but this one works
pretty well for me.
</para>
</sect2>
<sect2>
<title>Canon inkjet printers</title>
<para>
Basically, a new Canon printer can be added to
<filename>print-canon.c</filename> in a similar way as
described above for the epson inkjet printers. The main
differences are noted here.
</para>
<para>
In general, Canon printers have more “built-in
intelligence“ than Epson printers which results in the
fact that the driver only has to tell the printing conditions
like resolutions, dot sizes, etc. to the printer and
afterwards transfer the raster data line by line for each
color used.
</para>
<para>
<type>canon_cap_t</type> is a C struct defined as follows:
</para>
<informalexample>
<programlisting>typedef struct canon_caps {
int model; /* model number as used in printers.xml */
int max_width; /* maximum printable paper size */
int max_height;
int base_res; /* base resolution - shall be 150 or 180 */
int max_xdpi; /* maximum horizontal resolution */
int max_ydpi; /* maximum vertical resolution */
int max_quality;
int border_left; /* left margin, points */
int border_right; /* right margin, points */
int border_top; /* absolute top margin, points */
int border_bottom; /* absolute bottom margin, points */
int inks; /* installable cartridges (CANON_INK_*) */
int slots; /* available paperslots */
int features; /* special bjl settings */
canon_dot_size_t dot_sizes; /* Vector of dot sizes for resolutions */
canon_densities_t densities; /* List of densities for each printer */
canon_variable_inklist_t *inxs; /* Choices of inks for this printer */
} canon_cap_t;</programlisting>
</informalexample>
<para>
Since there are Canon printers which print in resolutions of
2<superscript>n</superscript> × 150 DPI (e.g. 300, 600,
1200) and others which support resolutions of
2<superscript>n</superscript> × 180 DPI (e.g. 360, 720,
1440), there's a base resolution (150 or 180, respectively)
given in the <type>canon_cap_t</type>. The structs
<type>canon_dot_size_t</type>, <type>canon_densities_t</type>
and <type>canon_variable_inklist_t</type> refer to resolutions
being multiples of the base resolution.
</para>
<para>
For the Canon driver, the struct <type>canon_dot_size_t</type>
holds values for a model's capabilities at a given resolution,
or <constant>-1</constant> if the resolution is not supported.
<constant>0</constant> if it can be used and
<constant>1</constant> if the resolution can be used for
variable dot size printing.
</para>
<para>
In <type>canon_densities_t</type> the base densities for each
resolution can be specified like for an epson printer. The
same holds true for <type>canon_variable_inklist_t</type>.
See the descriptions above to learn about how to adjust your
model's output to yield nice results.
</para>
<para>
There's a slight difference though in the way the Canon driver
and the escp2 driver define their variable inklists: In the
Canon driver, you need to define an inklist like this:
</para>
<informalexample>
<programlisting>static const canon_variable_inklist_t canon_ink_myinks[] =
{
{
1,4, /* 1bit/pixel, 4 colors */
&ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
&ci_CMYK_1, &ci_CMYK_1, &ci_CMYK_1,
},
{
3,4, /* 3bit/pixel, 4 colors */
&ci_CMYK_3, &ci_CMYK_3, &ci_CMYK_3,
&ci_CMYK_3, &ci_CMYK_3, &ci_CMYK_3,
},
};</programlisting>
</informalexample>
<para>
where the <literal>&ci_CMYK_1</literal> and
<literal>&ci_CMYK_3</literal> entries are references to a
previously defined const of type
<type>canon_variable_inkset_t</type>.
</para>
</sect2>
</sect1>
</chapter>
|