{"id":16971549,"url":"https://github.com/thomastjdev/nim_qr","last_synced_at":"2025-04-12T00:42:52.424Z","repository":{"id":45464278,"uuid":"240722451","full_name":"ThomasTJdev/nim_qr","owner":"ThomasTJdev","description":"QR-code package for Nim","archived":false,"fork":false,"pushed_at":"2022-08-26T06:52:43.000Z","size":79,"stargazers_count":20,"open_issues_count":0,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-12T00:42:48.493Z","etag":null,"topics":["nim","qr","qrcode","qrcode-generator"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ThomasTJdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-15T14:03:48.000Z","updated_at":"2025-01-24T23:33:28.000Z","dependencies_parsed_at":"2022-07-15T02:16:55.871Z","dependency_job_id":null,"html_url":"https://github.com/ThomasTJdev/nim_qr","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasTJdev%2Fnim_qr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasTJdev%2Fnim_qr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasTJdev%2Fnim_qr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasTJdev%2Fnim_qr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ThomasTJdev","download_url":"https://codeload.github.com/ThomasTJdev/nim_qr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248501959,"owners_count":21114681,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nim","qr","qrcode","qrcode-generator"],"created_at":"2024-10-14T00:52:31.038Z","updated_at":"2025-04-12T00:42:52.383Z","avatar_url":"https://github.com/ThomasTJdev.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nim QR\nQR-code package for Nim. Create SVG and Raster Image files with QR-codes from strings.\n\nThe code is based on [bunkford's qrcodegen package](https://github.com/bunkford/qrcodegen), which is a wrapper for [nayuki's QR-code](https://github.com/nayuki/QR-Code-generator).\n\n\n# Install\n\n## Nimble\n\n```\nnimble install qr\n# and then just `import qr`\n```\n\n## Manually\n```\ngit clone https://github.com/ThomasTJdev/nim_qr.git\ncd qr\nnimble install\n# and then just `import qr`\n```\n\n# Examples\n\nGenerate a SVG file:\n```nim\nimport qr\n\nqrSvgFile(\"https://forum.nim-lang.org\", \"test.svg\")\n# Data:        https://forum.nim-lang.org\n# Output file: test.svg\n# This uses the standard configuration, e.g. optimal size, mask pattern.\n```\n\n![alt text](test.svg \"Tot\")\n\n\nGenerate a Raster Image file:\n```nim\nimport qr\n\nqrPbmFile(\"https://forum.nim-lang.org\", \"test.pbm\")\n# Data:        https://forum.nim-lang.org\n# Output file: test.pbm\n# This uses the standard configuration, e.g. optimal size, mask pattern.\n```\n\nTiny program that generates SVG QR Codes from the terminal first argument:\n\n```nim\nimport os, qr\nqrSvgFile paramStr(1), \"output.svg\"\n```\n\nTiny program that generates Image QR Codes from the terminal first argument:\n\n```nim\nimport os, qr\nqrPbmFile paramStr(1), \"output.pbm\"\n```\n\n\n# Nim QR package procs\n\n## qrBinary*\n\n```nim\nproc qrBinary*(data: string, eccLevel = Ecc_Medium, verMin: cint = VERSION_MIN, verMax: cint = VERSION_MAX, mask = Mask_AUTO): string =\n```\n\nThis returns 1 (black) and 0's (whites) representing the QR code. Each row is separated by a newline `\\n`.\n\n\n**Example**\n```nim\n  let qr = qrBinary(\"Hello world\")\n  # qr = 1100111101\\n101001010\\n010101011\\n101......\n```\n\n\n____\n\n## qrRow*\n\n```nim\nproc qrRow*(data: string, eccLevel = Ecc_Medium, verMin: cint = VERSION_MIN, verMax: cint = VERSION_MAX, mask = Mask_AUTO): seq[seq[int]] =\n```\n\nReturn a seq[seq[int]] containing the QR-code. 1's is a black field, and 0's is blank field.\n\n\n**Example**\n```nim\n  let qr = qrRow(\"Hello world\")\n  # qr = @[@[0,1,1,0,1....],@[0,0,1,1,1...],@[0,1,1,1,0...\n```\n\n\n____\n\n## qrSvgFile*\n\n```nim\ntemplate qrSvgFile*(data, filename: string, size: int32 = 0, border: cint = 0, eccLevel = Ecc_Medium, verMin: cint = VERSION_MIN, verMax: cint = VERSION_MAX, mask = Mask_AUTO) =\n```\n\nCreates a SVG file for the QR and saves it.\n\nThe `size` should be in pixels. If set to 0, the optimal size will be used based on the density.\n\nYou can set the minimum and maximum size params, `verMin` and `verMax`. You can use values from 1-40.\n\nYou only need to define the `data` and a `filename`. Please note there's no error checking when creating the file, you have to that yourself.\n\n\n**Example**\n```nim\n  qrSvgFile(\"Hello world\", \"test.svg\")\n```\n\n\n____\n\n## qrSvg*\n\n```nim\nproc qrSvg*(data: string, size: int32 = 0, border: cint = 0, eccLevel = Ecc_Medium, verMin: cint = VERSION_MIN, verMax: cint = VERSION_MAX, mask = Mask_AUTO): string =\n```\n\nReturns the SVG data\n\nThe `size` should be in pixels. If set to 0, the optimal size will be used based on the density.\n\nYou can set the minimum and maximum size params, `verMin` and `verMax`. You can use values from 1-40.\n\nYou only need to define the `data`.\n\n\n**Example**\n```nim\n  let htmlReadySvg = qrSvg(\"Hello world\")\n```\n\n\n____\n\n## qrPrint*\n\n```nim\nproc qrPrint*(data: string, border: cint = 0, eccLevel = Ecc_Medium, verMin: cint = VERSION_MIN, verMax: cint = VERSION_MAX, mask = Mask_AUTO, fgColor = \"##\", bgColor = \"  \") =\n```\n\nPrints the QR-code to the console with `\"#\"`'s.\n\nYou can customize the character representing the Black \u0026 White colors,\n\n`fgColor` is for Foreground Color, `bgColor` is for Background Color.\n\n\n**Example**\n```nim\n  qrPrint(\"Hello world\", fgColor = \"⬛\", bgColor = \"..\")\n```\n\n____\n\n## qrPbmFile*\n\n```nim\ntemplate qrPbmFile*(data, filename: string, eccLevel = Ecc_Medium, verMin: cint = VERSION_MIN, verMax: cint = VERSION_MAX, mask = Mask_AUTO, comment = \"\") =\n```\n\nCreates a PBM file for the QR and saves it. Format is Monochrome (Black \u0026 White), but is really lighweight too.\n\n`comment` is metadata string comment, optional.\n\nThe `size` should be in pixels. If set to 0, the optimal size will be used based on the density.\n\nYou can set the minimum and maximum size params, `verMin` and `verMax`. You can use values from 1-40.\n\nYou only need to define the `data` and a `filename`. Please note there's no error checking when creating the file, you have to that yourself.\n\n**Example**\n```nim\n  qrPbmFile(\"Hello world\", \"test.pbm\")\n```\n\n____\n\n\n# Const\n\nVersion:\n```nim\nconst\n  VERSION_MIN* = 1  ## QR Code Minimum Version\n  VERSION_MAX* = 40 ## QR Code Maximum Version\n```\n\n_____\n\n# Types\n\n## Ecc* = enum\n\nThe error correction level in a QR Code symbol. `Ecc_MEDIUM` is used as standard.\n\n* __Ecc_LOW__: The QR Code can tolerate about  7% erroneous codewords\n\n* __Ecc_MEDIUM__: The QR Code can tolerate about 15% erroneous codewords\n\n* __Ecc_QUARTILE__: The QR Code can tolerate about 25% erroneous codewords\n\n* __Ecc_HIGH__: The QR Code can tolerate about 30% erroneous codewords\n```nim\n  Ecc* {.size: sizeof(cint).} = enum\n    Ecc_LOW = 0,\n    Ecc_MEDIUM,\n    Ecc_QUARTILE,\n    Ecc_HIGH\n```\n\n____\n\n## Mask* = enum\n\n The mask pattern used in a QR Code symbol. Mask_AUTO is used as standard.\n\n* __Mask_AUTO__: A special value to tell the QR Code encoder to automatically select an appropriate mask pattern\n\n* __Mask_0 = 0, Mask_1, Mask_2, Mask_3, Mask_4, Mask_5, Mask_6, Mask_7__: The eight actual mask patterns\n```nim\n  Mask* {.size: sizeof(cint).} = enum\n    Mask_AUTO = -1,\n    Mask_0 = 0, Mask_1, Mask_2, Mask_3, Mask_4, Mask_5, Mask_6, Mask_7\n```\n\n____\n\n\n# Wrapped from C\n\n\nThe text below is a direct copy'n'paste from [bunkford's qrcodegen package](https://github.com/bunkford/qrcodegen), which is a wrapper for [nayuki's QR-code](https://github.com/nayuki/QR-Code-generator). Therefore, thanks to nayuki for the detailed description.\n\nAll the _items_ are available, but please keep in mind, that they use `ptr uint8`, `cint`, `cstring`, etc.\n\n\n# Object\n\n## Segment* {.bycopy.} = object\n\nA segment of character/binary/control data in a QR Code symbol. The mid-level way to create a segment is to take the payload data and call a factory function such as makeNumeric().\n\nThe low-level way to create a segment is to custom-make the bit buffer and initialize a Segment struct with appropriate values. Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. Any segment longer than this is meaningless for the purpose of generating QR Codes.\n\nMoreover, the maximum allowed bit length is 32767 because the largest QR Code (version 40) has 31329 modules.\n\n* __mode*: Mode__: The mode indicator of this segment. The length of this segment's unencoded data. Measured in characters for numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. Always zero or positive. Not the same as the data's bit length.\n\n* __numChars*: cint__: The data bits of this segment, packed in bitwise big endian. Can be null if the bit length is zero.\n\n* __data*: ptr uint8__: The number of valid data bits used in the buffer. Requires 0 \u003c= bitLength \u003c= 32767, and bitLength \u003c= (capacity of data array) * 8. The character count (numChars) must agree with the mode and the bit buffer length.\n```nim\n  Segment* {.bycopy.} = object\n    mode*: Mode\n    numChars*: cint\n    data*: ptr uint8\n    bitLength*: cint\n```\n\n____\n\n\n# Procs\n\n## encodeText*\n\n```nim\nproc encodeText*(text: cstring; tempBuffer: ptr uint8; qrcode: ptr uint8; ecl: Ecc; minVersion: cint; maxVersion: cint; mask: Mask; boostEcl: bool): bool {.cdecl, importc: \"qrcodegen_encodeText\", dynlib: libname.}\n```\n\nEncodes the given text string to a QR Code, returning true if encoding succeeded. If the data is too long to fit in any version in the given range at the given ECC level, then false is returned.\n- The input text must be encoded in UTF-8 and contain no NULs.\n- The variables ecl and mask must correspond to enum constant values.\n- Requires 1 \u003c= minVersion \u003c= maxVersion \u003c= 40.\n- The arrays tempBuffer and qrcode must each have a length of at least BUFFER_LEN_FOR_VERSION(maxVersion). - After the function returns, tempBuffer contains no useful data.\n- If successful, the resulting QR Code may use numeric, alphanumeric, or byte mode to encode the text.\n- In the most optimistic case, a QR Code at version 40 with low ECC can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string up to 4296 characters, or any digit string up to 7089 characters. These numbers represent the hard upper limit of the QR Code standard.\n- Please consult the QR Code specification for information on data capacities per version, ECC level, and text encoding mode.\n\n\n____\n\n## encodeBinary*\n\n```nim\nproc encodeBinary*(dataAndTemp: ptr uint8; dataLen: csize; qrcode: ptr uint8; ecl: Ecc; minVersion: cint; maxVersion: cint; mask: Mask; boostEcl: bool): bool {.cdecl, importc: \"qrcodegen_encodeBinary\", dynlib: libname.}\n```\n\nEncodes the given binary data to a QR Code, returning true if encoding succeeded. If the data is too long to fit in any version in the given range at the given ECC level, then false is returned.\n- The input array range dataAndTemp[0 : dataLen] should normally be valid UTF-8 text, but is not required by the QR Code standard.\n- The variables ecl and mask must correspond to enum constant values.\n- Requires 1 \u003c= minVersion \u003c= maxVersion \u003c= 40.\n- The arrays dataAndTemp and qrcode must each have a length of at least BUFFER_LEN_FOR_VERSION(maxVersion).\n- After the function returns, the contents of dataAndTemp may have changed, and does not represent useful data anymore.\n- If successful, the resulting QR Code will use byte mode to encode the data.\n- In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte sequence up to length 2953. This is the hard upper limit of the QR Code standard.\n- Please consult the QR Code specification for information on data capacities per version, ECC level, and text encoding mode.\n\n\n____\n\n## encodeSegments*\n\n```nim\nproc encodeSegments*(segs: ptr Segment; len: csize; ecl: Ecc; tempBuffer: ptr uint8; qrcode: ptr uint8): bool {.cdecl, importc: \"qrcodegen_encodeSegments\", dynlib: libname.}\n```\n\nRenders a QR Code representing the given segments at the given error correction level.\n\nThe smallest possible QR Code version is automatically chosen for the output. Returns true if QR Code creation succeeded, or false if the data is too long to fit in any version.\nThe ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.\n\nThis function allows the user to create a custom sequence of segments that switches between modes (such as alphanumeric and byte) to encode text in less space.\n\nThis is a low-level API; the high-level API is encodeText() and encodeBinary().\n\nTo save memory, the segments' data buffers can alias/overlap tempBuffer, and will result in them being clobbered, but the QR Code output will still be correct. But the qrcode array must not overlap tempBuffer or any segment's data buffer.\n\n\n____\n\n## encodeSegmentsAdvanced*\n\n```nim\nproc encodeSegmentsAdvanced*(segs: ptr Segment; len: csize; ecl: Ecc; minVersion: cint; maxVersion: cint; mask: Mask; boostEcl: bool; tempBuffer: ptr uint8; qrcode: ptr uint8): bool {. cdecl, importc: \"qrcodegen_encodeSegmentsAdvanced\", dynlib: libname.}\n```\n\nRenders a QR Code representing the given segments with the given encoding parameters.\n\nReturns true if QR Code creation succeeded, or false if the data is too long to fit in the range of versions.\n\nThe smallest possible QR Code version within the given range is automatically chosen for the output. Iff boostEcl is true, then the ECC level of the result may be higher than the ecl argument if it can be done without increasing the version. The mask is either between Mask_0 to 7 to force that mask, or Mask_AUTO to automatically choose an appropriate mask (which may be slow).\n\nThis function allows the user to create a custom sequence of segments that switches between modes (such as alphanumeric and byte) to encode text in less space.\n\nThis is a low-level API; the high-level API is encodeText() and encodeBinary(). To save memory, the segments' data buffers can alias/overlap tempBuffer, and will result in them being clobbered, but the QR Code output will still be correct. But the qrcode array must not overlap tempBuffer or any segment's data buffer.\n\n\n____\n\n## isAlphanumeric*\n\n```nim\nproc isAlphanumeric*(text: cstring): bool {.cdecl, importc: \"qrcodegen_isAlphanumeric\", dynlib: libname.}\n```\n\nTests whether the given string can be encoded as a segment in alphanumeric mode. A string is encodable iff each character is in the following set: 0 to 9, A to Z (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.\n\n\n____\n\n## isNumeric*\n\n```nim\nproc isNumeric*(text: cstring): bool {.cdecl, importc: \"qrcodegen_isNumeric\", dynlib: libname.}\n```\n\nTests whether the given string can be encoded as a segment in numeric mode. A string is encodable iff each character is in the range 0 to 9.\n\n\n____\n\n## calcSegmentBufferSize*\n\n```nim\nproc calcSegmentBufferSize*(mode: Mode; numChars: csize): csize {.cdecl, importc: \"qrcodegen_calcSegmentBufferSize\", dynlib: libname.}\n```\n\nReturns the number of bytes (uint8) needed for the data buffer of a segment containing the given number of characters using the given mode. Notes:\n- Returns SIZE_MAX on failure, i.e. numChars \u003e INT16_MAX or the number of needed bits exceeds INT16_MAX (i.e. 32767).\n- Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096. - It is okay for the user to allocate more bytes for the buffer than needed.\n- For byte mode, numChars measures the number of bytes, not Unicode code points.\n- For ECI mode, numChars must be 0, and the worst-case number of bytes is returned. An actual ECI segment can have shorter data. For non-ECI modes, the result is exact.\n\n\n____\n\n## makeBytes*\n\n```nim\nproc makeBytes*(data: ptr uint8; len: csize; buf: ptr uint8): Segment {.cdecl, importc: \"qrcodegen_makeBytes\", dynlib: libname.}\n```\n\nReturns a segment representing the given binary data encoded in byte mode. All input byte arrays are acceptable. Any text string can be converted to UTF-8 bytes and encoded as a byte mode segment.\n\n\n____\n\n## makeNumeric*\n\n```nim\nproc makeNumeric*(digits: cstring; buf: ptr uint8): Segment {.cdecl, importc: \"qrcodegen_makeNumeric\", dynlib: libname.}\n```\n\nReturns a segment representing the given string of decimal digits encoded in numeric mode.\n\n\n____\n\n## makeAlphanumeric*\n\n```nim\nproc makeAlphanumeric*(text: cstring; buf: ptr uint8): Segment {.cdecl, importc: \"qrcodegen_makeAlphanumeric\", dynlib: libname.}\n```\n\nReturns a segment representing the given text string encoded in alphanumeric mode. The characters allowed are: 0 to 9, A to Z (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.\n\n\n____\n\n## makeEci*\n\n```nim\nproc makeEci*(assignVal: clong; buf: ptr uint8): Segment {.cdecl, importc: \"qrcodegen_makeEci\", dynlib: libname.}\n```\n\nReturns a segment representing an Extended Channel Interpretation (ECI) designator with the given assignment value.\n\n\n____\n\n## getSize*\n\n```nim\nproc getSize*(qrcode: ptr uint8): cint {.cdecl, importc: \"qrcodegen_getSize\", dynlib: libname.}\n```\n\nReturns the side length of the given QR Code, assuming that encoding succeeded. The result is in the range [21, 177]. Note that the length of the array buffer is related to the side length - every 'uint8 qrcode[]' must have length at least BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1).\n\n\n____\n\n## getModule*\n\n```nim\nproc getModule*(qrcode: ptr uint8; x: cint; y: cint): bool {.cdecl, importc: \"qrcodegen_getModule\", dynlib: libname.}\n```\n\nReturns the color of the module (pixel) at the given coordinates, which is false for white or true for black. The top left corner has the coordinates (x=0, y=0). If the given coordinates are out of bounds, then false (white) is returned.\n\n____\n\nReadme generated with [NimToMd](https://github.com/ThomasTJdev/nimtomd)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomastjdev%2Fnim_qr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomastjdev%2Fnim_qr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomastjdev%2Fnim_qr/lists"}