...

Source file src/golang.org/x/image/ccitt/gen.go

Documentation: golang.org/x/image/ccitt

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ignore
     6  
     7  package main
     8  
     9  import (
    10  	"bytes"
    11  	"flag"
    12  	"fmt"
    13  	"go/format"
    14  	"io/ioutil"
    15  	"log"
    16  	"os"
    17  )
    18  
    19  var debug = flag.Bool("debug", false, "")
    20  
    21  func main() {
    22  	flag.Parse()
    23  
    24  	// Generate table.go.
    25  	{
    26  		w := &bytes.Buffer{}
    27  		w.WriteString(header)
    28  		w.WriteString(decodeHeaderComment)
    29  		writeDecodeTable(w, build(modeCodes[:], 0), "modeDecodeTable",
    30  			"// modeDecodeTable represents Table 1 and the End-of-Line code.\n")
    31  		writeDecodeTable(w, build(whiteCodes[:], 0), "whiteDecodeTable",
    32  			"// whiteDecodeTable represents Tables 2 and 3 for a white run.\n")
    33  		writeDecodeTable(w, build(blackCodes[:], 0), "blackDecodeTable",
    34  			"// blackDecodeTable represents Tables 2 and 3 for a black run.\n")
    35  		writeMaxCodeLength(w, modeCodes[:], whiteCodes[:], blackCodes[:])
    36  		w.WriteString(encodeHeaderComment)
    37  		w.WriteString(bitStringTypeDef)
    38  		writeEncodeTable(w, modeCodes[:], "modeEncodeTable",
    39  			"// modeEncodeTable represents Table 1 and the End-of-Line code.\n")
    40  		writeEncodeTable(w, whiteCodes[:64], "whiteEncodeTable2",
    41  			"// whiteEncodeTable2 represents Table 2 for a white run.\n")
    42  		writeEncodeTable(w, whiteCodes[64:], "whiteEncodeTable3",
    43  			"// whiteEncodeTable3 represents Table 3 for a white run.\n")
    44  		writeEncodeTable(w, blackCodes[:64], "blackEncodeTable2",
    45  			"// blackEncodeTable2 represents Table 2 for a black run.\n")
    46  		writeEncodeTable(w, blackCodes[64:], "blackEncodeTable3",
    47  			"// blackEncodeTable3 represents Table 3 for a black run.\n")
    48  		finish(w, "table.go")
    49  	}
    50  
    51  	// Generate table_test.go.
    52  	{
    53  		w := &bytes.Buffer{}
    54  		w.WriteString(header)
    55  		finish(w, "table_test.go")
    56  	}
    57  }
    58  
    59  const header = `// generated by "go run gen.go". DO NOT EDIT.
    60  
    61  package ccitt
    62  
    63  `
    64  
    65  const decodeHeaderComment = `
    66  // Each decodeTable is represented by an array of [2]int16's: a binary tree.
    67  // Each array element (other than element 0, which means invalid) is a branch
    68  // node in that tree. The root node is always element 1 (the second element).
    69  //
    70  // To walk the tree, look at the next bit in the bit stream, using it to select
    71  // the first or second element of the [2]int16. If that int16 is 0, we have an
    72  // invalid code. If it is positive, go to that branch node. If it is negative,
    73  // then we have a leaf node, whose value is the bitwise complement (the ^
    74  // operator) of that int16.
    75  //
    76  // Comments above each decodeTable also show the same structure visually. The
    77  // "b123" lines show the 123'rd branch node. The "=XXXXX" lines show an invalid
    78  // code. The "=v1234" lines show a leaf node with value 1234. When reading the
    79  // bit stream, a 0 or 1 bit means to go up or down, as you move left to right.
    80  //
    81  // For example, in modeDecodeTable, branch node b005 is three steps up from the
    82  // root node, meaning that we have already seen "000". If the next bit is "0"
    83  // then we move to branch node b006. Otherwise, the next bit is "1", and we
    84  // move to the leaf node v0000 (also known as the modePass constant). Indeed,
    85  // the bits that encode modePass are "0001".
    86  //
    87  // Tables 1, 2 and 3 come from the "ITU-T Recommendation T.6: FACSIMILE CODING
    88  // SCHEMES AND CODING CONTROL FUNCTIONS FOR GROUP 4 FACSIMILE APPARATUS"
    89  // specification:
    90  //
    91  // https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.6-198811-I!!PDF-E&type=items
    92  
    93  
    94  `
    95  
    96  const encodeHeaderComment = `
    97  // Each encodeTable is represented by an array of bitStrings.
    98  
    99  
   100  `
   101  
   102  type node struct {
   103  	children    [2]*node
   104  	val         uint32
   105  	branchIndex int32
   106  }
   107  
   108  func (n *node) isBranch() bool {
   109  	return (n != nil) && ((n.children[0] != nil) || (n.children[1] != nil))
   110  }
   111  
   112  func (n *node) String() string {
   113  	if n == nil {
   114  		return "0"
   115  	}
   116  	if n.branchIndex > 0 {
   117  		return fmt.Sprintf("%d", n.branchIndex)
   118  	}
   119  	return fmt.Sprintf("^%d", n.val)
   120  }
   121  
   122  func build(codes []code, prefixLen int) *node {
   123  	if len(codes) == 0 {
   124  		return nil
   125  	}
   126  
   127  	if prefixLen == len(codes[0].str) {
   128  		if len(codes) != 1 {
   129  			panic("ambiguous codes")
   130  		}
   131  		return &node{
   132  			val: codes[0].val,
   133  		}
   134  	}
   135  
   136  	childrenCodes := [2][]code{}
   137  	for _, code := range codes {
   138  		bit := code.str[prefixLen] & 1
   139  		childrenCodes[bit] = append(childrenCodes[bit], code)
   140  	}
   141  	return &node{
   142  		children: [2]*node{
   143  			build(childrenCodes[0], prefixLen+1),
   144  			build(childrenCodes[1], prefixLen+1),
   145  		},
   146  	}
   147  }
   148  
   149  func writeDecodeTable(w *bytes.Buffer, root *node, varName, comment string) {
   150  	assignBranchIndexes(root)
   151  
   152  	w.WriteString(comment)
   153  	w.WriteString("//\n")
   154  	writeComment(w, root, "  ", false)
   155  	fmt.Fprintf(w, "var %s = [...][2]int16{\n", varName)
   156  	fmt.Fprintf(w, "0: {0, 0},\n")
   157  
   158  	// Walk the tree in breadth-first order.
   159  	for queue := []*node{root}; len(queue) > 0; {
   160  		n := queue[0]
   161  		queue = queue[1:]
   162  
   163  		if n.isBranch() {
   164  			fmt.Fprintf(w, "%d: {%v, %v},\n", n.branchIndex, n.children[0], n.children[1])
   165  			queue = append(queue, n.children[0], n.children[1])
   166  		}
   167  	}
   168  
   169  	fmt.Fprintf(w, "}\n\n")
   170  }
   171  
   172  const bitStringTypeDef = `
   173  // bitString is a pair of uint32 values representing a bit code.
   174  // The nBits low bits of bits make up the actual bit code.
   175  // Eg. bitString{0x0004, 8} represents the bitcode "00000100".
   176  type bitString struct {
   177  	bits  uint32
   178  	nBits uint32
   179  }
   180  
   181  `
   182  
   183  func writeEncodeTable(w *bytes.Buffer, codes []code, varName, comment string) {
   184  	w.WriteString(comment)
   185  	fmt.Fprintf(w, "var %s = [...]bitString{\n", varName)
   186  	for i, code := range codes {
   187  		s := code.str
   188  		n := uint32(len(s))
   189  		c := uint32(0)
   190  		for j := uint32(0); j < n; j++ {
   191  			c |= uint32(s[j]&1) << (n - j - 1)
   192  		}
   193  		fmt.Fprintf(w, "%d: {0x%04x, %v}, // %q \n", i, c, n, s)
   194  	}
   195  	fmt.Fprintf(w, "}\n\n")
   196  }
   197  
   198  func assignBranchIndexes(root *node) {
   199  	// 0 is reserved for an invalid value.
   200  	branchIndex := int32(1)
   201  
   202  	// Walk the tree in breadth-first order.
   203  	for queue := []*node{root}; len(queue) > 0; {
   204  		n := queue[0]
   205  		queue = queue[1:]
   206  
   207  		if n.isBranch() {
   208  			n.branchIndex = branchIndex
   209  			branchIndex++
   210  			queue = append(queue, n.children[0], n.children[1])
   211  		}
   212  	}
   213  }
   214  
   215  func writeComment(w *bytes.Buffer, n *node, prefix string, down bool) {
   216  	if n.isBranch() {
   217  		prefixUp := prefix[:len(prefix)-2] + "  | "
   218  		prefixDown := prefix + "| "
   219  		if down {
   220  			prefixUp, prefixDown = prefixDown, prefixUp
   221  		}
   222  
   223  		writeComment(w, n.children[0], prefixUp, false)
   224  		defer writeComment(w, n.children[1], prefixDown, true)
   225  
   226  		fmt.Fprintf(w, "//\tb%03d ", n.branchIndex)
   227  	} else {
   228  		fmt.Fprintf(w, "//\t     ")
   229  	}
   230  
   231  	w.WriteString(prefix[:len(prefix)-2])
   232  
   233  	if n == nil {
   234  		fmt.Fprintf(w, "+=XXXXX\n")
   235  		return
   236  	}
   237  	if !n.isBranch() {
   238  		fmt.Fprintf(w, "+=v%04d\n", n.val)
   239  		return
   240  	}
   241  	w.WriteString("+-+\n")
   242  }
   243  
   244  func writeMaxCodeLength(w *bytes.Buffer, codesList ...[]code) {
   245  	maxCodeLength := 0
   246  	for _, codes := range codesList {
   247  		for _, code := range codes {
   248  			if n := len(code.str); maxCodeLength < n {
   249  				maxCodeLength = n
   250  			}
   251  		}
   252  	}
   253  	fmt.Fprintf(w, "const maxCodeLength = %d\n\n", maxCodeLength)
   254  }
   255  
   256  func finish(w *bytes.Buffer, filename string) {
   257  	copyPaste(w, filename)
   258  	if *debug {
   259  		os.Stdout.Write(w.Bytes())
   260  		return
   261  	}
   262  	out, err := format.Source(w.Bytes())
   263  	if err != nil {
   264  		log.Fatalf("format.Source: %v", err)
   265  	}
   266  	if err := ioutil.WriteFile(filename, out, 0660); err != nil {
   267  		log.Fatalf("ioutil.WriteFile: %v", err)
   268  	}
   269  }
   270  
   271  func copyPaste(w *bytes.Buffer, filename string) {
   272  	b, err := ioutil.ReadFile("gen.go")
   273  	if err != nil {
   274  		log.Fatalf("ioutil.ReadFile: %v", err)
   275  	}
   276  	begin := []byte("\n// COPY PASTE " + filename + " BEGIN\n\n")
   277  	end := []byte("\n// COPY PASTE " + filename + " END\n\n")
   278  
   279  	for len(b) > 0 {
   280  		i := bytes.Index(b, begin)
   281  		if i < 0 {
   282  			break
   283  		}
   284  		b = b[i:]
   285  
   286  		j := bytes.Index(b, end)
   287  		if j < 0 {
   288  			break
   289  		}
   290  		j += len(end)
   291  
   292  		w.Write(b[:j])
   293  		b = b[j:]
   294  	}
   295  }
   296  
   297  // COPY PASTE table.go BEGIN
   298  
   299  const (
   300  	modePass = iota // Pass
   301  	modeH           // Horizontal
   302  	modeV0          // Vertical-0
   303  	modeVR1         // Vertical-Right-1
   304  	modeVR2         // Vertical-Right-2
   305  	modeVR3         // Vertical-Right-3
   306  	modeVL1         // Vertical-Left-1
   307  	modeVL2         // Vertical-Left-2
   308  	modeVL3         // Vertical-Left-3
   309  	modeExt         // Extension
   310  )
   311  
   312  // COPY PASTE table.go END
   313  
   314  // The data that is the rest of this file is taken from Tables 1, 2 and 3 from
   315  // the "ITU-T Recommendation T.6" spec.
   316  
   317  // COPY PASTE table_test.go BEGIN
   318  
   319  type code struct {
   320  	val uint32
   321  	str string
   322  }
   323  
   324  var modeCodes = []code{
   325  	{modePass, "0001"},
   326  	{modeH, "001"},
   327  	{modeV0, "1"},
   328  	{modeVR1, "011"},
   329  	{modeVR2, "000011"},
   330  	{modeVR3, "0000011"},
   331  	{modeVL1, "010"},
   332  	{modeVL2, "000010"},
   333  	{modeVL3, "0000010"},
   334  	{modeExt, "0000001"},
   335  }
   336  
   337  var whiteCodes = []code{
   338  	// Terminating codes (0-63).
   339  	{0x0000, "00110101"},
   340  	{0x0001, "000111"},
   341  	{0x0002, "0111"},
   342  	{0x0003, "1000"},
   343  	{0x0004, "1011"},
   344  	{0x0005, "1100"},
   345  	{0x0006, "1110"},
   346  	{0x0007, "1111"},
   347  	{0x0008, "10011"},
   348  	{0x0009, "10100"},
   349  	{0x000A, "00111"},
   350  	{0x000B, "01000"},
   351  	{0x000C, "001000"},
   352  	{0x000D, "000011"},
   353  	{0x000E, "110100"},
   354  	{0x000F, "110101"},
   355  	{0x0010, "101010"},
   356  	{0x0011, "101011"},
   357  	{0x0012, "0100111"},
   358  	{0x0013, "0001100"},
   359  	{0x0014, "0001000"},
   360  	{0x0015, "0010111"},
   361  	{0x0016, "0000011"},
   362  	{0x0017, "0000100"},
   363  	{0x0018, "0101000"},
   364  	{0x0019, "0101011"},
   365  	{0x001A, "0010011"},
   366  	{0x001B, "0100100"},
   367  	{0x001C, "0011000"},
   368  	{0x001D, "00000010"},
   369  	{0x001E, "00000011"},
   370  	{0x001F, "00011010"},
   371  	{0x0020, "00011011"},
   372  	{0x0021, "00010010"},
   373  	{0x0022, "00010011"},
   374  	{0x0023, "00010100"},
   375  	{0x0024, "00010101"},
   376  	{0x0025, "00010110"},
   377  	{0x0026, "00010111"},
   378  	{0x0027, "00101000"},
   379  	{0x0028, "00101001"},
   380  	{0x0029, "00101010"},
   381  	{0x002A, "00101011"},
   382  	{0x002B, "00101100"},
   383  	{0x002C, "00101101"},
   384  	{0x002D, "00000100"},
   385  	{0x002E, "00000101"},
   386  	{0x002F, "00001010"},
   387  	{0x0030, "00001011"},
   388  	{0x0031, "01010010"},
   389  	{0x0032, "01010011"},
   390  	{0x0033, "01010100"},
   391  	{0x0034, "01010101"},
   392  	{0x0035, "00100100"},
   393  	{0x0036, "00100101"},
   394  	{0x0037, "01011000"},
   395  	{0x0038, "01011001"},
   396  	{0x0039, "01011010"},
   397  	{0x003A, "01011011"},
   398  	{0x003B, "01001010"},
   399  	{0x003C, "01001011"},
   400  	{0x003D, "00110010"},
   401  	{0x003E, "00110011"},
   402  	{0x003F, "00110100"},
   403  
   404  	// Make-up codes between 64 and 1728.
   405  	{0x0040, "11011"},
   406  	{0x0080, "10010"},
   407  	{0x00C0, "010111"},
   408  	{0x0100, "0110111"},
   409  	{0x0140, "00110110"},
   410  	{0x0180, "00110111"},
   411  	{0x01C0, "01100100"},
   412  	{0x0200, "01100101"},
   413  	{0x0240, "01101000"},
   414  	{0x0280, "01100111"},
   415  	{0x02C0, "011001100"},
   416  	{0x0300, "011001101"},
   417  	{0x0340, "011010010"},
   418  	{0x0380, "011010011"},
   419  	{0x03C0, "011010100"},
   420  	{0x0400, "011010101"},
   421  	{0x0440, "011010110"},
   422  	{0x0480, "011010111"},
   423  	{0x04C0, "011011000"},
   424  	{0x0500, "011011001"},
   425  	{0x0540, "011011010"},
   426  	{0x0580, "011011011"},
   427  	{0x05C0, "010011000"},
   428  	{0x0600, "010011001"},
   429  	{0x0640, "010011010"},
   430  	{0x0680, "011000"},
   431  	{0x06C0, "010011011"},
   432  
   433  	// Make-up codes between 1792 and 2560.
   434  	{0x0700, "00000001000"},
   435  	{0x0740, "00000001100"},
   436  	{0x0780, "00000001101"},
   437  	{0x07C0, "000000010010"},
   438  	{0x0800, "000000010011"},
   439  	{0x0840, "000000010100"},
   440  	{0x0880, "000000010101"},
   441  	{0x08C0, "000000010110"},
   442  	{0x0900, "000000010111"},
   443  	{0x0940, "000000011100"},
   444  	{0x0980, "000000011101"},
   445  	{0x09C0, "000000011110"},
   446  	{0x0A00, "000000011111"},
   447  }
   448  
   449  var blackCodes = []code{
   450  	// Terminating codes (0-63).
   451  	{0x0000, "0000110111"},
   452  	{0x0001, "010"},
   453  	{0x0002, "11"},
   454  	{0x0003, "10"},
   455  	{0x0004, "011"},
   456  	{0x0005, "0011"},
   457  	{0x0006, "0010"},
   458  	{0x0007, "00011"},
   459  	{0x0008, "000101"},
   460  	{0x0009, "000100"},
   461  	{0x000A, "0000100"},
   462  	{0x000B, "0000101"},
   463  	{0x000C, "0000111"},
   464  	{0x000D, "00000100"},
   465  	{0x000E, "00000111"},
   466  	{0x000F, "000011000"},
   467  	{0x0010, "0000010111"},
   468  	{0x0011, "0000011000"},
   469  	{0x0012, "0000001000"},
   470  	{0x0013, "00001100111"},
   471  	{0x0014, "00001101000"},
   472  	{0x0015, "00001101100"},
   473  	{0x0016, "00000110111"},
   474  	{0x0017, "00000101000"},
   475  	{0x0018, "00000010111"},
   476  	{0x0019, "00000011000"},
   477  	{0x001A, "000011001010"},
   478  	{0x001B, "000011001011"},
   479  	{0x001C, "000011001100"},
   480  	{0x001D, "000011001101"},
   481  	{0x001E, "000001101000"},
   482  	{0x001F, "000001101001"},
   483  	{0x0020, "000001101010"},
   484  	{0x0021, "000001101011"},
   485  	{0x0022, "000011010010"},
   486  	{0x0023, "000011010011"},
   487  	{0x0024, "000011010100"},
   488  	{0x0025, "000011010101"},
   489  	{0x0026, "000011010110"},
   490  	{0x0027, "000011010111"},
   491  	{0x0028, "000001101100"},
   492  	{0x0029, "000001101101"},
   493  	{0x002A, "000011011010"},
   494  	{0x002B, "000011011011"},
   495  	{0x002C, "000001010100"},
   496  	{0x002D, "000001010101"},
   497  	{0x002E, "000001010110"},
   498  	{0x002F, "000001010111"},
   499  	{0x0030, "000001100100"},
   500  	{0x0031, "000001100101"},
   501  	{0x0032, "000001010010"},
   502  	{0x0033, "000001010011"},
   503  	{0x0034, "000000100100"},
   504  	{0x0035, "000000110111"},
   505  	{0x0036, "000000111000"},
   506  	{0x0037, "000000100111"},
   507  	{0x0038, "000000101000"},
   508  	{0x0039, "000001011000"},
   509  	{0x003A, "000001011001"},
   510  	{0x003B, "000000101011"},
   511  	{0x003C, "000000101100"},
   512  	{0x003D, "000001011010"},
   513  	{0x003E, "000001100110"},
   514  	{0x003F, "000001100111"},
   515  
   516  	// Make-up codes between 64 and 1728.
   517  	{0x0040, "0000001111"},
   518  	{0x0080, "000011001000"},
   519  	{0x00C0, "000011001001"},
   520  	{0x0100, "000001011011"},
   521  	{0x0140, "000000110011"},
   522  	{0x0180, "000000110100"},
   523  	{0x01C0, "000000110101"},
   524  	{0x0200, "0000001101100"},
   525  	{0x0240, "0000001101101"},
   526  	{0x0280, "0000001001010"},
   527  	{0x02C0, "0000001001011"},
   528  	{0x0300, "0000001001100"},
   529  	{0x0340, "0000001001101"},
   530  	{0x0380, "0000001110010"},
   531  	{0x03C0, "0000001110011"},
   532  	{0x0400, "0000001110100"},
   533  	{0x0440, "0000001110101"},
   534  	{0x0480, "0000001110110"},
   535  	{0x04C0, "0000001110111"},
   536  	{0x0500, "0000001010010"},
   537  	{0x0540, "0000001010011"},
   538  	{0x0580, "0000001010100"},
   539  	{0x05C0, "0000001010101"},
   540  	{0x0600, "0000001011010"},
   541  	{0x0640, "0000001011011"},
   542  	{0x0680, "0000001100100"},
   543  	{0x06C0, "0000001100101"},
   544  
   545  	// Make-up codes between 1792 and 2560.
   546  	{0x0700, "00000001000"},
   547  	{0x0740, "00000001100"},
   548  	{0x0780, "00000001101"},
   549  	{0x07C0, "000000010010"},
   550  	{0x0800, "000000010011"},
   551  	{0x0840, "000000010100"},
   552  	{0x0880, "000000010101"},
   553  	{0x08C0, "000000010110"},
   554  	{0x0900, "000000010111"},
   555  	{0x0940, "000000011100"},
   556  	{0x0980, "000000011101"},
   557  	{0x09C0, "000000011110"},
   558  	{0x0A00, "000000011111"},
   559  }
   560  
   561  // COPY PASTE table_test.go END
   562  
   563  // This final comment makes the "END" above be followed by "\n\n".
   564  

View as plain text