!DOCTYPE = 'thresholds [
            <!ELEMENT thresholds (threshold)+>
            <!ATTLIST thresholds xmlns CDATA #FIXED "">
            <!ELEMENT threshold (description , levels)>
            <!ATTLIST threshold xmlns CDATA #FIXED "">
            <!ATTLIST threshold alias NMTOKEN #IMPLIED>
            <!ATTLIST threshold map NMTOKEN #REQUIRED>
            <!ELEMENT description (#PCDATA)>
            <!ATTLIST description xmlns CDATA #FIXED "">
            <!ELEMENT levels (#PCDATA)>
            <!ATTLIST levels xmlns CDATA #FIXED "">
            <!ATTLIST levels divisor CDATA #REQUIRED>
            <!ATTLIST levels height CDATA #REQUIRED>
            <!ATTLIST levels width CDATA #REQUIRED>
            ]'
/* Threshold Maps for Ordered Posterized Dither

   Each "<threshold>" element defines the map name, description, and an array
   of "levels" used to provide the threshold map for ordered dithering and
   digital halftoning.

   The "alias" attribute provides a backward compatible name for this threshold
   map (pre-dating IM v6.2.9-6), and are deprecated.

   The description is a english description of what the threshold map achieves
   and is only used for 'listing' the maps.

   The map itself is a rectangular array of integers or threshold "levels"
   of the given "width" and "height" declared within the enclosing <levels>
   element.  That is "width*height" integers or "levels" *must* be provided
   within each map.

   Each of the "levels" integer values (each value representing the threshold
   intensity "level/divisor" at which that pixel is turned on.  The "levels"
   integers given can be any postive integers between "0" and the "divisor",
   excluding those limits.

   The "divisor" not only defines the upper limit and threshold divisor for each
   "level" but also the total number of pseudo-levels the threshold mapping
   creates and fills with a dither pattern.  That is a ordered bitmap dither
   of a pure greyscale gradient will use a maximum of "divisor" ordered bitmap
   patterns, including the patterns with all the pixels 'on' and all the pixel
   'off'. It may define less patterns than that, but the color channels will
   be thresholded in units based on "divisor".

   Alternatively for a multi-level posterization, ImageMagick inserts
   "divisor-2" dither patterns (as defined by the threshold map) between each of
   channel color level produced.

   For example the map "o2x2" has a divisor of 5, which will define 3 bitmap
   patterns plus the patterns with all pixels 'on' and 'off'.  A greyscale
   gradient will thus have 5 distinct areas. */
thresholds(xmlns = '')
{
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       Minimal Dither and Non-Dither Threshold Maps */
    threshold(map   = threshold
              alias = 1x1
              xmlns = '')
    {
        description(xmlns = '') = 'Threshold 1x1 (non-dither)'
        levels(width   = 1
               height  = 1
               divisor = 2
               xmlns   = '') = 1
    }
    threshold(map   = checks
              alias = 2x1
              xmlns = '')
    {
        description(xmlns = '') = 'Checkerboard 2x1 (dither)'
        levels(width   = 2
               height  = 2
               divisor = 3
               xmlns   = '') = '1 2
                                2 1'
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       (dispersed) Ordered Dither Patterns */
    threshold(map   = o2x2
              alias = 2x2
              xmlns = '')
    {
        description(xmlns = '') = 'Ordered 2x2 (dispersed)'
        levels(width   = 2
               height  = 2
               divisor = 5
               xmlns   = '') = '1  3
                                4  2'
    }
    threshold(map   = o3x3
              alias = 3x3
              xmlns = '')
    {
        description(xmlns = '') = 'Ordered 3x3 (dispersed)'
        levels(width   = 3
               height  = 3
               divisor = 10
               xmlns   = '') = '3  7  4
                                6  1  9
                                2  8  5'
    }
    threshold(map   = o4x4
              alias = 4x4
              xmlns = '')
    {
        /* From "Dithering Algorithms"
           http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT */
        description(xmlns = '') = 'Ordered 4x4 (dispersed)'
        levels(width   = 4
               height  = 4
               divisor = 17
               xmlns   = '') = ' 1   9   3  11
                                13   5  15   7
                                 4  12   2  10
                                16   8  14   6'
    }
    threshold(map   = o8x8
              alias = 8x8
              xmlns = '')
    {
        // Extracted from original 'OrderedDither()' Function
        description(xmlns = '') = 'Ordered 8x8 (dispersed)'
        levels(width   = 8
               height  = 8
               divisor = 65
               xmlns   = '') = ' 1  49  13  61   4  52  16  64
                                33  17  45  29  36  20  48  32
                                 9  57   5  53  12  60   8  56
                                41  25  37  21  44  28  40  24
                                 3  51  15  63   2  50  14  62
                                35  19  47  31  34  18  46  30
                                11  59   7  55  10  58   6  54
                                43  27  39  23  42  26  38  22'
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       Halftones - Angled 45 degrees

       Initially added to ImageMagick by Glenn Randers-Pehrson, IM v6.2.8-6,
       modified to be more symmetrical with intensity by Anthony, IM v6.2.9-7

       These patterns initially start as circles, but then form diamonds
       pattern at the 50% threshold level, before forming negated circles,
       as it approached the other threshold extereme. */
    threshold(map   = h4x4a
              alias = 4x1
              xmlns = '')
    {
        description(xmlns = '') = 'Halftone 4x4 (angled)'
        levels(width   = 4
               height  = 4
               divisor = 9
               xmlns   = '') = '4  2  7  5
                                3  1  8  6
                                7  5  4  2
                                8  6  3  1'
    }
    threshold(map   = h6x6a
              alias = 6x1
              xmlns = '')
    {
        description(xmlns = '') = 'Halftone 6x6 (angled)'
        levels(width   = 6
               height  = 6
               divisor = 19
               xmlns   = '') = '14  13  10   8   2   3
                                16  18  12   7   1   4
                                15  17  11   9   6   5
                                 8   2   3  14  13  10
                                 7   1   4  16  18  12
                                 9   6   5  15  17  11'
    }
    threshold(map   = h8x8a
              alias = 8x1
              xmlns = '')
    {
        description(xmlns = '') = 'Halftone 8x8 (angled)'
        levels(width   = 8
               height  = 8
               divisor = 33
               xmlns   = '') = '13   7   8  14  17  21  22  18
                                 6   1   3   9  28  31  29  23
                                 5   2   4  10  27  32  30  24
                                16  12  11  15  20  26  25  19
                                17  21  22  18  13   7   8  14
                                28  31  29  23   6   1   3   9
                                27  32  30  24   5   2   4  10
                                20  26  25  19  16  12  11  15'
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       Halftones - Orthogonally Aligned, or Un-angled

       Initially added by Anthony Thyssen, IM v6.2.9-5 using techniques from
       "Dithering & Halftoning" by Gernot Haffmann
       http://www.fho-emden.de/~hoffmann/hilb010101.pdf

       These patterns initially start as circles, but then form square
       pattern at the 50% threshold level, before forming negated circles,
       as it approached the other threshold extereme. */
    threshold(map   = h4x4o
              xmlns = '')
    {
        description(xmlns = '') = 'Halftone 4x4 (orthogonal)'
        levels(width   = 4
               height  = 4
               divisor = 17
               xmlns   = '') = ' 7  13  11   4
                                12  16  14   8
                                10  15   6   2
                                 5   9   3   1'
    }
    threshold(map   = h6x6o
              xmlns = '')
    {
        description(xmlns = '') = 'Halftone 6x6 (orthogonal)'
        levels(width   = 6
               height  = 6
               divisor = 37
               xmlns   = '') = ' 7  17  27  14   9   4
                                21  29  33  31  18  11
                                24  32  36  34  25  22
                                19  30  35  28  20  10
                                 8  15  26  16   6   2
                                 5  13  23  12   3   1'
    }
    threshold(map   = h8x8o
              xmlns = '')
    {
        description(xmlns = '') = 'Halftone 8x8 (orthogonal)'
        levels(width   = 8
               height  = 8
               divisor = 65
               xmlns   = '') = ' 7  21  33  43  36  19   9   4
                                16  27  51  55  49  29  14  11
                                31  47  57  61  59  45  35  23
                                41  53  60  64  62  52  40  38
                                37  44  58  63  56  46  30  22
                                15  28  48  54  50  26  17  10
                                 8  18  34  42  32  20   6   2
                                 5  13  25  39  24  12   3   1'
    }
    threshold(map   = h16x16o
              xmlns = '')
    {
        /* Direct extract from "Dithering & Halftoning" by Gernot Haffmann.
           This may need some fine tuning for symmetry of the halftone dots,
           as it was a mathematically formulated pattern. */
        description(xmlns = '') = 'Halftone 16x16 (orthogonal)'
        levels(width   = 16
               height  = 16
               divisor = 257
               xmlns   = '') = '  4  12  24  44  72 100 136 152 150 134  98  70  42  23  11   3
                                  7  16  32  52  76 104 144 160 158 142 102  74  50  31  15   6
                                 19  27  40  60  92 132 168 180 178 166 130  90  58  39  26  18
                                 36  48  56  80 124 176 188 204 203 187 175 122  79  55  47  35
                                 64  68  84 116 164 200 212 224 223 211 199 162 114  83  67  63
                                 88  96 112 156 192 216 232 240 239 231 214 190 154 111  95  87
                                108 120 148 184 208 228 244 252 251 243 226 206 182 147 119 107
                                128 140 172 196 219 235 247 256 255 246 234 218 194 171 139 127
                                126 138 170 195 220 236 248 253 254 245 233 217 193 169 137 125
                                106 118 146 183 207 227 242 249 250 241 225 205 181 145 117 105
                                 86  94 110 155 191 215 229 238 237 230 213 189 153 109  93  85
                                 62  66  82 115 163 198 210 221 222 209 197 161 113  81  65  61
                                 34  46  54  78 123 174 186 202 201 185 173 121  77  53  45  33
                                 20  28  37  59  91 131 167 179 177 165 129  89  57  38  25  17
                                  8  13  29  51  75 103 143 159 157 141 101  73  49  30  14   5
                                  1   9  21  43  71  99 135 151 149 133  97  69  41  22  10   2'
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       Halftones - Orthogonally Expanding Circle Patterns

       Added by Glenn Randers-Pehrson, 4 Nov 2010, ImageMagick 6.6.5-6

       Rather than producing a diamond 50% threshold pattern, these
       continue to generate larger (overlapping) circles.  They are
       more like a true halftone pattern formed by covering a surface
       with either pure white or pure black circular dots.

       WARNING: true halftone patterns only use true circles even in
       areas of highly varying intensity.  Threshold dither patterns
       can generate distorted circles in such areas. */
    threshold(map   = c5x5b
              alias = c5x5
              xmlns = '')
    {
        description(xmlns = '') = 'Circles 5x5 (black)'
        levels(width   = 5
               height  = 5
               divisor = 26
               xmlns   = '') = '1 21 16 15  4
                                5 17 20 19 14
                                6 21 25 24 12
                                7 18 22 23 11
                                2  8  9 10  3'
    }
    threshold(map   = c5x5w
              xmlns = '')
    {
        description(xmlns = '') = 'Circles 5x5 (white)'
        levels(width   = 5
               height  = 5
               divisor = 26
               xmlns   = '') = '25 21 10 11 22
                                20  9  6  7 12
                                19  5  1  2 13
                                18  8  4  3 14
                                24 17 16 15 23'
    }
    threshold(map   = c6x6b
              alias = c6x6
              xmlns = '')
    {
        description(xmlns = '') = 'Circles 6x6 (black)'
        levels(width   = 6
               height  = 6
               divisor = 37
               xmlns   = '') = ' 1  5 14 13 12  4
                                 6 22 28 27 21 11
                                15 29 35 34 26 20
                                16 30 36 33 25 19
                                 7 23 31 32 24 10
                                 2  8 17 18  9  3'
    }
    threshold(map   = c6x6w
              xmlns = '')
    {
        description(xmlns = '') = 'Circles 6x6 (white)'
        levels(width   = 6
               height  = 6
               divisor = 37
               xmlns   = '') = '36 32 23 24 25 33
                                31 15  9 10 16 26
                                22  8  2  3 11 17
                                21  7  1  4 12 18
                                30 14  6  5 13 27
                                35 29 20 19 28 34'
    }
    threshold(map   = c7x7b
              alias = c7x7
              xmlns = '')
    {
        description(xmlns = '') = 'Circles 7x7 (black)'
        levels(width   = 7
               height  = 7
               divisor = 50
               xmlns   = '') = ' 3  9 18 28 17  8  2
                                10 24 33 39 32 23  7
                                19 34 44 48 43 31 16
                                25 40 45 49 47 38 27
                                20 35 41 46 42 29 15
                                11 21 36 37 28 22  6
                                 4 12 13 26 14  5  1'
    }
    threshold(map   = c7x7w
              xmlns = '')
    {
        description(xmlns = '') = 'Circles 7x7 (white)'
        levels(width   = 7
               height  = 7
               divisor = 50
               xmlns   = '') = '47 41 32 22 33 42 48
                                40 26 17 11 18 27 43
                                31 16  6  2  7 19 34
                                25 10  5  1  3 12 23
                                30 15  9  4  8 20 35
                                39 29 14 13 21 28 44
                                46 38 37 24 36 45 49'
    }
    /* - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       Special Purpose Dithers */
}