From 02a0d7c30dea21680a8e13a63c884bf06e51e3e7 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 10:05:28 +0900 Subject: [PATCH 001/128] add procs --- src/pnm/types.nim | 9 +++++++++ src/pnm/util.nim | 29 ++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/pnm/types.nim diff --git a/src/pnm/types.nim b/src/pnm/types.nim new file mode 100644 index 0000000..38edb8f --- /dev/null +++ b/src/pnm/types.nim @@ -0,0 +1,9 @@ +type + Header* = object + descriptor*: string + col*, row*: int + max*: uint8 + Descriptor* = enum + P1, P2, P3, P4, P5, P6 + +var descriptors* = @[P1, P2, P3, P4, P5, P6] diff --git a/src/pnm/util.nim b/src/pnm/util.nim index f1436ae..7376aad 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -3,7 +3,10 @@ ## **You don't need to use directly this module for pnm module.** from sequtils import mapIt -from strutils import join +from strutils import join, split, parseInt, parseUint +import streams + +import types proc toBinSeq*(b: uint8): seq[uint8] = ## Return binary sequence from each bits of uint8. @@ -118,3 +121,27 @@ proc replaceWhiteSpace*(s: string): string = continue ignoreWhiteSpace = false result.add c + + +proc readHeader*(strm: Stream): Header = + # read descriptor + result.descriptor = strm.readLine() + doAssert result.descriptor[0] == 'P' + doAssert result.descriptor[1] in '1'..'6' + doAssert result.descriptor.len == 2 + + # read comment line + let b = strm.peekChar() + if b == '#': + # コメント行を読み取って破棄 + discard strm.readLine() + + # read column size and row size + let sizeLine = strm.readLine() + let colRow = sizeLine.split(" ") + result.col = colRow[0].parseInt() + result.row = colRow[1].parseInt() + + # read max data + if result.descriptor in ["P2", "P3", "P5", "P6"]: + result.max = strm.readLine().parseUint.uint8 From 75f408b415eb2834a829d8f69dea145d5859faff Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 20:36:59 +0900 Subject: [PATCH 002/128] impl ppm --- src/pnm/ppm.nim | 25 +++++++++++++++++++++++++ src/pnm/types.nim | 26 +++++++++++++++++++++++--- src/pnm/util.nim | 8 ++------ 3 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 src/pnm/ppm.nim diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim new file mode 100644 index 0000000..a83daed --- /dev/null +++ b/src/pnm/ppm.nim @@ -0,0 +1,25 @@ +import streams +from strutils import parseUint, split +from sequtils import mapIt +import types, util + +proc readPPMP3*(strm: Stream): seq[uint8] = + var line: string + while strm.readLine(line): + result.add(line.split(" ").mapIt(it.parseUInt.uint8)) + +proc readPPM*(strm: Stream): PPM = + result.header = strm.readHeader() + case result.header.descriptor + of P3: + result.data = strm.readPPMP3() + of P6: + result.data = strm.readAll().mapIt(it.uint8) + else: + # TODO: raise error + discard + +proc readPPMFile*(file: string): PPM = + var strm = newFileStream(file) + defer: strm.close() + result = strm.readPPM() diff --git a/src/pnm/types.nim b/src/pnm/types.nim index 38edb8f..991c26e 100644 --- a/src/pnm/types.nim +++ b/src/pnm/types.nim @@ -1,9 +1,29 @@ +from strformat import `&` + type Header* = object - descriptor*: string + descriptor*: Descriptor col*, row*: int max*: uint8 - Descriptor* = enum + PPM* = object + header*: Header + data*: seq[uint8] + Descriptor* {.pure.} = enum P1, P2, P3, P4, P5, P6 + IllegalFileDescriptorError* = object of Defect + ## Return this when file descriptor is wrong. + ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. + +func isPgmPnmDescriptors*(d: Descriptor): bool = + return d in @[P2, P3, P5, P6] -var descriptors* = @[P1, P2, P3, P4, P5, P6] +func toDescriptor*(str: string): Descriptor = + case str + of "P1": P1 + of "P2": P2 + of "P3": P3 + of "P4": P4 + of "P5": P5 + of "P6": P6 + else: + raise newException(IllegalFileDescriptorError, &"IllegalFileDescriptor: file descriptor is {fd}") diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 7376aad..37c29eb 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -122,13 +122,9 @@ proc replaceWhiteSpace*(s: string): string = ignoreWhiteSpace = false result.add c - proc readHeader*(strm: Stream): Header = # read descriptor - result.descriptor = strm.readLine() - doAssert result.descriptor[0] == 'P' - doAssert result.descriptor[1] in '1'..'6' - doAssert result.descriptor.len == 2 + result.descriptor = strm.readLine().toDescriptor() # read comment line let b = strm.peekChar() @@ -143,5 +139,5 @@ proc readHeader*(strm: Stream): Header = result.row = colRow[1].parseInt() # read max data - if result.descriptor in ["P2", "P3", "P5", "P6"]: + if result.descriptor.isPgmPnmDescriptors: result.max = strm.readLine().parseUint.uint8 From b32ec3ac15c4ac2f3a9a2117bdb8dd0d672c9366 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 20:52:05 +0900 Subject: [PATCH 003/128] impl pgm --- src/pnm/pgm.nim | 12 ++++++++++++ src/pnm/ppm.nim | 17 ++--------------- src/pnm/types.nim | 7 ++++--- src/pnm/util.nim | 16 ++++++++++++++++ 4 files changed, 34 insertions(+), 18 deletions(-) create mode 100644 src/pnm/pgm.nim diff --git a/src/pnm/pgm.nim b/src/pnm/pgm.nim new file mode 100644 index 0000000..b5f88cf --- /dev/null +++ b/src/pnm/pgm.nim @@ -0,0 +1,12 @@ +import streams +import types, util +export types + +proc readPGM*(strm: Stream): PGM = + result.header = strm.readHeader() + result.data = strm.readPGMPPMData(result.header.descriptor) + +proc readPGMFile*(file: string): PGM = + var strm = newFileStream(file) + defer: strm.close() + result = strm.readPGM() diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim index a83daed..0de4aef 100644 --- a/src/pnm/ppm.nim +++ b/src/pnm/ppm.nim @@ -1,23 +1,10 @@ import streams -from strutils import parseUint, split -from sequtils import mapIt import types, util - -proc readPPMP3*(strm: Stream): seq[uint8] = - var line: string - while strm.readLine(line): - result.add(line.split(" ").mapIt(it.parseUInt.uint8)) +export types proc readPPM*(strm: Stream): PPM = result.header = strm.readHeader() - case result.header.descriptor - of P3: - result.data = strm.readPPMP3() - of P6: - result.data = strm.readAll().mapIt(it.uint8) - else: - # TODO: raise error - discard + result.data = strm.readPGMPPMData(result.header.descriptor) proc readPPMFile*(file: string): PPM = var strm = newFileStream(file) diff --git a/src/pnm/types.nim b/src/pnm/types.nim index 991c26e..5eb487d 100644 --- a/src/pnm/types.nim +++ b/src/pnm/types.nim @@ -1,10 +1,11 @@ -from strformat import `&` - type Header* = object descriptor*: Descriptor col*, row*: int max*: uint8 + PGM* = object + header*: Header + data*: seq[uint8] PPM* = object header*: Header data*: seq[uint8] @@ -26,4 +27,4 @@ func toDescriptor*(str: string): Descriptor = of "P5": P5 of "P6": P6 else: - raise newException(IllegalFileDescriptorError, &"IllegalFileDescriptor: file descriptor is {fd}") + raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & str) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 37c29eb..0a0ca5c 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -141,3 +141,19 @@ proc readHeader*(strm: Stream): Header = # read max data if result.descriptor.isPgmPnmDescriptors: result.max = strm.readLine().parseUint.uint8 + +proc readP2P3Data*(strm: Stream): seq[uint8] = + ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 + var line: string + while strm.readLine(line): + result.add(line.split(" ").mapIt(it.parseUInt.uint8)) + +proc readPGMPPMData*(strm: Stream, descr: Descriptor): seq[uint8] = + ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 + case descr + of P2, P3: + result = strm.readP2P3Data() + of P5, P6: + result = strm.readAll().mapIt(it.uint8) + else: + raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & $descr) From 1d312b41e12fc743a1f767b0d3eaef8324d5c599 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 21:04:53 +0900 Subject: [PATCH 004/128] impl pbm --- src/pnm/pbm.nim | 12 ++++++++++++ src/pnm/types.nim | 3 +++ 2 files changed, 15 insertions(+) create mode 100644 src/pnm/pbm.nim diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim new file mode 100644 index 0000000..c8e321b --- /dev/null +++ b/src/pnm/pbm.nim @@ -0,0 +1,12 @@ +import streams +import types, util +export types + +proc readPBM*(strm: Stream): PBM = + result.header = strm.readHeader() + result.data = strm.readPGMPPMData(result.header.descriptor) + +proc readPBMFile*(file: string): PBM = + var strm = newFileStream(file) + defer: strm.close() + result = strm.readPBM() diff --git a/src/pnm/types.nim b/src/pnm/types.nim index 5eb487d..64fa707 100644 --- a/src/pnm/types.nim +++ b/src/pnm/types.nim @@ -3,6 +3,9 @@ type descriptor*: Descriptor col*, row*: int max*: uint8 + PBM* = object + header*: Header + data*: seq[uint8] PGM* = object header*: Header data*: seq[uint8] From 7ba7ec2106f3c7016d7b635b6d067743d9c69524 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 21:14:44 +0900 Subject: [PATCH 005/128] fix --- src/pnm/util.nim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 0a0ca5c..0fd417b 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -142,7 +142,7 @@ proc readHeader*(strm: Stream): Header = if result.descriptor.isPgmPnmDescriptors: result.max = strm.readLine().parseUint.uint8 -proc readP2P3Data*(strm: Stream): seq[uint8] = +proc readTextDataPart(strm: Stream): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 var line: string while strm.readLine(line): @@ -151,9 +151,9 @@ proc readP2P3Data*(strm: Stream): seq[uint8] = proc readPGMPPMData*(strm: Stream, descr: Descriptor): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 case descr - of P2, P3: - result = strm.readP2P3Data() - of P5, P6: + of P1, P2, P3: + result = strm.readTextDataPart() + of P4, P5, P6: result = strm.readAll().mapIt(it.uint8) else: raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & $descr) From 0eaa3b550aadb716d9f9c66d9f11b71323c717e3 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 21:15:29 +0900 Subject: [PATCH 006/128] fix --- src/pnm/pbm.nim | 2 +- src/pnm/pgm.nim | 2 +- src/pnm/ppm.nim | 2 +- src/pnm/util.nim | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index c8e321b..c540ee2 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -4,7 +4,7 @@ export types proc readPBM*(strm: Stream): PBM = result.header = strm.readHeader() - result.data = strm.readPGMPPMData(result.header.descriptor) + result.data = strm.readBinaryDataPart(result.header.descriptor) proc readPBMFile*(file: string): PBM = var strm = newFileStream(file) diff --git a/src/pnm/pgm.nim b/src/pnm/pgm.nim index b5f88cf..7a0f8fb 100644 --- a/src/pnm/pgm.nim +++ b/src/pnm/pgm.nim @@ -4,7 +4,7 @@ export types proc readPGM*(strm: Stream): PGM = result.header = strm.readHeader() - result.data = strm.readPGMPPMData(result.header.descriptor) + result.data = strm.readBinaryDataPart(result.header.descriptor) proc readPGMFile*(file: string): PGM = var strm = newFileStream(file) diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim index 0de4aef..053ba83 100644 --- a/src/pnm/ppm.nim +++ b/src/pnm/ppm.nim @@ -4,7 +4,7 @@ export types proc readPPM*(strm: Stream): PPM = result.header = strm.readHeader() - result.data = strm.readPGMPPMData(result.header.descriptor) + result.data = strm.readBinaryDataPart(result.header.descriptor) proc readPPMFile*(file: string): PPM = var strm = newFileStream(file) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 0fd417b..f3ce900 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -148,7 +148,7 @@ proc readTextDataPart(strm: Stream): seq[uint8] = while strm.readLine(line): result.add(line.split(" ").mapIt(it.parseUInt.uint8)) -proc readPGMPPMData*(strm: Stream, descr: Descriptor): seq[uint8] = +proc readBinaryDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 case descr of P1, P2, P3: From 2fe538b448c84a78f3df7bbf14c448c538d8bb09 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 21:16:14 +0900 Subject: [PATCH 007/128] delete --- src/pnm/util.nim | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index f3ce900..4659eba 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -155,5 +155,3 @@ proc readBinaryDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = result = strm.readTextDataPart() of P4, P5, P6: result = strm.readAll().mapIt(it.uint8) - else: - raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & $descr) From 61c5ceacd57ed98a62d605fc62bfeb61522d4c6b Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 22:03:42 +0900 Subject: [PATCH 008/128] impl write --- src/pnm/ppm.nim | 5 +++++ src/pnm/types.nim | 2 +- src/pnm/util.nim | 26 ++++++++++++++++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim index 053ba83..55a252c 100644 --- a/src/pnm/ppm.nim +++ b/src/pnm/ppm.nim @@ -10,3 +10,8 @@ proc readPPMFile*(file: string): PPM = var strm = newFileStream(file) defer: strm.close() result = strm.readPPM() + +proc writePPMFile*(fn: string, data: PPM) = + var strm = newFileStream(fn, fmWrite) + defer: strm.close() + strm.writeHeader(data.header) diff --git a/src/pnm/types.nim b/src/pnm/types.nim index 64fa707..f5f7e4a 100644 --- a/src/pnm/types.nim +++ b/src/pnm/types.nim @@ -18,7 +18,7 @@ type ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. -func isPgmPnmDescriptors*(d: Descriptor): bool = +func isPgmPnmDescriptor*(d: Descriptor): bool = return d in @[P2, P3, P5, P6] func toDescriptor*(str: string): Descriptor = diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 4659eba..d33e579 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -2,7 +2,7 @@ ## ## **You don't need to use directly this module for pnm module.** -from sequtils import mapIt +from sequtils import mapIt, distribute from strutils import join, split, parseInt, parseUint import streams @@ -139,7 +139,7 @@ proc readHeader*(strm: Stream): Header = result.row = colRow[1].parseInt() # read max data - if result.descriptor.isPgmPnmDescriptors: + if result.descriptor.isPgmPnmDescriptor: result.max = strm.readLine().parseUint.uint8 proc readTextDataPart(strm: Stream): seq[uint8] = @@ -155,3 +155,25 @@ proc readBinaryDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = result = strm.readTextDataPart() of P4, P5, P6: result = strm.readAll().mapIt(it.uint8) + +proc writeHeader*(strm: Stream, header: Header) = + strm.writeLine(header.descriptor) + strm.writeLine($header.col & " " & $header.row) + if header.descriptor.isPgmPnmDescriptor: + strm.writeLine(header.max) + +proc writeTextDataPartOfPGMOrPPM*(strm: Stream, data: seq[uint8], rowCount: int) = + for row in data.distribute(rowCount): + strm.writeLine(row.mapIt($it).join(" ")) + +proc writeDataPart*(strm: Stream, header: Header, data: seq[uint8]) = + case header.descriptor + of P1: + discard + of P2: + strm.writeTextDataPartOfPGMOrPPM(data, header.row) + of P3: + strm.writeTextDataPartOfPGMOrPPM(data, header.row * 3) + of P4, P5, P6: + for b in data: + strm.write(b) From fb607bf47ee157099d3b262daeda239ecb76089a Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 22:29:53 +0900 Subject: [PATCH 009/128] fix --- src/pnm/util.nim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index d33e579..eda1dd8 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -168,12 +168,12 @@ proc writeTextDataPartOfPGMOrPPM*(strm: Stream, data: seq[uint8], rowCount: int) proc writeDataPart*(strm: Stream, header: Header, data: seq[uint8]) = case header.descriptor - of P1: - discard - of P2: + of P1, P2: strm.writeTextDataPartOfPGMOrPPM(data, header.row) of P3: strm.writeTextDataPartOfPGMOrPPM(data, header.row * 3) - of P4, P5, P6: + of P4: + discard + of P5, P6: for b in data: strm.write(b) From ef4d535148f6c1820d6cfbbb03580d96184c68eb Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 22:44:59 +0900 Subject: [PATCH 010/128] fix --- src/pnm/util.nim | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index eda1dd8..52a3cce 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -162,18 +162,25 @@ proc writeHeader*(strm: Stream, header: Header) = if header.descriptor.isPgmPnmDescriptor: strm.writeLine(header.max) -proc writeTextDataPartOfPGMOrPPM*(strm: Stream, data: seq[uint8], rowCount: int) = +proc writeBinaryDataPartOfPBM*(strm: Stream, data: seq[uint8], rowCount: int) = for row in data.distribute(rowCount): - strm.writeLine(row.mapIt($it).join(" ")) + # strm.writeLine(row.mapIt($it).join(" ")) + discard + +proc writeTextDataPartOfPGMOrPPM*(strm: Stream, data: seq[uint8], rowCount: int, delim: string) = + for row in data.distribute(rowCount): + strm.writeLine(row.mapIt($it).join(delim)) proc writeDataPart*(strm: Stream, header: Header, data: seq[uint8]) = case header.descriptor - of P1, P2: - strm.writeTextDataPartOfPGMOrPPM(data, header.row) + of P1: + strm.writeTextDataPartOfPGMOrPPM(data, header.row, "") + of P2: + strm.writeTextDataPartOfPGMOrPPM(data, header.row, " ") of P3: - strm.writeTextDataPartOfPGMOrPPM(data, header.row * 3) + strm.writeTextDataPartOfPGMOrPPM(data, header.row * 3, " ") of P4: - discard + strm.writeBinaryDataPartOfPBM(data, header.row) of P5, P6: for b in data: strm.write(b) From edcacab49383b8490b3db46d7aebb9bfd77097b4 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 22:58:37 +0900 Subject: [PATCH 011/128] fix --- src/pnm/pbm.nim | 6 ++++++ src/pnm/pgm.nim | 6 ++++++ src/pnm/ppm.nim | 3 ++- src/pnm/util.nim | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index c540ee2..bdf31c9 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -10,3 +10,9 @@ proc readPBMFile*(file: string): PBM = var strm = newFileStream(file) defer: strm.close() result = strm.readPBM() + +proc writePBMFile*(fn: string, data: PBM) = + var strm = newFileStream(fn, fmWrite) + defer: strm.close() + strm.writeHeaderPart(data.header) + strm.writeDataPart(data.header, data.data) diff --git a/src/pnm/pgm.nim b/src/pnm/pgm.nim index 7a0f8fb..d3ed5fb 100644 --- a/src/pnm/pgm.nim +++ b/src/pnm/pgm.nim @@ -10,3 +10,9 @@ proc readPGMFile*(file: string): PGM = var strm = newFileStream(file) defer: strm.close() result = strm.readPGM() + +proc writePGMFile*(fn: string, data: PGM) = + var strm = newFileStream(fn, fmWrite) + defer: strm.close() + strm.writeHeaderPart(data.header) + strm.writeDataPart(data.header, data.data) diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim index 55a252c..38b9ced 100644 --- a/src/pnm/ppm.nim +++ b/src/pnm/ppm.nim @@ -14,4 +14,5 @@ proc readPPMFile*(file: string): PPM = proc writePPMFile*(fn: string, data: PPM) = var strm = newFileStream(fn, fmWrite) defer: strm.close() - strm.writeHeader(data.header) + strm.writeHeaderPart(data.header) + strm.writeDataPart(data.header, data.data) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 52a3cce..08004ab 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -156,7 +156,7 @@ proc readBinaryDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = of P4, P5, P6: result = strm.readAll().mapIt(it.uint8) -proc writeHeader*(strm: Stream, header: Header) = +proc writeHeaderPart*(strm: Stream, header: Header) = strm.writeLine(header.descriptor) strm.writeLine($header.col & " " & $header.row) if header.descriptor.isPgmPnmDescriptor: From f0e19f8e8715da55ed5a10b918561b1841d51b85 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 23:00:27 +0900 Subject: [PATCH 012/128] change --- src/pnm.nim | 747 +--------------------------------------------------- 1 file changed, 2 insertions(+), 745 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index c96f48c..1715b11 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -235,748 +235,5 @@ ## * `(EN) Portable Anymap - Wikipedia `_ ## * `(JA) PNM(画像フォーマット) - Wikipedia `_ -from strformat import `&` -from sequtils import mapIt, filterIt, concat -import strutils - -import pnm/util - -type - PBMObj* = object - ## PBM object. - ## Don't directly use this type. - fileDescriptor*: string ## File descriptor (P1 or P4) - col*, row*: int ## Column count - data*: seq[uint8] ## Byte (pixel) data - PBM* = ref PBMObj - ## PBM ref object. - ## Procedures use this type. Not PBMobj. - PGMObj* = object - ## PGM object. - ## Don't directly use this type. - fileDescriptor*: string ## File descriptor (P2 or P5) - col*, row*: int ## Column count - max*: uint8 ## Max value - data*: seq[uint8] ## Byte (pixel) data - PGM* = ref PGMObj - ## PGM ref object. - ## Procedures use this type. Not PGMObj. - PPMObj* = object - ## PPM object. - ## Don't directly use this type. - fileDescriptor*: string ## File descriptor (P3 or P6) - col*, row*: int ## Column count - max*: uint8 ## Max value - data*: seq[uint8] ## Byte (pixel) data - PPM* = ref PPMObj - ## PPM ref object. - ## Procedures use this type. Not PPMObj. - IllegalFileDescriptorError* = object of Defect - ## Return this when file descriptor is wrong. - ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. - IllegalColumnRowError* = object of Defect - ## Return this when column or row value is wrong. - IllegalMaxValueError* = object of Defect - ## Return this when max value is wrong. - -const - pbmFileDescriptorP1* = "P1" - pgmFileDescriptorP2* = "P2" - ppmFileDescriptorP3* = "P3" - pbmFileDescriptorP4* = "P4" - pgmFileDescriptorP5* = "P5" - ppmFileDescriptorP6* = "P6" - -proc newPBM*(fileDescriptor: string, col, row: int, data: seq[uint8]): PBM = - ## Return new PBM. - runnableExamples: - let p1 = newPBM(pbmFileDescriptorP1, 1, 1, @[1'u8]) - let p4 = newPBM(pbmFileDescriptorP4, 1, 1, @[1'u8]) - new result - result.fileDescriptor = fileDescriptor - result.col = col - result.row = row - result.data = data - -proc newPGM*(fileDescriptor: string, col, row: int, max: uint8, data: seq[uint8]): PGM = - ## Return new PGM. - runnableExamples: - let p2 = newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[1'u8]) - let p5 = newPGM(pgmFileDescriptorP5, 1, 1, 255'u8, @[1'u8]) - new result - result.fileDescriptor = fileDescriptor - result.col = col - result.row = row - result.max = max - result.data = data - -proc newPGM*(fileDescriptor: string, col, row: int, data: seq[uint8]): PGM = - ## Return a new PGM with the maximum brightness of the data as the maximum brightness of the image. - runnableExamples: - let p2 = newPGM(pgmFileDescriptorP2, 1, 1, @[1'u8]) - let p5 = newPGM(pgmFileDescriptorP5, 1, 1, @[1'u8]) - result = newPGM(fileDescriptor, col, row, data.max, data) - -proc newPPM*(fileDescriptor: string, col, row: int, max: uint8, data: seq[uint8]): PPM = - ## Return new PPM. - runnableExamples: - let p3 = newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[255'u8, 255, 255]) - let p6 = newPPM(ppmFileDescriptorP6, 1, 1, 255'u8, @[255'u8, 255, 255]) - new result - result.fileDescriptor = fileDescriptor - result.col = col - result.row = row - result.max = max - result.data = data - -proc newPPM*(fileDescriptor: string, col, row: int, data: seq[uint8]): PPM = - ## Return a new PPM with the maximum brightness of the data as the maximum brightness of the image. - runnableExamples: - let p3 = newPPM(ppmFileDescriptorP3, 1, 1, @[255'u8, 255, 255]) - let p6 = newPPM(ppmFileDescriptorP6, 1, 1, @[255'u8, 255, 255]) - result = newPPM(fileDescriptor, col, row, data.max, data) - -proc formatP1*(self: PBM): string = - ## Return formatted string for PBM P1. - runnableExamples: - let p1 = newPBM(pbmFileDescriptorP1, 1, 1, @[0b1000_0000'u8]) - doAssert p1.formatP1 == "P1\n1 1\n1" - let data = self.data.toBinString(self.col).toMatrixString(self.col) - result = &"""{self.fileDescriptor} -{self.col} {self.row} -{data}""" - -proc formatP2*(self: PGM): string = - ## Return formatted string for PGM P2. - runnableExamples: - let p = newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[2'u8]) - doAssert p.formatP2 == "P2\n1 1\n255\n2" - let data = self.data.toMatrixString(self.col) - result = &"""{self.fileDescriptor} -{self.col} {self.row} -{self.max} -{data}""" - -proc formatP3*(self: PPM): string = - ## Return formatted string for PPM P3. - runnableExamples: - let p = newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[255'u8, 255, 255]) - doAssert p.formatP3 == "P3\n1 1\n255\n255 255 255" - let data = self.data.toMatrixString 3 - result = &"""{self.fileDescriptor} -{self.col} {self.row} -{self.max} -{data}""" - -proc formatP4*(self: PBM): seq[uint8] = - ## Return formatted byte data for PBM P4. - runnableExamples: - let p4 = newPBM(pbmFileDescriptorP4, 1, 1, @[0b1000_0000'u8]) - doAssert p4.formatP4 == @[ - 'P'.uint8, '4'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - 0b10000000'u8, - ] - # header part - # ----------- - # file descriptor - result.add self.fileDescriptor.mapIt(it.uint8) - result.add '\n'.uint8 - # col and row - result.add self.col.`$`.mapIt(it.uint8) - result.add ' '.uint8 - result.add self.row.`$`.mapIt(it.uint8) - result.add '\n'.uint8 - # data part - # --------- - result.add self.data - -proc formatP5*(self: PGM): seq[uint8] = - ## Return formatted byte data for PGM P5. - runnableExamples: - let p = newPGM(pgmFileDescriptorP5, 1, 1, 255'u8, @[2'u8]) - doAssert p.formatP5 == @[ - 'P'.uint8, '5'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8, - 2'u8, - ] - # header part - # ----------- - # file descriptor - result.add self.fileDescriptor.mapIt(it.uint8) - result.add '\n'.uint8 - # col and row - result.add self.col.`$`.mapIt(it.uint8) - result.add ' '.uint8 - result.add self.row.`$`.mapIt(it.uint8) - result.add '\n'.uint8 - result.add self.max.`$`.mapIt(it.uint8) - result.add '\n'.uint8 - # data part - # --------- - result.add self.data - -proc formatP6*(self: PPM): seq[uint8] = - ## Return formatted byte data for PPM P6. - runnableExamples: - let p = newPPM(ppmFileDescriptorP6, 1, 1, 255'u8, @[255'u8, 255, 255]) - doAssert p.formatP6 == @[ - 'P'.uint8, '6'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8, - 255'u8, 255, 255, - ] - # header part - # ----------- - # file descriptor - result.add self.fileDescriptor.mapIt(it.uint8) - result.add '\n'.uint8 - # col and row - result.add self.col.`$`.mapIt(it.uint8) - result.add ' '.uint8 - result.add self.row.`$`.mapIt(it.uint8) - result.add '\n'.uint8 - result.add self.max.`$`.mapIt(it.uint8) - result.add '\n'.uint8 - # data part - # --------- - result.add self.data - -proc parsePBM*(s: string): PBM = - ## Return PBM that is parsed from string. - ## This proc is function for PBM P1. - ## You should validate string to use this proc with `validatePBM proc - ## <#validatePBM,openArray[uint8]>`_ . - runnableExamples: - doAssert "P1\n1 1\n1".parsePBM[] == newPBM(pbmFileDescriptorP1, 1, 1, @[0b1000_0000'u8])[] - ## P1用 - new(result) - var lines: seq[string] - for line in s.splitLines: - if not line.startsWith "#": - lines.add line - - if lines.len < 3: - return - let colRow = lines[1].split(" ") - if colRow.len < 2: - return - - result.fileDescriptor = lines[0] - result.col = colRow[0].parseInt - result.row = colRow[1].parseInt - for line in lines[2..^1]: - result.data.add line.split(" ").mapIt(it.parseUInt.uint8).toBin - -proc parsePBM*(s: openArray[uint8]): PBM = - ## Return PBM that is parsed from uint8 sequence. - ## This proc is function for PBM P4. - ## You should validate string to use this proc with `validatePBM proc - ## <#validatePBM,openArray[uint8]>`_ . - runnableExamples: - doAssert @[ - 'P'.uint8, '4'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - 0b1000_0000'u8, - ].parsePBM[] == newPBM(pbmFileDescriptorP4, 1, 1, @[0b1000_0000'u8])[] - new(result) - var dataPos = 3 - var colRowLine: string - for i, b in s[3..^1]: - if b == '\n'.uint8: - dataPos += (i+1) - break - colRowLine.add b.char - let colRow = colRowLine.split(" ") - result.fileDescriptor = s[0..1].mapIt(it.char).join("") - result.col = colRow[0].parseInt - result.row = colRow[1].parseInt - result.data = s[dataPos..^1] - -proc parsePGM*(s: string): PGM = - ## Return PGM that is parsed from string. - ## This proc is function for PGM P2. - ## You should validate string to use this proc with `validatePGM proc - ## <#validatePGM,openArray[uint8]>`_ . - runnableExamples: - doAssert "P2\n1 1\n255\n2".parsePGM[] == newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[2'u8])[] - doAssert "P5\n1 1\n255\n2".parsePGM[] == newPGM(pgmFileDescriptorP5, 1, 1, 255'u8, @[2'u8])[] - new(result) - var lines: seq[string] - for line in s.replaceWhiteSpace.splitLines.mapIt(it.strip): - if not line.startsWith "#": - lines.add line - - if lines.len < 3: - return - let colRow = lines[1].split(" ") - if colRow.len < 2: - return - - result.fileDescriptor = lines[0] - result.col = colRow[0].parseInt - result.row = colRow[1].parseInt - result.max = lines[2].parseUint.uint8 - for line in lines[3..^1]: - result.data.add line.split(" ").mapIt(it.parseUInt.uint8) - -proc parsePGM*(s: openArray[uint8]): PGM = - ## Return PGM that is parsed from string. - ## This proc is function for PGM P2. - ## You should validate string to use this proc with `validatePGM proc - ## <#validatePGM,openArray[uint8]>`_ . - runnableExamples: - doAssert @['P'.uint8, '2'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8, - 2'u8, - ].parsePGM[] == newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[2'u8])[] - new(result) - var dataPos = 3 - var colRowLine: string - for i, b in s[3..^1]: - if b == '\n'.uint8: - dataPos += (i+1) - break - colRowLine.add b.char - let colRow = colRowLine.split(" ") - result.fileDescriptor = s[0..1].mapIt(it.char).join("") - result.col = colRow[0].parseInt - result.row = colRow[1].parseInt - var maxV: string - for i, b in s[dataPos..^1]: - if b == '\n'.uint8: - dataPos += (i+1) - break - maxV.add b.char - result.max = maxV.parseUint.uint8 - result.data = s[dataPos..^1] - -proc parsePPM*(s: string): PPM = - ## Return PPM that is parsed from string. - ## This proc is function for PPM P3. - ## You should validate string to use this proc with `validatePPM proc - ## <#validatePPM,openArray[uint8]>`_ . - runnableExamples: - doAssert "P3\n1 1\n255\n255 255 255".parsePPM[] == newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[255'u8, 255, 255])[] - new(result) - var lines: seq[string] - for line in s.replaceWhiteSpace.splitLines.mapIt(it.strip): - if not line.startsWith "#": - lines.add line - - if lines.len < 3: - return - let colRow = lines[1].split(" ") - if colRow.len < 2: - return - - result.fileDescriptor = lines[0] - result.col = colRow[0].parseInt - result.row = colRow[1].parseInt - result.max = lines[2].parseUint.uint8 - for line in lines[3..^1]: - result.data.add line.split(" ").mapIt(it.parseUInt.uint8) - -proc parsePPM*(s: openArray[uint8]): PPM = - ## Return PPM that is parsed from string. - ## This proc is function for PPM P3. - ## You should validate string to use this proc with `validatePPM proc - ## <#validatePPM,openArray[uint8]>`_ . - runnableExamples: - doAssert @['P'.uint8, '6'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8, - 255'u8, 255, 255 - ].parsePPM[] == newPPM(ppmFileDescriptorP6, 1, 1, 255'u8, @[255'u8, 255, 255])[] - new(result) - var dataPos = 3 - var colRowLine: string - for i, b in s[3..^1]: - if b == '\n'.uint8: - dataPos += (i+1) - break - colRowLine.add b.char - let colRow = colRowLine.split(" ") - result.fileDescriptor = s[0..1].mapIt(it.char).join("") - result.col = colRow[0].parseInt - result.row = colRow[1].parseInt - var maxV: string - for i, b in s[dataPos..^1]: - if b == '\n'.uint8: - dataPos += (i+1) - break - maxV.add b.char - result.max = maxV.parseUint.uint8 - result.data = s[dataPos..^1] - -proc validateFileDescriptor(s: openArray[uint8], fds: varargs[string]) = - ## Validate file descriptor of `s`. - ## Validation targets are `fds`. - ## Raise IllegalFileDescriptorError when illegal was found. - let fd = s[0..1].mapIt(it.char).join("") - if fd notin fds: - raise newException(IllegalFileDescriptorError, &"IllegalFileDescriptor: file descriptor is {fd}") - -proc validateColumnAndRow(s: openArray[uint8], start: int) = - ## Validate column and row value of `s`. - ## Column and row value must be Digits. - ## Raise IllegalColumnRowError when illegal was found. - # check column and row - var whiteSpaceCount: int - var lfExist: bool - for i, b in s[start..^1]: - let c = b.char - if c == '\n': - lfExist = true - break - if c == ' ': - whiteSpaceCount.inc - continue - if c notin Digits: - raise newException(IllegalColumnRowError, &"byteIndex is {i}, value is {c}") - if whiteSpaceCount != 1: - raise newException(IllegalColumnRowError, &"whitespace count is {whiteSpaceCount}") - -proc validateMaxValue(s: openArray[uint8], start: int) = - ## Validate max value of `s`. - ## Max value must be Digits. - ## Raise IllegalMaxValueError when illegal was found. - for i, b in s[start..^1]: - let c = b.char - if c == '\n': - break - if c notin Digits: - raise newException(IllegalMaxValueError, &"byteIndex is {i}, value is {c}") - -proc validatePBM*(s: openArray[uint8]) = - ## Validate PBM data format. - ## - ## Validating contents are: - ## 1. It is P1 or P4 that 2 byte data at the head. - ## 2. It is decimal number that data on 2 line. - ## - ## Raise IllegalFileDescriptorError or IllegalColumnRowError when illegal was - ## found. - runnableExamples: - ## No error - validatePBM(@['P'.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - validatePBM(@['P'.uint8, '4'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - let s2 = s.removeCommentLine - s2.validateFileDescriptor(pbmFileDescriptorP1, pbmFileDescriptorP4) - s2.validateColumnAndRow 3 - -proc validatePGM*(s: openArray[uint8]) = - ## Validate PGM data format. - ## - ## Validating contents are: - ## 1. It is P2 or P5 that 2 byte data at the head. - ## 2. It is decimal number that data on 2 line. - ## 3. It is max value of data that data on 3 line. - ## - ## Raise IllegalFileDescriptorError or IllegalColumnRowError when illegal was - ## found. - runnableExamples: - ## No error - validatePGM(@['P'.uint8, '2'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - validatePGM(@['P'.uint8, '5'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - let s2 = s.removeCommentLine - s2.validateFileDescriptor(pgmFileDescriptorP2, pgmFileDescriptorP5) - s2.validateColumnAndRow 3 - var lfCnt: int - var pos: int - for i, v in s2: - if v.char == '\n': - lfCnt.inc - if 2 <= lfCnt: - pos = (i+1) - break - s2.validateMaxValue pos - -proc validatePPM*(s: openArray[uint8]) = - ## Validate PPM data format. - ## - ## Validating contents are: - ## 1. It is P3 or P6 that 2 byte data at the head. - ## 2. It is decimal number that data on 2 line. - ## 3. It is max value of data that data on 3 line. - ## - ## Raise IllegalFileDescriptorError or IllegalColumnRowError when illegal was - ## found. - runnableExamples: - ## No error - validatePPM(@['P'.uint8, '3'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8, '\n'.uint8, - '1'.uint8]) - validatePPM(@['P'.uint8, '6'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8, '\n'.uint8, - '1'.uint8]) - let s2 = s.removeCommentLine - s2.validateFileDescriptor(ppmFileDescriptorP3, ppmFileDescriptorP6) - s2.validateColumnAndRow 3 - var lfCnt: int - var pos: int - for i, v in s2: - if v.char == '\n': - lfCnt.inc - if 2 <= lfCnt: - pos = (i+1) - break - s2.validateMaxValue pos - -proc readPBM*(f: File): PBM = - ## Return PBM (P1 or P4) from file. This proc validates data before reading - ## data. Raise errors when illegal was found. At seeing description of erros, - ## see `validatePBM proc `_ - runnableExamples: - try: - var f = open("p1.pbm") - let p = f.readPBM - ## do something... - f.close - except: - stderr.writeLine getCurrentExceptionMsg() - let data = f.readAll.mapIt(it.uint8) - f.setFilePos 0 - validatePBM(data) - - let fd = f.readLine - f.setFilePos 0 - case fd - of pbmFileDescriptorP1: - result = f.readAll.parsePBM - of pbmFileDescriptorP4: - result = data.parsePBM - else: discard - -proc readPGM*(f: File): PGM = - ## Return PGM (P2 or P5) from file. This proc validates data before reading - ## data. Raise errors when illegal was found. At seeing description of erros, - ## see `validatePGM proc `_ - runnableExamples: - try: - var f = open("p2.pgm") - let p = f.readPGM - ## do something... - f.close - except: - stderr.writeLine getCurrentExceptionMsg() - let data = f.readAll.mapIt(it.uint8) - f.setFilePos 0 - validatePGM(data) - - let fd = f.readLine - f.setFilePos 0 - case fd - of pgmFileDescriptorP2: - result = f.readAll.parsePGM - of pgmFileDescriptorP5: - result = data.parsePGM - else: discard - -proc readPPM*(f: File): PPM = - ## Return PPM (P3 or P6) from file. This proc validates data before reading - ## data. Raise errors when illegal was found. At seeing description of erros, - ## see `validatePPM proc `_ - runnableExamples: - try: - var f = open("p3.ppm") - let p = f.readPPM - ## do something... - f.close - except: - stderr.writeLine getCurrentExceptionMsg() - let data = f.readAll.mapIt(it.uint8) - f.setFilePos 0 - validatePPM(data) - - let fd = f.readLine - f.setFilePos 0 - case fd - of ppmFileDescriptorP3: - result = f.readAll.parsePPM - of ppmFileDescriptorP6: - result = data.parsePPM - else: discard - -proc readPBMFile*(fn: string): PBM = - ## Return PBM (P1 or P4) from file. This proc validates data before reading - ## data. Raise errors when illegal was found. At seeing description of erros, - ## see `validatePBM proc `_ - runnableExamples: - try: - let p = readPBMFile("p1.pbm") - ## do something... - except: - stderr.writeLine getCurrentExceptionMsg() - var f = open(fn) - defer: f.close - result = f.readPBM - -proc readPGMFile*(fn: string): PGM = - ## Return PGM (P2 or P5) from file. This proc validates data before reading - ## data. Raise errors when illegal was found. At seeing description of erros, - ## see `validatePGM proc `_ - runnableExamples: - try: - let p = readPGMFile("p2.pgm") - ## do something... - except: - stderr.writeLine getCurrentExceptionMsg() - var f = open(fn) - defer: f.close - result = f.readPGM - -proc readPPMFile*(fn: string): PPM = - ## Return PPM (P3 or P6) from file. This proc validates data before reading - ## data. Raise errors when illegal was found. At seeing description of erros, - ## see `validatePPM proc `_ - runnableExamples: - try: - let p = readPPMFile("p3.ppm") - ## do something... - except: - stderr.writeLine getCurrentExceptionMsg() - var f = open(fn) - defer: f.close - result = f.readPPM - -proc writePBM*(f: File, data: PBM) = - ## Write PBM (P1 or P4) to file. - ## Raise IllegalFileDescriptorError when illegal was found from file - ## descriptor. - runnableExamples: - from os import removeFile - try: - let p1 = newPBM(pbmFileDescriptorP1, 1, 1, @[1'u8]) - var f = open("p1.pbm", fmWrite) - f.writePBM p1 - f.close - removeFile "p1.pbm" - except: - stderr.writeLine getCurrentExceptionMsg() - let fd = data.fileDescriptor - case fd - of pbmFileDescriptorP1: - f.write data.formatP1 - of pbmFileDescriptorP4: - let bin = data.formatP4 - discard f.writeBytes(bin, 0, bin.len) - else: - raise newException(IllegalFileDescriptorError, &"file descriptor is {fd}") - -proc writePGM*(f: File, data: PGM) = - ## Write PGM (P2 or P5) to file. - ## Raise IllegalFileDescriptorError when illegal was found from file - ## descriptor. - runnableExamples: - from os import removeFile - try: - let p1 = newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[1'u8]) - var f = open("p2.pgm", fmWrite) - f.writePGM p1 - f.close - removeFile "p2.pgm" - except: - stderr.writeLine getCurrentExceptionMsg() - let fd = data.fileDescriptor - case fd - of pgmFileDescriptorP2: - f.write data.formatP2 - of pgmFileDescriptorP5: - let bin = data.formatP5 - discard f.writeBytes(bin, 0, bin.len) - else: - raise newException(IllegalFileDescriptorError, &"file descriptor is {fd}") - -proc writePPM*(f: File, data: PPM) = - ## Write PPM (P3 or P6) to file. - ## Raise IllegalFileDescriptorError when illegal was found from file - ## descriptor. - runnableExamples: - from os import removeFile - try: - let p1 = newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[1'u8]) - var f = open("p3.ppm", fmWrite) - f.writePPM p1 - f.close - removeFile "p3.ppm" - except: - stderr.writeLine getCurrentExceptionMsg() - let fd = data.fileDescriptor - case fd - of ppmFileDescriptorP3: - f.write data.formatP3 - of ppmFileDescriptorP6: - let bin = data.formatP6 - discard f.writeBytes(bin, 0, bin.len) - else: - raise newException(IllegalFileDescriptorError, &"file descriptor is {fd}") - -proc writePBMFile*(fn: string, data: PBM) = - ## Write PBM (P1 or P4) to file. - ## Raise IllegalFileDescriptorError when illegal was found from file - ## descriptor. - runnableExamples: - from os import removeFile - try: - let p1 = newPBM(pbmFileDescriptorP1, 1, 1, @[1'u8]) - writePBMFile "p1.pbm", p1 - removeFile "p1.pbm" - except: - stderr.writeLine getCurrentExceptionMsg() - var f = open(fn, fmWrite) - defer: f.close - f.writePBM data - -proc writePGMFile*(fn: string, data: PGM) = - ## Write PGM (P2 or P5) to file. - ## Raise IllegalFileDescriptorError when illegal was found from file - ## descriptor. - runnableExamples: - from os import removeFile - try: - let p1 = newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[1'u8]) - writePGMFile "p2.pgm", p1 - removeFile "p2.pgm" - except: - stderr.writeLine getCurrentExceptionMsg() - var f = open(fn, fmWrite) - defer: f.close - f.writePGM data - -proc writePPMFile*(fn: string, data: PPM) = - ## Write PPM (P3 or P6) to file. - ## Raise IllegalFileDescriptorError when illegal was found from file - ## descriptor. - runnableExamples: - from os import removeFile - try: - let p1 = newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[1'u8]) - writePPMFile "p3.ppm", p1 - removeFile "p3.ppm" - except: - stderr.writeLine getCurrentExceptionMsg() - var f = open(fn, fmWrite) - defer: f.close - f.writePPM data - -proc `$`*(self: PBM): string = - result = $self[] - -proc `$`*(self: PGM): string = - result = $self[] - -proc `$`*(self: PPM): string = - result = $self[] +import pnm/[pbm, pgm, ppm, types] +export pbm, pgm, ppm, types From 78de44a25b21a6abca3e91e83d4078db9d3f8319 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 23:00:32 +0900 Subject: [PATCH 013/128] rename --- tests/{tpnm.nim => bak.tpnm.nim} | 0 tests/{tutil.nim => bak.tutil.nim} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/{tpnm.nim => bak.tpnm.nim} (100%) rename tests/{tutil.nim => bak.tutil.nim} (100%) diff --git a/tests/tpnm.nim b/tests/bak.tpnm.nim similarity index 100% rename from tests/tpnm.nim rename to tests/bak.tpnm.nim diff --git a/tests/tutil.nim b/tests/bak.tutil.nim similarity index 100% rename from tests/tutil.nim rename to tests/bak.tutil.nim From c2d940d03060596cc5ea3b262476921d223973f0 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 23:01:57 +0900 Subject: [PATCH 014/128] rename --- src/pnm/pbm.nim | 2 +- src/pnm/pgm.nim | 2 +- src/pnm/ppm.nim | 2 +- src/pnm/util.nim | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index bdf31c9..38e40c0 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -4,7 +4,7 @@ export types proc readPBM*(strm: Stream): PBM = result.header = strm.readHeader() - result.data = strm.readBinaryDataPart(result.header.descriptor) + result.data = strm.readDataPart(result.header.descriptor) proc readPBMFile*(file: string): PBM = var strm = newFileStream(file) diff --git a/src/pnm/pgm.nim b/src/pnm/pgm.nim index d3ed5fb..2933cb1 100644 --- a/src/pnm/pgm.nim +++ b/src/pnm/pgm.nim @@ -4,7 +4,7 @@ export types proc readPGM*(strm: Stream): PGM = result.header = strm.readHeader() - result.data = strm.readBinaryDataPart(result.header.descriptor) + result.data = strm.readDataPart(result.header.descriptor) proc readPGMFile*(file: string): PGM = var strm = newFileStream(file) diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim index 38b9ced..88e07ae 100644 --- a/src/pnm/ppm.nim +++ b/src/pnm/ppm.nim @@ -4,7 +4,7 @@ export types proc readPPM*(strm: Stream): PPM = result.header = strm.readHeader() - result.data = strm.readBinaryDataPart(result.header.descriptor) + result.data = strm.readDataPart(result.header.descriptor) proc readPPMFile*(file: string): PPM = var strm = newFileStream(file) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 08004ab..fdf7850 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -148,7 +148,7 @@ proc readTextDataPart(strm: Stream): seq[uint8] = while strm.readLine(line): result.add(line.split(" ").mapIt(it.parseUInt.uint8)) -proc readBinaryDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = +proc readDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 case descr of P1, P2, P3: From 42f2f1054b82f03d59a2d1e15b51df60e92cf589 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 23:03:20 +0900 Subject: [PATCH 015/128] rename --- src/pnm/pbm.nim | 2 +- src/pnm/pgm.nim | 2 +- src/pnm/ppm.nim | 2 +- src/pnm/util.nim | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index 38e40c0..502b23c 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -3,7 +3,7 @@ import types, util export types proc readPBM*(strm: Stream): PBM = - result.header = strm.readHeader() + result.header = strm.readHeaderPart() result.data = strm.readDataPart(result.header.descriptor) proc readPBMFile*(file: string): PBM = diff --git a/src/pnm/pgm.nim b/src/pnm/pgm.nim index 2933cb1..6450c1d 100644 --- a/src/pnm/pgm.nim +++ b/src/pnm/pgm.nim @@ -3,7 +3,7 @@ import types, util export types proc readPGM*(strm: Stream): PGM = - result.header = strm.readHeader() + result.header = strm.readHeaderPart() result.data = strm.readDataPart(result.header.descriptor) proc readPGMFile*(file: string): PGM = diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim index 88e07ae..103dd9f 100644 --- a/src/pnm/ppm.nim +++ b/src/pnm/ppm.nim @@ -3,7 +3,7 @@ import types, util export types proc readPPM*(strm: Stream): PPM = - result.header = strm.readHeader() + result.header = strm.readHeaderPart() result.data = strm.readDataPart(result.header.descriptor) proc readPPMFile*(file: string): PPM = diff --git a/src/pnm/util.nim b/src/pnm/util.nim index fdf7850..9d1e779 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -122,7 +122,7 @@ proc replaceWhiteSpace*(s: string): string = ignoreWhiteSpace = false result.add c -proc readHeader*(strm: Stream): Header = +proc readHeaderPart*(strm: Stream): Header = # read descriptor result.descriptor = strm.readLine().toDescriptor() From 993e4b6627894fc2c84b25775bbaa361246524f5 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 23:09:14 +0900 Subject: [PATCH 016/128] impl --- src/pnm/util.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 9d1e779..53b214d 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -164,8 +164,8 @@ proc writeHeaderPart*(strm: Stream, header: Header) = proc writeBinaryDataPartOfPBM*(strm: Stream, data: seq[uint8], rowCount: int) = for row in data.distribute(rowCount): - # strm.writeLine(row.mapIt($it).join(" ")) - discard + for b in row.toBin: + strm.write(b) proc writeTextDataPartOfPGMOrPPM*(strm: Stream, data: seq[uint8], rowCount: int, delim: string) = for row in data.distribute(rowCount): From 483f98fa9574a555a66aa7d9667b388ecbb22817 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 23:15:17 +0900 Subject: [PATCH 017/128] fix p1 --- src/pnm/util.nim | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 53b214d..cd3142a 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -2,8 +2,8 @@ ## ## **You don't need to use directly this module for pnm module.** -from sequtils import mapIt, distribute -from strutils import join, split, parseInt, parseUint +from sequtils import mapIt, distribute, toSeq +from strutils import join, split, parseInt, parseUint, replace import streams import types @@ -142,6 +142,13 @@ proc readHeaderPart*(strm: Stream): Header = if result.descriptor.isPgmPnmDescriptor: result.max = strm.readLine().parseUint.uint8 +proc readTextDataPartOfP1(strm: Stream): seq[uint8] = + ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 + # P1は空白文字があってもなくても良い + var line: string + while strm.readLine(line): + result.add(toSeq(line.replace(" ", "").items).mapIt(it.uint8)) + proc readTextDataPart(strm: Stream): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 var line: string @@ -151,7 +158,9 @@ proc readTextDataPart(strm: Stream): seq[uint8] = proc readDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 case descr - of P1, P2, P3: + of P1: + result = strm.readTextDataPartOfP1() + of P2, P3: result = strm.readTextDataPart() of P4, P5, P6: result = strm.readAll().mapIt(it.uint8) From 9279c312830c2e9b0e981ae1059807981209dc17 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 23:18:34 +0900 Subject: [PATCH 018/128] TODO --- src/pnm/util.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index cd3142a..8d7b4dd 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -162,7 +162,9 @@ proc readDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = result = strm.readTextDataPartOfP1() of P2, P3: result = strm.readTextDataPart() - of P4, P5, P6: + of P4: + discard # TODO + of P5, P6: result = strm.readAll().mapIt(it.uint8) proc writeHeaderPart*(strm: Stream, header: Header) = From 798e7faf467a7c3b001db5a76602450489d74ec8 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 2 Feb 2021 23:23:47 +0900 Subject: [PATCH 019/128] wip --- src/pnm/util.nim | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 8d7b4dd..31c7a8d 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -89,6 +89,12 @@ proc toBin*(arr: openArray[uint8], col: int = 8): seq[uint8] = if data != 0: result.add data shl (8 - (i mod 8)) +proc toBitSeq*(data: openArray[uint8], col: int): seq[uint8] = + ## Returns sequences that binary sequence is converted to uint8 every 8 bits. + runnableExamples: + doAssert @[255'u8, 127].toBitSeq(9) == @[1'u8, 1, 1, 1, 1, 1, 1, 1, 1] + discard + proc removeCommentLine*(s: openArray[uint8]): seq[uint8] = ## Return sequence that removed comment line. ## Range of comment is from '#' to first '\n'. From e86f9850aec3c513453bf282c616590e2dbe2fb2 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 3 Feb 2021 01:05:30 +0900 Subject: [PATCH 020/128] wip --- src/pnm/util.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 31c7a8d..6917d9e 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -169,7 +169,8 @@ proc readDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = of P2, P3: result = strm.readTextDataPart() of P4: - discard # TODO + while not strm.atEnd: + let ch = strm.readChar() of P5, P6: result = strm.readAll().mapIt(it.uint8) From 4bc9e7616327c9a477615c971ffab8c835933424 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 00:28:28 +0900 Subject: [PATCH 021/128] wip --- src/pnm/pbm.nim | 22 ++++++++++++++++++++-- src/pnm/pgm.nim | 7 ++++++- src/pnm/ppm.nim | 7 ++++++- src/pnm/util.nim | 22 +++------------------- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index 502b23c..8ef174e 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -1,10 +1,28 @@ -import streams +import streams, sequtils, strutils import types, util export types +proc readTextDataPartOfPBM(strm: Stream): seq[uint8] = + ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 + # P1は空白文字があってもなくても良い + var line: string + while strm.readLine(line): + result.add(toSeq(line.replace(" ", "").items).mapIt(it.uint8)) + +proc readBinaryDataPartOfPBM(strm: Stream): seq[uint8] = + ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 + # P1は空白文字があってもなくても良い + while not strm.atEnd: + let ch = strm.readChar() + proc readPBM*(strm: Stream): PBM = result.header = strm.readHeaderPart() - result.data = strm.readDataPart(result.header.descriptor) + result.data = + case result.header.descriptor + of P1: strm.readTextDataPartOfPBM() + of P4: strm.readBinaryDataPartOfPBM() + else: + raise newException(IllegalFileDescriptorError, "TODO") proc readPBMFile*(file: string): PBM = var strm = newFileStream(file) diff --git a/src/pnm/pgm.nim b/src/pnm/pgm.nim index 6450c1d..2323a58 100644 --- a/src/pnm/pgm.nim +++ b/src/pnm/pgm.nim @@ -4,7 +4,12 @@ export types proc readPGM*(strm: Stream): PGM = result.header = strm.readHeaderPart() - result.data = strm.readDataPart(result.header.descriptor) + result.data = + case result.header.descriptor + of P2: strm.readTextDataPart() + of P5: strm.readBinaryDataPart() + else: + raise newException(IllegalFileDescriptorError, "TODO") proc readPGMFile*(file: string): PGM = var strm = newFileStream(file) diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim index 103dd9f..a9efd17 100644 --- a/src/pnm/ppm.nim +++ b/src/pnm/ppm.nim @@ -4,7 +4,12 @@ export types proc readPPM*(strm: Stream): PPM = result.header = strm.readHeaderPart() - result.data = strm.readDataPart(result.header.descriptor) + result.data = + case result.header.descriptor + of P3: strm.readTextDataPart() + of P6: strm.readBinaryDataPart() + else: + raise newException(IllegalFileDescriptorError, "TODO") proc readPPMFile*(file: string): PPM = var strm = newFileStream(file) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 6917d9e..8177da9 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -148,31 +148,15 @@ proc readHeaderPart*(strm: Stream): Header = if result.descriptor.isPgmPnmDescriptor: result.max = strm.readLine().parseUint.uint8 -proc readTextDataPartOfP1(strm: Stream): seq[uint8] = - ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 - # P1は空白文字があってもなくても良い - var line: string - while strm.readLine(line): - result.add(toSeq(line.replace(" ", "").items).mapIt(it.uint8)) - -proc readTextDataPart(strm: Stream): seq[uint8] = +proc readTextDataPart*(strm: Stream): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 var line: string while strm.readLine(line): result.add(line.split(" ").mapIt(it.parseUInt.uint8)) -proc readDataPart*(strm: Stream, descr: Descriptor): seq[uint8] = +proc readBinaryDataPart*(strm: Stream): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 - case descr - of P1: - result = strm.readTextDataPartOfP1() - of P2, P3: - result = strm.readTextDataPart() - of P4: - while not strm.atEnd: - let ch = strm.readChar() - of P5, P6: - result = strm.readAll().mapIt(it.uint8) + result = strm.readAll().mapIt(it.uint8) proc writeHeaderPart*(strm: Stream, header: Header) = strm.writeLine(header.descriptor) From 3cc78c7198927514a017b82a33fba29c63501dff Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 00:36:42 +0900 Subject: [PATCH 022/128] pbm --- src/pnm/pbm.nim | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index 8ef174e..66842a7 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -9,18 +9,36 @@ proc readTextDataPartOfPBM(strm: Stream): seq[uint8] = while strm.readLine(line): result.add(toSeq(line.replace(" ", "").items).mapIt(it.uint8)) -proc readBinaryDataPartOfPBM(strm: Stream): seq[uint8] = +proc toBinSeq(b: uint8): seq[uint8] = + ## Return binary sequence from each bits of uint8. + runnableExamples: + from sequtils import repeat + doAssert 0'u8.toBinSeq == 0'u8.repeat(8) + doAssert 0b1010_1010.toBinSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] + var c = b + for i in 1..8: + result.add (uint8(c and 0b1000_0000) shr 7) + c = c shl 1 + +proc readBinaryDataPartOfPBM(strm: Stream, columnSize: int): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 # P1は空白文字があってもなくても良い + var rowBin: seq[uint8] while not strm.atEnd: - let ch = strm.readChar() + let bins = strm.readChar().uint8.toBinSeq() + for b in bins: + rowBin.add(b) + if columnSize <= rowBin.len: + result.add(rowBin) + rowBin = @[] + break proc readPBM*(strm: Stream): PBM = result.header = strm.readHeaderPart() result.data = case result.header.descriptor of P1: strm.readTextDataPartOfPBM() - of P4: strm.readBinaryDataPartOfPBM() + of P4: strm.readBinaryDataPartOfPBM(result.header.col) else: raise newException(IllegalFileDescriptorError, "TODO") From 74ff3f93a897b58dddcdae2c4b326cf45d0140af Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 00:42:46 +0900 Subject: [PATCH 023/128] wip --- src/pnm/pgm.nim | 6 +++++- src/pnm/ppm.nim | 6 +++++- src/pnm/util.nim | 21 ++++----------------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/pnm/pgm.nim b/src/pnm/pgm.nim index 2323a58..162c94c 100644 --- a/src/pnm/pgm.nim +++ b/src/pnm/pgm.nim @@ -20,4 +20,8 @@ proc writePGMFile*(fn: string, data: PGM) = var strm = newFileStream(fn, fmWrite) defer: strm.close() strm.writeHeaderPart(data.header) - strm.writeDataPart(data.header, data.data) + case data.header.descriptor + of P2: strm.writeTextDataPartOfPGMOrPPM(data.data, data.header.row, " ") + of P5: strm.writeBinaryDataPart(data.data) + else: + raise newException(IllegalFileDescriptorError, "TODO") diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim index a9efd17..1e5911f 100644 --- a/src/pnm/ppm.nim +++ b/src/pnm/ppm.nim @@ -20,4 +20,8 @@ proc writePPMFile*(fn: string, data: PPM) = var strm = newFileStream(fn, fmWrite) defer: strm.close() strm.writeHeaderPart(data.header) - strm.writeDataPart(data.header, data.data) + case data.header.descriptor + of P3: strm.writeTextDataPartOfPGMOrPPM(data.data, data.header.row * 3, " ") + of P6: strm.writeBinaryDataPart(data.data) + else: + raise newException(IllegalFileDescriptorError, "TODO") diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 8177da9..8a07c7d 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -8,17 +8,6 @@ import streams import types -proc toBinSeq*(b: uint8): seq[uint8] = - ## Return binary sequence from each bits of uint8. - runnableExamples: - from sequtils import repeat - doAssert 0'u8.toBinSeq == 0'u8.repeat(8) - doAssert 0b1010_1010.toBinSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] - var c = b - for i in 1..8: - result.add (uint8(c and 0b1000_0000) shr 7) - c = c shl 1 - proc toBinString*(data: openArray[uint8], col: int): string = ## Return binary string from each bits of uint8. runnableExamples: @@ -89,12 +78,6 @@ proc toBin*(arr: openArray[uint8], col: int = 8): seq[uint8] = if data != 0: result.add data shl (8 - (i mod 8)) -proc toBitSeq*(data: openArray[uint8], col: int): seq[uint8] = - ## Returns sequences that binary sequence is converted to uint8 every 8 bits. - runnableExamples: - doAssert @[255'u8, 127].toBitSeq(9) == @[1'u8, 1, 1, 1, 1, 1, 1, 1, 1] - discard - proc removeCommentLine*(s: openArray[uint8]): seq[uint8] = ## Return sequence that removed comment line. ## Range of comment is from '#' to first '\n'. @@ -173,6 +156,10 @@ proc writeTextDataPartOfPGMOrPPM*(strm: Stream, data: seq[uint8], rowCount: int, for row in data.distribute(rowCount): strm.writeLine(row.mapIt($it).join(delim)) +proc writeBinaryDataPart*(strm: Stream, data: seq[uint8]) = + for b in data: + strm.write(b) + proc writeDataPart*(strm: Stream, header: Header, data: seq[uint8]) = case header.descriptor of P1: From c3c564efdf4f2fa515951863f818612d3995ddeb Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 00:44:04 +0900 Subject: [PATCH 024/128] fix --- src/pnm/pbm.nim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index 66842a7..c3e3968 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -51,4 +51,8 @@ proc writePBMFile*(fn: string, data: PBM) = var strm = newFileStream(fn, fmWrite) defer: strm.close() strm.writeHeaderPart(data.header) - strm.writeDataPart(data.header, data.data) + case data.header.descriptor + of P1: strm.writeTextDataPartOfPGMOrPPM(data.data, data.header.row, "") + of P4: strm.writeBinaryDataPart(data.data) + else: + raise newException(IllegalFileDescriptorError, "TODO") From 9991dc467843092230683f29b66b95236b713683 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 00:44:38 +0900 Subject: [PATCH 025/128] rename --- src/pnm/pbm.nim | 2 +- src/pnm/pgm.nim | 2 +- src/pnm/ppm.nim | 2 +- src/pnm/util.nim | 16 +--------------- 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index c3e3968..7f78842 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -52,7 +52,7 @@ proc writePBMFile*(fn: string, data: PBM) = defer: strm.close() strm.writeHeaderPart(data.header) case data.header.descriptor - of P1: strm.writeTextDataPartOfPGMOrPPM(data.data, data.header.row, "") + of P1: strm.writeTextDataPart(data.data, data.header.row, "") of P4: strm.writeBinaryDataPart(data.data) else: raise newException(IllegalFileDescriptorError, "TODO") diff --git a/src/pnm/pgm.nim b/src/pnm/pgm.nim index 162c94c..49b1555 100644 --- a/src/pnm/pgm.nim +++ b/src/pnm/pgm.nim @@ -21,7 +21,7 @@ proc writePGMFile*(fn: string, data: PGM) = defer: strm.close() strm.writeHeaderPart(data.header) case data.header.descriptor - of P2: strm.writeTextDataPartOfPGMOrPPM(data.data, data.header.row, " ") + of P2: strm.writeTextDataPart(data.data, data.header.row, " ") of P5: strm.writeBinaryDataPart(data.data) else: raise newException(IllegalFileDescriptorError, "TODO") diff --git a/src/pnm/ppm.nim b/src/pnm/ppm.nim index 1e5911f..163deda 100644 --- a/src/pnm/ppm.nim +++ b/src/pnm/ppm.nim @@ -21,7 +21,7 @@ proc writePPMFile*(fn: string, data: PPM) = defer: strm.close() strm.writeHeaderPart(data.header) case data.header.descriptor - of P3: strm.writeTextDataPartOfPGMOrPPM(data.data, data.header.row * 3, " ") + of P3: strm.writeTextDataPart(data.data, data.header.row * 3, " ") of P6: strm.writeBinaryDataPart(data.data) else: raise newException(IllegalFileDescriptorError, "TODO") diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 8a07c7d..699febc 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -152,24 +152,10 @@ proc writeBinaryDataPartOfPBM*(strm: Stream, data: seq[uint8], rowCount: int) = for b in row.toBin: strm.write(b) -proc writeTextDataPartOfPGMOrPPM*(strm: Stream, data: seq[uint8], rowCount: int, delim: string) = +proc writeTextDataPart*(strm: Stream, data: seq[uint8], rowCount: int, delim: string) = for row in data.distribute(rowCount): strm.writeLine(row.mapIt($it).join(delim)) proc writeBinaryDataPart*(strm: Stream, data: seq[uint8]) = for b in data: strm.write(b) - -proc writeDataPart*(strm: Stream, header: Header, data: seq[uint8]) = - case header.descriptor - of P1: - strm.writeTextDataPartOfPGMOrPPM(data, header.row, "") - of P2: - strm.writeTextDataPartOfPGMOrPPM(data, header.row, " ") - of P3: - strm.writeTextDataPartOfPGMOrPPM(data, header.row * 3, " ") - of P4: - strm.writeBinaryDataPartOfPBM(data, header.row) - of P5, P6: - for b in data: - strm.write(b) From 0c139baccdde02b9924d7085c483134d1b16284a Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 00:46:10 +0900 Subject: [PATCH 026/128] fix --- src/pnm/pbm.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index 7f78842..bebec47 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -47,12 +47,15 @@ proc readPBMFile*(file: string): PBM = defer: strm.close() result = strm.readPBM() +proc writeBinaryDataPartOfPBM(strm: Stream, data: seq[uint8], columnSize: int) = + discard + proc writePBMFile*(fn: string, data: PBM) = var strm = newFileStream(fn, fmWrite) defer: strm.close() strm.writeHeaderPart(data.header) case data.header.descriptor of P1: strm.writeTextDataPart(data.data, data.header.row, "") - of P4: strm.writeBinaryDataPart(data.data) + of P4: strm.writeBinaryDataPartOfPBM(data.data, data.header.col) else: raise newException(IllegalFileDescriptorError, "TODO") From 926968c56581dbfd46e01393d86dadf4a91b1ba3 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 00:47:32 +0900 Subject: [PATCH 027/128] delete unused procedures --- src/pnm/util.nim | 108 ----------------------------------------------- 1 file changed, 108 deletions(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 699febc..ceece47 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -8,109 +8,6 @@ import streams import types -proc toBinString*(data: openArray[uint8], col: int): string = - ## Return binary string from each bits of uint8. - runnableExamples: - doAssert @[0b0000_1111'u8, 0b1010_1010].toBinString(8) == "0000111110101010" - doAssert @[0b1000_0000'u8, 0b0000_0000].toBinString(1) == "10" - for b in data.mapIt(it.toBinSeq.mapIt(it.`$`[0].char)): - for i, c in b: - if i < col: - result.add c - -proc toMatrixString*(data: openArray[uint8], col: int): string = - ## Return matrix string from decimal sequence. - ## Matrix string is joined by whitespace. - ## And matrix string add new line when counter of column is reached `col`. - runnableExamples: - doAssert @[0'u8, 1, 8, 9].toMatrixString(2) == "0 1\n8 9" - doAssert @[0'u8, 1, 10, 99].toMatrixString(2) == "0 1\n10 99" - var line: seq[string] - var lines: seq[seq[string]] - for i, c in data: - line.add $c - if (i+1) mod col == 0: - lines.add line - line = @[] - if 0 < line.len: - lines.add line - result = lines.mapIt(it.join(" ")).join("\n") - -proc toMatrixString*(s: string, col: int): string = - ## Return matrix string from decimal sequence. - ## Matrix string is joined by whitespace. - ## And matrix string add new line when counter of column is reached `col`. - runnableExamples: - doAssert "1111111100000000".toMatrixString(8) == "1 1 1 1 1 1 1 1\n0 0 0 0 0 0 0 0" - var line: seq[char] - var lines: seq[seq[char]] - for i, c in s: - line.add c - if (i+1) mod col == 0: - lines.add line - line = @[] - if 0 < line.len: - lines.add line - result = lines.mapIt(it.join(" ")).join("\n") - -proc toBin*(arr: openArray[uint8], col: int = 8): seq[uint8] = - ## Returns sequences that binary sequence is converted to uint8 every 8 bits. - runnableExamples: - doAssert @[1'u8, 1, 1, 1, 0, 0, 0, 0].toBin == @[0b1111_0000'u8] - doAssert @[1'u8, 1, 1, 1, 1, 1].toBin == @[0b1111_1100'u8] - var s: seq[uint8] - doAssert s.toBin == s - var data: uint8 - var i = 0 - for u in arr: - data = data shl 1 - data += u - i.inc - if i mod 8 == 0: - result.add data - data = 0'u8 - continue - if i mod col == 0: - data = data shl (8 - (i mod 8)) - result.add data - data = 0'u8 - i = 0 - if data != 0: - result.add data shl (8 - (i mod 8)) - -proc removeCommentLine*(s: openArray[uint8]): seq[uint8] = - ## Return sequence that removed comment line. - ## Range of comment is from '#' to first '\n'. - runnableExamples: - doAssert @['a'.uint8, '#'.uint8, ' '.uint8, '\n'.uint8, 'b'.uint8].removeCommentLine == @['a'.uint8, 'b'.uint8] - doAssert @['a'.uint8, '#'.uint8, ' '.uint8, '\n'.uint8].removeCommentLine == @['a'.uint8] - var s: seq[uint8] - doAssert @['#'.uint8, ' '.uint8, '\n'.uint8].removeCommentLine == s - var commentLineFound: bool - for b in s: - if b == '#'.uint8: - commentLineFound = true - continue - if commentLineFound and b == '\n'.uint8: - commentLineFound = false - continue - if not commentLineFound: - result.add b - -proc replaceWhiteSpace*(s: string): string = - ## Replace continued whitespace to simgle whitespace. - var ignoreWhiteSpace = false - for c in s: - if ignoreWhiteSpace == false and c == ' ': - ignoreWhiteSpace = true - result.add c - continue - if ignoreWhiteSpace: - if c == ' ': - continue - ignoreWhiteSpace = false - result.add c - proc readHeaderPart*(strm: Stream): Header = # read descriptor result.descriptor = strm.readLine().toDescriptor() @@ -147,11 +44,6 @@ proc writeHeaderPart*(strm: Stream, header: Header) = if header.descriptor.isPgmPnmDescriptor: strm.writeLine(header.max) -proc writeBinaryDataPartOfPBM*(strm: Stream, data: seq[uint8], rowCount: int) = - for row in data.distribute(rowCount): - for b in row.toBin: - strm.write(b) - proc writeTextDataPart*(strm: Stream, data: seq[uint8], rowCount: int, delim: string) = for row in data.distribute(rowCount): strm.writeLine(row.mapIt($it).join(delim)) From 409bfa3f6f1b003e34a57d6e32823a1bfa9289a5 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:10:44 +0900 Subject: [PATCH 028/128] pbm --- src/pnm/pbm.nim | 54 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index bebec47..6e6a5de 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -9,12 +9,12 @@ proc readTextDataPartOfPBM(strm: Stream): seq[uint8] = while strm.readLine(line): result.add(toSeq(line.replace(" ", "").items).mapIt(it.uint8)) -proc toBinSeq(b: uint8): seq[uint8] = +proc toBitSeq(b: uint8): seq[uint8] = ## Return binary sequence from each bits of uint8. runnableExamples: from sequtils import repeat - doAssert 0'u8.toBinSeq == 0'u8.repeat(8) - doAssert 0b1010_1010.toBinSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] + doAssert 0'u8.toBitSeq == 0'u8.repeat(8) + doAssert 0b1010_1010.toBitSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] var c = b for i in 1..8: result.add (uint8(c and 0b1000_0000) shr 7) @@ -25,7 +25,7 @@ proc readBinaryDataPartOfPBM(strm: Stream, columnSize: int): seq[uint8] = # P1は空白文字があってもなくても良い var rowBin: seq[uint8] while not strm.atEnd: - let bins = strm.readChar().uint8.toBinSeq() + let bins = strm.readChar().uint8.toBitSeq() for b in bins: rowBin.add(b) if columnSize <= rowBin.len: @@ -47,8 +47,40 @@ proc readPBMFile*(file: string): PBM = defer: strm.close() result = strm.readPBM() +func bitSeqToByteSeq(arr: openArray[uint8], col: int = 8): seq[uint8] = + ## Returns sequences that binary sequence is converted to uint8 every 8 bits. + var data: uint8 + var i = 0 + for u in arr: + data = data shl 1 + data += u + i.inc + if i mod 8 == 0: + result.add data + data = 0'u8 + continue + if i mod col == 0: + data = data shl (8 - (i mod 8)) + result.add data + data = 0'u8 + i = 0 + if data != 0: + result.add data shl (8 - (i mod 8)) + +func headTail[T](data: seq[T], size: int): (seq[T], seq[T]) = + if data.len < size: + result[0] = data + return + result[0] = data[0.. Date: Thu, 4 Feb 2021 01:12:22 +0900 Subject: [PATCH 029/128] fix --- src/pnm/pbm.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim index 6e6a5de..13e45f6 100644 --- a/src/pnm/pbm.nim +++ b/src/pnm/pbm.nim @@ -47,7 +47,7 @@ proc readPBMFile*(file: string): PBM = defer: strm.close() result = strm.readPBM() -func bitSeqToByteSeq(arr: openArray[uint8], col: int = 8): seq[uint8] = +func bitSeqToByteSeq(arr: openArray[uint8], col: int): seq[uint8] = ## Returns sequences that binary sequence is converted to uint8 every 8 bits. var data: uint8 var i = 0 @@ -97,8 +97,8 @@ when isMainModule: doAssert 0'u8.toBitSeq == 0'u8.repeat(8) doAssert 0b1010_1010.toBitSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] - doAssert @[1'u8, 1, 1, 1, 0, 0, 0, 0].bitSeqToByteSeq == @[0b1111_0000'u8] - doAssert @[1'u8, 1, 1, 1, 1, 1].bitSeqToByteSeq == @[0b1111_1100'u8] + doAssert @[1'u8, 1, 1, 1, 0, 0, 0, 0].bitSeqToByteSeq(8) == @[0b1111_0000'u8] + doAssert @[1'u8, 1, 1, 1, 1, 1].bitSeqToByteSeq(8) == @[0b1111_1100'u8] doAssert @[1, 2, 3, 4].headTail(2) == (@[1, 2], @[3, 4]) doAssert @[1, 2, 3, 4].headTail(4) == (@[1, 2, 3, 4], @[]) From 8f0658a9ef6ed854203733dba1e495c1d522be3e Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:24:01 +0900 Subject: [PATCH 030/128] add monit --- .monit.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .monit.yml diff --git a/.monit.yml b/.monit.yml new file mode 100644 index 0000000..26b55ea --- /dev/null +++ b/.monit.yml @@ -0,0 +1,14 @@ +%YAML 1.2 +%TAG !n! tag:nimyaml.org,2016: +--- !n!custom:MonitorConfig +sleep: 1 +targets: + - + name: Test + paths: [src, tests] + commands: [nimble test] + extensions: [.nim] + files: [] + exclude_extensions: [] + exclude_files: [] + once: y From 3f422e522565be778f21aa24d4ffeb6b9e07d041 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:24:03 +0900 Subject: [PATCH 031/128] add test --- tests/test_util.nim | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/test_util.nim diff --git a/tests/test_util.nim b/tests/test_util.nim new file mode 100644 index 0000000..ddf9729 --- /dev/null +++ b/tests/test_util.nim @@ -0,0 +1,12 @@ +import unittest + +include pnm/util + +suite "proc readHeaderPart": + test "0b0000_0000": + var strm = newStringStream("""P1 +5 3 +""") + let want = strm.readHeaderPart + let got = Header(descriptor: P1, col: 5, row: 3) + check want == got From 1e5d1e6d0cef6f70c8e59bcdf29ae5c7e70f28de Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:24:10 +0900 Subject: [PATCH 032/128] fix --- tests/test_util.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_util.nim b/tests/test_util.nim index ddf9729..4fafb93 100644 --- a/tests/test_util.nim +++ b/tests/test_util.nim @@ -3,7 +3,7 @@ import unittest include pnm/util suite "proc readHeaderPart": - test "0b0000_0000": + test "P1": var strm = newStringStream("""P1 5 3 """) From 59b497d3fcb55f40d24094f26f8b7d36ce24b2b6 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:25:12 +0900 Subject: [PATCH 033/128] add test --- tests/test_util.nim | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test_util.nim b/tests/test_util.nim index 4fafb93..eb10af7 100644 --- a/tests/test_util.nim +++ b/tests/test_util.nim @@ -10,3 +10,21 @@ suite "proc readHeaderPart": let want = strm.readHeaderPart let got = Header(descriptor: P1, col: 5, row: 3) check want == got + + test "P2": + var strm = newStringStream("""P2 +5 3 +255 +""") + let want = strm.readHeaderPart + let got = Header(descriptor: P2, col: 5, row: 3, max: 255'u8) + check want == got + + test "P3": + var strm = newStringStream("""P3 +5 3 +255 +""") + let want = strm.readHeaderPart + let got = Header(descriptor: P3, col: 5, row: 3, max: 255'u8) + check want == got From 1e99b98cb3f1a1436f98633227aa096298ce4020 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:28:33 +0900 Subject: [PATCH 034/128] add test --- .gitignore | 2 ++ src/pnm/util.nim | 1 + tests/test_util.nim | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/.gitignore b/.gitignore index 254704e..0d752d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ tests/tpnm tests/tutil main + +tests/test_util \ No newline at end of file diff --git a/src/pnm/util.nim b/src/pnm/util.nim index ceece47..8cd4371 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -29,6 +29,7 @@ proc readHeaderPart*(strm: Stream): Header = result.max = strm.readLine().parseUint.uint8 proc readTextDataPart*(strm: Stream): seq[uint8] = + ## P2, P3用のデータ部を取得する。 ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 var line: string while strm.readLine(line): diff --git a/tests/test_util.nim b/tests/test_util.nim index eb10af7..49e1c83 100644 --- a/tests/test_util.nim +++ b/tests/test_util.nim @@ -28,3 +28,23 @@ suite "proc readHeaderPart": let want = strm.readHeaderPart let got = Header(descriptor: P3, col: 5, row: 3, max: 255'u8) check want == got + +suite "proc readTextDataPart": + test "P2: single spaces": + var strm = newStringStream("""1 2 3 4 5 +6 7 8 9 10 +""") + let want = strm.readTextDataPart + let got = @[1'u8, 2, 3, 4, 5, + 6, 7, 8, 9, 10] + check want == got + + test "P2: multi spaces": + var strm = newStringStream("""1 2 3 4 5 +6 7 8 9 10 +""") + let want = strm.readTextDataPart + let got = @[1'u8, 2, 3, 4, 5, + 6, 7, 8, 9, 10] + check want == got + From 295ad8c0363421147cfc0f650e33df9dc64d508e Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:35:40 +0900 Subject: [PATCH 035/128] fix --- src/pnm/util.nim | 4 ++-- tests/test_util.nim | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/pnm/util.nim b/src/pnm/util.nim index 8cd4371..271621d 100644 --- a/src/pnm/util.nim +++ b/src/pnm/util.nim @@ -3,7 +3,7 @@ ## **You don't need to use directly this module for pnm module.** from sequtils import mapIt, distribute, toSeq -from strutils import join, split, parseInt, parseUint, replace +import strutils import streams import types @@ -33,7 +33,7 @@ proc readTextDataPart*(strm: Stream): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 var line: string while strm.readLine(line): - result.add(line.split(" ").mapIt(it.parseUInt.uint8)) + result.add(line.splitWhitespace().mapIt(it.parseUInt.uint8)) proc readBinaryDataPart*(strm: Stream): seq[uint8] = ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 diff --git a/tests/test_util.nim b/tests/test_util.nim index 49e1c83..52037dc 100644 --- a/tests/test_util.nim +++ b/tests/test_util.nim @@ -48,3 +48,24 @@ suite "proc readTextDataPart": 6, 7, 8, 9, 10] check want == got + test "P3: single spaces": + var strm = newStringStream("""0 0 255 +0 255 0 +255 0 0 +""") + let want = strm.readTextDataPart + let got = @[0'u8, 0, 255, + 0, 255, 0, + 255, 0, 0] + check want == got + + test "P3: multi spaces": + var strm = newStringStream("""0 0 255 + 0 255 0 + 255 0 0 +""") + let want = strm.readTextDataPart + let got = @[0'u8, 0, 255, + 0, 255, 0, + 255, 0, 0] + check want == got From a474ad50c7f3ea0f200c60fc0c6665eb8edd1da9 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:46:58 +0900 Subject: [PATCH 036/128] add test --- tests/test_util.nim | 65 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/tests/test_util.nim b/tests/test_util.nim index 52037dc..1b7999a 100644 --- a/tests/test_util.nim +++ b/tests/test_util.nim @@ -4,7 +4,8 @@ include pnm/util suite "proc readHeaderPart": test "P1": - var strm = newStringStream("""P1 + var strm = newStringStream(""" +P1 5 3 """) let want = strm.readHeaderPart @@ -12,7 +13,8 @@ suite "proc readHeaderPart": check want == got test "P2": - var strm = newStringStream("""P2 + var strm = newStringStream(""" +P2 5 3 255 """) @@ -21,7 +23,8 @@ suite "proc readHeaderPart": check want == got test "P3": - var strm = newStringStream("""P3 + var strm = newStringStream(""" +P3 5 3 255 """) @@ -31,7 +34,8 @@ suite "proc readHeaderPart": suite "proc readTextDataPart": test "P2: single spaces": - var strm = newStringStream("""1 2 3 4 5 + var strm = newStringStream(""" +1 2 3 4 5 6 7 8 9 10 """) let want = strm.readTextDataPart @@ -40,7 +44,8 @@ suite "proc readTextDataPart": check want == got test "P2: multi spaces": - var strm = newStringStream("""1 2 3 4 5 + var strm = newStringStream(""" +1 2 3 4 5 6 7 8 9 10 """) let want = strm.readTextDataPart @@ -49,7 +54,8 @@ suite "proc readTextDataPart": check want == got test "P3: single spaces": - var strm = newStringStream("""0 0 255 + var strm = newStringStream(""" +0 0 255 0 255 0 255 0 0 """) @@ -60,12 +66,53 @@ suite "proc readTextDataPart": check want == got test "P3: multi spaces": - var strm = newStringStream("""0 0 255 - 0 255 0 - 255 0 0 + var strm = newStringStream(""" + 0 0 255 + 0 255 0 + 255 0 0 """) let want = strm.readTextDataPart let got = @[0'u8, 0, 255, 0, 255, 0, 255, 0, 0] check want == got + +suite "proc readBinaryDataPart": + test "read all binaries": + var strm = newStringStream("fo") + let want = strm.readBinaryDataPart + let got = @['f'.uint8, 'o'.uint8] + check want == got + +suite "proc writeHeaderPart": + test "P1": + var strm = newStringStream("") + let header = Header(descriptor: P1, col: 5, row: 3) + strm.writeHeaderPart(header) + strm.setPosition(0) + let want = """P1 +5 3 +""" + let got = strm.readAll() + check want == got + + test "P1: but max is not 0": + var strm = newStringStream("") + let header = Header(descriptor: P1, col: 5, row: 3, max: 255'u8) + strm.writeHeaderPart(header) + strm.setPosition(0) + let want = """P1 +5 3 +""" + let got = strm.readAll() + check want == got + + test "P2, P3, P5, P6": + for descr in [P2, P3, P5, P6]: + var strm = newStringStream("") + let header = Header(descriptor: descr, col: 5, row: 3, max: 255'u8) + strm.writeHeaderPart(header) + strm.setPosition(0) + let want = $descr & "\n5 3\n255\n" + let got = strm.readAll() + check want == got From 9c9d588bf18c1a44ca1896d5dd9e9056d5bd924a Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:49:06 +0900 Subject: [PATCH 037/128] add test --- tests/test_util.nim | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/tests/test_util.nim b/tests/test_util.nim index 1b7999a..9966372 100644 --- a/tests/test_util.nim +++ b/tests/test_util.nim @@ -85,27 +85,25 @@ suite "proc readBinaryDataPart": check want == got suite "proc writeHeaderPart": - test "P1": - var strm = newStringStream("") - let header = Header(descriptor: P1, col: 5, row: 3) - strm.writeHeaderPart(header) - strm.setPosition(0) - let want = """P1 -5 3 -""" - let got = strm.readAll() - check want == got + test "P1, P4": + for descr in [P1, P4]: + var strm = newStringStream("") + let header = Header(descriptor: descr, col: 5, row: 3) + strm.writeHeaderPart(header) + strm.setPosition(0) + let want = $descr & "\n5 3\n" + let got = strm.readAll() + check want == got - test "P1: but max is not 0": - var strm = newStringStream("") - let header = Header(descriptor: P1, col: 5, row: 3, max: 255'u8) - strm.writeHeaderPart(header) - strm.setPosition(0) - let want = """P1 -5 3 -""" - let got = strm.readAll() - check want == got + test "P1, P4: but max is not zero (illegal case)": + for descr in [P1, P4]: + var strm = newStringStream("") + let header = Header(descriptor: descr, col: 5, row: 3, max: 99'u8) + strm.writeHeaderPart(header) + strm.setPosition(0) + let want = $descr & "\n5 3\n" + let got = strm.readAll() + check want == got test "P2, P3, P5, P6": for descr in [P2, P3, P5, P6]: From ea3d9da3bf44477086b5ee5444cafdb570929abf Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:57:38 +0900 Subject: [PATCH 038/128] add test --- tests/test_util.nim | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/test_util.nim b/tests/test_util.nim index 9966372..b49203a 100644 --- a/tests/test_util.nim +++ b/tests/test_util.nim @@ -114,3 +114,26 @@ suite "proc writeHeaderPart": let want = $descr & "\n5 3\n255\n" let got = strm.readAll() check want == got + +suite "proc writeTextDataPart": + setup: + type TestData = object + data: seq[uint8] + row: int + delim: string + want: string + + test "normal case": + let inData = [ + TestData(data: @[1'u8, 2, 3, 4, 5, 6], row: 1, delim: " ", want: "1 2 3 4 5 6\n"), + TestData(data: @[1'u8, 2, 3, 4, 5, 6], row: 2, delim: " ", want: "1 2 3\n4 5 6\n"), + TestData(data: @[1'u8, 2, 3, 4, 5, 6], row: 3, delim: " ", want: "1 2\n3 4\n5 6\n"), + TestData(data: @[1'u8, 1, 0, 0, 1, 1], row: 3, delim: "", want: "11\n00\n11\n"), + ] + for v in inData: + var strm = newStringStream("") + strm.writeTextDataPart(v.data, v.row, v.delim) + strm.setPosition(0) + let got = strm.readAll() + check v.want == got + From cb5e0952d558553c03fd2aa95696ceb7b0d61387 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 01:59:12 +0900 Subject: [PATCH 039/128] add test --- tests/test_util.nim | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_util.nim b/tests/test_util.nim index b49203a..81ac5da 100644 --- a/tests/test_util.nim +++ b/tests/test_util.nim @@ -137,3 +137,12 @@ suite "proc writeTextDataPart": let got = strm.readAll() check v.want == got +suite "proc writeBinaryDataPart": + test "normal": + var strm = newStringStream("") + strm.writeBinaryDataPart(@['f'.uint8, 'o'.uint8]) + strm.setPosition(0) + let want = "fo" + let got = strm.readAll() + check want == got + From a67fac1403b22f2f40e0e693161f495c9c91cb68 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 02:00:50 +0900 Subject: [PATCH 040/128] version up --- pnm.nimble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pnm.nimble b/pnm.nimble index 6eef65b..30996e9 100644 --- a/pnm.nimble +++ b/pnm.nimble @@ -1,6 +1,6 @@ # Package -version = "2.1.1" +version = "3.0.0" author = "jiro4989" description = "pnm is library for PNM (Portable AnyMap)." license = "MIT" From de2b1d88e7d6c42181ff55ee9558febe2aa74379 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 02:01:58 +0900 Subject: [PATCH 041/128] commentout --- .github/workflows/test.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d262a1c..d72f320 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,15 +25,15 @@ jobs: run: nimble install -Y - name: Unit test run: nimble test -Y - - name: Examples test - run: | - find examples/ -mindepth 1 -type d | while read -r dir; do - ( - cd "$dir" - nim c -d:release main.nim - ./main - ) - done + # - name: Examples test + # run: | + # find examples/ -mindepth 1 -type d | while read -r dir; do + # ( + # cd "$dir" + # nim c -d:release main.nim + # ./main + # ) + # done docs: runs-on: ubuntu-latest From 243e0f2d934d9d634112df285838d668cf328948 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 02:08:21 +0900 Subject: [PATCH 042/128] add test --- tests/test_pbm.nim | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/test_pbm.nim diff --git a/tests/test_pbm.nim b/tests/test_pbm.nim new file mode 100644 index 0000000..29698ce --- /dev/null +++ b/tests/test_pbm.nim @@ -0,0 +1,39 @@ +import unittest + +include pnm/pbm + +suite "proc readTextDataPartOfPBM": + test "P1": + discard + +suite "proc toBitSeq": + test "P1": + discard + +suite "proc readBinaryDataPartOfPBM": + test "P1": + discard + +suite "proc readPBM": + test "P1": + discard + +suite "proc readPBMFile": + test "P1": + discard + +suite "proc bitSeqToByteSeq": + test "P1": + discard + +suite "proc headTail": + test "P1": + discard + +suite "proc writeBinaryDataPartOfPBM": + test "P1": + discard + +suite "proc writePBMFile": + test "P1": + discard From 03cee29f345f6ec5de764f2e1087aa94dd9ab88e Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 02:11:31 +0900 Subject: [PATCH 043/128] add test --- tests/test_pbm.nim | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_pbm.nim b/tests/test_pbm.nim index 29698ce..af8372d 100644 --- a/tests/test_pbm.nim +++ b/tests/test_pbm.nim @@ -7,8 +7,10 @@ suite "proc readTextDataPartOfPBM": discard suite "proc toBitSeq": - test "P1": - discard + test "0b0000_0000": check 0'u8.toBitSeq == @[0'u8, 0, 0, 0, 0, 0, 0, 0] + test "0b1000_0001": check 0b1000_0001.toBitSeq == @[1'u8, 0, 0, 0, 0, 0, 0, 1] + test "0b1010_1010": check 0b1010_1010.toBitSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] + test "0b1111_1111": check 0b1111_1111.toBitSeq == @[1'u8, 1, 1, 1, 1, 1, 1, 1] suite "proc readBinaryDataPartOfPBM": test "P1": From f5becf577c2916bebc261210b8584289e4634ecf Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 02:13:23 +0900 Subject: [PATCH 044/128] add test --- tests/test_pbm.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_pbm.nim b/tests/test_pbm.nim index af8372d..a0f4f9a 100644 --- a/tests/test_pbm.nim +++ b/tests/test_pbm.nim @@ -25,8 +25,9 @@ suite "proc readPBMFile": discard suite "proc bitSeqToByteSeq": - test "P1": - discard + test "1, 1, 1, 1, 1, 1": check @[1'u8, 1, 1, 1, 1, 1].bitSeqToByteSeq(8) == @[0b1111_1100'u8] + test "1, 1, 1, 1, 0, 0, 0, 0": check @[1'u8, 1, 1, 1, 0, 0, 0, 0].bitSeqToByteSeq(8) == @[0b1111_0000'u8] + test "1, 1, 1, 1, 0, 0, 0, 0, 1, 1": check @[1'u8, 1, 1, 1, 0, 0, 0, 0, 1, 1].bitSeqToByteSeq(8) == @[0b1111_0000'u8, 0b1100_0000] suite "proc headTail": test "P1": From 73686bc312df48b1493a96d8cfb9f5fd2825b48f Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 02:20:09 +0900 Subject: [PATCH 045/128] add test --- tests/test_pbm.nim | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/tests/test_pbm.nim b/tests/test_pbm.nim index a0f4f9a..d3c79a0 100644 --- a/tests/test_pbm.nim +++ b/tests/test_pbm.nim @@ -7,10 +7,17 @@ suite "proc readTextDataPartOfPBM": discard suite "proc toBitSeq": - test "0b0000_0000": check 0'u8.toBitSeq == @[0'u8, 0, 0, 0, 0, 0, 0, 0] - test "0b1000_0001": check 0b1000_0001.toBitSeq == @[1'u8, 0, 0, 0, 0, 0, 0, 1] - test "0b1010_1010": check 0b1010_1010.toBitSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] - test "0b1111_1111": check 0b1111_1111.toBitSeq == @[1'u8, 1, 1, 1, 1, 1, 1, 1] + test "0b0000_0000": + check 0'u8.toBitSeq == @[0'u8, 0, 0, 0, 0, 0, 0, 0] + + test "0b1000_0001": + check 0b1000_0001.toBitSeq == @[1'u8, 0, 0, 0, 0, 0, 0, 1] + + test "0b1010_1010": + check 0b1010_1010.toBitSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] + + test "0b1111_1111": + check 0b1111_1111.toBitSeq == @[1'u8, 1, 1, 1, 1, 1, 1, 1] suite "proc readBinaryDataPartOfPBM": test "P1": @@ -30,8 +37,17 @@ suite "proc bitSeqToByteSeq": test "1, 1, 1, 1, 0, 0, 0, 0, 1, 1": check @[1'u8, 1, 1, 1, 0, 0, 0, 0, 1, 1].bitSeqToByteSeq(8) == @[0b1111_0000'u8, 0b1100_0000] suite "proc headTail": - test "P1": - discard + setup: + var emptyData: seq[int] + + test "head 2, tail 2": + check @[1, 2, 3, 4].headTail(2) == (@[1, 2], @[3, 4]) + + test "data size and argument size is same": + check @[1, 2, 3, 4].headTail(4) == (@[1, 2, 3, 4], emptyData) + + test "argument size is over data size": + check @[1, 2, 3, 4].headTail(5) == (@[1, 2, 3, 4], emptyData) suite "proc writeBinaryDataPartOfPBM": test "P1": From 92b3162ace611e8454bc2a5035488f4eed4d8cc7 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 02:21:23 +0900 Subject: [PATCH 046/128] fix --- tests/test_pbm.nim | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/test_pbm.nim b/tests/test_pbm.nim index d3c79a0..342a47e 100644 --- a/tests/test_pbm.nim +++ b/tests/test_pbm.nim @@ -32,9 +32,14 @@ suite "proc readPBMFile": discard suite "proc bitSeqToByteSeq": - test "1, 1, 1, 1, 1, 1": check @[1'u8, 1, 1, 1, 1, 1].bitSeqToByteSeq(8) == @[0b1111_1100'u8] - test "1, 1, 1, 1, 0, 0, 0, 0": check @[1'u8, 1, 1, 1, 0, 0, 0, 0].bitSeqToByteSeq(8) == @[0b1111_0000'u8] - test "1, 1, 1, 1, 0, 0, 0, 0, 1, 1": check @[1'u8, 1, 1, 1, 0, 0, 0, 0, 1, 1].bitSeqToByteSeq(8) == @[0b1111_0000'u8, 0b1100_0000] + test "1, 1, 1, 1, 1, 1": + check @[1'u8, 1, 1, 1, 1, 1].bitSeqToByteSeq(8) == @[0b1111_1100'u8] + + test "1, 1, 1, 1, 0, 0, 0, 0": + check @[1'u8, 1, 1, 1, 0, 0, 0, 0].bitSeqToByteSeq(8) == @[0b1111_0000'u8] + + test "1, 1, 1, 1, 0, 0, 0, 0, 1, 1": + check @[1'u8, 1, 1, 1, 0, 0, 0, 0, 1, 1].bitSeqToByteSeq(8) == @[0b1111_0000'u8, 0b1100_0000] suite "proc headTail": setup: From 4428e9a5d5b83adfc80efac62df06c7cf40e5831 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 02:29:03 +0900 Subject: [PATCH 047/128] delete unused test --- tests/bak.tpnm.nim | 486 -------------------------------------------- tests/bak.tutil.nim | 84 -------- 2 files changed, 570 deletions(-) delete mode 100644 tests/bak.tpnm.nim delete mode 100644 tests/bak.tutil.nim diff --git a/tests/bak.tpnm.nim b/tests/bak.tpnm.nim deleted file mode 100644 index 5c2cb9a..0000000 --- a/tests/bak.tpnm.nim +++ /dev/null @@ -1,486 +0,0 @@ -import unittest -from sequtils import repeat - -include pnm - -## PBM - -block: - let col = 32 - let row = 12 - let data = @[ - 0b11111111'u8, 0b00000000, 0b11111111, 0b00000000, - 0b11111111, 0b00000000, 0b11111111, 0b00000000, - 0b11111111, 0b00000000, 0b11111111, 0b00000000, - 0b11111111, 0b00000000, 0b11111111, 0b00000000, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - ] - - let pbm1 = newPBM(pbmFileDescriptorP1, col, row, data) - let pbm4 = newPBM(pbmFileDescriptorP4, col, row, data) - - let pbm1str = """P1 -32 12 -1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0""" - - let pbm1bin = @[ - 'P'.uint8, '1'.uint8, '\n'.uint8, - '3'.uint8, '2'.uint8, ' '.uint8, '1'.uint8, '2'.uint8, '\n'.uint8, - 0b11111111'u8, 0b00000000, 0b11111111, 0b00000000, - 0b11111111, 0b00000000, 0b11111111, 0b00000000, - 0b11111111, 0b00000000, 0b11111111, 0b00000000, - 0b11111111, 0b00000000, 0b11111111, 0b00000000, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - ] - - suite "formatP1": - test "normal": - check pbm1.formatP1 == pbm1str - test "column size is 1": - check newPBM(pbmFileDescriptorP1, 1, 1, @[0b1000_0000'u8]).formatP1 == "P1\n1 1\n1" - - suite "formatP4": - test "normal": - check pbm1.formatP4 == pbm1bin - test "column size is 1": - check newPBM(pbmFileDescriptorP4, 1, 1, @[0b1000_0000'u8]).formatP4 == @[ - 'P'.uint8, '4'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - 0b1000_0000'u8, - ] - - suite "validatePBM": - test "NoError": - validatePBM(@['P'.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - validatePBM(@['P'.uint8, '4'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - test "IllegalFileDescriptorError": - expect IllegalFileDescriptorError: - validatePBM(@['P'.uint8, '9'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - test "IllegalColumnRowError": - expect IllegalColumnRowError: - validatePBM(@['P'.uint8, '1'.uint8, '\n'.uint8, - 'a'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - validatePBM(@['P'.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - validatePBM(@['P'.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8]) - - suite "parsePBM(string)": - test "normal": - check pbm1str.parsePBM[] == pbm1[] - - suite "parsePBM(openArray[uint8])": - test "normal": - check pbm1bin.parsePBM[] == pbm1[] - - suite "usecase": - test "write P1": - writePBMFile("tests/out/p1.pbm", pbm1) - test "write P4": - writePBMFile("tests/out/p4.pbm", pbm4) - test "read p1 file": - check readPBMFile("tests/out/p1.pbm")[] == pbm1[] - test "read p4 file": - check readPBMFile("tests/out/p4.pbm")[] == pbm4[] - -# PGM - -block: - let col = 6 - let row = 12 - let max = 2 - let data = @[ - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, - ] - - let data2 = @[ - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, - 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, - ] - - let pgm2 = newPGM(pgmFileDescriptorP2, col, row, data) - let pgm5 = newPGM(pgmFileDescriptorP5, col, row, data) - let pgm2_2 = newPGM(pgmFileDescriptorP2, 6, 12, data2) - let pgm2_3 = newPGM(pgmFileDescriptorP2, col, row, 255, data) - let pgm5_2 = newPGM(pgmFileDescriptorP5, col, row, 255, data) - - const pgm2str = """P2 -6 12 -2 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -1 1 1 1 1 1 -1 1 1 1 1 1 -1 1 1 1 1 1 -1 1 1 1 1 1 -2 2 2 2 2 2 -2 2 2 2 2 2 -2 2 2 2 2 2 -2 2 2 2 2 2""" - - const pgm2_2str = """P2 -6 12 -20 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -10 10 10 10 10 10 -10 10 10 10 10 10 -10 10 10 10 10 10 -10 10 10 10 10 10 -20 20 20 20 20 20 -20 20 20 20 20 20 -20 20 20 20 20 20 -20 20 20 20 20 20""" - - const pgm2_2str_whitespace = """P2 -6 12 -20 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -10 10 10 10 10 10 -10 10 10 10 10 10 -10 10 10 10 10 10 -10 10 10 10 10 10 -20 20 20 20 20 20 -20 20 20 20 20 20 -20 20 20 20 20 20 -20 20 20 20 20 20""" - - const pgm2_3str = """P2 -6 12 -255 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -1 1 1 1 1 1 -1 1 1 1 1 1 -1 1 1 1 1 1 -1 1 1 1 1 1 -2 2 2 2 2 2 -2 2 2 2 2 2 -2 2 2 2 2 2 -2 2 2 2 2 2""" - - let pgm5bin = @[ - 'P'.uint8, '5'.uint8, '\n'.uint8, - '6'.uint8, ' '.uint8, '1'.uint8, '2'.uint8, '\n'.uint8, - '2'.uint8, '\n'.uint8, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, - ] - - let pgm5_2bin = @[ - 'P'.uint8, '5'.uint8, '\n'.uint8, - '6'.uint8, ' '.uint8, '1'.uint8, '2'.uint8, '\n'.uint8, - '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 0'u8, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, - ] - - suite "formatP2": - test "normal": - check pgm2.formatP2 == pgm2str - test "number of data part is over 10": - check pgm2_2.formatP2 == pgm2_2str - test "the maximum brightness is set": - check pgm2_3.formatP2 == pgm2_3str - test "column size is 1": - check newPGM(pgmFileDescriptorP2, 1, 2, @[0b1000_0000'u8, 0b1000_0000'u8]).formatP2 == "P2\n1 2\n128\n128\n128" - - suite "formatP5": - test "normal": - check pgm5.formatP5 == pgm5bin - test "the maximum brightness is set": - check pgm5_2.formatP5 == pgm5_2bin - test "column size is 1": - check newPGM(pgmFileDescriptorP5, 1, 1, @[0b1000_0000'u8, 0b1000_0000'u8]).formatP5 == @[ - 'P'.uint8, '5'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, - '1'.uint8, '2'.uint8, '8'.uint8, '\n'.uint8, - 0b1000_0000'u8, - 0b1000_0000'u8, - ] - - suite "validatePGM": - test "NoError P2": - @['P'.uint8, '2'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, '\n'.uint8, '1'.uint8,].validatePGM - test "NoError P5": - @['P'.uint8, '5'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, '\n'.uint8, '1'.uint8,].validatePGM - test "IllegalFileDescriptorError": - expect IllegalFileDescriptorError: - @['P'.uint8, '3'.uint8, '\n'.uint8].validatePGM - @['P'.uint8].validatePGM - @[].validatePGM - test "IllegalColumnRowError": - expect IllegalColumnRowError: - @['P'.uint8, '2'.uint8, '\n'.uint8, 'a'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, ].validatePGM - @['P'.uint8, '2'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, 'a'.uint8, '\n'.uint8, '1'.uint8, ].validatePGM - @['P'.uint8, '2'.uint8, '\n'.uint8, '1'.uint8, '1'.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, ].validatePGM - @['P'.uint8, '2'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '\n'.uint8, '1'.uint8, ].validatePGM - @['P'.uint8, '2'.uint8, '\n'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, ].validatePGM - @['P'.uint8, '2'.uint8, '\n'.uint8, ' '.uint8, '\n'.uint8, '1'.uint8, ].validatePGM - test "IllegalMaxValueError": - expect IllegalMaxValueError: - @['P'.uint8, '2'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, 'a'.uint8, ].validatePGM - @['P'.uint8, '2'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, ' '.uint8, ].validatePGM - @['P'.uint8, '2'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, ].validatePGM - - suite "parsePGM(string)": - test "normal": - check pgm2str.parsePGM[] == pgm2[] - test "multi whitespace": - check pgm2_2str_whitespace.parsePGM[] == pgm2_2[] - - suite "parsePGM(openArray[uint8])": - test "normal": - check pgm5bin.parsePGM[] == pgm5[] - - suite "usecase": - test "write P2": - writePGMFile("tests/out/p2.pgm", pgm2) - test "write P5": - writePGMFile("tests/out/p5.pgm", pgm5) - test "read P2": - check readPGMFile("tests/out/p2.pgm")[] == pgm2[] - test "read P5": - check readPGMFile("tests/out/p5.pgm")[] == pgm5[] - -block: - let col = 3 - let row = 2 - let max = 255 - let data = @[ - 255'u8, 0, 0, - 0, 255, 0, - 0, 0, 255, - 255, 255, 0, - 255, 255, 255, - 0, 0, 0, - ] - - let data2 = @[ - 100'u8, 0, 0, - 0, 100, 0, - 0, 0, 100, - 100, 100, 0, - 100, 100, 100, - 0, 0, 0 - ] - - let p1 = newPPM(ppmFileDescriptorP3, col, row, data) - let p2 = newPPM(ppmFileDescriptorP6, col, row, data) - let p1_2 = newPPM(ppmFileDescriptorP3, col, row, 255, data2) - let p2_2 = newPPM(ppmFileDescriptorP6, col, row, 255, data2) - - const p1str = """P3 -3 2 -255 -255 0 0 -0 255 0 -0 0 255 -255 255 0 -255 255 255 -0 0 0""" - - const p1str2 = """P3 -3 2 -255 -255 0 0 0 255 0 0 0 255 -255 255 0 255 255 255 0 0 0""" - - const p1str_whitespace = """P3 -3 2 -255 -255 0 0 -0 255 0 -0 0 255 -255 255 0 -255 255 255 -0 0 0 """ - - const p1_2str = """P3 -3 2 -255 -100 0 0 -0 100 0 -0 0 100 -100 100 0 -100 100 100 -0 0 0""" - - let p2bin = @[ - 'P'.uint8, '6'.uint8, '\n'.uint8, - '3'.uint8, ' '.uint8, '2'.uint8, '\n'.uint8, - '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8, - 255'u8, 0, 0, - 0, 255'u8, 0, - 0, 0, 255'u8, - 255, 255, 0, - 255, 255, 255, - 0, 0, 0, - ] - - let p2_2bin = @[ - 'P'.uint8, '6'.uint8, '\n'.uint8, - '3'.uint8, ' '.uint8, '2'.uint8, '\n'.uint8, - '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8, - 100'u8, 0, 0, - 0, 100'u8, 0, - 0, 0, 100'u8, - 100, 100, 0, - 100, 100, 100, - 0, 0, 0, - ] - - - suite "formatP3": - test "normal": - check p1.formatP3 == p1str - test "the maximum brightness is set": - check p1_2.formatP3 == p1_2str - test "column size is 1": - check newPPM(ppmFileDescriptorP3, 1, 2, @[128'u8, 128, 128, 0, 0, 0]).formatP3 == "P3\n1 2\n128\n128 128 128\n0 0 0" - - suite "formatP6": - test "normal": - check p2.formatP6 == p2bin - test "the maximum brightness is set": - check p2_2.formatP6 == p2_2bin - test "column size is 1": - check newPPM(ppmFileDescriptorP6, 1, 2, @[128'u8, 128, 128, 0, 0, 0]).formatP6 == @[ - 'P'.uint8, '6'.uint8, '\n'.uint8, - '1'.uint8, ' '.uint8, '2'.uint8, '\n'.uint8, - '1'.uint8, '2'.uint8, '8'.uint8, '\n'.uint8, - 128'u8, 128, 128, - 0, 0, 0, - ] - - suite "validatePPM": - test "NoError P3": - @['P'.uint8, '3'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, '\n'.uint8, '1'.uint8,].validatePPM - test "NoError P6": - @['P'.uint8, '6'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, '\n'.uint8, '1'.uint8,].validatePPM - test "IllegalFileDescriptorError": - expect IllegalFileDescriptorError: - @['P'.uint8, '4'.uint8, '\n'.uint8].validatePPM - @['P'.uint8, 'a'.uint8, '\n'.uint8].validatePPM - @['P'.uint8].validatePPM - @['\n'.uint8].validatePPM - @[].validatePPM - test "IllegalColumnRowError": - expect IllegalColumnRowError: - @['P'.uint8, '3'.uint8, '\n'.uint8, 'a'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, ].validatePPM - @['P'.uint8, '3'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, 'a'.uint8, '\n'.uint8, '1'.uint8, ].validatePPM - @['P'.uint8, '3'.uint8, '\n'.uint8, '1'.uint8, '1'.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, ].validatePPM - @['P'.uint8, '3'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '\n'.uint8, '1'.uint8, ].validatePPM - @['P'.uint8, '3'.uint8, '\n'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, '1'.uint8, ].validatePPM - @['P'.uint8, '3'.uint8, '\n'.uint8, ' '.uint8, '\n'.uint8, '1'.uint8, ].validatePPM - test "IllegalMaxValueError": - expect IllegalMaxValueError: - @['P'.uint8, '3'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, 'a'.uint8, ].validatePPM - @['P'.uint8, '3'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, ' '.uint8, ].validatePPM - @['P'.uint8, '3'.uint8, '\n'.uint8, '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8, ].validatePPM - - suite "parsePPM(string)": - test "normal": - check p1str.parsePPM[] == p1[] - test "multi column": - check p1str2.parsePPM[] == p1[] - test "multi whitespace": - check p1str_whitespace.parsePPM[] == p1[] - - suite "parsePPM(openArray[uint8])": - test "normal": - check p2bin.parsePPM[] == p2[] - - suite "usecase": - test "write P3": - writePPMFile("tests/out/p3.ppm", p1) - test "write P6": - writePPMFile("tests/out/p6.ppm", p2) - test "read P2": - check readPPMFile("tests/out/p3.ppm")[] == p1[] - test "read P5": - check readPPMFile("tests/out/p6.ppm")[] == p2[] \ No newline at end of file diff --git a/tests/bak.tutil.nim b/tests/bak.tutil.nim deleted file mode 100644 index 7242a42..0000000 --- a/tests/bak.tutil.nim +++ /dev/null @@ -1,84 +0,0 @@ -import unittest -from sequtils import repeat - -include pnm/util - -suite "toBinSeq": - test "0b0000_0000": - check 0'u8.toBinSeq == 0'u8.repeat(8) - test "0b1010_1010": - check 0b1010_1010.toBinSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] - -suite "toBinString": - test "normal": - check @[0b0000_1111'u8, 0b1010_1010].toBinString(8) == "0000111110101010" - test "column size is 1": - check @[0b1000_0000'u8, 0b0000_0000].toBinString(1) == "10" - -suite "toMatrixString(openArray[uint])": - test "1 digit": - check @[0'u8, 1, 8, 9].toMatrixString(2) == "0 1\n8 9" - test "2 digit": - check @[0'u8, 1, 10, 99].toMatrixString(2) == "0 1\n10 99" - -suite "toMatrixString(string)": - test "normal": - check "1111111100000000".toMatrixString(8) == "1 1 1 1 1 1 1 1\n0 0 0 0 0 0 0 0" - check "1111111100000000".toMatrixString(4) == "1 1 1 1\n1 1 1 1\n0 0 0 0\n0 0 0 0" - -suite "toBin": - test "1 1 1 1 0 0 0 0": - check @[1'u8, 1, 1, 1, 0, 0, 0, 0].toBin == @[0b1111_0000'u8] - test "1 1 1 1 1 1": - check @[1'u8, 1, 1, 1, 1, 1].toBin == @[0b1111_1100'u8] - test "2行のデータ。1行8bit": - check @[1'u8, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1].toBin == @[0b1111_0000'u8, 0b0000_1111] - test "2行のデータ。1行5bit": - check @[1'u8, 1, 1, 0, 1, - 1, 1, 1, 0, 1].toBin(5) == @[0b1110_1000'u8, 0b1110_1000] - test "2行のデータ。1行9bit": - check @[1'u8, 1, 1, 1, 1, 1, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1].toBin(9) == @[0b1111_1110'u8, 0b1000_0000, - 0b1111_1110, 0b1000_0000] - test "2行のデータ。1行17bit": - check @[1'u8, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1].toBin(17) == - @[0b1111_1110'u8, 0b1111_1110, 0b1000_0000, - 0b1111_1110'u8, 0b1111_1110, 0b1000_0000] - test "2行のデータ。1行25bit": - check @[1'u8, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1].toBin(25) == - @[0b1111_1110'u8, 0b1111_1110, 0b1111_1110, 0b1000_0000, - 0b1111_1110'u8, 0b1111_1110, 0b1111_1110, 0b1000_0000] - test "empty": - var s: seq[uint8] - check s.toBin == s - -suite "removeCommentLine": - var s: seq[uint8] - test "normal": - check @['a'.uint8, '#'.uint8, ' '.uint8, '\n'.uint8, 'b'.uint8].removeCommentLine == @['a'.uint8, 'b'.uint8] - check @['a'.uint8, '#'.uint8, ' '.uint8, '\n'.uint8].removeCommentLine == @['a'.uint8] - check @['#'.uint8, ' '.uint8, '\n'.uint8].removeCommentLine == s - test "no comment": - check @['a'.uint8, '\n'.uint8, - 'b'.uint8, '\n'.uint8, - 'c'.uint8, - ].removeCommentLine == @['a'.uint8, '\n'.uint8, 'b'.uint8, '\n'.uint8, 'c'.uint8] - test "3 line": - check @['a'.uint8, '#'.uint8, ' '.uint8, '\n'.uint8, - 'b'.uint8, '#'.uint8, ' '.uint8, '\n'.uint8, - 'c'.uint8, '#'.uint8, ' '.uint8, '\n'.uint8, - ].removeCommentLine == @['a'.uint8, 'b'.uint8, 'c'.uint8] - test "empty": - check s.removeCommentLine == s - -suite "replaceWhiteSpace": - test "normal": - check "a b c d".replaceWhiteSpace == "a b c d" - test "line field": - check "ab cd e f\n1 2".replaceWhiteSpace == "ab cd e f\n1 2" - test "no whitespace": - check "abc".replaceWhiteSpace == "abc" - test "single whitespace": - check "a b c".replaceWhiteSpace == "a b c" \ No newline at end of file From 34b5c8e846b0bed470f876a1066e5ed5a4912deb Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 21:45:29 +0900 Subject: [PATCH 048/128] add test case --- tests/in/p3.ppm | 7 +++++++ tests/test_ppm.nim | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 tests/in/p3.ppm create mode 100644 tests/test_ppm.nim diff --git a/tests/in/p3.ppm b/tests/in/p3.ppm new file mode 100644 index 0000000..55d1f31 --- /dev/null +++ b/tests/in/p3.ppm @@ -0,0 +1,7 @@ +P3 +# The P3 means colors are in ASCII, then 3 columns and 2 rows, then 255 for max color, then RGB triplets +3 1 +255 +255 0 0 +0 255 0 +0 0 255 diff --git a/tests/test_ppm.nim b/tests/test_ppm.nim new file mode 100644 index 0000000..7ed9433 --- /dev/null +++ b/tests/test_ppm.nim @@ -0,0 +1,43 @@ +import unittest, os + +include pnm/ppm + +const + inputDataDir = "tests"/"in" + outputDataDir = "tests"/"out" + +suite "proc readPPM": + test "P3": + var strm = newStringStream(""" +P3 +2 2 +100 +50 100 +25 75 +""") + let got = strm.readPPM() + check got.header.descriptor == P3 + check got.header.col == 2 + check got.header.row == 2 + check got.header.max == 100'u8 + check got.data == @[ + 50'u8, 100, + 25, 75, + ] + +suite "proc readPPMFile": + test "P3": + let got = readPPMFile(inputDataDir/"p3.ppm") + check got.header.descriptor == P3 + check got.header.col == 3 + check got.header.row == 1 + check got.header.max == 255'u8 + check got.data == @[ + 255'u8, 0, 0, + 0, 255'u8, 0, + 0, 0, 255'u8, + ] + +suite "proc writePPMFile": + test "0b1111_1111": + discard From d0b50fad3600d943230e73b57ca81270693287ee Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 21:51:17 +0900 Subject: [PATCH 049/128] add constructor --- src/pnm/types.nim | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/pnm/types.nim b/src/pnm/types.nim index f5f7e4a..7f4293a 100644 --- a/src/pnm/types.nim +++ b/src/pnm/types.nim @@ -18,6 +18,18 @@ type ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. +func newPBM*(descriptor: Descriptor, col, row: int): PBM = + let h = Header(descriptor: descriptor, col: col, row: row) + return PBM(header: h) + +func newPGM*(descriptor: Descriptor, col, row: int, max: uint8): PGM = + let h = Header(descriptor: descriptor, col: col, row: row, max: max) + return PGM(header: h) + +func newPPM*(descriptor: Descriptor, col, row: int, max: uint8): PPM = + let h = Header(descriptor: descriptor, col: col, row: row, max: max) + return PPM(header: h) + func isPgmPnmDescriptor*(d: Descriptor): bool = return d in @[P2, P3, P5, P6] From eceb0224ab0aca4847d56e50bb7591da4c2c2e3a Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 4 Feb 2021 21:51:22 +0900 Subject: [PATCH 050/128] add test --- tests/test_ppm.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_ppm.nim b/tests/test_ppm.nim index 7ed9433..ce07c9b 100644 --- a/tests/test_ppm.nim +++ b/tests/test_ppm.nim @@ -40,4 +40,6 @@ suite "proc readPPMFile": suite "proc writePPMFile": test "0b1111_1111": - discard + var data = newPPM(P3, 2, 2, 4'u8) + data.data = @[1'u8, 2, 3, 4] + writePPMFile(outputDataDir/"p3.ppm", data) From 82fb2c7094296f627da03710826d08fc97572501 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 13 Feb 2021 13:54:27 +0900 Subject: [PATCH 051/128] wip --- src/pnm.nim | 106 ++++++++++++++++++++++++++++++- src/pnm/ppm.nim | 43 ++++++------- src/pnm/types.nim | 92 ++++++++++++++++++++++++++- tests/test_pbm.nim | 63 ------------------- tests/test_pnm.nim | 16 +++++ tests/test_ppm.nim | 45 -------------- tests/test_util.nim | 148 -------------------------------------------- 7 files changed, 232 insertions(+), 281 deletions(-) delete mode 100644 tests/test_pbm.nim create mode 100644 tests/test_pnm.nim delete mode 100644 tests/test_ppm.nim delete mode 100644 tests/test_util.nim diff --git a/src/pnm.nim b/src/pnm.nim index 1715b11..a7da1e4 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -235,5 +235,107 @@ ## * `(EN) Portable Anymap - Wikipedia `_ ## * `(JA) PNM(画像フォーマット) - Wikipedia `_ -import pnm/[pbm, pgm, ppm, types] -export pbm, pgm, ppm, types +import streams, strformat +from sequtils import mapIt, repeat + +type + Image[T: Color] = object + width*, height*: int + data*: seq[T] + Descriptor* {.pure.} = enum + P1, P2, P3, P4, P5, P6 + + Color* = ref object of RootObj # base class + ColorComponent* = uint8 + ColorBit* = ref object of Color + bit: uint8 # 0 or 1 + ColorGray* = ref object of Color + gray: ColorComponent + ColorRGB* = ref object of Color + red*, green*, blue*: ColorComponent + + Point* = object + x*, y*: int + + IllegalFileDescriptorError* = object of Defect + ## Return this when file descriptor is wrong. + ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. + +proc newImage*[T](width, height: int): Image[T] = + result = Image[T](width: width, height: height) + result.data = repeat(T(), width * height) + +template w*(img: Image): int = + img.width + +template h*(img: Image): int = + img.height + +template b*(c: ColorBit): uint8 = c.bit +template g*(c: ColorGray): ColorComponent = c.gray +template r*(c: ColorRGB): ColorComponent = c.red +template g*(c: ColorRGB): ColorComponent = c.green +template b*(c: ColorRGB): ColorComponent = c.blue +template line*[T: Color](img: Image[T], y: int): seq[T] = + let startPos = y * img.w + img.data[startPos ..< startPos+img.w] + +template `[]`*(img: Image, x, y: int): Color = + img.data[x + y * img.w] + +template `[]`*(img: Image, p: Point): Color = + img[p.x, p.y] + +template `[]=`*(img: var Image, x, y: int, c: Color) = + img.data[x + y * img.w] = c + +template `[]=`*(img: var Image, p: Point, c: Color) = + img[p.x, p.y] = c + +method str(c: Color): string {.base.} = discard +method str(c: ColorBit): string = $c[] +method str(c: ColorGray): string = $c[] +method str(c: ColorRGB): string = &"{c.r} {c.g} {c.b}" + +method write(c: Color, strm: Stream) {.base.} = + discard + +method write(c: ColorBit, strm: Stream) = + discard + +method write(c: ColorGray, strm: Stream) = + strm.write(c.g) + +method write(c: ColorRGB, strm: Stream) = + strm.write(c.r) + strm.write(c.g) + strm.write(c.b) + +proc writeFile*(fn: string, data: Image, descr: Descriptor, comment = "") = + var strm = newFileStream(fn, fmWrite) + defer: strm.close() + + # header + strm.writeLine(descr) + if comment != "": + strm.writeLine("#" & comment) + strm.writeLine($data.w & " " & $data.h) + case descr + of P2, P3, P5, P6: + strm.writeLine($data[0, 0].high) + else: + discard + + # body + case descr + of P1, P2, P3: + for y in 0.. Date: Sat, 13 Feb 2021 16:27:55 +0900 Subject: [PATCH 052/128] fix --- src/pnm.nim | 27 +++++++++++++++++---------- tests/test_pnm.nim | 4 ++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index a7da1e4..feddc9f 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -237,11 +237,12 @@ import streams, strformat from sequtils import mapIt, repeat +from strutils import join type - Image[T: Color] = object + Image = object width*, height*: int - data*: seq[T] + data*: seq[Color] Descriptor* {.pure.} = enum P1, P2, P3, P4, P5, P6 @@ -261,9 +262,10 @@ type ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. -proc newImage*[T](width, height: int): Image[T] = - result = Image[T](width: width, height: height) - result.data = repeat(T(), width * height) +proc newImage*(t: typedesc, width, height: int): Image = + result = Image(width: width, height: height) + let c: Color = t() + result.data = repeat(c, width * height) template w*(img: Image): int = img.width @@ -276,7 +278,7 @@ template g*(c: ColorGray): ColorComponent = c.gray template r*(c: ColorRGB): ColorComponent = c.red template g*(c: ColorRGB): ColorComponent = c.green template b*(c: ColorRGB): ColorComponent = c.blue -template line*[T: Color](img: Image[T], y: int): seq[T] = +template line*(img: Image, y: int): seq[Color] = let startPos = y * img.w img.data[startPos ..< startPos+img.w] @@ -293,8 +295,8 @@ template `[]=`*(img: var Image, p: Point, c: Color) = img[p.x, p.y] = c method str(c: Color): string {.base.} = discard -method str(c: ColorBit): string = $c[] -method str(c: ColorGray): string = $c[] +method str(c: ColorBit): string = $c.b +method str(c: ColorGray): string = $c.g method str(c: ColorRGB): string = &"{c.r} {c.g} {c.b}" method write(c: Color, strm: Stream) {.base.} = @@ -311,6 +313,11 @@ method write(c: ColorRGB, strm: Stream) = strm.write(c.g) strm.write(c.b) +method high(c: Color): int {.base.} = int.high +method high(c: ColorBit): int = 1 +method high(c: ColorGray): int = ColorComponent.high.int +method high(c: ColorRGB): int = ColorComponent.high.int + proc writeFile*(fn: string, data: Image, descr: Descriptor, comment = "") = var strm = newFileStream(fn, fmWrite) defer: strm.close() @@ -329,8 +336,8 @@ proc writeFile*(fn: string, data: Image, descr: Descriptor, comment = "") = # body case descr of P1, P2, P3: - for y in 0.. Date: Sat, 13 Feb 2021 16:37:43 +0900 Subject: [PATCH 053/128] fix --- tests/test_pnm.nim | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/test_pnm.nim b/tests/test_pnm.nim index c3e0a1a..b897187 100644 --- a/tests/test_pnm.nim +++ b/tests/test_pnm.nim @@ -7,10 +7,29 @@ const outputDataDir = "tests"/"out" suite "usecase": - test "create pgm image and save file": + test "create PBM image and save file": + var img = newImage(ColorBit, 50, 255) + for y in 0.. Date: Sat, 13 Feb 2021 16:37:52 +0900 Subject: [PATCH 054/128] fix --- tests/out/p1.pbm | 269 +++++++++++++++++++++++++++++++++++++++++++--- tests/out/p2.pgm | 271 ++++++++++++++++++++++++++++++++++++++++++++--- tests/out/p3.ppm | 263 +++++++++++++++++++++++++++++++++++++++++++-- tests/out/p5.pgm | Bin 82 -> 12764 bytes tests/out/p6.ppm | Bin 29 -> 38264 bytes 5 files changed, 769 insertions(+), 34 deletions(-) diff --git a/tests/out/p1.pbm b/tests/out/p1.pbm index 748661e..feb94c1 100644 --- a/tests/out/p1.pbm +++ b/tests/out/p1.pbm @@ -1,14 +1,257 @@ P1 -32 12 -1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file +50 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 diff --git a/tests/out/p2.pgm b/tests/out/p2.pgm index e308997..dee41cb 100644 --- a/tests/out/p2.pgm +++ b/tests/out/p2.pgm @@ -1,15 +1,258 @@ P2 -6 12 -2 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -0 0 0 0 0 0 -1 1 1 1 1 1 -1 1 1 1 1 1 -1 1 1 1 1 1 -1 1 1 1 1 1 -2 2 2 2 2 2 -2 2 2 2 2 2 -2 2 2 2 2 2 -2 2 2 2 2 2 \ No newline at end of file +50 255 +255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 +5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 +6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 +9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 +10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 +11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 +12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 12 +13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 +14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 +15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 +16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 +18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 +19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 19 +20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 +21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 21 +22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 22 +23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 +24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 +25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 25 +26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 26 +27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 27 +28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 28 +29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 +30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 +31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 +32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 +33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 +34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 +35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 +36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 +37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 +38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 +39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 +40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 +41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 +42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 +43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 +44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 +45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 45 +46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 46 +47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 47 +48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 48 +49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 49 +50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 +51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 +52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 +53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 +54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 +55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 +56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 56 +57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 +58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 +59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 59 +60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 60 +61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 +62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 62 +63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 +64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 64 +65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 +66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 66 +67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 67 +68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 68 +69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 +70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 +71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 +72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 72 +73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 73 +74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 74 +75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 75 +76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 +77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 77 +78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 +79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 79 +80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 +81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 +82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 82 +83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 +84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 84 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 86 +87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 +88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 88 +89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 +90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 +91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 +92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 +93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 93 +94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 +95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 95 +96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 96 +97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 +98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 98 +99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 +100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 +101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 101 +102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 102 +103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 103 +104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 104 +105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 105 +106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 106 +107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 107 +108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 108 +109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 109 +110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 110 +111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 +112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 112 +113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 113 +114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 114 +115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 115 +116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 116 +117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 117 +118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 118 +119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 119 +120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 120 +121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 121 +122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 122 +123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 +124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 124 +125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 125 +126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 126 +127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 +128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128 +129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 129 +130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 130 +131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 131 +132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 +133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 133 +134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 134 +135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 135 +136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 136 +137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 137 +138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 138 +139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 139 +140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 140 +141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 141 +142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 142 +143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 143 +144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 144 +145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 145 +146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 146 +147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 147 +148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 148 +149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 149 +150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 150 +151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 +152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 152 +153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 +154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 154 +155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 155 +156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 156 +157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 157 +158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 158 +159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 +160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 160 +161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 161 +162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 162 +163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 163 +164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 164 +165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 165 +166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 166 +167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 167 +168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 168 +169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 169 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 171 +172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 172 +173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 173 +174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 174 +175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 175 +176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 176 +177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 177 +178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 178 +179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 179 +180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 180 +181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 181 +182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 182 +183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 +184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 184 +185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 185 +186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 186 +187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 187 +188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 188 +189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 +190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 190 +191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 +192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 192 +193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 193 +194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 194 +195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 195 +196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 196 +197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 197 +198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 198 +199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 199 +200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 +201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 201 +202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 202 +203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 203 +204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 204 +205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 +206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 206 +207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 207 +208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 208 +209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 209 +210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 210 +211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 211 +212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 212 +213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 213 +214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 214 +215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 215 +216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 216 +217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 217 +218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 218 +219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 +220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 220 +221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 221 +222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 +223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 +224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 +225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 +226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 226 +227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 227 +228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 228 +229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 229 +230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 230 +231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 231 +232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 232 +233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 233 +234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 234 +235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 235 +236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 +237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 237 +238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 238 +239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 239 +240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 240 +241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 241 +242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 +243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 243 +244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 244 +245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 245 +246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 246 +247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 247 +248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 248 +249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 249 +250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 250 +251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 251 +252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 252 +253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 +254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 254 diff --git a/tests/out/p3.ppm b/tests/out/p3.ppm index 1ffafb6..d96df01 100644 --- a/tests/out/p3.ppm +++ b/tests/out/p3.ppm @@ -1,9 +1,258 @@ P3 -3 2 +50 255 255 -255 0 0 -0 255 0 -0 0 255 -255 255 0 -255 255 255 -0 0 0 \ No newline at end of file +0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 0 25 0 +1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 1 25 0 +2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 2 25 0 +3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 3 25 0 +4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 4 25 0 +5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 5 25 0 +6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 6 25 0 +7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 7 25 0 +8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 8 25 0 +9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 9 25 0 +10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 10 25 0 +11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 11 25 0 +12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 12 25 0 +13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 13 25 0 +14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 14 25 0 +15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 15 25 0 +16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 16 25 0 +17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 17 25 0 +18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 18 25 0 +19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 19 25 0 +20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 20 25 0 +21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 21 25 0 +22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 22 25 0 +23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 23 25 0 +24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 24 25 0 +25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 25 25 0 +26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 26 25 0 +27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 27 25 0 +28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 28 25 0 +29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 29 25 0 +30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 30 25 0 +31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 31 25 0 +32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 32 25 0 +33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 33 25 0 +34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 34 25 0 +35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 35 25 0 +36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 36 25 0 +37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 37 25 0 +38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 38 25 0 +39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 39 25 0 +40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 40 25 0 +41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 41 25 0 +42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 42 25 0 +43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 43 25 0 +44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 44 25 0 +45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 45 25 0 +46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 46 25 0 +47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 47 25 0 +48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 48 25 0 +49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 49 25 0 +50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 50 25 0 +51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 51 25 0 +52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 52 25 0 +53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 53 25 0 +54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 54 25 0 +55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 55 25 0 +56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 56 25 0 +57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 57 25 0 +58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 58 25 0 +59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 59 25 0 +60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 60 25 0 +61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 61 25 0 +62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 62 25 0 +63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 63 25 0 +64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 64 25 0 +65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 65 25 0 +66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 66 25 0 +67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 67 25 0 +68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 68 25 0 +69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 69 25 0 +70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 70 25 0 +71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 71 25 0 +72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 72 25 0 +73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 73 25 0 +74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 74 25 0 +75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 75 25 0 +76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 76 25 0 +77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 77 25 0 +78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 78 25 0 +79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 79 25 0 +80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 80 25 0 +81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 81 25 0 +82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 82 25 0 +83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 83 25 0 +84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 84 25 0 +85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 85 25 0 +86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 86 25 0 +87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 87 25 0 +88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 88 25 0 +89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 89 25 0 +90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 90 25 0 +91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 91 25 0 +92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 92 25 0 +93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 93 25 0 +94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 94 25 0 +95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 95 25 0 +96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 96 25 0 +97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 97 25 0 +98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 98 25 0 +99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 99 25 0 +100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 100 25 0 +101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 101 25 0 +102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 102 25 0 +103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 103 25 0 +104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 104 25 0 +105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 105 25 0 +106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 106 25 0 +107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 107 25 0 +108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 108 25 0 +109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 109 25 0 +110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 110 25 0 +111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 111 25 0 +112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 112 25 0 +113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 113 25 0 +114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 114 25 0 +115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 115 25 0 +116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 116 25 0 +117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 117 25 0 +118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 118 25 0 +119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 119 25 0 +120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 120 25 0 +121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 121 25 0 +122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 122 25 0 +123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 123 25 0 +124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 124 25 0 +125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 125 25 0 +126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 126 25 0 +127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 127 25 0 +128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 128 25 0 +129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 129 25 0 +130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 130 25 0 +131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 131 25 0 +132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 132 25 0 +133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 133 25 0 +134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 134 25 0 +135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 135 25 0 +136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 136 25 0 +137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 137 25 0 +138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 138 25 0 +139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 139 25 0 +140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 140 25 0 +141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 141 25 0 +142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 142 25 0 +143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 143 25 0 +144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 144 25 0 +145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 145 25 0 +146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 146 25 0 +147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 147 25 0 +148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 148 25 0 +149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 149 25 0 +150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 150 25 0 +151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 151 25 0 +152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 152 25 0 +153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 153 25 0 +154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 154 25 0 +155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 155 25 0 +156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 156 25 0 +157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 157 25 0 +158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 158 25 0 +159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 159 25 0 +160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 160 25 0 +161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 161 25 0 +162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 162 25 0 +163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 163 25 0 +164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 164 25 0 +165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 165 25 0 +166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 166 25 0 +167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 167 25 0 +168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 168 25 0 +169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 169 25 0 +170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 170 25 0 +171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 171 25 0 +172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 172 25 0 +173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 173 25 0 +174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 174 25 0 +175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 175 25 0 +176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 176 25 0 +177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 177 25 0 +178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 178 25 0 +179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 179 25 0 +180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 180 25 0 +181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 181 25 0 +182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 182 25 0 +183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 183 25 0 +184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 184 25 0 +185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 185 25 0 +186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 186 25 0 +187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 187 25 0 +188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 188 25 0 +189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 189 25 0 +190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 190 25 0 +191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 191 25 0 +192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 192 25 0 +193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 193 25 0 +194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 194 25 0 +195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 195 25 0 +196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 196 25 0 +197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 197 25 0 +198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 198 25 0 +199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 199 25 0 +200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 200 25 0 +201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 201 25 0 +202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 202 25 0 +203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 203 25 0 +204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 204 25 0 +205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 205 25 0 +206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 206 25 0 +207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 207 25 0 +208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 208 25 0 +209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 209 25 0 +210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 210 25 0 +211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 211 25 0 +212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 212 25 0 +213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 213 25 0 +214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 214 25 0 +215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 215 25 0 +216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 216 25 0 +217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 217 25 0 +218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 218 25 0 +219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 219 25 0 +220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 220 25 0 +221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 221 25 0 +222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 222 25 0 +223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 223 25 0 +224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 224 25 0 +225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 225 25 0 +226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 226 25 0 +227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 227 25 0 +228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 228 25 0 +229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 229 25 0 +230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 230 25 0 +231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 231 25 0 +232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 232 25 0 +233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 233 25 0 +234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 234 25 0 +235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 235 25 0 +236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 236 25 0 +237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 237 25 0 +238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 238 25 0 +239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 239 25 0 +240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 240 25 0 +241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 241 25 0 +242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 242 25 0 +243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 243 25 0 +244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 244 25 0 +245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 245 25 0 +246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 246 25 0 +247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 247 25 0 +248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 248 25 0 +249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 249 25 0 +250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 250 25 0 +251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 251 25 0 +252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 252 25 0 +253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 253 25 0 +254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 254 25 0 diff --git a/tests/out/p5.pgm b/tests/out/p5.pgm index 9fc02a7f378feabe9e36dfcbabf6a6b03ca84460..f7bfd4c36d596008cb6b94382e0c9fe7580c13b1 100644 GIT binary patch literal 12764 zcmb8e1Gg3i007X8ms{q`t{1*+W7Vt0W!tvREiYrp*jn7OZQHhSI{k!u&$*$2pg>4) zu0SB@`!Fml3&+B<2rMFt#3HjOEGi3P(O7gAgT-XASZo%D#brORcq~3kz!I`VEHO*M zlCoqhIZMG(vS5~qrDkbZT9%HbXBk*VmWgF%Sy)zar{K7Rsuz>g*?0gVkiU zSZ!8^)nz}kdaOQcz#6hftTAiCnzClBIcvdMvR14$Ys1>IcC0%;o8eyl$mzy`8GY%m+bhO%L7I2*x6vQca_8^gx3acn%Bz$UUuY%=?W z{mQ1WscagX&StQgY!>^C&1Q4hTsDu*XA9UuwumieOW5!15B4Yfi!Ei#*mAaltz@g% zYPN>0W$W1A>>swC{mVA6jcgO!%(k$t>_7HD+s3xD9c(At#dfnjY%kl#_Ok=*AUnhk zvm@*%JI0Q)6YL~A#ZI#`>?}LS&a(^bBD=&cvn%W>yT-1w8|)^##cs1Z>@K^F>@9o8-m?$vBm2ZYvoGu``vxe)xcdMA literal 82 ZcmWGAt*l8myNypz1+gG?OIw~wwGJBZQEXM*;ux1oKFA6J?HyY96D%V z_Q6921_u2Z2^vO%hLxb%3ro-<611oU{au0VXbA~gQi7I} zprs{f83|fef|iq@~MEkV~v(6thDodjJkK{rUyjS_T|1l=q_w@A>f5_Fpc z-7Z0QNYI@Ube9C(EkXB4(7h7$UkSQTg6@}~2PEi033^C^9+sd-B|OVBG4^r{5?UxHqfpw}hn4GDTv zg5Hv#w Date: Sat, 13 Feb 2021 16:50:23 +0900 Subject: [PATCH 055/128] fix --- src/pnm.nim | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/pnm.nim b/src/pnm.nim index feddc9f..6665492 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -267,6 +267,26 @@ proc newImage*(t: typedesc, width, height: int): Image = let c: Color = t() result.data = repeat(c, width * height) +func bitSeqToByteSeq(arr: openArray[uint8], col: int): seq[uint8] = + ## Returns sequences that binary sequence is converted to uint8 every 8 bits. + var data: uint8 + var i = 0 + for u in arr: + data = data shl 1 + data += u + i.inc + if i mod 8 == 0: + result.add data + data = 0'u8 + continue + if i mod col == 0: + data = data shl (8 - (i mod 8)) + result.add data + data = 0'u8 + i = 0 + if data != 0: + result.add data shl (8 - (i mod 8)) + template w*(img: Image): int = img.width @@ -299,6 +319,9 @@ method str(c: ColorBit): string = $c.b method str(c: ColorGray): string = $c.g method str(c: ColorRGB): string = &"{c.r} {c.g} {c.b}" +method bit(c: Color): uint8 {.base.} = discard +method bit(c: ColorBit): uint8 = c.b + method write(c: Color, strm: Stream) {.base.} = discard @@ -341,7 +364,8 @@ proc writeFile*(fn: string, data: Image, descr: Descriptor, comment = "") = let lineStr = line.mapIt(it.str).join(" ") strm.writeLine(lineStr) of P4: - discard + for b in data.data.mapIt(it.bit).bitSeqToByteSeq(8): + strm.write(b) of P5, P6: for c in data.data: c.write(strm) From cdee064ee2c49ce42a246151b637fad1155f66fb Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 13 Feb 2021 17:04:26 +0900 Subject: [PATCH 056/128] fix --- tests/out/p1.pbm | 512 ++++++++++++++++++++++----------------------- tests/out/p4.pbm | Bin 57 -> 2050 bytes tests/test_pnm.nim | 16 +- 3 files changed, 271 insertions(+), 257 deletions(-) diff --git a/tests/out/p1.pbm b/tests/out/p1.pbm index feb94c1..2f2417a 100644 --- a/tests/out/p1.pbm +++ b/tests/out/p1.pbm @@ -1,257 +1,257 @@ P1 -50 255 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +64 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 diff --git a/tests/out/p4.pbm b/tests/out/p4.pbm index 05da40ea2340a59140a30cf08b2413e1113e88ba..849c35e0e8548b15716c8a5554ee088ccec695af 100644 GIT binary patch literal 2050 zcmeH_!3_W)3<7;Sg)xn5L1Z_(PX r_EUbqTMN?)oADySQy8Y=@!DWoVKZJNcnZT*JYE}2D{RJ#gun6ttS{yS literal 57 ZcmWGA;W9Q-Ff`)&&wvL1qXGsr0015N8EF6j diff --git a/tests/test_pnm.nim b/tests/test_pnm.nim index b897187..aac588a 100644 --- a/tests/test_pnm.nim +++ b/tests/test_pnm.nim @@ -8,7 +8,7 @@ const suite "usecase": test "create PBM image and save file": - var img = newImage(ColorBit, 50, 255) + var img = newImage(ColorBit, 64, 255) for y in 0.. Date: Sat, 13 Feb 2021 17:19:49 +0900 Subject: [PATCH 057/128] fix --- src/pnm.nim | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 6665492..8576a2e 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -236,7 +236,7 @@ ## * `(JA) PNM(画像フォーマット) - Wikipedia `_ import streams, strformat -from sequtils import mapIt, repeat +from sequtils import mapIt, repeat, distribute from strutils import join type @@ -364,8 +364,19 @@ proc writeFile*(fn: string, data: Image, descr: Descriptor, comment = "") = let lineStr = line.mapIt(it.str).join(" ") strm.writeLine(lineStr) of P4: - for b in data.data.mapIt(it.bit).bitSeqToByteSeq(8): - strm.write(b) + let bits = data.data.mapIt(it.bit) + var rows: seq[seq[uint8]] + var row: seq[uint8] + for bit in bits: + row.add(bit) + if data.w <= row.len: + rows.add(row) + row = @[] + if 0 < row.len: + rows.add(row) + for row in rows: + for b in row.bitSeqToByteSeq(8): + strm.write(b) of P5, P6: for c in data.data: c.write(strm) From a3984a703ca030a613624148e0105aa67e8bf753 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 13 Feb 2021 17:19:53 +0900 Subject: [PATCH 058/128] fix --- tests/test_pnm.nim | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/test_pnm.nim b/tests/test_pnm.nim index aac588a..1117a68 100644 --- a/tests/test_pnm.nim +++ b/tests/test_pnm.nim @@ -8,15 +8,17 @@ const suite "usecase": test "create PBM image and save file": - var img = newImage(ColorBit, 64, 255) - for y in 0.. Date: Sat, 13 Feb 2021 17:26:05 +0900 Subject: [PATCH 059/128] change function name --- src/pnm.nim | 2 +- tests/test_pnm.nim | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 8576a2e..6936c8f 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -341,7 +341,7 @@ method high(c: ColorBit): int = 1 method high(c: ColorGray): int = ColorComponent.high.int method high(c: ColorRGB): int = ColorComponent.high.int -proc writeFile*(fn: string, data: Image, descr: Descriptor, comment = "") = +proc writePNMFile*(fn: string, data: Image, descr: Descriptor, comment = "") = var strm = newFileStream(fn, fmWrite) defer: strm.close() diff --git a/tests/test_pnm.nim b/tests/test_pnm.nim index 1117a68..39a338c 100644 --- a/tests/test_pnm.nim +++ b/tests/test_pnm.nim @@ -17,24 +17,24 @@ suite "usecase": if y div 10 mod 2 == 0: 0'u8 else: 1'u8 img[x, y] = ColorBit(bit: b) - writeFile(outputDataDir/"p1_" & $w & ".pbm", img, P1) - writeFile(outputDataDir/"p4_" & $w & ".pbm", img, P4) + writePNMFile(outputDataDir/"p1_" & $w & ".pbm", img, P1) + writePNMFile(outputDataDir/"p4_" & $w & ".pbm", img, P4) test "create PGM image and save file": var img = newImage(ColorGray, 50, 255) for y in 0.. Date: Sat, 13 Feb 2021 17:42:09 +0900 Subject: [PATCH 060/128] add read --- src/pnm.nim | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 6936c8f..d715d94 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -235,12 +235,15 @@ ## * `(EN) Portable Anymap - Wikipedia `_ ## * `(JA) PNM(画像フォーマット) - Wikipedia `_ -import streams, strformat +import streams, strformat, strutils from sequtils import mapIt, repeat, distribute -from strutils import join type - Image = object + PNM* = object + descriptor*: Descriptor + max: int + image: Image + Image* = object width*, height*: int data*: seq[Color] Descriptor* {.pure.} = enum @@ -267,6 +270,17 @@ proc newImage*(t: typedesc, width, height: int): Image = let c: Color = t() result.data = repeat(c, width * height) +func toDescriptor*(str: string): Descriptor = + case str + of "P1": P1 + of "P2": P2 + of "P3": P3 + of "P4": P4 + of "P5": P5 + of "P6": P6 + else: + raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & str) + func bitSeqToByteSeq(arr: openArray[uint8], col: int): seq[uint8] = ## Returns sequences that binary sequence is converted to uint8 every 8 bits. var data: uint8 @@ -341,6 +355,33 @@ method high(c: ColorBit): int = 1 method high(c: ColorGray): int = ColorComponent.high.int method high(c: ColorRGB): int = ColorComponent.high.int +proc readPNM*(strm: Stream): PNM = + # read descriptor + result.descriptor = strm.readLine().toDescriptor() + + # read comment line + let b = strm.peekChar() + if b == '#': + # コメント行を読み取って破棄 + discard strm.readLine() + + # read column size and row size + let sizeLine = strm.readLine() + let wh = sizeLine.split(" ") + let width = wh[0].parseInt() + let height = wh[1].parseInt() + result.image = + case result.descriptor + of P1, P4: newImage(ColorBit, width, height) + of P2, P5: newImage(ColorGray, width, height) + of P3, P6: newImage(ColorRGB, width, height) + + # read max data + case result.descriptor + of P2, P3, P5, P6: + result.max = strm.readLine().parseInt + else: discard + proc writePNMFile*(fn: string, data: Image, descr: Descriptor, comment = "") = var strm = newFileStream(fn, fmWrite) defer: strm.close() From a6f1583b5b973bcf3ebbb93c87cacc5777428bcd Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 16 Feb 2021 00:09:06 +0900 Subject: [PATCH 061/128] wip --- src/pnm.nim | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/pnm.nim b/src/pnm.nim index d715d94..3814673 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -236,7 +236,7 @@ ## * `(JA) PNM(画像フォーマット) - Wikipedia `_ import streams, strformat, strutils -from sequtils import mapIt, repeat, distribute +from sequtils import map, mapIt, repeat, distribute type PNM* = object @@ -356,6 +356,8 @@ method high(c: ColorGray): int = ColorComponent.high.int method high(c: ColorRGB): int = ColorComponent.high.int proc readPNM*(strm: Stream): PNM = + # TODO: refactoring + # read descriptor result.descriptor = strm.readLine().toDescriptor() @@ -382,6 +384,41 @@ proc readPNM*(strm: Stream): PNM = result.max = strm.readLine().parseInt else: discard + # body + case result.descriptor + of P2, P3: + var line: string + var bytes: seq[uint8] + while strm.readLine(line): + for b in line.splitWhitespace().mapIt(it.parseUInt.uint8): + # TODO: varidate data size + bytes.add(b) + case result.descriptor + of P2: + # TODO: move to procedure + var img = newImage(ColorGray, width, height) + img.data = bytes.map(proc(n: uint8): Color = + var c: Color = ColorGray(gray: n) + return c) + result.image = img + of P3: + # TODO: move to procedure + var img = newImage(ColorRGB, width, height) + var data: seq[array[3, uint8]] + var arr: array[3, uint8] + for i, b in bytes: + let m = i mod 3 + arr[m] = b + if (i+1) mod 3 == 0: + data.add(arr) + arr = [0'u8, 0, 0] + img.data = data.map(proc(n: array[3, uint8]): Color = + var c: Color = ColorRGB(red: n[0], green: n[1], blue: n[2]) + return c) + result.image = img + else: discard + else: discard + proc writePNMFile*(fn: string, data: Image, descr: Descriptor, comment = "") = var strm = newFileStream(fn, fmWrite) defer: strm.close() From 4d644589c50a5db34c78631fccb354a98d15c802 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:26:48 +0900 Subject: [PATCH 062/128] to proc --- src/pnm.nim | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 3814673..851da9e 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -355,6 +355,14 @@ method high(c: ColorBit): int = 1 method high(c: ColorGray): int = ColorComponent.high.int method high(c: ColorRGB): int = ColorComponent.high.int +proc readDataPart(strm: Stream): seq[uint8] = + ## for P2 or P3. + var line: string + while strm.readLine(line): + for b in line.splitWhitespace().mapIt(it.parseUInt.uint8): + # TODO: varidate data size + result.add(b) + proc readPNM*(strm: Stream): PNM = # TODO: refactoring @@ -387,12 +395,7 @@ proc readPNM*(strm: Stream): PNM = # body case result.descriptor of P2, P3: - var line: string - var bytes: seq[uint8] - while strm.readLine(line): - for b in line.splitWhitespace().mapIt(it.parseUInt.uint8): - # TODO: varidate data size - bytes.add(b) + let bytes = strm.readDataPart() case result.descriptor of P2: # TODO: move to procedure From 41ed45eecaa08325f627c54662863a6637873133 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:28:18 +0900 Subject: [PATCH 063/128] to proc --- src/pnm.nim | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 851da9e..5363b3c 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -363,6 +363,12 @@ proc readDataPart(strm: Stream): seq[uint8] = # TODO: varidate data size result.add(b) +proc toColorGrayImage(bytes: seq[uint8], width, height: int): Image = + result = newImage(ColorGray, width, height) + result.data = bytes.map(proc(n: uint8): Color = + var c: Color = ColorGray(gray: n) + return c) + proc readPNM*(strm: Stream): PNM = # TODO: refactoring @@ -398,12 +404,7 @@ proc readPNM*(strm: Stream): PNM = let bytes = strm.readDataPart() case result.descriptor of P2: - # TODO: move to procedure - var img = newImage(ColorGray, width, height) - img.data = bytes.map(proc(n: uint8): Color = - var c: Color = ColorGray(gray: n) - return c) - result.image = img + result.image = bytes.toColorGrayImage(width, height) of P3: # TODO: move to procedure var img = newImage(ColorRGB, width, height) From f041e50c52d7059d479e9453899e80957481ce4f Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:29:41 +0900 Subject: [PATCH 064/128] to proc --- src/pnm.nim | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 5363b3c..c2504a5 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -369,6 +369,20 @@ proc toColorGrayImage(bytes: seq[uint8], width, height: int): Image = var c: Color = ColorGray(gray: n) return c) +proc toColorRGBImage(bytes: seq[uint8], width, height: int): Image = + result = newImage(ColorRGB, width, height) + var data: seq[array[3, uint8]] + var arr: array[3, uint8] + for i, b in bytes: + let m = i mod 3 + arr[m] = b + if (i+1) mod 3 == 0: + data.add(arr) + arr = [0'u8, 0, 0] + result.data = data.map(proc(n: array[3, uint8]): Color = + var c: Color = ColorRGB(red: n[0], green: n[1], blue: n[2]) + return c) + proc readPNM*(strm: Stream): PNM = # TODO: refactoring @@ -406,20 +420,7 @@ proc readPNM*(strm: Stream): PNM = of P2: result.image = bytes.toColorGrayImage(width, height) of P3: - # TODO: move to procedure - var img = newImage(ColorRGB, width, height) - var data: seq[array[3, uint8]] - var arr: array[3, uint8] - for i, b in bytes: - let m = i mod 3 - arr[m] = b - if (i+1) mod 3 == 0: - data.add(arr) - arr = [0'u8, 0, 0] - img.data = data.map(proc(n: array[3, uint8]): Color = - var c: Color = ColorRGB(red: n[0], green: n[1], blue: n[2]) - return c) - result.image = img + result.image = bytes.toColorRGBImage(width, height) else: discard else: discard From d760b1884b99fa94ccd6ac6a3023143cba264013 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:30:47 +0900 Subject: [PATCH 065/128] change proc name --- src/pnm.nim | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index c2504a5..0553d8a 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -355,7 +355,7 @@ method high(c: ColorBit): int = 1 method high(c: ColorGray): int = ColorComponent.high.int method high(c: ColorRGB): int = ColorComponent.high.int -proc readDataPart(strm: Stream): seq[uint8] = +proc readDataPartOfTextData(strm: Stream): seq[uint8] = ## for P2 or P3. var line: string while strm.readLine(line): @@ -414,14 +414,12 @@ proc readPNM*(strm: Stream): PNM = # body case result.descriptor - of P2, P3: - let bytes = strm.readDataPart() - case result.descriptor - of P2: - result.image = bytes.toColorGrayImage(width, height) - of P3: - result.image = bytes.toColorRGBImage(width, height) - else: discard + of P2: + let bytes = strm.readDataPartOfTextData() + result.image = bytes.toColorGrayImage(width, height) + of P3: + let bytes = strm.readDataPartOfTextData() + result.image = bytes.toColorRGBImage(width, height) else: discard proc writePNMFile*(fn: string, data: Image, descr: Descriptor, comment = "") = From 4ccfdd197ab03ece1ec0aa4a3de496de3cbc7b92 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:32:41 +0900 Subject: [PATCH 066/128] add p1 read --- src/pnm.nim | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pnm.nim b/src/pnm.nim index 0553d8a..75044e1 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -363,6 +363,12 @@ proc readDataPartOfTextData(strm: Stream): seq[uint8] = # TODO: varidate data size result.add(b) +proc toColorBitImage(bytes: seq[uint8], width, height: int): Image = + result = newImage(ColorBit, width, height) + result.data = bytes.map(proc(n: uint8): Color = + var c: Color = ColorBit(bit: n) + return c) + proc toColorGrayImage(bytes: seq[uint8], width, height: int): Image = result = newImage(ColorGray, width, height) result.data = bytes.map(proc(n: uint8): Color = @@ -414,6 +420,9 @@ proc readPNM*(strm: Stream): PNM = # body case result.descriptor + of P1: + let bytes = strm.readDataPartOfTextData() + result.image = bytes.toColorBitImage(width, height) of P2: let bytes = strm.readDataPartOfTextData() result.image = bytes.toColorGrayImage(width, height) From 3b74658a501d135b68f3c4b8800daef3eb4a0878 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:38:04 +0900 Subject: [PATCH 067/128] impl --- src/pnm.nim | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/pnm.nim b/src/pnm.nim index 75044e1..dde29b6 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -363,6 +363,11 @@ proc readDataPartOfTextData(strm: Stream): seq[uint8] = # TODO: varidate data size result.add(b) +proc readDataPartOfBinaryData(strm: Stream): seq[uint8] = + ## for P5 or P6. + ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 + result = strm.readAll().mapIt(it.uint8) + proc toColorBitImage(bytes: seq[uint8], width, height: int): Image = result = newImage(ColorBit, width, height) result.data = bytes.map(proc(n: uint8): Color = @@ -429,7 +434,17 @@ proc readPNM*(strm: Stream): PNM = of P3: let bytes = strm.readDataPartOfTextData() result.image = bytes.toColorRGBImage(width, height) - else: discard + of P4: + # TODO + # let bytes = strm.readDataPartOfTextData() + # result.image = bytes.toColorBitImage(width, height) + discard + of P5: + let bytes = strm.readDataPartOfBinaryData() + result.image = bytes.toColorGrayImage(width, height) + of P6: + let bytes = strm.readDataPartOfBinaryData() + result.image = bytes.toColorRGBImage(width, height) proc writePNMFile*(fn: string, data: Image, descr: Descriptor, comment = "") = var strm = newFileStream(fn, fmWrite) From 34decad165b8148c9cc9e96dc8e55d6f0c83469a Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:39:50 +0900 Subject: [PATCH 068/128] remove unused code --- src/pnm.nim | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index dde29b6..b5fa2b4 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -407,15 +407,11 @@ proc readPNM*(strm: Stream): PNM = discard strm.readLine() # read column size and row size - let sizeLine = strm.readLine() - let wh = sizeLine.split(" ") - let width = wh[0].parseInt() - let height = wh[1].parseInt() - result.image = - case result.descriptor - of P1, P4: newImage(ColorBit, width, height) - of P2, P5: newImage(ColorGray, width, height) - of P3, P6: newImage(ColorRGB, width, height) + let + sizeLine = strm.readLine() + wh = sizeLine.split(" ") + width = wh[0].parseInt() + height = wh[1].parseInt() # read max data case result.descriptor From a3c539058830adfbe2940907c646c6dc939ce07d Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:41:08 +0900 Subject: [PATCH 069/128] impl --- src/pnm.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pnm.nim b/src/pnm.nim index b5fa2b4..11a9eb2 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -366,6 +366,7 @@ proc readDataPartOfTextData(strm: Stream): seq[uint8] = proc readDataPartOfBinaryData(strm: Stream): seq[uint8] = ## for P5 or P6. ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 + # TODO: varidate data size result = strm.readAll().mapIt(it.uint8) proc toColorBitImage(bytes: seq[uint8], width, height: int): Image = From 1118a81c2e6fb3a4adeb6029987b267abfd5adb3 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:46:04 +0900 Subject: [PATCH 070/128] add early return --- src/pnm.nim | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 11a9eb2..7c78181 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -355,13 +355,17 @@ method high(c: ColorBit): int = 1 method high(c: ColorGray): int = ColorComponent.high.int method high(c: ColorRGB): int = ColorComponent.high.int -proc readDataPartOfTextData(strm: Stream): seq[uint8] = +proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = ## for P2 or P3. + let maxDataCount = width * height * byteSize var line: string + var dataCounter: int while strm.readLine(line): for b in line.splitWhitespace().mapIt(it.parseUInt.uint8): - # TODO: varidate data size result.add(b) + inc(dataCounter) + if maxDataCount <= dataCounter: + return proc readDataPartOfBinaryData(strm: Stream): seq[uint8] = ## for P5 or P6. @@ -421,15 +425,16 @@ proc readPNM*(strm: Stream): PNM = else: discard # body + const byteSize = 1 case result.descriptor of P1: - let bytes = strm.readDataPartOfTextData() + let bytes = strm.readDataPartOfTextData(width, height, byteSize) result.image = bytes.toColorBitImage(width, height) of P2: - let bytes = strm.readDataPartOfTextData() + let bytes = strm.readDataPartOfTextData(width, height, byteSize) result.image = bytes.toColorGrayImage(width, height) of P3: - let bytes = strm.readDataPartOfTextData() + let bytes = strm.readDataPartOfTextData(width, height, byteSize, true) result.image = bytes.toColorRGBImage(width, height) of P4: # TODO From 73c77ec1f40171582d09891e4cd8d9f4f4e5906e Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:53:07 +0900 Subject: [PATCH 071/128] add early return --- src/pnm.nim | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 7c78181..8a46651 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -367,11 +367,16 @@ proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = fa if maxDataCount <= dataCounter: return -proc readDataPartOfBinaryData(strm: Stream): seq[uint8] = +proc readDataPartOfBinaryData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = ## for P5 or P6. ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 - # TODO: varidate data size - result = strm.readAll().mapIt(it.uint8) + let maxDataCount = width * height * byteSize + var dataCounter: int + while not strm.atEnd(): + result.add(strm.readUint8()) + inc(dataCounter) + if maxDataCount <= dataCounter: + return proc toColorBitImage(bytes: seq[uint8], width, height: int): Image = result = newImage(ColorBit, width, height) @@ -442,10 +447,10 @@ proc readPNM*(strm: Stream): PNM = # result.image = bytes.toColorBitImage(width, height) discard of P5: - let bytes = strm.readDataPartOfBinaryData() + let bytes = strm.readDataPartOfBinaryData(width, height, byteSize) result.image = bytes.toColorGrayImage(width, height) of P6: - let bytes = strm.readDataPartOfBinaryData() + let bytes = strm.readDataPartOfBinaryData(width, height, byteSize, true) result.image = bytes.toColorRGBImage(width, height) proc writePNMFile*(fn: string, data: Image, descr: Descriptor, comment = "") = From 05c192dce409a6d3783106018bab3215ba6d302a Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:55:05 +0900 Subject: [PATCH 072/128] rgb --- src/pnm.nim | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 8a46651..ea972dd 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -357,7 +357,10 @@ method high(c: ColorRGB): int = ColorComponent.high.int proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = ## for P2 or P3. - let maxDataCount = width * height * byteSize + let singleDataSize = width * height * byteSize + let maxDataCount = + if rgb: singleDataSize * 3 + else: singleDataSize var line: string var dataCounter: int while strm.readLine(line): @@ -370,7 +373,10 @@ proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = fa proc readDataPartOfBinaryData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = ## for P5 or P6. ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 - let maxDataCount = width * height * byteSize + let singleDataSize = width * height * byteSize + let maxDataCount = + if rgb: singleDataSize * 3 + else: singleDataSize var dataCounter: int while not strm.atEnd(): result.add(strm.readUint8()) From d9a3a5092c1e5dcadb7d888e6760ac3aa7180ddb Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Feb 2021 23:55:34 +0900 Subject: [PATCH 073/128] remove comment --- src/pnm.nim | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index ea972dd..f38f1df 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -411,8 +411,6 @@ proc toColorRGBImage(bytes: seq[uint8], width, height: int): Image = return c) proc readPNM*(strm: Stream): PNM = - # TODO: refactoring - # read descriptor result.descriptor = strm.readLine().toDescriptor() From a6d02b99c3a107045f22c56f25db1f9132ba7e2e Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 18 Feb 2021 00:01:58 +0900 Subject: [PATCH 074/128] =?UTF-8?q?=E5=8F=A4=E3=81=84=E3=82=B3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=82=92=E5=85=A8=E9=83=A8=E5=89=8A=E9=99=A4=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pnm/pbm.nim | 105 ------------------------------------ src/pnm/pgm.nim | 27 ---------- src/pnm/ppm.nim | 28 ---------- src/pnm/types.nim | 133 ---------------------------------------------- src/pnm/util.nim | 54 ------------------- tests/out/p4.pbm | Bin 2050 -> 2032 bytes 6 files changed, 347 deletions(-) delete mode 100644 src/pnm/pbm.nim delete mode 100644 src/pnm/pgm.nim delete mode 100644 src/pnm/ppm.nim delete mode 100644 src/pnm/types.nim delete mode 100644 src/pnm/util.nim diff --git a/src/pnm/pbm.nim b/src/pnm/pbm.nim deleted file mode 100644 index 13e45f6..0000000 --- a/src/pnm/pbm.nim +++ /dev/null @@ -1,105 +0,0 @@ -import streams, sequtils, strutils -import types, util -export types - -proc readTextDataPartOfPBM(strm: Stream): seq[uint8] = - ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 - # P1は空白文字があってもなくても良い - var line: string - while strm.readLine(line): - result.add(toSeq(line.replace(" ", "").items).mapIt(it.uint8)) - -proc toBitSeq(b: uint8): seq[uint8] = - ## Return binary sequence from each bits of uint8. - runnableExamples: - from sequtils import repeat - doAssert 0'u8.toBitSeq == 0'u8.repeat(8) - doAssert 0b1010_1010.toBitSeq == @[1'u8, 0, 1, 0, 1, 0, 1, 0] - var c = b - for i in 1..8: - result.add (uint8(c and 0b1000_0000) shr 7) - c = c shl 1 - -proc readBinaryDataPartOfPBM(strm: Stream, columnSize: int): seq[uint8] = - ## **Note**: 事前にstrmからヘッダ部分の読み込みが完了していないといけない。 - # P1は空白文字があってもなくても良い - var rowBin: seq[uint8] - while not strm.atEnd: - let bins = strm.readChar().uint8.toBitSeq() - for b in bins: - rowBin.add(b) - if columnSize <= rowBin.len: - result.add(rowBin) - rowBin = @[] - break - -proc readPBM*(strm: Stream): PBM = - result.header = strm.readHeaderPart() - result.data = - case result.header.descriptor - of P1: strm.readTextDataPartOfPBM() - of P4: strm.readBinaryDataPartOfPBM(result.header.col) - else: - raise newException(IllegalFileDescriptorError, "TODO") - -proc readPBMFile*(file: string): PBM = - var strm = newFileStream(file) - defer: strm.close() - result = strm.readPBM() - -func bitSeqToByteSeq(arr: openArray[uint8], col: int): seq[uint8] = - ## Returns sequences that binary sequence is converted to uint8 every 8 bits. - var data: uint8 - var i = 0 - for u in arr: - data = data shl 1 - data += u - i.inc - if i mod 8 == 0: - result.add data - data = 0'u8 - continue - if i mod col == 0: - data = data shl (8 - (i mod 8)) - result.add data - data = 0'u8 - i = 0 - if data != 0: - result.add data shl (8 - (i mod 8)) - -func headTail[T](data: seq[T], size: int): (seq[T], seq[T]) = - if data.len < size: - result[0] = data - return - result[0] = data[0..JA5QSlkg$a!#=nMvIS;38TG)Hj+OAEu*PdvEv%Cbxn5L1Z_(PX r_EUbqTMN?)oADySQy8Y=@!DWoVKZJNcnZT*JYE}2D{RJ#gun6ttS{yS From dfec69714734ca87265ad89a4c885ea9da24506f Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 18 Feb 2021 00:05:43 +0900 Subject: [PATCH 075/128] =?UTF-8?q?public=E3=81=AA=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=82=B7=E3=83=BC=E3=82=B8=E3=83=A3=E3=82=92private=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pnm.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pnm.nim b/src/pnm.nim index f38f1df..d2e0c4b 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -270,7 +270,7 @@ proc newImage*(t: typedesc, width, height: int): Image = let c: Color = t() result.data = repeat(c, width * height) -func toDescriptor*(str: string): Descriptor = +func toDescriptor(str: string): Descriptor = case str of "P1": P1 of "P2": P2 From 8c3c74c54b1812a896bb07df83d432d12d3adc69 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 18 Feb 2021 00:12:12 +0900 Subject: [PATCH 076/128] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E8=A1=8C=E3=82=92=E8=AA=AD=E3=81=BF=E5=8F=96=E3=82=8C=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pnm.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index d2e0c4b..9d9bc9e 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -241,6 +241,7 @@ from sequtils import map, mapIt, repeat, distribute type PNM* = object descriptor*: Descriptor + comment: string max: int image: Image Image* = object @@ -417,8 +418,8 @@ proc readPNM*(strm: Stream): PNM = # read comment line let b = strm.peekChar() if b == '#': - # コメント行を読み取って破棄 - discard strm.readLine() + discard strm.readChar() # remove comment prefix + result.comment = strm.readLine() # read column size and row size let From d0e50d29a2667e0fe7183aa716dcd7af5fb63100 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 18 Feb 2021 00:15:42 +0900 Subject: [PATCH 077/128] =?UTF-8?q?writePNM=E3=82=92PNM=E3=82=AA=E3=83=96?= =?UTF-8?q?=E3=82=B8=E3=82=A7=E3=82=AF=E3=83=88=E3=82=92=E5=8F=97=E3=81=91?= =?UTF-8?q?=E5=8F=96=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pnm.nim | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 9d9bc9e..43aabaf 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -458,35 +458,33 @@ proc readPNM*(strm: Stream): PNM = let bytes = strm.readDataPartOfBinaryData(width, height, byteSize, true) result.image = bytes.toColorRGBImage(width, height) -proc writePNMFile*(fn: string, data: Image, descr: Descriptor, comment = "") = - var strm = newFileStream(fn, fmWrite) - defer: strm.close() - +proc writePNM*(strm: Stream, data: PNM) = + let image = data.image # header - strm.writeLine(descr) - if comment != "": - strm.writeLine("#" & comment) - strm.writeLine($data.w & " " & $data.h) - case descr + strm.writeLine(data.descriptor) + if data.comment != "": + strm.writeLine("#" & data.comment) + strm.writeLine($image.w & " " & $image.h) + case data.descriptor of P2, P3, P5, P6: - strm.writeLine($data[0, 0].high) + strm.writeLine($image[0, 0].high) else: discard # body - case descr + case data.descriptor of P1, P2, P3: - for y in 0.. Date: Thu, 18 Feb 2021 00:18:01 +0900 Subject: [PATCH 078/128] =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB?= =?UTF-8?q?=E3=82=92=E7=9B=B4=E6=8E=A5=E6=89=B1=E3=81=86=E3=81=9F=E3=82=81?= =?UTF-8?q?=E3=81=AE=E3=83=97=E3=83=AD=E3=82=B7=E3=83=BC=E3=82=B8=E3=83=A3?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pnm.nim | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pnm.nim b/src/pnm.nim index 43aabaf..38c782b 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -496,3 +496,13 @@ proc writePNM*(strm: Stream, data: PNM) = for c in image.data: c.write(strm) +when not defined js: + proc readPNMFile*(fn: string): PNM = + var strm = newFileStream(fn, fmRead) + defer: strm.close() + result = strm.readPNM() + + proc writePNMFile*(fn: string, data: PNM) = + var strm = newFileStream(fn, fmWrite) + defer: strm.close() + strm.writePNM(data) From 1d2d9d96ee8c0707131cdeac1fa1214f18b21c97 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Thu, 18 Feb 2021 00:18:55 +0900 Subject: [PATCH 079/128] =?UTF-8?q?=E3=81=84=E3=82=89=E3=81=AA=E3=81=84?= =?UTF-8?q?=E6=B0=97=E3=81=8C=E3=81=97=E3=81=9F=E3=81=AE=E3=81=A7Point?= =?UTF-8?q?=E5=9E=8B=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pnm.nim | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 38c782b..6bb6886 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -259,9 +259,6 @@ type ColorRGB* = ref object of Color red*, green*, blue*: ColorComponent - Point* = object - x*, y*: int - IllegalFileDescriptorError* = object of Defect ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. @@ -320,15 +317,9 @@ template line*(img: Image, y: int): seq[Color] = template `[]`*(img: Image, x, y: int): Color = img.data[x + y * img.w] -template `[]`*(img: Image, p: Point): Color = - img[p.x, p.y] - template `[]=`*(img: var Image, x, y: int, c: Color) = img.data[x + y * img.w] = c -template `[]=`*(img: var Image, p: Point, c: Color) = - img[p.x, p.y] = c - method str(c: Color): string {.base.} = discard method str(c: ColorBit): string = $c.b method str(c: ColorGray): string = $c.g From 9e619d09507140fcb5f6d20c92b5c7bc66223bf8 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sun, 14 Mar 2021 16:45:23 +0900 Subject: [PATCH 080/128] impl pgm, ppm --- src/pnm.nim | 540 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 359 insertions(+), 181 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 6bb6886..3845386 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -239,114 +239,35 @@ import streams, strformat, strutils from sequtils import map, mapIt, repeat, distribute type - PNM* = object - descriptor*: Descriptor + Pnm* = ref PnmObj + PnmObj* = object of RootObj + descriptor: Descriptor comment: string - max: int - image: Image - Image* = object - width*, height*: int - data*: seq[Color] + width, height, max: int + + Pbm* = ref PbmObj + PbmObj* = object of PnmObj + data: seq[ColorBit] + + Pgm* = ref PgmObj + PgmObj* = object of PnmObj + data: seq[ColorGray] + + Ppm* = ref PpmObj + PpmObj* = object of PnmObj + data: seq[ColorRgb] + Descriptor* {.pure.} = enum P1, P2, P3, P4, P5, P6 - Color* = ref object of RootObj # base class - ColorComponent* = uint8 - ColorBit* = ref object of Color - bit: uint8 # 0 or 1 - ColorGray* = ref object of Color - gray: ColorComponent - ColorRGB* = ref object of Color - red*, green*, blue*: ColorComponent + ColorBit* = byte + ColorGray* = byte + ColorRgb* = array[3, byte] IllegalFileDescriptorError* = object of Defect ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. -proc newImage*(t: typedesc, width, height: int): Image = - result = Image(width: width, height: height) - let c: Color = t() - result.data = repeat(c, width * height) - -func toDescriptor(str: string): Descriptor = - case str - of "P1": P1 - of "P2": P2 - of "P3": P3 - of "P4": P4 - of "P5": P5 - of "P6": P6 - else: - raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & str) - -func bitSeqToByteSeq(arr: openArray[uint8], col: int): seq[uint8] = - ## Returns sequences that binary sequence is converted to uint8 every 8 bits. - var data: uint8 - var i = 0 - for u in arr: - data = data shl 1 - data += u - i.inc - if i mod 8 == 0: - result.add data - data = 0'u8 - continue - if i mod col == 0: - data = data shl (8 - (i mod 8)) - result.add data - data = 0'u8 - i = 0 - if data != 0: - result.add data shl (8 - (i mod 8)) - -template w*(img: Image): int = - img.width - -template h*(img: Image): int = - img.height - -template b*(c: ColorBit): uint8 = c.bit -template g*(c: ColorGray): ColorComponent = c.gray -template r*(c: ColorRGB): ColorComponent = c.red -template g*(c: ColorRGB): ColorComponent = c.green -template b*(c: ColorRGB): ColorComponent = c.blue -template line*(img: Image, y: int): seq[Color] = - let startPos = y * img.w - img.data[startPos ..< startPos+img.w] - -template `[]`*(img: Image, x, y: int): Color = - img.data[x + y * img.w] - -template `[]=`*(img: var Image, x, y: int, c: Color) = - img.data[x + y * img.w] = c - -method str(c: Color): string {.base.} = discard -method str(c: ColorBit): string = $c.b -method str(c: ColorGray): string = $c.g -method str(c: ColorRGB): string = &"{c.r} {c.g} {c.b}" - -method bit(c: Color): uint8 {.base.} = discard -method bit(c: ColorBit): uint8 = c.b - -method write(c: Color, strm: Stream) {.base.} = - discard - -method write(c: ColorBit, strm: Stream) = - discard - -method write(c: ColorGray, strm: Stream) = - strm.write(c.g) - -method write(c: ColorRGB, strm: Stream) = - strm.write(c.r) - strm.write(c.g) - strm.write(c.b) - -method high(c: Color): int {.base.} = int.high -method high(c: ColorBit): int = 1 -method high(c: ColorGray): int = ColorComponent.high.int -method high(c: ColorRGB): int = ColorComponent.high.int - proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = ## for P2 or P3. let singleDataSize = width * height * byteSize @@ -376,34 +297,123 @@ proc readDataPartOfBinaryData(strm: Stream, width, height, byteSize: int, rgb = if maxDataCount <= dataCounter: return -proc toColorBitImage(bytes: seq[uint8], width, height: int): Image = - result = newImage(ColorBit, width, height) - result.data = bytes.map(proc(n: uint8): Color = - var c: Color = ColorBit(bit: n) - return c) - -proc toColorGrayImage(bytes: seq[uint8], width, height: int): Image = - result = newImage(ColorGray, width, height) - result.data = bytes.map(proc(n: uint8): Color = - var c: Color = ColorGray(gray: n) - return c) - -proc toColorRGBImage(bytes: seq[uint8], width, height: int): Image = - result = newImage(ColorRGB, width, height) - var data: seq[array[3, uint8]] - var arr: array[3, uint8] +func toDescriptor(str: string): Descriptor = + case str + of "P1": P1 + of "P2": P2 + of "P3": P3 + of "P4": P4 + of "P5": P5 + of "P6": P6 + else: + raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & str) + +#[ +================================================================================ + PGM +================================================================================ +]# + +template line(p: Pgm, y: int): seq[ColorGray] = + let startPos = y * p.width + p.data[startPos ..< startPos+p.width] + +proc `[]`*(p: Pgm, x, y: int): ColorGray = + p.data[x + y * p.width] + +proc `[]=`*(p: Pgm, x, y: int, c: ColorGray) = + p.data[x + y * p.width] = c + +proc readPgm*(strm: Stream): Pgm = + new result + result.descriptor = strm.readLine().toDescriptor() + + # read comment line + let b = strm.peekChar() + if b == '#': + discard strm.readChar() # remove comment prefix + result.comment = strm.readLine() + + # read column size and row size + let + sizeLine = strm.readLine() + wh = sizeLine.split(" ") + width = wh[0].parseInt() + height = wh[1].parseInt() + + result.width = width + result.height = height + + # read max data + case result.descriptor + of P2, P5: + result.max = strm.readLine().parseInt + else: discard + + # body + const byteSize = 1 + case result.descriptor + of P2: result.data = strm.readDataPartOfTextData(width, height, byteSize) + of P5: result.data = strm.readDataPartOfBinaryData(width, height, byteSize) + else: discard + +proc writePgm*(strm: Stream, data: Pgm) = + # header + strm.writeLine(data.descriptor) + if data.comment != "": + strm.writeLine("#" & data.comment) + strm.writeLine($data.width & " " & $data.height) + strm.writeLine($high(ColorGray)) + + # body + case data.descriptor + of P2: + for y in 0.. Date: Mon, 15 Mar 2021 09:54:49 +0900 Subject: [PATCH 081/128] fix --- src/pnm.nim | 57 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 3845386..b59892a 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -241,7 +241,7 @@ from sequtils import map, mapIt, repeat, distribute type Pnm* = ref PnmObj PnmObj* = object of RootObj - descriptor: Descriptor + descriptor: PnmDescriptor comment: string width, height, max: int @@ -257,7 +257,7 @@ type PpmObj* = object of PnmObj data: seq[ColorRgb] - Descriptor* {.pure.} = enum + PnmDescriptor* {.pure.} = enum P1, P2, P3, P4, P5, P6 ColorBit* = byte @@ -268,6 +268,17 @@ type ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. +proc width*(p: Pnm): int = p.width +proc height*(p: Pnm): int = p.height + +template validateDescriptorPgm(d: PnmDescriptor) = + if d notin [P2, P5]: + raise newException(IllegalFileDescriptorError, "the descriptor of PGM must be P2 or P5") + +template validateDescriptorPpm(d: PnmDescriptor) = + if d notin [P3, P6]: + raise newException(IllegalFileDescriptorError, "the descriptor of PPM must be P3 or P6") + proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = ## for P2 or P3. let singleDataSize = width * height * byteSize @@ -297,7 +308,7 @@ proc readDataPartOfBinaryData(strm: Stream, width, height, byteSize: int, rgb = if maxDataCount <= dataCounter: return -func toDescriptor(str: string): Descriptor = +func toDescriptor(str: string): PnmDescriptor = case str of "P1": P1 of "P2": P2 @@ -314,6 +325,17 @@ func toDescriptor(str: string): Descriptor = ================================================================================ ]# +proc newPgm*(descriptor: PnmDescriptor, width, height, max: int, comment = ""): Pgm = + validateDescriptorPgm(descriptor) + + new result + result.descriptor = descriptor + result.width = width + result.height = height + result.max = max + result.comment = comment + result.data = repeat(ColorGray(0'u8), width*height) + template line(p: Pgm, y: int): seq[ColorGray] = let startPos = y * p.width p.data[startPos ..< startPos+p.width] @@ -321,8 +343,12 @@ template line(p: Pgm, y: int): seq[ColorGray] = proc `[]`*(p: Pgm, x, y: int): ColorGray = p.data[x + y * p.width] -proc `[]=`*(p: Pgm, x, y: int, c: ColorGray) = - p.data[x + y * p.width] = c +proc `[]=`*(p: Pgm, x, y: int, color: ColorGray) = + p.data[x + y * p.width] = color + +proc `descriptor=`*(p: Pgm, descriptor: PnmDescriptor) = + validateDescriptorPgm(descriptor) + p.descriptor = descriptor proc readPgm*(strm: Stream): Pgm = new result @@ -383,6 +409,17 @@ proc writePgm*(strm: Stream, data: Pgm) = ================================================================================ ]# +proc newPpm*(descriptor: PnmDescriptor, width, height, max: int, comment = ""): Ppm = + validateDescriptorPpm(descriptor) + + new result + result.descriptor = descriptor + result.width = width + result.height = height + result.max = max + result.comment = comment + result.data = repeat(ColorRgb([0'u8, 0, 0]), width*height) + template line(p: Ppm, y: int): seq[ColorRgb] = let startPos = y * p.width p.data[startPos ..< startPos+p.width] @@ -398,8 +435,12 @@ template `b=`*(c: ColorRGB, b: byte) = c[2] = b proc `[]`*(p: Ppm, x, y: int): ColorRgb = p.data[x + y * p.width] -proc `[]=`*(p: Ppm, x, y: int, c: ColorRgb) = - p.data[x + y * p.width] = c +proc `[]=`*(p: Ppm, x, y: int, color: ColorRgb) = + p.data[x + y * p.width] = color + +proc `descriptor=`*(p: Ppm, descriptor: PnmDescriptor) = + validateDescriptorPpm(descriptor) + p.descriptor = descriptor proc toColorRgb(bytes: seq[uint8]): seq[ColorRgb] = var data: seq[ColorRgb] @@ -474,7 +515,7 @@ when false: let c: Color = t() result.data = repeat(c, width * height) - func toDescriptor(str: string): Descriptor = + func toDescriptor(str: string): PnmDescriptor = case str of "P1": P1 of "P2": P2 From 72f23d4b7b7e0f02e0f5eac6798e9538e5d9947c Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Mon, 15 Mar 2021 09:54:54 +0900 Subject: [PATCH 082/128] add cfg --- nim.cfg | 1 + 1 file changed, 1 insertion(+) create mode 100644 nim.cfg diff --git a/nim.cfg b/nim.cfg new file mode 100644 index 0000000..e390429 --- /dev/null +++ b/nim.cfg @@ -0,0 +1 @@ +path="./src" From 777b0a2192a20d3058bed684ab2372651471209a Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Mon, 15 Mar 2021 09:55:15 +0900 Subject: [PATCH 083/128] backup --- tests/{test_pnm.nim => test_pnm.nim.bk} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{test_pnm.nim => test_pnm.nim.bk} (100%) diff --git a/tests/test_pnm.nim b/tests/test_pnm.nim.bk similarity index 100% rename from tests/test_pnm.nim rename to tests/test_pnm.nim.bk From e399ed6008e219aa55734b09cd0c37bec33a84e0 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Mon, 15 Mar 2021 09:55:24 +0900 Subject: [PATCH 084/128] add example code --- tests/examples/write_pgm.nim | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/examples/write_pgm.nim diff --git a/tests/examples/write_pgm.nim b/tests/examples/write_pgm.nim new file mode 100644 index 0000000..1b541c2 --- /dev/null +++ b/tests/examples/write_pgm.nim @@ -0,0 +1,31 @@ +discard """ + output: ''' +P2 +5 5 +255 +0 0 0 0 0 +1 1 1 1 1 +0 0 0 0 0 +1 1 1 1 1 +0 0 0 0 0 +''' +""" + +import pnm + +import streams + +var strm = newStringStream() +var p = newPgm(PnmDescriptor.P2, 5, 5, 255) + +for y in 0 ..< p.height: + for x in 0 ..< p.width: + let b = + if y mod 2 == 0: 0'u8 + else: 1'u8 + p[x, y] = ColorBit(b) + +strm.writePgm p +strm.setPosition 0 +echo strm.readAll +strm.close From 7b0c4c59aa248ff0ed2d4bd0b2411be886d3f796 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Mon, 15 Mar 2021 09:55:37 +0900 Subject: [PATCH 085/128] add task --- pnm.nimble | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pnm.nimble b/pnm.nimble index 30996e9..37360b2 100644 --- a/pnm.nimble +++ b/pnm.nimble @@ -13,6 +13,9 @@ requires "nim >= 0.19.4" import strformat +task tests, "Run tests": + exec "testament p 'tests/*/*.nim'" + task examples, "Run example code": for d in ["write_pbm", "write_pgm", "write_ppm", "read_file"]: withDir &"examples/{d}": From dfd62ec4ca0a687d4e700e5d9b14d6a49fc47c44 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Mon, 15 Mar 2021 09:55:40 +0900 Subject: [PATCH 086/128] add gitignore --- .gitignore | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0d752d5..099af7b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,9 @@ tests/tpnm tests/tutil main -tests/test_util \ No newline at end of file +tests/test_util +/nimcache/ + +outputGotten.txt +testresults/pattern.json +tests/examples/write_pgm \ No newline at end of file From 9666b31a75cc5c40dc171492b264e22fcfb05fdc Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Mon, 15 Mar 2021 09:56:25 +0900 Subject: [PATCH 087/128] fix Ci --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d72f320..feab9e3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,7 @@ jobs: - name: Install test run: nimble install -Y - name: Unit test - run: nimble test -Y + run: nimble tests # - name: Examples test # run: | # find examples/ -mindepth 1 -type d | while read -r dir; do From d744fa9fff3dc3159a1de9c24654e666e02a9f02 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Mon, 15 Mar 2021 10:03:22 +0900 Subject: [PATCH 088/128] add proc --- src/pnm.nim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pnm.nim b/src/pnm.nim index b59892a..32dd423 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -268,6 +268,9 @@ type ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. +proc newColorRgb*(r, g, b: byte): ColorRgb = + ColorRgb([r, g, b]) + proc width*(p: Pnm): int = p.width proc height*(p: Pnm): int = p.height From d4fcdb96f5b173cf8f64bd3c46d31072b935d06b Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Mon, 15 Mar 2021 10:03:24 +0900 Subject: [PATCH 089/128] add example --- tests/examples/write_ppm.nim | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/examples/write_ppm.nim diff --git a/tests/examples/write_ppm.nim b/tests/examples/write_ppm.nim new file mode 100644 index 0000000..a120a17 --- /dev/null +++ b/tests/examples/write_ppm.nim @@ -0,0 +1,31 @@ +discard """ + output: ''' +P3 +5 5 +255 +100 50 0 100 50 0 100 50 0 100 50 0 100 50 0 +0 50 0 0 50 0 0 50 0 0 50 0 0 50 0 +100 50 0 100 50 0 100 50 0 100 50 0 100 50 0 +0 50 0 0 50 0 0 50 0 0 50 0 0 50 0 +100 50 0 100 50 0 100 50 0 100 50 0 100 50 0 +''' +""" + +import pnm + +import streams + +var strm = newStringStream() +var p = newPpm(PnmDescriptor.P3, 5, 5, 255) + +for y in 0 ..< p.height: + for x in 0 ..< p.width: + let b = + if y mod 2 == 0: 100'u8 + else: 0'u8 + p[x, y] = newColorRgb(b, 50, 0) + +strm.writePpm p +strm.setPosition 0 +echo strm.readAll +strm.close From 4abb310cc5d7881338fcd6b81a703bdc6f8279d2 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 16 Mar 2021 08:56:57 +0900 Subject: [PATCH 090/128] add validation --- src/pnm.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pnm.nim b/src/pnm.nim index 32dd423..200779c 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -356,6 +356,7 @@ proc `descriptor=`*(p: Pgm, descriptor: PnmDescriptor) = proc readPgm*(strm: Stream): Pgm = new result result.descriptor = strm.readLine().toDescriptor() + validateDescriptorPgm result.descriptor # read comment line let b = strm.peekChar() @@ -459,6 +460,7 @@ proc toColorRgb(bytes: seq[uint8]): seq[ColorRgb] = proc readPpm*(strm: Stream): Ppm = new result result.descriptor = strm.readLine().toDescriptor() + validateDescriptorPpm result.descriptor # read comment line let b = strm.peekChar() From 7f120620597c217b59cbb26063a9a08295c9125a Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 16 Mar 2021 09:09:13 +0900 Subject: [PATCH 091/128] add read pgm p2 example --- tests/examples/p2.pgm | 6 ++++++ tests/examples/read_pgm.nim | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tests/examples/p2.pgm create mode 100644 tests/examples/read_pgm.nim diff --git a/tests/examples/p2.pgm b/tests/examples/p2.pgm new file mode 100644 index 0000000..c925d35 --- /dev/null +++ b/tests/examples/p2.pgm @@ -0,0 +1,6 @@ +P2 +5 3 +255 +0 1 2 3 4 +5 6 7 8 9 10 +11 12 13 14 15 diff --git a/tests/examples/read_pgm.nim b/tests/examples/read_pgm.nim new file mode 100644 index 0000000..c15b56b --- /dev/null +++ b/tests/examples/read_pgm.nim @@ -0,0 +1,17 @@ +import pnm + +import streams, unittest, os + +const file = "tests"/"examples"/"p2.pgm" +check fileExists(file) + +var strm = newFileStream(file, fmRead) +var p = strm.readPgm +var p2 = newPgm(P2, 5, 3, 255) +var i: int +for y in 0 ..< 3: + for x in 0 ..< 5: + p2[x, y] = ColorGray(i) + inc i +check p[] == p2[] +strm.close From f2867c254c263e22f3b096976db61d92dbdb20ac Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 16 Mar 2021 09:13:25 +0900 Subject: [PATCH 092/128] add read ppm p3 example --- tests/examples/p3.ppm | 6 ++++++ tests/examples/read_ppm.nim | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tests/examples/p3.ppm create mode 100644 tests/examples/read_ppm.nim diff --git a/tests/examples/p3.ppm b/tests/examples/p3.ppm new file mode 100644 index 0000000..2c0aa5d --- /dev/null +++ b/tests/examples/p3.ppm @@ -0,0 +1,6 @@ +P3 +5 3 +255 +0 1 2 1 2 3 2 3 4 3 4 5 4 5 6 +5 6 7 6 7 8 7 8 9 8 9 10 9 10 11 +10 11 12 11 12 13 12 13 14 13 14 15 14 15 16 diff --git a/tests/examples/read_ppm.nim b/tests/examples/read_ppm.nim new file mode 100644 index 0000000..6f1f93c --- /dev/null +++ b/tests/examples/read_ppm.nim @@ -0,0 +1,17 @@ +import pnm + +import streams, unittest, os + +const file = "tests"/"examples"/"p3.ppm" +check fileExists(file) + +var strm = newFileStream(file, fmRead) +var p = strm.readPpm +var p2 = newPpm(P3, 5, 3, 255) +var i: int +for y in 0 ..< 3: + for x in 0 ..< 5: + p2[x, y] = newColorRgb(byte(i), byte(i+1), byte(i+2)) + inc i +check p[] == p2[] +strm.close From b8cf9bca6943d3b26a9a4c8e7cef0ed77dd02b40 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 16 Mar 2021 09:13:33 +0900 Subject: [PATCH 093/128] add ignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 099af7b..6ac5c1f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,7 @@ tests/test_util outputGotten.txt testresults/pattern.json -tests/examples/write_pgm \ No newline at end of file +tests/examples/write_pgm +tests/examples/write_ppm +tests/examples/read_pgm +tests/examples/read_ppm \ No newline at end of file From 11c84dcecb07438e0ce943f9fc185f6458a2b324 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 16 Mar 2021 09:35:51 +0900 Subject: [PATCH 094/128] change read descriptor validation --- src/pnm.nim | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 200779c..ec7da94 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -278,10 +278,24 @@ template validateDescriptorPgm(d: PnmDescriptor) = if d notin [P2, P5]: raise newException(IllegalFileDescriptorError, "the descriptor of PGM must be P2 or P5") +template validateRawStringDescriptorPgm(d: string) = + if not (d.len == 3 and + d[0] == 'P' and + d[1] in ['2', '5'] and + d[2] == '\n'): + raise newException(IllegalFileDescriptorError, "the descriptor of PGM must be P2 or P5") + template validateDescriptorPpm(d: PnmDescriptor) = if d notin [P3, P6]: raise newException(IllegalFileDescriptorError, "the descriptor of PPM must be P3 or P6") +template validateRawStringDescriptorPpm(d: string) = + if not (d.len == 3 and + d[0] == 'P' and + d[1] in ['3', '6'] and + d[2] == '\n'): + raise newException(IllegalFileDescriptorError, "the descriptor of PPM must be P3 or P6") + proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = ## for P2 or P3. let singleDataSize = width * height * byteSize @@ -354,9 +368,13 @@ proc `descriptor=`*(p: Pgm, descriptor: PnmDescriptor) = p.descriptor = descriptor proc readPgm*(strm: Stream): Pgm = + # P1 ~ P6しか取り得ないので 3byte だけ読み取ってバリデーション + var d: string + strm.peekStr(3, d) + validateRawStringDescriptorPgm d + new result result.descriptor = strm.readLine().toDescriptor() - validateDescriptorPgm result.descriptor # read comment line let b = strm.peekChar() @@ -458,9 +476,13 @@ proc toColorRgb(bytes: seq[uint8]): seq[ColorRgb] = return data proc readPpm*(strm: Stream): Ppm = + # P1 ~ P6しか取り得ないので 3byte だけ読み取ってバリデーション + var d: string + strm.peekStr(3, d) + validateRawStringDescriptorPpm d + new result result.descriptor = strm.readLine().toDescriptor() - validateDescriptorPpm result.descriptor # read comment line let b = strm.peekChar() From bc5614014795514b4a29010981762085daa7226e Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Tue, 16 Mar 2021 09:37:43 +0900 Subject: [PATCH 095/128] add func --- src/pnm.nim | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index ec7da94..734787b 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -336,6 +336,9 @@ func toDescriptor(str: string): PnmDescriptor = else: raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & str) +proc readDescriptor(strm: Stream): PnmDescriptor = + strm.readLine().toDescriptor() + #[ ================================================================================ PGM @@ -374,7 +377,7 @@ proc readPgm*(strm: Stream): Pgm = validateRawStringDescriptorPgm d new result - result.descriptor = strm.readLine().toDescriptor() + result.descriptor = strm.readDescriptor # read comment line let b = strm.peekChar() @@ -482,7 +485,7 @@ proc readPpm*(strm: Stream): Ppm = validateRawStringDescriptorPpm d new result - result.descriptor = strm.readLine().toDescriptor() + result.descriptor = strm.readDescriptor # read comment line let b = strm.peekChar() From 946c0d57c00f78a3d075c06b69fb0dbddcaa60ef Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Mar 2021 00:16:32 +0900 Subject: [PATCH 096/128] add readComment --- src/pnm.nim | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 734787b..938d596 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -339,6 +339,12 @@ func toDescriptor(str: string): PnmDescriptor = proc readDescriptor(strm: Stream): PnmDescriptor = strm.readLine().toDescriptor() +proc readComment(strm: Stream): string = + let b = strm.peekChar + if b == '#': + discard strm.readChar # remove comment prefix + result.add strm.readLine + #[ ================================================================================ PGM @@ -372,18 +378,14 @@ proc `descriptor=`*(p: Pgm, descriptor: PnmDescriptor) = proc readPgm*(strm: Stream): Pgm = # P1 ~ P6しか取り得ないので 3byte だけ読み取ってバリデーション - var d: string - strm.peekStr(3, d) - validateRawStringDescriptorPgm d + block: + var d: string + strm.peekStr(3, d) + validateRawStringDescriptorPgm d new result result.descriptor = strm.readDescriptor - - # read comment line - let b = strm.peekChar() - if b == '#': - discard strm.readChar() # remove comment prefix - result.comment = strm.readLine() + result.comment = strm.readComment # read column size and row size let @@ -480,18 +482,14 @@ proc toColorRgb(bytes: seq[uint8]): seq[ColorRgb] = proc readPpm*(strm: Stream): Ppm = # P1 ~ P6しか取り得ないので 3byte だけ読み取ってバリデーション - var d: string - strm.peekStr(3, d) - validateRawStringDescriptorPpm d + block: + var d: string + strm.peekStr(3, d) + validateRawStringDescriptorPpm d new result result.descriptor = strm.readDescriptor - - # read comment line - let b = strm.peekChar() - if b == '#': - discard strm.readChar() # remove comment prefix - result.comment = strm.readLine() + result.comment = strm.readComment # read column size and row size let From 56128fcef6be95010185964d10b424595972ffc7 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Mar 2021 00:32:02 +0900 Subject: [PATCH 097/128] add readWidthHeight --- src/pnm.nim | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 938d596..94c5b58 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -345,6 +345,14 @@ proc readComment(strm: Stream): string = discard strm.readChar # remove comment prefix result.add strm.readLine +proc readWidthHeight(strm: Stream): (int, int) = + let + sizeLine = strm.readLine + wh = sizeLine.split(" ") + width = wh[0].parseInt + height = wh[1].parseInt + return (width, height) + #[ ================================================================================ PGM @@ -388,12 +396,7 @@ proc readPgm*(strm: Stream): Pgm = result.comment = strm.readComment # read column size and row size - let - sizeLine = strm.readLine() - wh = sizeLine.split(" ") - width = wh[0].parseInt() - height = wh[1].parseInt() - + let (width, height) = strm.readWidthHeight result.width = width result.height = height @@ -492,12 +495,7 @@ proc readPpm*(strm: Stream): Ppm = result.comment = strm.readComment # read column size and row size - let - sizeLine = strm.readLine() - wh = sizeLine.split(" ") - width = wh[0].parseInt() - height = wh[1].parseInt() - + let (width, height) = strm.readWidthHeight result.width = width result.height = height From fa09417499cbd6a7ee327c30b2fb70ef2fc2c495 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Mar 2021 00:37:51 +0900 Subject: [PATCH 098/128] add readMax --- src/pnm.nim | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 94c5b58..73b84d4 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -353,6 +353,12 @@ proc readWidthHeight(strm: Stream): (int, int) = height = wh[1].parseInt return (width, height) +proc readMax(strm: Stream, d: PnmDescriptor): int = + case d + of P2, P3, P5, P6: + return strm.readLine().parseInt + else: discard + #[ ================================================================================ PGM @@ -399,12 +405,7 @@ proc readPgm*(strm: Stream): Pgm = let (width, height) = strm.readWidthHeight result.width = width result.height = height - - # read max data - case result.descriptor - of P2, P5: - result.max = strm.readLine().parseInt - else: discard + result.max = strm.readMax(result.descriptor) # body const byteSize = 1 @@ -498,12 +499,7 @@ proc readPpm*(strm: Stream): Ppm = let (width, height) = strm.readWidthHeight result.width = width result.height = height - - # read max data - case result.descriptor - of P3, P6: - result.max = strm.readLine().parseInt - else: discard + result.max = strm.readMax(result.descriptor) # body const byteSize = 3 From 872ea427b348a54b23b114f81ef18440c77d10ea Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Mar 2021 00:38:47 +0900 Subject: [PATCH 099/128] add comment --- src/pnm.nim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 73b84d4..9b3505d 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -398,10 +398,10 @@ proc readPgm*(strm: Stream): Pgm = validateRawStringDescriptorPgm d new result + + # header result.descriptor = strm.readDescriptor result.comment = strm.readComment - - # read column size and row size let (width, height) = strm.readWidthHeight result.width = width result.height = height @@ -492,10 +492,10 @@ proc readPpm*(strm: Stream): Ppm = validateRawStringDescriptorPpm d new result + + # header result.descriptor = strm.readDescriptor result.comment = strm.readComment - - # read column size and row size let (width, height) = strm.readWidthHeight result.width = width result.height = height From b450d663d26a4a71f3223d7b3de3d864fb8e8fba Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Mar 2021 00:42:06 +0900 Subject: [PATCH 100/128] delete unused procs --- src/pnm.nim | 65 ----------------------------------------------------- 1 file changed, 65 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 9b3505d..90c7e5b 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -532,22 +532,6 @@ proc writePpm*(strm: Stream, data: Ppm) = when false: - proc newImage*(t: typedesc, width, height: int): Image = - result = Image(width: width, height: height) - let c: Color = t() - result.data = repeat(c, width * height) - - func toDescriptor(str: string): PnmDescriptor = - case str - of "P1": P1 - of "P2": P2 - of "P3": P3 - of "P4": P4 - of "P5": P5 - of "P6": P6 - else: - raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & str) - func bitSeqToByteSeq(arr: openArray[uint8], col: int): seq[uint8] = ## Returns sequences that binary sequence is converted to uint8 every 8 bits. var data: uint8 @@ -568,55 +552,6 @@ when false: if data != 0: result.add data shl (8 - (i mod 8)) - template w*(img: Image): int = - img.width - - template h*(img: Image): int = - img.height - - template b*(c: ColorBit): uint8 = c.bit - template g*(c: ColorGray): ColorComponent = c.gray - template r*(c: ColorRGB): ColorComponent = c.red - template g*(c: ColorRGB): ColorComponent = c.green - template b*(c: ColorRGB): ColorComponent = c.blue - template line*(img: Image, y: int): seq[Color] = - let startPos = y * img.w - img.data[startPos ..< startPos+img.w] - - template `[]`*(img: Image, x, y: int): Color = - img.data[x + y * img.w] - - template `[]=`*(img: var Image, x, y: int, c: Color) = - img.data[x + y * img.w] = c - - method str(c: Color): string {.base.} = discard - method str(c: ColorBit): string = $c.b - method str(c: ColorGray): string = $c.g - method str(c: ColorRGB): string = &"{c.r} {c.g} {c.b}" - - method bit(c: Color): uint8 {.base.} = discard - method bit(c: ColorBit): uint8 = c.b - - method write(c: Color, strm: Stream) {.base.} = - discard - - method write(c: ColorBit, strm: Stream) = - discard - - method write(c: ColorGray, strm: Stream) = - strm.write(c.g) - - method write(c: ColorRGB, strm: Stream) = - strm.write(c.r) - strm.write(c.g) - strm.write(c.b) - - method high(c: Color): int {.base.} = int.high - method high(c: ColorBit): int = 1 - method high(c: ColorGray): int = ColorComponent.high.int - method high(c: ColorRGB): int = ColorComponent.high.int - - proc toColorBitImage(bytes: seq[uint8], width, height: int): Image = result = newImage(ColorBit, width, height) result.data = bytes.map(proc(n: uint8): Color = From a6f1e6f7516048b4f22bf8fa65031e0fa4de4462 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Mar 2021 01:15:26 +0900 Subject: [PATCH 101/128] delete code --- src/pnm.nim | 387 ++-------------------------------------------------- 1 file changed, 8 insertions(+), 379 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 90c7e5b..521fd1d 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -1,239 +1,4 @@ ## pnm is parser/generator of PNM (Portable Anymap). -## -## Basic usage -## =========== -## -## PBM (Portable bitmap) -## --------------------- -## -## Reading PBM file -## ^^^^^^^^^^^^^^^^ -## -## `readPBMFile proc <#readPBMFile,string>`_ can read PBM (P1 and P4). -## -## .. code-block:: nim -## -## import pnm -## -## block: -## # P1 -## let p = readPBMFile("tests/out/p1.pbm") -## echo p -## -## block: -## # P4 -## let p = readPBMFile("tests/out/p4.pbm") -## echo p -## -## Writing PBM file -## ^^^^^^^^^^^^^^^^ -## -## `writePBMFile proc <#writePBMFile,string,PBM>`_ can write PBM (P1 and P4). -## -## .. code-block:: nim -## -## import pnm -## -## let col = 32 # 8 (bit) x 4 (column) == 32 -## let row = 12 -## let data = @[ -## 0b11111111'u8, 0b00000000, 0b11111111, 0b00000000, -## 0b11111111, 0b00000000, 0b11111111, 0b00000000, -## 0b11111111, 0b00000000, 0b11111111, 0b00000000, -## 0b11111111, 0b00000000, 0b11111111, 0b00000000, -## 0b11111111, 0b11111111, 0b11111111, 0b11111111, -## 0b11111111, 0b11111111, 0b11111111, 0b11111111, -## 0b11111111, 0b11111111, 0b11111111, 0b11111111, -## 0b11111111, 0b11111111, 0b11111111, 0b11111111, -## 0b00000000, 0b00000000, 0b00000000, 0b00000000, -## 0b00000000, 0b00000000, 0b00000000, 0b00000000, -## 0b00000000, 0b00000000, 0b00000000, 0b00000000, -## 0b00000000, 0b00000000, 0b00000000, 0b00000000, -## ] -## -## block: -## # P1 -## let p = newPBM(pbmFileDescriptorP1, col, row, data) -## writePBMFile("tests/out/p1.pbm", p) -## -## block: -## # P4 -## let p = newPBM(pbmFileDescriptorP4, col, row, data) -## writePBMFile("tests/out/p4.pbm", p) -## -## PGM (Portable graymap) -## ---------------------- -## -## Reading PGM file -## ^^^^^^^^^^^^^^^^ -## -## `readPGMFile proc <#readPGMFile,string>`_ can read PGM (P2 and P5). -## -## .. code-block:: nim -## -## import pnm -## -## block: -## # P2 -## let p = readPGMFile("tests/out/p2.pgm") -## echo p -## -## block: -## # P5 -## let p = readPGMFile("tests/out/p5.pgm") -## echo p -## -## Writing PGM file -## ^^^^^^^^^^^^^^^^ -## -## `writePGMFile proc <#writePGMFile,string,PGM>`_ can write PGM (P2 and P5). -## -## .. code-block:: nim -## -## import pnm -## -## let col = 6 -## let row = 12 -## let max = 2 -## let data = @[ -## 0'u8, 0, 0, 0, 0, 0, -## 0'u8, 0, 0, 0, 0, 0, -## 0'u8, 0, 0, 0, 0, 0, -## 0'u8, 0, 0, 0, 0, 0, -## 1, 1, 1, 1, 1, 1, -## 1, 1, 1, 1, 1, 1, -## 1, 1, 1, 1, 1, 1, -## 1, 1, 1, 1, 1, 1, -## 2, 2, 2, 2, 2, 2, -## 2, 2, 2, 2, 2, 2, -## 2, 2, 2, 2, 2, 2, -## 2, 2, 2, 2, 2, 2, -## ] -## -## block: -## # P2 -## let p = newPGM(pgmFileDescriptorP2, col, row, data) -## writePGMFile("tests/out/p2.pgm", p) -## -## block: -## # P5 -## let p = newPGM(pgmFileDescriptorP5, col, row, data) -## writePGMFile("tests/out/p5.pgm", p) -## -## PPM (Portable pixmap) -## ---------------------- -## -## Reading PPM file -## ^^^^^^^^^^^^^^^^ -## -## `readPPMFile proc <#readPPMFile,string>`_ can read PPM (P3 and P6). -## -## .. code-block:: nim -## -## import pnm -## -## block: -## # P3 -## let p = readPPMFile("tests/out/p3.ppm") -## echo p -## -## block: -## # P6 -## let p = readPPMFile("tests/out/p6.ppm") -## echo p -## -## Writing PPM file -## ^^^^^^^^^^^^^^^^ -## -## `writePPMFile proc <#writePPMFile,string,PPM>`_ can write PPM (P3 and P6). -## -## .. code-block:: nim -## -## import pnm -## -## let col = 6 -## let row = 12 -## let max = 2 -## let data = @[ -## 0'u8, 0, 0, 0, 0, 0, -## 0'u8, 0, 0, 0, 0, 0, -## 0'u8, 0, 0, 0, 0, 0, -## 0'u8, 0, 0, 0, 0, 0, -## 1, 1, 1, 1, 1, 1, -## 1, 1, 1, 1, 1, 1, -## 1, 1, 1, 1, 1, 1, -## 1, 1, 1, 1, 1, 1, -## 2, 2, 2, 2, 2, 2, -## 2, 2, 2, 2, 2, 2, -## 2, 2, 2, 2, 2, 2, -## 2, 2, 2, 2, 2, 2, -## ] -## -## block: -## # P3 -## let p = newPPM(ppmFileDescriptorP3, col, row, data) -## writePPMFile("tests/out/p3.ppm", p) -## -## block: -## # P6 -## let p = newPPM(ppmFileDescriptorP6, col, row, data) -## writePPMFile("tests/out/p6.ppm", p) -## -## PNM format examples -## =================== -## -## PBM -## ---- -## -## .. code-block:: -## -## P1 -## # comment -## 5 6 -## 0 0 1 0 0 -## 0 1 1 0 0 -## 0 0 1 0 0 -## 0 0 1 0 0 -## 0 0 1 0 0 -## 1 1 1 1 1 -## -## PGM -## ---- -## -## .. code-block:: text -## -## P2 -## # Shows the word "FEEP" (example from Netpgm man page on PGM) -## 24 7 -## 15 -## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -## 0 3 3 3 3 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 15 15 15 0 -## 0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 15 0 -## 0 3 3 3 0 0 0 7 7 7 0 0 0 11 11 11 0 0 0 15 15 15 15 0 -## 0 3 0 0 0 0 0 7 0 0 0 0 0 11 0 0 0 0 0 15 0 0 0 0 -## 0 3 0 0 0 0 0 7 7 7 7 0 0 11 11 11 11 0 0 15 0 0 0 0 -## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -## -## PPM -## ---- -## -## .. code-block:: -## -## P3 -## # The P3 means colors are in ASCII, then 3 columns and 2 rows, then 255 for max color, then RGB triplets -## 3 2 -## 255 -## 255 0 0 -## 0 255 0 -## 0 0 255 -## 255 255 0 -## 255 255 255 -## 0 0 0 -## -## See also -## ======== -## * `(EN) Portable Anymap - Wikipedia `_ -## * `(JA) PNM(画像フォーマット) - Wikipedia `_ import streams, strformat, strutils from sequtils import map, mapIt, repeat, distribute @@ -359,6 +124,14 @@ proc readMax(strm: Stream, d: PnmDescriptor): int = return strm.readLine().parseInt else: discard +#[ +================================================================================ + PBM +================================================================================ +]# + +# TODO + #[ ================================================================================ PGM @@ -529,147 +302,3 @@ proc writePpm*(strm: Stream, data: Ppm) = strm.write(c.g) strm.write(c.b) else: discard - - -when false: - func bitSeqToByteSeq(arr: openArray[uint8], col: int): seq[uint8] = - ## Returns sequences that binary sequence is converted to uint8 every 8 bits. - var data: uint8 - var i = 0 - for u in arr: - data = data shl 1 - data += u - i.inc - if i mod 8 == 0: - result.add data - data = 0'u8 - continue - if i mod col == 0: - data = data shl (8 - (i mod 8)) - result.add data - data = 0'u8 - i = 0 - if data != 0: - result.add data shl (8 - (i mod 8)) - - proc toColorBitImage(bytes: seq[uint8], width, height: int): Image = - result = newImage(ColorBit, width, height) - result.data = bytes.map(proc(n: uint8): Color = - var c: Color = ColorBit(bit: n) - return c) - - proc toColorGrayImage(bytes: seq[uint8], width, height: int): Image = - result = newImage(ColorGray, width, height) - result.data = bytes.map(proc(n: uint8): Color = - var c: Color = ColorGray(gray: n) - return c) - - proc toColorRGBImage(bytes: seq[uint8], width, height: int): Image = - result = newImage(ColorRGB, width, height) - var data: seq[array[3, uint8]] - var arr: array[3, uint8] - for i, b in bytes: - let m = i mod 3 - arr[m] = b - if (i+1) mod 3 == 0: - data.add(arr) - arr = [0'u8, 0, 0] - result.data = data.map(proc(n: array[3, uint8]): Color = - var c: Color = ColorRGB(red: n[0], green: n[1], blue: n[2]) - return c) - - proc readPNM*(strm: Stream): PNM = - # read descriptor - result.descriptor = strm.readLine().toDescriptor() - - # read comment line - let b = strm.peekChar() - if b == '#': - discard strm.readChar() # remove comment prefix - result.comment = strm.readLine() - - # read column size and row size - let - sizeLine = strm.readLine() - wh = sizeLine.split(" ") - width = wh[0].parseInt() - height = wh[1].parseInt() - - # read max data - case result.descriptor - of P2, P3, P5, P6: - result.max = strm.readLine().parseInt - else: discard - - # body - const byteSize = 1 - case result.descriptor - of P1: - let bytes = strm.readDataPartOfTextData(width, height, byteSize) - result.image = bytes.toColorBitImage(width, height) - of P2: - let bytes = strm.readDataPartOfTextData(width, height, byteSize) - result.image = bytes.toColorGrayImage(width, height) - of P3: - let bytes = strm.readDataPartOfTextData(width, height, byteSize, true) - result.image = bytes.toColorRGBImage(width, height) - of P4: - # TODO - # let bytes = strm.readDataPartOfTextData() - # result.image = bytes.toColorBitImage(width, height) - discard - of P5: - let bytes = strm.readDataPartOfBinaryData(width, height, byteSize) - result.image = bytes.toColorGrayImage(width, height) - of P6: - let bytes = strm.readDataPartOfBinaryData(width, height, byteSize, true) - result.image = bytes.toColorRGBImage(width, height) - - proc writePNM*(strm: Stream, data: PNM) = - let image = data.image - # header - strm.writeLine(data.descriptor) - if data.comment != "": - strm.writeLine("#" & data.comment) - strm.writeLine($image.w & " " & $image.h) - case data.descriptor - of P2, P3, P5, P6: - strm.writeLine($image[0, 0].high) - else: - discard - - # body - case data.descriptor - of P1, P2, P3: - for y in 0.. Date: Wed, 17 Mar 2021 01:15:33 +0900 Subject: [PATCH 102/128] add file procs --- src/pnm.nim | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/pnm.nim b/src/pnm.nim index 521fd1d..bf2a74d 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -302,3 +302,33 @@ proc writePpm*(strm: Stream, data: Ppm) = strm.write(c.g) strm.write(c.b) else: discard + +when not defined js: + # ============================================================ + # reader + # ============================================================ + + proc readPgmFile*(file: string): Pgm = + var strm = newFileStream(file, fmRead) + defer: strm.close + strm.readPgm + + proc readPpmFile*(file: string): Ppm = + var strm = newFileStream(file, fmRead) + defer: strm.close + strm.readPpm + + # ============================================================ + # writer + # ============================================================ + + proc writePgmFile*(file: string, data: Pgm) = + var strm = newFileStream(file, fmWrite) + defer: strm.close + strm.writePgm(data) + + proc writePpmFile*(file: string, data: Ppm) = + var strm = newFileStream(file, fmWrite) + defer: strm.close + strm.writePpm(data) + From d318d7470f20aac4ef945eeb0cd5cbdb2790f98b Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Wed, 17 Mar 2021 01:22:04 +0900 Subject: [PATCH 103/128] add pbm --- src/pnm.nim | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/src/pnm.nim b/src/pnm.nim index bf2a74d..28bc5f3 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -39,10 +39,21 @@ proc newColorRgb*(r, g, b: byte): ColorRgb = proc width*(p: Pnm): int = p.width proc height*(p: Pnm): int = p.height +template validateDescriptorPbm(d: PnmDescriptor) = + if d notin [P1, P4]: + raise newException(IllegalFileDescriptorError, "the descriptor of PBM must be P1 or P4") + template validateDescriptorPgm(d: PnmDescriptor) = if d notin [P2, P5]: raise newException(IllegalFileDescriptorError, "the descriptor of PGM must be P2 or P5") +template validateRawStringDescriptorPbm(d: string) = + if not (d.len == 3 and + d[0] == 'P' and + d[1] in ['1', '4'] and + d[2] == '\n'): + raise newException(IllegalFileDescriptorError, "the descriptor of PBM must be P1 or P4") + template validateRawStringDescriptorPgm(d: string) = if not (d.len == 3 and d[0] == 'P' and @@ -130,7 +141,69 @@ proc readMax(strm: Stream, d: PnmDescriptor): int = ================================================================================ ]# -# TODO +proc newPbm*(descriptor: PnmDescriptor, width, height: int, comment = ""): Pbm = + validateDescriptorPbm(descriptor) + + new result + result.descriptor = descriptor + result.width = width + result.height = height + result.comment = comment + result.data = repeat(ColorBit(0'u8), width*height) + +template line(p: Pbm, y: int): seq[ColorBit] = + let startPos = y * p.width + p.data[startPos ..< startPos+p.width] + +proc `[]`*(p: Pbm, x, y: int): ColorBit = + p.data[x + y * p.width] + +proc `[]=`*(p: Pbm, x, y: int, color: ColorBit) = + p.data[x + y * p.width] = color + +proc `descriptor=`*(p: Pbm, descriptor: PnmDescriptor) = + validateDescriptorPbm(descriptor) + p.descriptor = descriptor + +proc readPbm*(strm: Stream): Pbm = + # P1 ~ P6しか取り得ないので 3byte だけ読み取ってバリデーション + block: + var d: string + strm.peekStr(3, d) + validateRawStringDescriptorPbm d + + new result + + # header + result.descriptor = strm.readDescriptor + result.comment = strm.readComment + let (width, height) = strm.readWidthHeight + result.width = width + result.height = height + + # body + const byteSize = 1 + case result.descriptor + of P1: result.data = strm.readDataPartOfTextData(width, height, byteSize) + of P4: result.data = strm.readDataPartOfBinaryData(width, height, byteSize) + else: discard + +proc writePbm*(strm: Stream, data: Pbm) = + # header + strm.writeLine(data.descriptor) + if data.comment != "": + strm.writeLine("#" & data.comment) + strm.writeLine($data.width & " " & $data.height) + + # body + case data.descriptor + of P1: + # TODO + discard + of P4: + for c in data.data: + strm.write(c) + else: discard #[ ================================================================================ From b22f80213cc94017504b897cd1768be14fff16d5 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 18:49:06 +0900 Subject: [PATCH 104/128] fix comment --- src/pnm.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pnm.nim b/src/pnm.nim index 28bc5f3..09ca775 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -73,7 +73,7 @@ template validateRawStringDescriptorPpm(d: string) = raise newException(IllegalFileDescriptorError, "the descriptor of PPM must be P3 or P6") proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = - ## for P2 or P3. + ## for P1, P2, P3 let singleDataSize = width * height * byteSize let maxDataCount = if rgb: singleDataSize * 3 @@ -84,6 +84,7 @@ proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = fa for b in line.splitWhitespace().mapIt(it.parseUInt.uint8): result.add(b) inc(dataCounter) + # 取得しうるデータ数以上取得する必要がないので早期リターン if maxDataCount <= dataCounter: return @@ -98,6 +99,7 @@ proc readDataPartOfBinaryData(strm: Stream, width, height, byteSize: int, rgb = while not strm.atEnd(): result.add(strm.readUint8()) inc(dataCounter) + # 取得しうるデータ数以上取得する必要がないので早期リターン if maxDataCount <= dataCounter: return From 611d8a196035d0f6f7dfb11a864f159f848d26a7 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 18:49:43 +0900 Subject: [PATCH 105/128] add test case --- tests/unit/read_pbm.nim | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 tests/unit/read_pbm.nim diff --git a/tests/unit/read_pbm.nim b/tests/unit/read_pbm.nim new file mode 100644 index 0000000..414d5d6 --- /dev/null +++ b/tests/unit/read_pbm.nim @@ -0,0 +1,64 @@ +import pnm + +import streams, unittest + +# normal case +block: + const inData = """ +P1 +5 3 +0 1 0 1 0 +1 0 1 0 1 +0 1 0 1 0 +""" + const inData2 = """ +P1 +5 3 +0 1 0 1 0 1 0 1 0 1 0 1 0 1 0""" + const inIllegalData = """ +P1 +5 3 +0 1 0 1 0 +1 0 1 0 1 +0 1 0 1 0 +1 1 1 1 1 +""" # too many data + + var want = newPbm(P1, 5, 3) + const row1 = [0'u8, 1, 0, 1, 0] + const row2 = [1'u8, 0, 1, 0, 1] + proc setRow(y: int, row: array[5, byte]) = + for x in 0..<5: + want[x, y] = row[x] + setRow(0, row1) + setRow(1, row2) + setRow(2, row1) + + # ============ + # normal cases + # ============ + + block: + # multi line case + var strm = newStringStream(inData) + var got = strm.readPbm + check got[] == want[] + strm.close + + block: + # 1 line case + var strm = newStringStream(inData2) + var got = strm.readPbm + check got[] == want[] + strm.close + + # ============== + # illegal casses + # ============== + + block: + var strm = newStringStream(inIllegalData) + var got = strm.readPbm + check got[] == want[] + strm.close + From 6c3fcfd9e2a5c7ef14f4cf95afde3d6b1fa148dd Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 18:50:29 +0900 Subject: [PATCH 106/128] update ignore pattern --- .gitignore | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 6ac5c1f..962a9e5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,5 @@ tests/test_util outputGotten.txt testresults/pattern.json -tests/examples/write_pgm -tests/examples/write_ppm -tests/examples/read_pgm -tests/examples/read_ppm \ No newline at end of file +tests/**/* +!tests/**/*.* From d2f71a8aa1fcd0774da7a5ff93eabca758ba1275 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:00:41 +0900 Subject: [PATCH 107/128] change type name --- src/pnm.nim | 28 ++++++++++++++-------------- tests/examples/write_pgm.nim | 2 +- tests/examples/write_ppm.nim | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index 09ca775..2d71382 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -6,7 +6,7 @@ from sequtils import map, mapIt, repeat, distribute type Pnm* = ref PnmObj PnmObj* = object of RootObj - descriptor: PnmDescriptor + descriptor: PnmFileDescriptor comment: string width, height, max: int @@ -22,7 +22,7 @@ type PpmObj* = object of PnmObj data: seq[ColorRgb] - PnmDescriptor* {.pure.} = enum + PnmFileDescriptor* {.pure.} = enum P1, P2, P3, P4, P5, P6 ColorBit* = byte @@ -39,11 +39,11 @@ proc newColorRgb*(r, g, b: byte): ColorRgb = proc width*(p: Pnm): int = p.width proc height*(p: Pnm): int = p.height -template validateDescriptorPbm(d: PnmDescriptor) = +template validateDescriptorPbm(d: PnmFileDescriptor) = if d notin [P1, P4]: raise newException(IllegalFileDescriptorError, "the descriptor of PBM must be P1 or P4") -template validateDescriptorPgm(d: PnmDescriptor) = +template validateDescriptorPgm(d: PnmFileDescriptor) = if d notin [P2, P5]: raise newException(IllegalFileDescriptorError, "the descriptor of PGM must be P2 or P5") @@ -61,7 +61,7 @@ template validateRawStringDescriptorPgm(d: string) = d[2] == '\n'): raise newException(IllegalFileDescriptorError, "the descriptor of PGM must be P2 or P5") -template validateDescriptorPpm(d: PnmDescriptor) = +template validateDescriptorPpm(d: PnmFileDescriptor) = if d notin [P3, P6]: raise newException(IllegalFileDescriptorError, "the descriptor of PPM must be P3 or P6") @@ -103,7 +103,7 @@ proc readDataPartOfBinaryData(strm: Stream, width, height, byteSize: int, rgb = if maxDataCount <= dataCounter: return -func toDescriptor(str: string): PnmDescriptor = +func toDescriptor(str: string): PnmFileDescriptor = case str of "P1": P1 of "P2": P2 @@ -114,7 +114,7 @@ func toDescriptor(str: string): PnmDescriptor = else: raise newException(IllegalFileDescriptorError, "IllegalFileDescriptor: file descriptor is " & str) -proc readDescriptor(strm: Stream): PnmDescriptor = +proc readDescriptor(strm: Stream): PnmFileDescriptor = strm.readLine().toDescriptor() proc readComment(strm: Stream): string = @@ -131,7 +131,7 @@ proc readWidthHeight(strm: Stream): (int, int) = height = wh[1].parseInt return (width, height) -proc readMax(strm: Stream, d: PnmDescriptor): int = +proc readMax(strm: Stream, d: PnmFileDescriptor): int = case d of P2, P3, P5, P6: return strm.readLine().parseInt @@ -143,7 +143,7 @@ proc readMax(strm: Stream, d: PnmDescriptor): int = ================================================================================ ]# -proc newPbm*(descriptor: PnmDescriptor, width, height: int, comment = ""): Pbm = +proc newPbm*(descriptor: PnmFileDescriptor, width, height: int, comment = ""): Pbm = validateDescriptorPbm(descriptor) new result @@ -163,7 +163,7 @@ proc `[]`*(p: Pbm, x, y: int): ColorBit = proc `[]=`*(p: Pbm, x, y: int, color: ColorBit) = p.data[x + y * p.width] = color -proc `descriptor=`*(p: Pbm, descriptor: PnmDescriptor) = +proc `descriptor=`*(p: Pbm, descriptor: PnmFileDescriptor) = validateDescriptorPbm(descriptor) p.descriptor = descriptor @@ -213,7 +213,7 @@ proc writePbm*(strm: Stream, data: Pbm) = ================================================================================ ]# -proc newPgm*(descriptor: PnmDescriptor, width, height, max: int, comment = ""): Pgm = +proc newPgm*(descriptor: PnmFileDescriptor, width, height, max: int, comment = ""): Pgm = validateDescriptorPgm(descriptor) new result @@ -234,7 +234,7 @@ proc `[]`*(p: Pgm, x, y: int): ColorGray = proc `[]=`*(p: Pgm, x, y: int, color: ColorGray) = p.data[x + y * p.width] = color -proc `descriptor=`*(p: Pgm, descriptor: PnmDescriptor) = +proc `descriptor=`*(p: Pgm, descriptor: PnmFileDescriptor) = validateDescriptorPgm(descriptor) p.descriptor = descriptor @@ -288,7 +288,7 @@ proc writePgm*(strm: Stream, data: Pgm) = ================================================================================ ]# -proc newPpm*(descriptor: PnmDescriptor, width, height, max: int, comment = ""): Ppm = +proc newPpm*(descriptor: PnmFileDescriptor, width, height, max: int, comment = ""): Ppm = validateDescriptorPpm(descriptor) new result @@ -317,7 +317,7 @@ proc `[]`*(p: Ppm, x, y: int): ColorRgb = proc `[]=`*(p: Ppm, x, y: int, color: ColorRgb) = p.data[x + y * p.width] = color -proc `descriptor=`*(p: Ppm, descriptor: PnmDescriptor) = +proc `descriptor=`*(p: Ppm, descriptor: PnmFileDescriptor) = validateDescriptorPpm(descriptor) p.descriptor = descriptor diff --git a/tests/examples/write_pgm.nim b/tests/examples/write_pgm.nim index 1b541c2..938d063 100644 --- a/tests/examples/write_pgm.nim +++ b/tests/examples/write_pgm.nim @@ -16,7 +16,7 @@ import pnm import streams var strm = newStringStream() -var p = newPgm(PnmDescriptor.P2, 5, 5, 255) +var p = newPgm(PnmFileDescriptor.P2, 5, 5, 255) for y in 0 ..< p.height: for x in 0 ..< p.width: diff --git a/tests/examples/write_ppm.nim b/tests/examples/write_ppm.nim index a120a17..2a9de64 100644 --- a/tests/examples/write_ppm.nim +++ b/tests/examples/write_ppm.nim @@ -16,7 +16,7 @@ import pnm import streams var strm = newStringStream() -var p = newPpm(PnmDescriptor.P3, 5, 5, 255) +var p = newPpm(PnmFileDescriptor.P3, 5, 5, 255) for y in 0 ..< p.height: for x in 0 ..< p.width: From de14314db4987c0fb6b99244316035b13dd255a6 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:05:03 +0900 Subject: [PATCH 108/128] add exception pattern --- src/pnm.nim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pnm.nim b/src/pnm.nim index 2d71382..bcf8db8 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -33,6 +33,9 @@ type ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. + IllegalDataSizeError* = object of Defect + ## Return this when data size didn't match data size (width x height) of PNM. + proc newColorRgb*(r, g, b: byte): ColorRgb = ColorRgb([r, g, b]) @@ -87,6 +90,7 @@ proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = fa # 取得しうるデータ数以上取得する必要がないので早期リターン if maxDataCount <= dataCounter: return + raise newException(IllegalDataSizeError, "data size too little. dataCounter must equal data size (width x height)") proc readDataPartOfBinaryData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = ## for P5 or P6. @@ -102,6 +106,7 @@ proc readDataPartOfBinaryData(strm: Stream, width, height, byteSize: int, rgb = # 取得しうるデータ数以上取得する必要がないので早期リターン if maxDataCount <= dataCounter: return + raise newException(IllegalDataSizeError, "data size too little. dataCounter must equal data size (width x height)") func toDescriptor(str: string): PnmFileDescriptor = case str From 42226e7833653e66b0fa5ac5322b458a3902d987 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:08:27 +0900 Subject: [PATCH 109/128] change extends type --- src/pnm.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index bcf8db8..b9f1484 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -29,11 +29,11 @@ type ColorGray* = byte ColorRgb* = array[3, byte] - IllegalFileDescriptorError* = object of Defect + IllegalFileDescriptorError* = object of CatchableError ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. - IllegalDataSizeError* = object of Defect + IllegalDataSizeError* = object of CatchableError ## Return this when data size didn't match data size (width x height) of PNM. proc newColorRgb*(r, g, b: byte): ColorRgb = From 952a020f47566788ee781576c834468a5166a5d3 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:09:06 +0900 Subject: [PATCH 110/128] fix ignore --- .gitignore | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.gitignore b/.gitignore index 962a9e5..206661e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,4 @@ -tests/tpnm -tests/tutil -main - -tests/test_util /nimcache/ - outputGotten.txt testresults/pattern.json tests/**/* From 49f9b4c21fa427ae100566a06c81ed61fec09844 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:09:16 +0900 Subject: [PATCH 111/128] add illegal test case --- tests/unit/read_pbm.nim | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/unit/read_pbm.nim b/tests/unit/read_pbm.nim index 414d5d6..016aebe 100644 --- a/tests/unit/read_pbm.nim +++ b/tests/unit/read_pbm.nim @@ -62,3 +62,12 @@ P1 check got[] == want[] strm.close + block: + const inIllegalData = """ +P1 +5 3 +0 1 0 1 0 +""" # too little data + var strm = newStringStream(inIllegalData) + expect IllegalDataSizeError: + discard strm.readPbm From 63fe5f9ba6643154f16cc23cfbf81e392d7426c8 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:18:19 +0900 Subject: [PATCH 112/128] add validation --- src/pnm.nim | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index b9f1484..fbdb84d 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -32,9 +32,10 @@ type IllegalFileDescriptorError* = object of CatchableError ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. - IllegalDataSizeError* = object of CatchableError ## Return this when data size didn't match data size (width x height) of PNM. + IllegalPbmDataError* = object of CatchableError + ## Return this when PBM has byte data outside of 0 or 1. proc newColorRgb*(r, g, b: byte): ColorRgb = ColorRgb([r, g, b]) @@ -75,7 +76,7 @@ template validateRawStringDescriptorPpm(d: string) = d[2] == '\n'): raise newException(IllegalFileDescriptorError, "the descriptor of PPM must be P3 or P6") -proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = false): seq[uint8] = +proc readDataPartOfTextData(strm: Stream, descriptor: PnmFileDescriptor, width, height, byteSize: int, rgb = false): seq[uint8] = ## for P1, P2, P3 let singleDataSize = width * height * byteSize let maxDataCount = @@ -85,6 +86,9 @@ proc readDataPartOfTextData(strm: Stream, width, height, byteSize: int, rgb = fa var dataCounter: int while strm.readLine(line): for b in line.splitWhitespace().mapIt(it.parseUInt.uint8): + if descriptor == P1: + if b notin [0'u8, 1]: + raise newException(IllegalPbmDataError, "PBM data must be 0 or 1. this stream has illegal byte data.") result.add(b) inc(dataCounter) # 取得しうるデータ数以上取得する必要がないので早期リターン @@ -191,7 +195,7 @@ proc readPbm*(strm: Stream): Pbm = # body const byteSize = 1 case result.descriptor - of P1: result.data = strm.readDataPartOfTextData(width, height, byteSize) + of P1: result.data = strm.readDataPartOfTextData(result.descriptor, width, height, byteSize) of P4: result.data = strm.readDataPartOfBinaryData(width, height, byteSize) else: discard @@ -263,7 +267,7 @@ proc readPgm*(strm: Stream): Pgm = # body const byteSize = 1 case result.descriptor - of P2: result.data = strm.readDataPartOfTextData(width, height, byteSize) + of P2: result.data = strm.readDataPartOfTextData(result.descriptor, width, height, byteSize) of P5: result.data = strm.readDataPartOfBinaryData(width, height, byteSize) else: discard @@ -357,7 +361,7 @@ proc readPpm*(strm: Stream): Ppm = # body const byteSize = 3 case result.descriptor - of P3: result.data = strm.readDataPartOfTextData(width, height, byteSize).toColorRgb + of P3: result.data = strm.readDataPartOfTextData(result.descriptor, width, height, byteSize).toColorRgb of P6: result.data = strm.readDataPartOfBinaryData(width, height, byteSize).toColorRgb else: discard From 7f20b56e9350197383473044fc4014ad5a555568 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:18:33 +0900 Subject: [PATCH 113/128] add illegal test case --- tests/unit/read_pbm.nim | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/unit/read_pbm.nim b/tests/unit/read_pbm.nim index 016aebe..f582c2a 100644 --- a/tests/unit/read_pbm.nim +++ b/tests/unit/read_pbm.nim @@ -71,3 +71,15 @@ P1 var strm = newStringStream(inIllegalData) expect IllegalDataSizeError: discard strm.readPbm + + block: + const inIllegalData = """ +P1 +5 3 +0 1 0 1 0 +9 1 0 1 0 +0 1 0 1 0 +""" # too little data + var strm = newStringStream(inIllegalData) + expect IllegalPbmDataError: + discard strm.readPbm From 00a008de8e0b64107a3855ce75dd127d733999df Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:29:21 +0900 Subject: [PATCH 114/128] fix ignore --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 206661e..1621003 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /nimcache/ outputGotten.txt testresults/pattern.json -tests/**/* -!tests/**/*.* +tests/*/* +!tests/*/*.* From 510a5f65a822ba451625b1a54ed5013a94fb093d Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:29:00 +0900 Subject: [PATCH 115/128] add illegal test case --- tests/unit/read_pbm.nim | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/unit/read_pbm.nim b/tests/unit/read_pbm.nim index f582c2a..0f16638 100644 --- a/tests/unit/read_pbm.nim +++ b/tests/unit/read_pbm.nim @@ -71,6 +71,7 @@ P1 var strm = newStringStream(inIllegalData) expect IllegalDataSizeError: discard strm.readPbm + strm.close block: const inIllegalData = """ @@ -83,3 +84,30 @@ P1 var strm = newStringStream(inIllegalData) expect IllegalPbmDataError: discard strm.readPbm + strm.close + + block: + const inIllegalData = """ +P2 +5 3 +0 1 0 1 0 +0 1 0 1 0 +0 1 0 1 0 +""" # illegal file descriptor + var strm = newStringStream(inIllegalData) + expect IllegalFileDescriptorError: + discard strm.readPbm + strm.close + + block: + const inIllegalData = """ +P1 +5 3 +0 1 0 1 0 +0 1 0 1 0 +0 1 0 1 0 +""" # illegal file descriptor + var strm = newStringStream(inIllegalData) + expect IllegalFileDescriptorError: + discard strm.readPbm + strm.close From 5ad602baa1e548dece6ac710d037657537e5cbb4 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:40:29 +0900 Subject: [PATCH 116/128] change comment field accessor --- src/pnm.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pnm.nim b/src/pnm.nim index fbdb84d..83dfd3c 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -7,7 +7,7 @@ type Pnm* = ref PnmObj PnmObj* = object of RootObj descriptor: PnmFileDescriptor - comment: string + comment*: string width, height, max: int Pbm* = ref PbmObj From 122ca962345fdf899e83e9997ae9532ae02217d8 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:40:34 +0900 Subject: [PATCH 117/128] add comment test case --- tests/unit/read_pbm.nim | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/unit/read_pbm.nim b/tests/unit/read_pbm.nim index 0f16638..0ee9954 100644 --- a/tests/unit/read_pbm.nim +++ b/tests/unit/read_pbm.nim @@ -15,6 +15,14 @@ P1 P1 5 3 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0""" + const inData3 = """ +P1 +# this is comment +5 3 +0 1 0 1 0 +1 0 1 0 1 +0 1 0 1 0 +""" const inIllegalData = """ P1 5 3 @@ -52,6 +60,13 @@ P1 check got[] == want[] strm.close + block: + # has comment + var strm = newStringStream(inData3) + var got = strm.readPbm + check got.comment == " this is comment" + strm.close + # ============== # illegal casses # ============== From cd9f60f63c9db2c3d87cb342e522b1406016b241 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 19:56:14 +0900 Subject: [PATCH 118/128] add proc --- src/pnm.nim | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pnm.nim b/src/pnm.nim index 83dfd3c..15ee83e 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -392,6 +392,11 @@ when not defined js: # reader # ============================================================ + proc readPbmFile*(file: string): Pbm = + var strm = newFileStream(file, fmRead) + defer: strm.close + strm.readPbm + proc readPgmFile*(file: string): Pgm = var strm = newFileStream(file, fmRead) defer: strm.close @@ -406,6 +411,11 @@ when not defined js: # writer # ============================================================ + proc writePbmFile*(file: string, data: Pbm) = + var strm = newFileStream(file, fmWrite) + defer: strm.close + strm.writePbm(data) + proc writePgmFile*(file: string, data: Pgm) = var strm = newFileStream(file, fmWrite) defer: strm.close From 737b4fee8b5415e98fd6130be51d703c100570d3 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 20:02:34 +0900 Subject: [PATCH 119/128] upgrade nim version --- pnm.nimble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pnm.nimble b/pnm.nimble index 37360b2..8d3236d 100644 --- a/pnm.nimble +++ b/pnm.nimble @@ -9,7 +9,7 @@ srcDir = "src" # Dependencies -requires "nim >= 0.19.4" +requires "nim >= 1.4.4" import strformat From 94d6610118f982813b143310674eac6c4a108391 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 20:02:39 +0900 Subject: [PATCH 120/128] change test versions --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index feab9e3..b426140 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - nim-version: ['1.0.x', '1.2.x', 'stable'] + nim-version: ['1.4.4', '1.4.x', 'stable'] steps: - uses: actions/checkout@v1 - uses: jiro4989/setup-nim-action@v1 From 0719c7a742114632daed172c53aedc160f71cef2 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 20:13:39 +0900 Subject: [PATCH 121/128] add test cases --- tests/unit/read_pgm.nim | 23 +++++++++++++++++++++++ tests/unit/read_ppm.nim | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/unit/read_pgm.nim create mode 100644 tests/unit/read_ppm.nim diff --git a/tests/unit/read_pgm.nim b/tests/unit/read_pgm.nim new file mode 100644 index 0000000..b6c7c8b --- /dev/null +++ b/tests/unit/read_pgm.nim @@ -0,0 +1,23 @@ +import pnm + +import unittest, streams + +# illegal test cases + +block: + const inData = """ +P3 +""" + var strm = newStringStream(inData) + expect IllegalFileDescriptorError: + discard strm.readPgm + strm.close + +block: + const inData = """ +P2 +""" + var strm = newStringStream(inData) + expect IllegalFileDescriptorError: + discard strm.readPgm + strm.close diff --git a/tests/unit/read_ppm.nim b/tests/unit/read_ppm.nim new file mode 100644 index 0000000..4bcc348 --- /dev/null +++ b/tests/unit/read_ppm.nim @@ -0,0 +1,23 @@ +import pnm + +import unittest, streams + +# illegal test cases + +block: + const inData = """ +P2 +""" + var strm = newStringStream(inData) + expect IllegalFileDescriptorError: + discard strm.readPpm + strm.close + +block: + const inData = """ +P3 +""" + var strm = newStringStream(inData) + expect IllegalFileDescriptorError: + discard strm.readPgm + strm.close From 2b1f96f6865362384996fee0654e0fd0116086fe Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 20:34:54 +0900 Subject: [PATCH 122/128] add empty test file --- tests/unit/write_pbm.nim | 0 tests/unit/write_pgm.nim | 0 tests/unit/write_ppm.nim | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/unit/write_pbm.nim create mode 100644 tests/unit/write_pgm.nim create mode 100644 tests/unit/write_ppm.nim diff --git a/tests/unit/write_pbm.nim b/tests/unit/write_pbm.nim new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/write_pgm.nim b/tests/unit/write_pgm.nim new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/write_ppm.nim b/tests/unit/write_ppm.nim new file mode 100644 index 0000000..e69de29 From f0b14be70f217fdc98054083941491d23712ddfb Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 20:35:02 +0900 Subject: [PATCH 123/128] add validations --- src/pnm.nim | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/pnm.nim b/src/pnm.nim index 15ee83e..ae5d2b0 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -32,6 +32,10 @@ type IllegalFileDescriptorError* = object of CatchableError ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. + IllegalDataWidthError* = object of CatchableError + ## Return this when data width less than 0. + IllegalDataHeightError* = object of CatchableError + ## Return this when data height less than 1. IllegalDataSizeError* = object of CatchableError ## Return this when data size didn't match data size (width x height) of PNM. IllegalPbmDataError* = object of CatchableError @@ -43,6 +47,18 @@ proc newColorRgb*(r, g, b: byte): ColorRgb = proc width*(p: Pnm): int = p.width proc height*(p: Pnm): int = p.height +template validateWidth(width: int) = + if width < 1: + raise newException(IllegalDataWidthError, "width must not be less than 1.") + +template validateHeight(height: int) = + if height < 1: + raise newException(IllegalDataHeightError, "height must not be less than 1.") + +template validateWidthHeight(width, height: int) = + validateWidth(width) + validateHeight(height) + template validateDescriptorPbm(d: PnmFileDescriptor) = if d notin [P1, P4]: raise newException(IllegalFileDescriptorError, "the descriptor of PBM must be P1 or P4") @@ -154,6 +170,7 @@ proc readMax(strm: Stream, d: PnmFileDescriptor): int = proc newPbm*(descriptor: PnmFileDescriptor, width, height: int, comment = ""): Pbm = validateDescriptorPbm(descriptor) + validateWidthHeight(width, height) new result result.descriptor = descriptor @@ -224,6 +241,7 @@ proc writePbm*(strm: Stream, data: Pbm) = proc newPgm*(descriptor: PnmFileDescriptor, width, height, max: int, comment = ""): Pgm = validateDescriptorPgm(descriptor) + validateWidthHeight(width, height) new result result.descriptor = descriptor @@ -299,6 +317,7 @@ proc writePgm*(strm: Stream, data: Pgm) = proc newPpm*(descriptor: PnmFileDescriptor, width, height, max: int, comment = ""): Ppm = validateDescriptorPpm(descriptor) + validateWidthHeight(width, height) new result result.descriptor = descriptor From 72bd6a4aeb56c239a4f42d57c1654bcd5683cd85 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 20:35:05 +0900 Subject: [PATCH 124/128] add test cases --- tests/unit/utils.nim | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/unit/utils.nim diff --git a/tests/unit/utils.nim b/tests/unit/utils.nim new file mode 100644 index 0000000..cbc85a7 --- /dev/null +++ b/tests/unit/utils.nim @@ -0,0 +1,28 @@ +include pnm + +import unittest + +block: + # newPbm + block: + let got = newPbm(P1, 5, 3) + check got.data.len == 15 + + # block: + # let got = newPbm(P4, 5, 3) + # check got.data.len == 3 + # check got.data.len == 15 + + block: + expect IllegalFileDescriptorError: discard newPbm(P2, 5, 3) + expect IllegalFileDescriptorError: discard newPbm(P3, 5, 3) + expect IllegalFileDescriptorError: discard newPbm(P5, 5, 3) + expect IllegalFileDescriptorError: discard newPbm(P6, 5, 3) + + block: + expect IllegalDataWidthError: discard newPbm(P1, 0, 3) + expect IllegalDataWidthError: discard newPbm(P1, -1, 3) + + block: + expect IllegalDataHeightError: discard newPbm(P1, 5, 0) + expect IllegalDataHeightError: discard newPbm(P1, 5, -1) From 0d6b14bf9e5065e5236ace9dea60d5f8a395427f Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 20:47:17 +0900 Subject: [PATCH 125/128] add validation --- src/pnm.nim | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index ae5d2b0..dc9e014 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -33,11 +33,13 @@ type ## Return this when file descriptor is wrong. ## filedescriptors are P1 or P2 or P3 or P4 or P5 or P6. IllegalDataWidthError* = object of CatchableError - ## Return this when data width less than 0. + ## Return this when data width is less than 0. IllegalDataHeightError* = object of CatchableError - ## Return this when data height less than 1. + ## Return this when data height is less than 1. IllegalDataSizeError* = object of CatchableError ## Return this when data size didn't match data size (width x height) of PNM. + IllegalDataMaxError* = object of CatchableError + ## Return this when data max is greater than 255. IllegalPbmDataError* = object of CatchableError ## Return this when PBM has byte data outside of 0 or 1. @@ -59,6 +61,10 @@ template validateWidthHeight(width, height: int) = validateWidth(width) validateHeight(height) +template validateMax(max: int) = + if not (0 <= max and max < 256): + raise newException(IllegalDataMaxError, "max must be between 0 and 255.") + template validateDescriptorPbm(d: PnmFileDescriptor) = if d notin [P1, P4]: raise newException(IllegalFileDescriptorError, "the descriptor of PBM must be P1 or P4") @@ -242,6 +248,7 @@ proc writePbm*(strm: Stream, data: Pbm) = proc newPgm*(descriptor: PnmFileDescriptor, width, height, max: int, comment = ""): Pgm = validateDescriptorPgm(descriptor) validateWidthHeight(width, height) + validateMax(max) new result result.descriptor = descriptor @@ -318,6 +325,7 @@ proc writePgm*(strm: Stream, data: Pgm) = proc newPpm*(descriptor: PnmFileDescriptor, width, height, max: int, comment = ""): Ppm = validateDescriptorPpm(descriptor) validateWidthHeight(width, height) + validateMax(max) new result result.descriptor = descriptor From c80035401f83ca524772c3a3614f5c406e2c83f2 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 20:47:20 +0900 Subject: [PATCH 126/128] add test cases --- tests/unit/utils.nim | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/tests/unit/utils.nim b/tests/unit/utils.nim index cbc85a7..6e474c8 100644 --- a/tests/unit/utils.nim +++ b/tests/unit/utils.nim @@ -2,16 +2,14 @@ include pnm import unittest +# ====== +# newPbm +# ====== + block: - # newPbm block: - let got = newPbm(P1, 5, 3) - check got.data.len == 15 - - # block: - # let got = newPbm(P4, 5, 3) - # check got.data.len == 3 - # check got.data.len == 15 + check newPbm(P1, 5, 3).data.len == 15 + check newPbm(P4, 5, 3).data.len == 15 block: expect IllegalFileDescriptorError: discard newPbm(P2, 5, 3) @@ -26,3 +24,32 @@ block: block: expect IllegalDataHeightError: discard newPbm(P1, 5, 0) expect IllegalDataHeightError: discard newPbm(P1, 5, -1) + +# ====== +# newPgm +# ====== + +block: + block: + check newPgm(P2, 5, 3, 255).data.len == 15 + check newPgm(P5, 5, 3, 255).data.len == 15 + check newPgm(P2, 5, 3, 0).data.len == 15 # no error + check newPgm(P2, 5, 3, 1).data.len == 15 # no error + + block: + expect IllegalFileDescriptorError: discard newPgm(P1, 5, 3, 255) + expect IllegalFileDescriptorError: discard newPgm(P3, 5, 3, 255) + expect IllegalFileDescriptorError: discard newPgm(P4, 5, 3, 255) + expect IllegalFileDescriptorError: discard newPgm(P6, 5, 3, 255) + + block: + expect IllegalDataWidthError: discard newPgm(P2, 0, 3, 255) + expect IllegalDataWidthError: discard newPgm(P2, -1, 3, 255) + + block: + expect IllegalDataHeightError: discard newPgm(P2, 5, 0, 255) + expect IllegalDataHeightError: discard newPgm(P2, 5, -1, 255) + + block: + expect IllegalDataMaxError: discard newPgm(P2, 5, 3, -1) + expect IllegalDataMaxError: discard newPgm(P2, 5, 3, 256) From 255b843290925fbb8b4bbf2c0a870e0b52afeff8 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 20:49:05 +0900 Subject: [PATCH 127/128] add test cases --- tests/unit/utils.nim | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/unit/utils.nim b/tests/unit/utils.nim index 6e474c8..62d644e 100644 --- a/tests/unit/utils.nim +++ b/tests/unit/utils.nim @@ -53,3 +53,32 @@ block: block: expect IllegalDataMaxError: discard newPgm(P2, 5, 3, -1) expect IllegalDataMaxError: discard newPgm(P2, 5, 3, 256) + +# ====== +# newPpm +# ====== + +block: + block: + check newPpm(P3, 5, 3, 255).data.len == 15 + check newPpm(P6, 5, 3, 255).data.len == 15 + check newPpm(P3, 5, 3, 0).data.len == 15 # no error + check newPpm(P3, 5, 3, 1).data.len == 15 # no error + + block: + expect IllegalFileDescriptorError: discard newPpm(P1, 5, 3, 255) + expect IllegalFileDescriptorError: discard newPpm(P2, 5, 3, 255) + expect IllegalFileDescriptorError: discard newPpm(P4, 5, 3, 255) + expect IllegalFileDescriptorError: discard newPpm(P5, 5, 3, 255) + + block: + expect IllegalDataWidthError: discard newPpm(P3, 0, 3, 255) + expect IllegalDataWidthError: discard newPpm(P3, -1, 3, 255) + + block: + expect IllegalDataHeightError: discard newPpm(P3, 5, 0, 255) + expect IllegalDataHeightError: discard newPpm(P3, 5, -1, 255) + + block: + expect IllegalDataMaxError: discard newPpm(P3, 5, 3, -1) + expect IllegalDataMaxError: discard newPpm(P3, 5, 3, 256) From f1c5215e83898bf00750db8969a9737c78329306 Mon Sep 17 00:00:00 2001 From: jiro4989 Date: Sat, 20 Mar 2021 21:09:58 +0900 Subject: [PATCH 128/128] fix read text data part of ppm --- src/pnm.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pnm.nim b/src/pnm.nim index dc9e014..d8746f4 100644 --- a/src/pnm.nim +++ b/src/pnm.nim @@ -386,10 +386,10 @@ proc readPpm*(strm: Stream): Ppm = result.max = strm.readMax(result.descriptor) # body - const byteSize = 3 + const byteSize = 1 case result.descriptor - of P3: result.data = strm.readDataPartOfTextData(result.descriptor, width, height, byteSize).toColorRgb - of P6: result.data = strm.readDataPartOfBinaryData(width, height, byteSize).toColorRgb + of P3: result.data = strm.readDataPartOfTextData(result.descriptor, width, height, byteSize, rgb = true).toColorRgb + of P6: result.data = strm.readDataPartOfBinaryData(width, height, byteSize, rgb = true).toColorRgb else: discard proc writePpm*(strm: Stream, data: Ppm) =