summaryrefslogtreecommitdiff
path: root/doc/developer/reference-html/x1734.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/developer/reference-html/x1734.html')
-rw-r--r--doc/developer/reference-html/x1734.html1922
1 files changed, 1922 insertions, 0 deletions
diff --git a/doc/developer/reference-html/x1734.html b/doc/developer/reference-html/x1734.html
new file mode 100644
index 0000000..8c52bfd
--- /dev/null
+++ b/doc/developer/reference-html/x1734.html
@@ -0,0 +1,1922 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
+<HTML
+><HEAD
+><TITLE
+>Weaving algorithms</TITLE
+><META
+NAME="GENERATOR"
+CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK
+REL="HOME"
+TITLE="The Developer's Guide to Gutenprint"
+HREF="index.html"><LINK
+REL="UP"
+TITLE="Weaving for inkjet printers"
+HREF="c1717.html"><LINK
+REL="PREVIOUS"
+TITLE="Weaving for inkjet printers"
+HREF="c1717.html"><LINK
+REL="NEXT"
+TITLE="Dithering"
+HREF="c1968.html"></HEAD
+><BODY
+CLASS="sect1"
+BGCOLOR="#FFFFFF"
+TEXT="#000000"
+LINK="#0000FF"
+VLINK="#840084"
+ALINK="#0000FF"
+><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="c1717.html"
+ACCESSKEY="P"
+>Prev</A
+></TD
+><TD
+WIDTH="80%"
+ALIGN="center"
+VALIGN="bottom"
+>Chapter 6. Weaving for inkjet printers</TD
+><TD
+WIDTH="10%"
+ALIGN="right"
+VALIGN="bottom"
+><A
+HREF="c1968.html"
+ACCESSKEY="N"
+>Next</A
+></TD
+></TR
+></TABLE
+><HR
+ALIGN="LEFT"
+WIDTH="100%"></DIV
+><DIV
+CLASS="sect1"
+><H1
+CLASS="sect1"
+><A
+NAME="AEN1734"
+>6.2. Weaving algorithms</A
+></H1
+><P
+>&#13; I considered a few algorithms to perform the weave. The first
+ one I devised let me use only (jets &#8722;
+ distance_between_jets + 1) nozzles, or 25. This is OK in
+ principle, but it's slower than using all nozzles. By playing
+ around with it some more, I came up with an algorithm that lets
+ me use all of the nozzles, except near the top and bottom of the
+ page.
+ </P
+><P
+>&#13; This still produces some banding, though. Even better quality
+ can be achieved by using multiple nozzles on the same line. How
+ do we do this? In 1440×720 mode, we're printing two
+ output lines at the same vertical position. However, if we want
+ four passes, we have to effectively print each line twice.
+ Actually doing this would increase the density, so what we do is
+ print half the dots on each pass. This produces near-perfect
+ output, and it's far faster than using (pseudo)
+ &#8220;MicroWeave&#8221;.
+ </P
+><P
+>&#13; Yet another complication is how to get near the top and bottom
+ of the page. This algorithm lets us print to within one head
+ width of the top of the page, and a bit more than one head width
+ from the bottom. That leaves a lot of blank space. Doing the
+ weave properly outside of this region is increasingly difficult
+ as we get closer to the edge of the paper; in the interior
+ region, any nozzle can print any line, but near the top and
+ bottom edges, only some nozzles can print. We originally
+ handled this by using the naive way mentioned above near the
+ borders, and switching over to the high quality method in the
+ interior. Unfortunately, this meant that the quality is quite
+ visibly degraded near the top and bottom of the page. We have
+ since devised better algorithms that allow printing to the
+ extreme top and bottom of the region that can physically be
+ printed, with only minimal loss of quality.
+ </P
+><P
+>&#13; Epson does not advertise that the printers can print at the very
+ top of the page, although in practice most of them can. The
+ quality is degraded to some degree, and we have observed that in
+ some cases not all of the dots get printed. Epson may have
+ decided that the degradation in quality is sufficient that
+ printing in that region should not be allowed. That is a valid
+ decision, although we have taken another approach.
+ </P
+><DIV
+CLASS="sect2"
+><H2
+CLASS="sect2"
+><A
+NAME="AEN1740"
+>6.2.1. Simple weaving algorithms</A
+></H2
+><P
+>&#13; The initial problem is to calculate the starting position of
+ each pass; the row number of the printer's top jet when
+ printing that pass. Since we assume the paper cannot be
+ reverse-fed, the print head must, for each pass, start
+ either further down the page than the previous pass or at
+ the same position. Each pass's start point is therefore at
+ a non-negative offset from the previous pass's start point.
+ </P
+><P
+>&#13; Once we have a formula for the starting row of each pass, we
+ then turn that &#8220;inside out&#8221; to get a formula for
+ the pass number containing each row.
+ </P
+><P
+>&#13; First, let's define how our printer works. We measure
+ vertical position on the paper in &#8220;rows&#8221;; the
+ resolution with which the printer can position the paper
+ vertically. The print head contains J ink jets, which are
+ spaced S rows apart.
+ </P
+><P
+>&#13; Consider a very simple case: we want to print a page as
+ quickly as possible, and we mostly don't care how sparse the
+ printing is, so long as it's fairly even.
+ </P
+><P
+>&#13; It's pretty obvious how to do this. We make one pass with
+ the print head, printing J lines of data, each line S rows
+ after the previous one. We then advance the paper by S
+ × J rows and print the next row. For example, if J =
+ 7 and S = 4, this method can be illustrated like this:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1747"
+></A
+><PRE
+CLASS="screen"
+>pass number
+| row number-------&#62;
+| | 111111111122222222223333333333444444444455555555556666666666
+| 0123456789012345678901234567890123456789012345678901234567890123456789
+0 *---*---*---*---*---*---*
+1 *---*---*---*---*---*---*
+2 \-----------------------/ *---*---*---*---*---*-
+ 7 jets \---/
+ 4 rows offset from one jet to the next
+\---------------------------/
+ 7*4=28 rows offset from one pass to the next</PRE
+><P
+></P
+></DIV
+><P
+>&#13; In these examples, the vertical axis can be thought of as the
+ time axis, with the pass number shown at the left margin,
+ while the row number runs horizontally. A
+ <SAMP
+CLASS="computeroutput"
+>*</SAMP
+> shows each row printed by a
+ pass, and a row of <SAMP
+CLASS="computeroutput"
+>-</SAMP
+> is used
+ to link together the rows printed by one pass of the print
+ head. The first pass is numbered
+ <SAMP
+CLASS="computeroutput"
+>0</SAMP
+> and starts at row 0. Each
+ subsequent pass p starts at row p × S × J. Each
+ pass prints J lines, each line being S rows after the previous
+ one. (For ease of viewing this file on a standard terminal,
+ I'm clipping the examples at column 80.)
+ </P
+><P
+>&#13; This method covers the whole page with lines printed evenly
+ S rows apart. However, we want to fill in all the other
+ rows with printing to get a full-density page (we're
+ ignoring oversampling at this stage). Where we have
+ previously printed a single pass, we'll now print a
+ &#8220;pass block&#8221;: we print extra passes to fill in
+ the empty rows. A naive implementation might look like
+ this:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1754"
+></A
+><PRE
+CLASS="screen"
+>0 *---*---*---*---*---*---*
+1 *---*---*---*---*---*---*
+2 *---*---*---*---*---*---*
+3 *---*---*---*---*---*---*
+4 *---*---*---*---*---*---*
+5 *---*---*---*---*---*---*
+6 *---*---*---*---*---*---*
+7 *---*---*---*---*---*---*
+8 *---*---*---*---*---*-
+9 *---*---*---*---*---*
+10 *---*---*---*---*---
+11 *---*---*---*---*--</PRE
+><P
+></P
+></DIV
+><P
+>&#13; (Now you can see why this process is called
+ &#8220;weaving&#8221;!)
+ </P
+></DIV
+><DIV
+CLASS="sect2"
+><H2
+CLASS="sect2"
+><A
+NAME="AEN1757"
+>6.2.2. Perfect weaving</A
+></H2
+><P
+>&#13; This simple weave pattern prints every row, but will give
+ conspicuous banding patterns for the reasons discussed
+ above.
+ </P
+><P
+>&#13; Let's start improving this for our simple case. We can
+ reduce banding by making sure that any given jet never
+ prints a row too close to another row printed by the same
+ jet. This means we want to space the rows printed by a
+ given jet evenly down the page. In turn, this implies we
+ want to advance the paper by as nearly an equal amount after
+ each pass as possible.
+ </P
+><P
+>&#13; Each pass block prints S × J lines in S passes. The
+ first line printed in each pass block is S × J rows
+ lower on the page than the first line printed in the
+ previous pass block. Therefore, if we advance the paper by
+ J rows between each pass, we can print the right number of
+ passes in each block and advance the paper perfectly evenly.
+ </P
+><P
+>&#13; Here's what this &#8220;perfect&#8221; weave looks like:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1763"
+></A
+><PRE
+CLASS="screen"
+> start of full weave
+ |
+0 *---*---*---*---*---*---*
+1 *---*---*---*---*---*---*
+2 *---*---*---*---*---*---*
+3 *---*---*---*---*---*---*
+4 *---*---*---*---*---*---*
+5 *---*---*---*---*---*---*
+6 *---*---*---*---*---*---*
+7 *---*---*---*---*---*---*
+8 *---*---*---*---*---*-
+9 *---*---*---*--
+10 *---*---
+11 *</PRE
+><P
+></P
+></DIV
+><P
+>&#13; You'll notice that, for the first few rows, this weave is
+ too sparse. It is not until the row marked &#8220;start of
+ full weave&#8221; that every subsequent row is printed. We
+ can calculate this start position as follows:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1766"
+></A
+><PRE
+CLASS="screen"
+>start = (S &#8722; 1) × (J &#8722; 1)</PRE
+><P
+></P
+></DIV
+><P
+>&#13; For the moment, we will ignore this problem with the weave.
+ We'll consider later how to fill in the missing rows.
+ </P
+><P
+>&#13; Let's look at a few more examples of perfect weaves:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1770"
+></A
+><P
+>&#13; S = 2, J = 7, start = (2&#8722;1) × (7&#8722;1) = 6:
+ </P
+><PRE
+CLASS="screen"
+> starting row of full weave
+ |
+0 *-*-*-*-*-*-*
+1 *-*-*-*-*-*-*
+2 *-*-*-*-*-*-*
+3 *-*-*-*-*-*-*
+4 *-*-*-*-*-*-*
+5 *-*-*-*-*-*-*
+6 *-*-*-*-*-*-*
+7 *-*-*-*-*-*-*</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1773"
+></A
+><P
+>&#13; S = 7, J = 2, start = 6:
+ </P
+><PRE
+CLASS="screen"
+> start
+ |
+0 *------*
+1 *------*
+2 *------*
+3 *------*
+4 *------*
+5 *------*
+6 *------*
+7 *------*
+8 *------*
+9 *------*</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1776"
+></A
+><P
+>&#13; S = 4, J = 13, start = 36:
+ </P
+><PRE
+CLASS="screen"
+> start
+ |
+0 *---*---*---*---*---*---*---*---*---*---*---*---*
+1 *---*---*---*---*---*---*---*---*---*---*---*---*
+2 *---*---*---*---*---*---*---*---*---*---*---*---*
+3 *---*---*---*---*---*---*---*---*---*--
+4 *---*---*---*---*---*---*-
+5 *---*---*---*</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1779"
+></A
+><P
+>&#13; S = 13, J = 4, start = 36:
+ </P
+><PRE
+CLASS="screen"
+> start
+ |
+0 *------------*------------*------------*
+1 *------------*------------*------------*
+2 *------------*------------*------------*
+3 *------------*------------*------------*
+4 *------------*------------*------------*
+5 *------------*------------*------------*
+6 *------------*------------*------------*
+7 *------------*------------*------------*
+8 *------------*------------*------------*
+9 *------------*------------*------------*
+10 *------------*------------*-----------
+11 *------------*------------*-------
+12 *------------*------------*---
+13 *------------*------------
+14 *------------*--------
+15 *------------*----
+16 *------------*
+17 *---------
+18 *-----
+19 *-</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1782"
+></A
+><P
+>&#13; S = 8, J = 5, start = 28:
+ </P
+><PRE
+CLASS="screen"
+> start
+ |
+0 *-------*-------*-------*-------*
+1 *-------*-------*-------*-------*
+2 *-------*-------*-------*-------*
+3 *-------*-------*-------*-------*
+4 *-------*-------*-------*-------*
+5 *-------*-------*-------*-------*
+6 *-------*-------*-------*-------*
+7 *-------*-------*-------*-------*
+8 *-------*-------*-------*-------*
+9 *-------*-------*-------*-------*
+10 *-------*-------*-------*---
+11 *-------*-------*------
+12 *-------*-------*-
+13 *-------*----
+14 *-------
+15 *--</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1785"
+></A
+><P
+>&#13; S = 9, J = 5, start = 32:
+ </P
+><PRE
+CLASS="screen"
+> start
+ |
+0 *--------*--------*--------*--------*
+1 *--------*--------*--------*--------*
+2 *--------*--------*--------*--------*
+3 *--------*--------*--------*--------*
+4 *--------*--------*--------*--------*
+5 *--------*--------*--------*--------*
+6 *--------*--------*--------*--------*
+7 *--------*--------*--------*--------*
+8 *--------*--------*--------*--------*
+9 *--------*--------*--------*-----
+10 *--------*--------*--------*
+11 *--------*--------*----
+12 *--------*--------
+13 *--------*---
+14 *-------
+15 *--</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1788"
+></A
+><P
+>&#13; S = 6, J = 7, start = 30:
+ </P
+><PRE
+CLASS="screen"
+> start
+ |
+0 *-----*-----*-----*-----*-----*-----*
+1 *-----*-----*-----*-----*-----*-----*
+2 *-----*-----*-----*-----*-----*-----*
+3 *-----*-----*-----*-----*-----*-----*
+4 *-----*-----*-----*-----*-----*-----*
+5 *-----*-----*-----*-----*-----*-----*
+6 *-----*-----*-----*-----*-----*-----
+7 *-----*-----*-----*-----*----
+8 *-----*-----*-----*---
+9 *-----*-----*--
+10 *-----*-
+11 *</PRE
+><P
+></P
+></DIV
+></DIV
+><DIV
+CLASS="sect2"
+><H2
+CLASS="sect2"
+><A
+NAME="AEN1791"
+>6.2.3. Weaving collisions</A
+></H2
+><P
+>&#13; A perfect weave is not possible in all cases. Let's look at
+ another example:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1794"
+></A
+><P
+>&#13; S = 6, J = 4:
+ </P
+><PRE
+CLASS="screen"
+>0 *-----*-----*-----*
+1 *-----*-----*-----*
+2 *-----*-----*-----*
+3 *-----*-----*-----*
+4 ^ *-^---*-----*-----*
+5 | ^ | *-^---*-----*-----*
+ OUCH! ^ | ^
+ | |</PRE
+><P
+></P
+></DIV
+><P
+>&#13; Here we have a collision. Some lines printed in later
+ passes overprint lines printed by earlier passes. We can
+ see why by considering which row number is printed by a
+ given jet number j (numbered from 0) of a given pass, p:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1798"
+></A
+><PRE
+CLASS="screen"
+>row(p, j) = (p × J) + (j × S)</PRE
+><P
+></P
+></DIV
+><P
+>&#13; Because J = 4 and S = 6 have a common factor of 2, jet 2 of
+ pass 0 prints the same row as jet 0 of pass 3:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1801"
+></A
+><PRE
+CLASS="screen"
+>row(0, 2) = (0 × 4) + (2 × 6) = 12
+row(3, 0) = (3 × 4) + (0 × 6) = 12</PRE
+><P
+></P
+></DIV
+><P
+>&#13; In fact, with this particular weave pattern, jets 0 and 1 of
+ pass p + 3 always overprint jets 2 and 3 of pass p. We'll
+ represent overprinting rows by a
+ <SAMP
+CLASS="computeroutput"
+>^</SAMP
+> in our diagrams, and
+ correct rows by <SAMP
+CLASS="computeroutput"
+>*</SAMP
+>:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1806"
+></A
+><P
+>&#13; S = 6, J = 4:
+ </P
+><PRE
+CLASS="screen"
+>0 *-----*-----*-----*
+1 *-----*-----*-----*
+2 *-----*-----*-----*
+3 ^-----^-----*-----*
+4 ^-----^-----*-----*
+5 ^-----^-----*-----*</PRE
+><P
+></P
+></DIV
+></DIV
+><DIV
+CLASS="sect2"
+><H2
+CLASS="sect2"
+><A
+NAME="AEN1809"
+>6.2.4. What makes a &#8220;perfect&#8221; weave?</A
+></H2
+><P
+>&#13; So what causes the perfect weave cases to be perfect, and
+ the other cases not to be? In all the perfect cases above,
+ S and J are relatively prime (i.e. their greatest common
+ divisor (GCD) is 1). As we mentioned above, S = 6 and J = 4
+ have a common factor, which causes the overprinting. Where
+ S and J have a GCD of 1, they have no common factor other
+ than 1 and, as a result, no overprinting occurs. If S and J
+ are not relatively prime, their common factor will cause
+ overprinting.
+ </P
+><P
+>&#13; We can work out the greatest common divisor of a pair of
+ natural numbers using Euler's algorithm:
+ </P
+><P
+></P
+><OL
+TYPE="1"
+><LI
+><P
+>&#13; Start with the two numbers: (e.g.) 9, 24
+ </P
+></LI
+><LI
+><P
+>&#13; Swap them if necessary so that the larger one comes
+ first: 24, 9
+ </P
+></LI
+><LI
+><P
+>&#13; Subtract the second number from the first: 15, 9
+ </P
+></LI
+><LI
+><P
+>&#13; Repeat until the first number becomes smaller: 6, 9
+ </P
+></LI
+><LI
+><P
+>&#13; Swap the numbers again, so the larger one comes first:
+ 9, 6
+ </P
+></LI
+><LI
+><P
+>&#13; Subtract again: 3, 6
+ </P
+></LI
+><LI
+><P
+>&#13; Swap: 6, 3
+ </P
+></LI
+><LI
+><P
+>&#13; Subtract: 3, 3
+ </P
+></LI
+><LI
+><P
+>&#13; And again: 0, 3
+ </P
+></LI
+><LI
+><P
+>&#13; When one of the numbers becomes 0, the other number is
+ the GCD of the two numbers you started with.
+ </P
+></LI
+></OL
+><P
+>&#13; These repeated subtractions can be done with C's <TT
+CLASS="literal"
+>%</TT
+>
+ operator, so we can write this in C as follows:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1836"
+></A
+><PRE
+CLASS="programlisting"
+>unsigned int
+gcd(unsigned int x, unsigned int y)
+{
+ if (y == 0)
+ return x;
+ while (x != 0) {
+ if (y &#62; x)
+ swap (&#38;x, &#38;y);
+ x %= y;
+ }
+ return y;
+}</PRE
+><P
+></P
+></DIV
+><P
+>&#13; <TT
+CLASS="literal"
+>gcd(S,J)</TT
+> will feature quite prominently in our
+ weaving algorithm.
+ </P
+><P
+>&#13; If 0 &#8804; j &#60; J, there should only be a single pair (p, j)
+ for any given row number. If S and J are not relatively
+ prime, this assumption breaks down. (For conciseness, let G
+ = GCD(S,J).)
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1841"
+></A
+><P
+>&#13; S = 8, J = 6, G = 2:
+ </P
+><PRE
+CLASS="screen"
+>0 *-------*-------*-------*-------*-------*
+1 *-------*-------*-------*-------*-------*
+2 *-------*-------*-------*-------*-------*
+3 *-------*-------*-------*-------*-------*
+4 ^-------^-------^-------*-------*-------*
+5 ^-------^-------^-------*-------*-------*</PRE
+><P
+></P
+></DIV
+><P
+>&#13; In this case, jets 0, 1 and 2 of pass p + 4 collide with
+ jets 3, 4 and 5 of pass p.
+ </P
+><P
+>&#13; How can we calculate these numbers? Suppose we were to
+ print using fewer jets, say J / G jets. The greatest common
+ divisor of J / G and S is 1, enabling a perfect weave. But
+ to get a perfect weave, we also have to advance the paper by
+ a factor of G less:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1846"
+></A
+><PRE
+CLASS="screen"
+>0 *-------*-------* - - -
+1 *-------*-------* - - -
+2 *-------*-------* - - -
+3 *-------*-------* - - -
+4 *-------*-------* - - -
+5 *-------*-------* - - -</PRE
+><P
+></P
+></DIV
+><P
+>&#13; If we left the paper advance alone, we'd get a sparse weave;
+ only one row can be printed every G rows:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1849"
+></A
+><PRE
+CLASS="screen"
+>0 *-------*-------* - - -
+1 *-------*-------* - - -
+2 *-------*-------* - - -
+3 *-------*-------* - - -
+4 *-------*-------* - - -
+5 *-------*-------* - - -
+ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
+ These rows need filling in.</PRE
+><P
+></P
+></DIV
+><P
+>&#13; The rows that would have been printed by the jets we've now
+ omitted (shown as <SAMP
+CLASS="computeroutput"
+>-</SAMP
+>) are
+ printed by other jets on later passes.
+ </P
+><P
+>&#13; Let's analyse this. Consider how a pass p could collide
+ with pass 0. Pass p starts at offset p × J. Pass 0
+ prints at rows which are multiples of S. If p × J is
+ exactly divisible by S, a collision has occurred, unless (p
+ ×J) &#8805; J × S (which will happen when we
+ finish a pass block).
+ </P
+><P
+>&#13; So, we want to find p and q such that p × J = q
+ × S and p is minimised. Then p is the number of rows
+ before a collision, and q is the number of jets in pass 0
+ which are not involved in the collision. To do this, we
+ find the lowest common multiple of J and S, which is L = (J
+ × S) / G. L / J is the number of rows before a
+ collision, and L / S is the number of jets in the first pass
+ not involved in the collision.
+ </P
+><P
+>&#13; Thus, we see that the first J / G rows printed by a given
+ pass are not overprinted by any later pass. However, the
+ rest of the rows printed by pass p are overprinted by the
+ first J &#8722; (J / G) jets of pass p + (S / G). We will
+ use C to refer to S / G, the number of rows after which a
+ collision occurs.
+ </P
+><P
+>&#13; Another example:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1857"
+></A
+><P
+>&#13; S = 6, J = 9, G = 3, C = S / G = 2:
+ </P
+><PRE
+CLASS="screen"
+>0 *-----*-----*-----*-----*-----*-----*-----*-----*
+1 *-----*-----*-----*-----*-----*-----*-----*-----*
+2 ^-----^-----^-----^-----^-----^-----*-----*-----*
+3 ^-----^-----^-----^-----^-----^-----*-----*-----*
+4 ^-----^-----^-----^-----^-----^-----*-----
+5 ^-----^-----^-----^-----^-----^--
+ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^
+ These rows need filling in.</PRE
+><P
+></P
+></DIV
+><P
+>&#13; In this case, the first J &#8722; (J / G) = 9 &#8722; (9 /
+ 3) = 6 jets of pass p + (6 / 3) = p + 2 collide with the
+ last 6 jets of pass p. Only one row in every G = 2 rows is
+ printed by this weave.
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1861"
+></A
+><P
+>&#13; S = 9, J = 6, G = 3, C = 3:
+ </P
+><PRE
+CLASS="screen"
+>&#13;0 *--------*--------*--------*--------*--------*
+1 *--------*--------*--------*--------*--------*
+2 *--------*--------*--------*--------*--------*
+3 ^--------^--------^--------^--------*--------*
+4 ^--------^--------^--------^--------*--------*
+5 ^--------^--------^--------^--------*--------*</PRE
+><P
+>&#13; Here, the first J - (J / G) = 6 - (6 / 3) = 4 jets of pass
+ p + (9 / 3) = p + 3 collide with the last 4 jets of pass
+ p.
+ </P
+><P
+>&#13; Note that, in these overprinting cases, only rows
+ divisible by G are ever printed. The other rows, those
+ not divisible by G, are not touched by this weave.
+ </P
+><P
+>&#13; We can modify our weave pattern to avoid overprinting any
+ rows and simultaneously fill in the missing rows. Instead
+ of using J alone to determine the start of each pass from
+ the previous pass, we adjust the starting position of some
+ passes. As mentioned before, we will divide the page into
+ pass blocks, with S passes in each block. This ensures
+ that the first jet of the first pass in a block prints the
+ row which the Jth jet of the first pass of the previous
+ block would have printed, if the print head had one extra
+ jet.
+ </P
+><P
+>&#13; Looking back at an example of a perfect weave, we can
+ divide it into pass blocks:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1868"
+></A
+><P
+>&#13; S = 7, J = 2, G = 1:
+ </P
+><PRE
+CLASS="screen"
+> imaginary extra jet
+ |
+0 *------* * &#60;--start of pass block 0
+1 *------* |
+2 *------* |
+3 *------*|
+4 *-----|*
+5 *---|--*
+6 *-|----*
+ |
+7 *------* &#60;--start of pass block 1
+8 *------*
+9 *------*</PRE
+><P
+></P
+></DIV
+><P
+>&#13; We can now calculate the start of a given pass by
+ reference to its pass block. The first pass of pass block
+ b always starts at row (b × S × J). The start
+ row of each of the other passes in the block are
+ calculated using offsets from this row.
+ </P
+><P
+>&#13; For the example above, there are 7 passes in each pass
+ block, and their offsets are 0, 2, 4, 6, 8, 10 and 12.
+ The next pass block is offset S × J = 14 rows from
+ the start of the current pass block.
+ </P
+><P
+>&#13; The simplest way to modify the &#8220;perfect&#8221; weave
+ pattern to give a correct weave in cases where G &#8800; 1
+ is to simply change any offsets which would result in a
+ collision, until the collision disappears. Every printed
+ row in the weave, as we have shown it up to now, is
+ separated from each of its neighbouring printed rows by G
+ blank rows. We will add an extra offset to each colliding
+ pass in such a way that we push the pass onto these
+ otherwise blank rows.
+ </P
+><P
+>&#13; We have seen that, unless G = 1, the plain weave pattern
+ results in each pass colliding with the pass S / G passes
+ before. We will now subdivide our pass block into
+ subblocks, each consisting of B = S / G passes. There are
+ therefore G subblocks in a pass block.
+ </P
+><P
+>&#13; For each subblock, the passes in that subblock have a
+ constant offset added to them. The offset is different
+ for each subblock in a block. There are many ways we can
+ choose the offsets, but the simplest is to make the offset
+ equal to the subblock number (starting from 0).
+ </P
+><P
+>&#13; Thus, the passes in the first subblock in each pass block
+ remain at the offsets we've already calculated from J.
+ The passes in the second subblock each have 1 added to
+ their offset, the passes in the third subblock have 2
+ added, and so on. Thus, the offset of pass p (numbered
+ relative to the start of its pass block) is p × J +
+ floor(p / B).
+ </P
+><P
+>&#13; This gives us a weave pattern looking like this:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1878"
+></A
+><P
+>&#13; S = 6, J = 9, G = 3, B = 2:
+ </P
+><PRE
+CLASS="screen"
+>0 *-----*-----*-----*-----*-----*-----*-----*-----*
+1 ^ *-----*-----*-----*-----*-----*-----*-----*-----*
+2 | +-&#62; *-----*-----*-----*-----*-----*-----*-----*-----*
+3 | | *-----*-----*-----*-----*-----*-----*-----*-----*
+4 | | +-&#62; *-----*-----*-----*-----*-----*-----*---
+5 | | | *-----*-----*-----*-----*-----*
+6 | | | +-&#62; *-----*-----*-----*-----
+7 | | | | *-----*-----*--
+ | | | start of pass block 1
+ | | | (offset returns to 0)
+ | | start of subblock 2 (offset 2 rows)
+ | start of subblock 1 (following passes offset by 1 row)
+start of passblock 0, subblock 0 (pass start calculated as p*J)</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1881"
+></A
+><P
+>&#13; S = 9, J = 6, G = 3, B = 3:
+ </P
+><PRE
+CLASS="screen"
+>0 *--------*--------*--------*--------*--------*
+1 *--------*--------*--------*--------*--------*
+2 *--------*--------*--------*--------*--------*
+3 *--------*--------*--------*--------*--------*
+4 *--------*--------*--------*--------*--------*
+5 *--------*--------*--------*--------*--------*
+6 *--------*--------*--------*--------*---
+7 *--------*--------*--------*------
+8 *--------*--------*--------*
+9 *--------*--------*-----
+10 \---/ *--------*--------
+11 small offset *--------*--
+12 *----</PRE
+><P
+></P
+></DIV
+><P
+>&#13; This method of choosing offsets for subblocks can result
+ in an occasional small offset (as shown above) between one
+ pass and the next, particularly when G is large compared
+ to J. For example:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1885"
+></A
+><P
+>&#13; S = 8, J = 4, G = 4, B = 2:
+ </P
+><PRE
+CLASS="screen"
+>0 *-------*-------*-------*
+1 *-------*-------*-------*
+2 *-------*-------*-------*
+3 *-------*-------*-------*
+4 *-------*-------*-------*
+5 *-------*-------*-------*
+6 *-------*-------*-------*
+7 *-------*-------*-------*
+8 *-------*-------*-------*
+9 \/ *-------*-------*-------*
+ very small offset!</PRE
+><P
+></P
+></DIV
+><P
+>&#13; We can plot the offset against the subblock number as
+ follows:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1889"
+></A
+><PRE
+CLASS="screen"
+>subblock number
+| offset
+| |
+| 0123
+0 *
+1 *
+2 *
+3 *
+0 *
+1 *
+2 *
+3 *</PRE
+><P
+></P
+></DIV
+><P
+>&#13; The discontinuity in this plot results in the small offset
+ between passes.
+ </P
+><P
+>&#13; As we said at the beginning, we want the offsets from each
+ pass to the next to be as similar as possible. We can fix
+ this by calculating the offset for a given subblock b as
+ follows:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1893"
+></A
+><PRE
+CLASS="screen"
+>offset(b) = 2*b , if b &#60; ceiling(G/2)
+ = 2*(G-b)-1 , otherwise</PRE
+><P
+></P
+></DIV
+><P
+>&#13; We can visualise this as follows, for G = 10:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1896"
+></A
+><PRE
+CLASS="screen"
+>0123456789
+0 *
+1 *
+2 *
+3 *
+4 *
+5 *
+6 *
+7 *
+8 *
+9 *
+0 *
+1 *
+2 *
+3 *
+4 *
+5 *
+6 *
+7 *
+8 *
+9 *</PRE
+><P
+></P
+></DIV
+><P
+>&#13; and for G = 11:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1899"
+></A
+><PRE
+CLASS="screen"
+> 1
+ 01234567890
+ 0 *
+ 1 *
+ 2 *
+ 3 *
+ 4 *
+ 5 *
+ 6 *
+ 7 *
+ 8 *
+ 9 *
+10 *
+ 0 *
+ 1 *
+ 2 *
+ 3 *
+ 4 *
+ 5 *
+ 6 *
+ 7 *
+ 8 *
+ 9 *
+10 *</PRE
+><P
+></P
+></DIV
+><P
+>&#13; This gives a weave looking like this:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1902"
+></A
+><P
+>&#13; S = 12, J = 6, G = 6, B = 2:
+ </P
+><PRE
+CLASS="screen"
+>0 *-----------*-----------*-----------*-----------*-----------*
+1 *-----------*-----------*-----------*-----------*-----------*
+2 *-----------*-----------*-----------*-----------*-----------*
+3 *-----------*-----------*-----------*-----------*---------
+4 *-----------*-----------*-----------*-----------*-
+5 *-----------*-----------*-----------*-------
+6 *-----------*-----------*-----------*
+7 *-----------*-----------*------
+8 *-----------*-----------*--
+9 *-----------*--------
+10 *-----------*----
+11 *----------
+12 *-----</PRE
+><P
+></P
+></DIV
+><P
+>&#13; This method ensures that the offset between passes is
+ always in the range [J - 2, J + 2].
+ </P
+><P
+>&#13; (This might seem odd, but it occurs to me that a good
+ weave pattern might also make a good score for bell
+ ringers. When church bells are rung, a list of
+ &#8220;changes&#8221; are used. For example, if 8 bells
+ are being used, they will, at first, be rung in order:
+ 12345678. If the first change is for bells 5 and 6, the
+ bells will then be rung in the order 12346578. If the
+ second change is 1 and 2, the next notes are 21346578.
+ After a long list of changes, the order the bells are rung
+ in can become quite complex.
+ </P
+><P
+>&#13; For a group of bell-ringers to change the order of the
+ notes, they must each either delay their bell's next ring,
+ hasten it, or keep it the same as the time it takes to
+ ring all the bells once. The length of time between each
+ ring of a given bell can only be changed a little each
+ time, though; with an ink-jet weave pattern, we want the
+ same to apply to the distance between passes.)
+ </P
+><P
+>&#13; Finally, knowing the number of jets J and their separation
+ S, we can calculate the starting row of any given pass p
+ as follows:
+ <DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1909"
+></A
+><PRE
+CLASS="screen"
+>passesperblock = S
+passblock = floor(p / passesperblock)
+offsetinpassblock = p - passblock * passesperblock
+subblocksperblock = gcd(S, J)
+passespersubblock = S / subblocksperblock
+subpassblock = floor(offsetinpassblock / passespersubblock)
+if subpassblock &#60; ceiling(subblocksperblock/2)
+ subblockoffset = 2*subpassblock
+else
+ subblockoffset = 2*(subblocksperblock-subpassblock)-1
+startingrow = passblock * S * J + offsetinpassblock * J + subblockoffset</PRE
+><P
+></P
+></DIV
+>
+ </P
+><P
+>&#13; We can simplify this down to the following:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1912"
+></A
+><PRE
+CLASS="screen"
+>subblocksperblock = gcd(S, J)
+subpassblock = floor((p % S) * subblocksperblock / S)
+if subpassblock * 2 &#60; subblocksperblock
+ subblockoffset = 2*subpassblock
+else
+ subblockoffset = 2*(subblocksperblock-subpassblock)-1
+startingrow = p * J + subblockoffset</PRE
+><P
+></P
+></DIV
+><P
+>&#13; So the row number of jet j of pass p is
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1915"
+></A
+><PRE
+CLASS="screen"
+>subblocksperblock = gcd(S, J)
+
+subblockoffset(p)
+ = 2*subpassblock , if subpassblock * 2 &#60; subblocksperblock
+ = 2*(subblocksperblock-subpassblock)-1 , otherwise
+ where
+ subpassblock = floor((p % S) * subblocksperblock / S)
+
+row(j, p) = p * J + subblockoffset(p) + j * S</PRE
+><P
+></P
+></DIV
+><P
+>&#13; Together with the inequality 0 &#8804; j &#60; J, we can use
+ this definition in reverse to calculate the pass number
+ containing a given row, r. Working out the inverse
+ definition involves a little guesswork, but one possible
+ result is as follows. Given a row, r, which is known to
+ be the first row of a pass, we can calculate the pass
+ number as follows:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1918"
+></A
+><PRE
+CLASS="screen"
+>subblocksperblock = gcd(S, J)
+subblockoffset = r % subblocksperblock
+pass = (r - subblockoffset) / J</PRE
+><P
+></P
+></DIV
+><P
+>&#13; If G = 1, we can determine the pass number with this
+ algorithm:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1921"
+></A
+><PRE
+CLASS="screen"
+>offset = r % J
+pass = (r - offset) / J
+while (offset % S != 0)
+{
+pass--
+offset += J
+}
+jet = offset / S</PRE
+><P
+></P
+></DIV
+><P
+>&#13; Generalising, we come up with this algorithm. Given r, S
+ and J:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1924"
+></A
+><PRE
+CLASS="screen"
+>G = gcd(S, J)
+passespersubblock = S/G
+subblockoffset = r % G
+subpassblock = subblockoffset / 2 , if subblockoffset % 2 == 0
+ = G - (subblockoffset+1)/2 , otherwise
+baserow = r - subblockoffset - (subpassblock * passespersubblock * J)
+offset = baserow % J
+pass = (baserow - offset) / J
+while (offset % S != 0)
+{
+offset += J
+pass -= 1
+}
+subblockretreat = floor(pass / passespersubblock) % G
+pass -= subblockretreat * passespersubblock
+pass += subpassblock * passespersubblock
+jet = (r - subblockoffset - pass * J) / S</PRE
+><P
+></P
+></DIV
+><P
+>&#13; Let's look at some examples of imperfect but correct weave
+ patterns:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1927"
+></A
+><P
+>&#13; S = 6, J = 4, GCD = 2,
+ passesperblock = S = 6,
+ passespersubblock = S / G = 6 / 2 = 3:
+ </P
+><PRE
+CLASS="screen"
+>0 *-----*-----*-----*
+1 *-----*-----*-----*
+2 *-----*-----*-----*
+3 *-----*-----*-----*
+4 *-----*-----*-----*
+5 *-----*-----*-----*
+6 *-----*-----*-----*
+7 *-----*-----*-----*
+8 *-----*-----*-----*
+9 *-----*-----*-----*
+10 *-----*-----*-----*
+11 *-----*-----*-----*
+12 *-----*-----*-----*
+13 *-----*-----*-----*
+14 *-----*-----*-----*
+15 *-----*-----*----
+16 *-----*-----*
+17 *-----*--
+18 *-----
+19 *-</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1930"
+></A
+><P
+>&#13; S = 8, J = 6, G = 2,
+ passesperblock = S = 8,
+ passespersubblock= S / G = 8 / 2 = 4:
+ </P
+><PRE
+CLASS="screen"
+>0 *-------*-------*-------*-------*-------*
+1 *-------*-------*-------*-------*-------*
+2 *-------*-------*-------*-------*-------*
+3 *-------*-------*-------*-------*-------*
+4 *-------*-------*-------*-------*-------*
+5 *-------*-------*-------*-------*-------*
+6 *-------*-------*-------*-------*-------*
+7 *-------*-------*-------*-------*--
+8 *-------*-------*-------*-----
+9 *-------*-------*-------
+10 *-------*-------*-
+11 *-------*---
+12 *----</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1933"
+></A
+><P
+>&#13; S = 6, J = 12, G = 6,
+ passesperblock = S = 6,
+ passespersubblock= S / G = 6 / 6 = 1:
+ </P
+><PRE
+CLASS="screen"
+>0 *-----*-----*-----*-----*-----*-----*-----*-----*-----*-----*-----*
+1 *-----*-----*-----*-----*-----*-----*-----*-----*-----*-----*---
+2 *-----*-----*-----*-----*-----*-----*-----*-----*-
+3 *-----*-----*-----*-----*-----*-----*
+4 *-----*-----*-----*-----*--
+5 *-----*-----*----
+6 *-----</PRE
+><P
+></P
+></DIV
+><P
+>&#13; We have now solved the basic weaving problem. There are
+ two further refinements we need to consider: oversampling,
+ and filling in the missing rows at the start of the weave.
+ </P
+><P
+></P
+></DIV
+></DIV
+><DIV
+CLASS="sect2"
+><H2
+CLASS="sect2"
+><A
+NAME="AEN1937"
+>6.2.5. Oversampling</A
+></H2
+><P
+>&#13; By oversampling, we mean printing on the same row more than
+ once. There are two reasons for oversampling: to increase
+ the horizontal resolution of the printout and to reduce
+ banding.
+ </P
+><P
+>&#13; Oversampling to increase horizontal resolution is necessary
+ because, although the printer might be able to position an
+ ink drop to, for example, 1/1440" horizontally, it may not
+ be able to lay down two such drops 1/1440" apart. If it can
+ print two drops 1/720" apart, 2x oversampling will be
+ necessary to get a 1/1440" horizontal resolution. If it can
+ only print two drops 1/360" apart, 4x oversampling will be
+ necessary for a 1/1440" horizontal resolution. The printer
+ enforces this &#8220;drop spacing&#8221; by only accepting
+ raster passes with a horizontal resolution matching the
+ spacing with which it can print dots, so we must print
+ passes at different horizontal positions if we are to obtain
+ a higher horizontal resolution. (Another reason it does
+ this may be to reduce the amount of memory needed in the
+ printer.)
+ </P
+><P
+>&#13; Oversampling can also be done to decrease the banding
+ apparent in an image. By splitting a row into two or more
+ sets of dots (&#8220;lines&#8221;) and printing each line on
+ the same row, but with a different nozzle for each line, we
+ can get a smoother print.
+ </P
+><P
+>&#13; To quantify these two kinds of oversampling, we'll introduce
+ two new constants: H shows how many different horizontal
+ offsets we want to print at (the &#8220;horizontal
+ oversampling&#8221;) while O shows how many times we want to
+ print each row, over and above the number of times necessary
+ for horizontal oversampling (the &#8220;extra
+ oversampling&#8221;).
+ </P
+><P
+>&#13; It is necessary for all the lines printed by a given pass to
+ have the same horizontal offset, but there need not be any
+ relation between them in terms of extra oversampling. For
+ the moment, however, we will treat all oversampling as
+ potentially requiring this alignment; all lines in one pass
+ must be derived from the original row data in the same way.
+ Thus, we'll assume O = 1 for now.
+ </P
+><P
+>&#13; So, how do we do this oversampling? In fact, it can be done
+ easily: advance the paper by a factor of H less between each
+ pass. We'll define a new variable, A, to show how much we
+ advance the paper between passes. Previously, we'd have
+ defined A = J; we now let A = J / H. This also affects our
+ pass blocks. Printing one pass block used to involve
+ advancing the paper S × J rows; it now advances the
+ paper (S×J) / H rows. We therefore name a group of H
+ pass blocks a &#8220;band&#8221;. Printing one band
+ involves advancing the paper S×J rows, as a pass
+ block did before.
+ </P
+><P
+>&#13; To keep our weave pattern working correctly, so that
+ overprinting does not occur within a pass block, we also
+ have to redefine G as GCD(S,A). Here's an example of an
+ oversampled weave pattern:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1946"
+></A
+><P
+>&#13; S = 4, J = 10, H = 2, A = J/H = 10/2 = 5,
+ G= GCD(4,5) = 1,
+ passesperblock = S = 4,
+ passespersubblock = S/G = 4/1 = 4:
+ </P
+><PRE
+CLASS="screen"
+>0 *---*---*---*---*---*---*---*---*---*
+1 *---*---*---*---*---*---*---*---*---*
+2 *---*---*---*---*---*---*---*---*---*
+3 *---*---*---*---*---*---*---*---*---*
+4 *---*---*---*---*---*---*---*---*---*
+5 *---*---*---*---*---*---*---*---*---*
+6 *---*---*---*---*---*---*---*---*---*
+7 *---*---*---*---*---*---*---*---*---*
+8 *---*---*---*---*---*---*---*---*---*
+9 *---*---*---*---*---*---*---*---*
+10 *---*---*---*---*---*---*---
+11 *---*---*---*---*---*--
+12 *---*---*---*---*-
+13 *---*---*---*
+14 *---*---
+15 *--</PRE
+><P
+></P
+></DIV
+><P
+>&#13; Now we have to determine which line is printed by each jet on
+ each pass. If we number each line generated as we split up a
+ row, we can use these numbers. We'll number the lines in our
+ diagram by replacing the <SAMP
+CLASS="computeroutput"
+>*</SAMP
+>s
+ with integers in the range [0&#8230;H&#8722;1].
+ </P
+><P
+>&#13; Overprinting occurs once per pass block, so we can simply
+ print pass block 0 with line 0, pass block 1 with line 1,
+ pass block 2 with line 2, etc, wrapping to 0 when we've run
+ out of lines:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1952"
+></A
+><PRE
+CLASS="screen"
+>0 0---0---0---0---0---0---0---0---0---0
+1 0---0---0---0---0---0---0---0---0---0
+2 0---0---0---0---0---0---0---0---0---0
+3 0---0---0---0---0---0---0---0---0---0
+4 1---1---1---1---1---1---1---1---1---1
+5 1---1---1---1---1---1---1---1---1---1
+6 1---1---1---1---1---1---1---1---1---1
+7 1---1---1---1---1---1---1---1---1---1
+8 0---0---0---0---0---0---0---0---0---0
+9 0---0---0---0---0---0---0---0---0
+10 0---0---0---0---0---0---0---
+11 0---0---0---0---0---0--
+12 1---1---1---1---1-
+13 1---1---1---1
+14 1---1---
+15 1--</PRE
+><P
+></P
+></DIV
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1954"
+></A
+><P
+>&#13; S = 4, J = 12, H = 2, A = J/H = 12/2 = 6,
+ G= GCD(4,6) = 2,
+ passesperblock= S = 4,
+ passespersubblock= S/G = 4/2 = 2:
+ </P
+><PRE
+CLASS="screen"
+>0 0---0---0---0---0---0---0---0---0---0---0---0
+1 0---0---0---0---0---0---0---0---0---0---0---0
+2 0---0---0---0---0---0---0---0---0---0---0---0
+3 0---0---0---0---0---0---0---0---0---0---0---0
+4 1---1---1---1---1---1---1---1---1---1---1---1
+5 1---1---1---1---1---1---1---1---1---1---1---1
+6 1---1---1---1---1---1---1---1---1---1---1
+7 1---1---1---1---1---1---1---1---1--
+8 0---0---0---0---0---0---0---0-
+9 0---0---0---0---0---0---
+10 0---0---0---0---0
+11 0---0---0--
+12 1---1-</PRE
+><P
+></P
+></DIV
+><P
+>&#13; But what do we do if J is not an exact multiple of H? This
+ is a difficult problem, which I struggled with for quite a
+ few days before giving in and taking the easy (but less
+ elegant) way out. The easy solution is to round J / H down,
+ then add on the accumulated error at the end of each band.
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1958"
+></A
+><P
+>&#13; S = 4, J = 11, H = 2, A = floor(J/H) = floor(11/2) = 5,
+ G = GCD(4,5) = 1,
+ passesperblock = S = 4,
+ passespersubblock = S/G = 4/1 = 4
+ </P
+><PRE
+CLASS="screen"
+>Band 0:
+0 0---0---0---0---0---0---0---0---0---0---0
+1 0---0---0---0---0---0---0---0---0---0---0
+2 0---0---0---0---0---0---0---0---0---0---0
+3 0---0---0---0---0---0---0---0---0---0---0
+4 1---1---1---1---1---1---1---1---1---1---1
+5 1---1---1---1---1---1---1---1---1---1---1
+6 1---1---1---1---1---1---1---1---1---1---1
+7 1---1---1---1---1---1---1---1---1---1---
+
+Band 1:
+8 | 0---0---0---0---0---0---0---0---0-
+9 \-----------------------------------------/ 0---0---0---0---0---0---0---0
+10 S*J rows 0---0---0---0---0---0---
+11 0---0---0---0---0--
+12 1---1---1---1-
+13 1---1---1
+14 1---</PRE
+><P
+></P
+></DIV
+><P
+>&#13; We can calculate the starting row and subpass number of a
+ given pass in this scheme as follows:
+ </P
+><DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1962"
+></A
+><PRE
+CLASS="screen"
+>A = floor(J / H)
+subblocksperblock = gcd(S, A)
+subpassblock = floor((p % S) * subblocksperblock / S)
+if subpassblock * 2 &#60; subblocksperblock
+ subblockoffset = 2*subpassblock
+else
+ subblockoffset = 2*(subblocksperblock-subpassblock)-1
+band = floor(P / (S * H))
+passinband = P % (S * H)
+startingrow = band * S * J + passinband * A + subblockoffset
+subpass = passinband / S</PRE
+><P
+></P
+></DIV
+><P
+>&#13; So the row number of jet j of pass p is
+ <DIV
+CLASS="informalexample"
+><P
+></P
+><A
+NAME="AEN1965"
+></A
+><PRE
+CLASS="screen"
+>A = floor(J / H)
+subblocksperblock = gcd(S, A)
+
+subblockoffset(p)
+ = 2*subpassblock , if subpassblock * 2 &#60; subblocksperblock
+ = 2*(subblocksperblock-subpassblock)-1 , otherwise
+ where
+ subpassblock = floor((p % S) * subblocksperblock / S)
+
+band(p) = floor(p / (S * H))
+passinband(p) = p % (S * H)
+
+row(j, p) = band(p) * S * J + passinband(p) * A + subblockoffset(p) + j * S
+row(j, p) = p * J + subblockoffset(p) + j * S</PRE
+><P
+>&#13; To be continued&#8230;
+ </P
+><P
+></P
+></DIV
+>
+ </P
+></DIV
+></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="c1717.html"
+ACCESSKEY="P"
+>Prev</A
+></TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="index.html"
+ACCESSKEY="H"
+>Home</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+><A
+HREF="c1968.html"
+ACCESSKEY="N"
+>Next</A
+></TD
+></TR
+><TR
+><TD
+WIDTH="33%"
+ALIGN="left"
+VALIGN="top"
+>Weaving for inkjet printers</TD
+><TD
+WIDTH="34%"
+ALIGN="center"
+VALIGN="top"
+><A
+HREF="c1717.html"
+ACCESSKEY="U"
+>Up</A
+></TD
+><TD
+WIDTH="33%"
+ALIGN="right"
+VALIGN="top"
+>Dithering</TD
+></TR
+></TABLE
+></DIV
+></BODY
+></HTML
+> \ No newline at end of file