1
0
Fork 0

Adding upstream version 1.8.0+20250123.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-04-06 10:27:28 +02:00
parent 972340dc8c
commit 7d7607bd81
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
52 changed files with 15921 additions and 0 deletions

88
c/Makefile Normal file
View file

@ -0,0 +1,88 @@
#
# Makefile for QR Code generator (C)
#
# Copyright (c) Project Nayuki. (MIT License)
# https://www.nayuki.io/page/qr-code-generator-library
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# - The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# - The Software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
#
# ---- Configuration options ----
# External/implicit variables:
# - CC: The C compiler, such as gcc or clang.
# - CFLAGS: Any extra user-specified compiler flags (can be blank).
# Recommended compiler flags:
CFLAGS += -std=c99 -O
# Extra flags for diagnostics:
# CFLAGS += -g -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -fsanitize=undefined,address
# ---- Controlling make ----
# Clear default suffix rules
.SUFFIXES:
# Don't delete object files
.SECONDARY:
# Stuff concerning goals
.DEFAULT_GOAL = all
.PHONY: all clean
# ---- Targets to build ----
LIB = qrcodegen
LIBFILE = lib$(LIB).a
LIBOBJ = qrcodegen.o
MAINS = qrcodegen-demo qrcodegen-test
# Build all binaries
all: $(LIBFILE) $(MAINS)
# Delete build output
clean:
rm -f -- $(LIBOBJ) $(LIBFILE) $(MAINS:=.o) $(MAINS)
rm -rf .deps
# Executable files
%: %.o $(LIBFILE)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -L . -l $(LIB)
# Special executable
qrcodegen-test: qrcodegen-test.c $(LIBOBJ:%.o=%.c)
$(CC) $(CFLAGS) $(LDFLAGS) -DQRCODEGEN_TEST -o $@ $^
# The library
$(LIBFILE): $(LIBOBJ)
$(AR) -crs $@ -- $^
# Object files
%.o: %.c .deps/timestamp
$(CC) $(CFLAGS) -c -o $@ -MMD -MF .deps/$*.d $<
# Have a place to store header dependencies automatically generated by compiler
.deps/timestamp:
mkdir -p .deps
touch .deps/timestamp
# Make use of said dependencies if available
-include .deps/*.d

70
c/Readme.markdown Normal file
View file

@ -0,0 +1,70 @@
QR Code generator library - C
=============================
Introduction
------------
This project aims to be the best, clearest QR Code generator library. The primary goals are flexible options and absolute correctness. Secondary goals are compact implementation size and good documentation comments.
Home page with live JavaScript demo, extensive descriptions, and competitor comparisons: https://www.nayuki.io/page/qr-code-generator-library
Features
--------
Core features:
* Significantly shorter code but more documentation comments compared to competing libraries
* Supports encoding all 40 versions (sizes) and all 4 error correction levels, as per the QR Code Model 2 standard
* Output format: Raw modules/pixels of the QR symbol
* Detects finder-like penalty patterns more accurately than other implementations
* Encodes numeric and special-alphanumeric text in less space than general text
* Completely avoids heap allocation (`malloc()`), instead relying on suitably sized buffers from the caller and fixed-size stack allocations
* Coded carefully to prevent memory corruption, integer overflow, platform-dependent inconsistencies, and undefined behavior; tested rigorously to confirm safety
* Open-source code under the permissive MIT License
Manual parameters:
* User can specify minimum and maximum version numbers allowed, then library will automatically choose smallest version in the range that fits the data
* User can specify mask pattern manually, otherwise library will automatically evaluate all 8 masks and select the optimal one
* User can specify absolute error correction level, or allow the library to boost it if it doesn't increase the version number
* User can create a list of data segments manually and add ECI segments
More information about QR Code technology and this library's design can be found on the project home page.
Examples
--------
```c
#include <stdbool.h>
#include <stdint.h>
#include "qrcodegen.h"
// Text data
uint8_t qr0[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok = qrcodegen_encodeText("Hello, world!",
tempBuffer, qr0, qrcodegen_Ecc_MEDIUM,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX,
qrcodegen_Mask_AUTO, true);
if (!ok)
return;
int size = qrcodegen_getSize(qr0);
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
(... paint qrcodegen_getModule(qr0, x, y) ...)
}
}
// Binary data
uint8_t dataAndTemp[qrcodegen_BUFFER_LEN_FOR_VERSION(7)]
= {0xE3, 0x81, 0x82};
uint8_t qr1[qrcodegen_BUFFER_LEN_FOR_VERSION(7)];
ok = qrcodegen_encodeBinary(dataAndTemp, 3, qr1,
qrcodegen_Ecc_HIGH, 2, 7, qrcodegen_Mask_4, false);
```
More complete set of examples: https://github.com/nayuki/QR-Code-generator/blob/master/c/qrcodegen-demo.c .

335
c/qrcodegen-demo.c Normal file
View file

@ -0,0 +1,335 @@
/*
* QR Code generator demo (C)
*
* Run this command-line program with no arguments. The program
* computes a demonstration QR Codes and print it to the console.
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qrcodegen.h"
// Function prototypes
static void doBasicDemo(void);
static void doVarietyDemo(void);
static void doSegmentDemo(void);
static void doMaskDemo(void);
static void printQr(const uint8_t qrcode[]);
// The main application program.
int main(void) {
doBasicDemo();
doVarietyDemo();
doSegmentDemo();
doMaskDemo();
return EXIT_SUCCESS;
}
/*---- Demo suite ----*/
// Creates a single QR Code, then prints it to the console.
static void doBasicDemo(void) {
const char *text = "Hello, world!"; // User-supplied text
enum qrcodegen_Ecc errCorLvl = qrcodegen_Ecc_LOW; // Error correction level
// Make and print the QR Code symbol
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok = qrcodegen_encodeText(text, tempBuffer, qrcode, errCorLvl,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
}
// Creates a variety of QR Codes that exercise different features of the library, and prints each one to the console.
static void doVarietyDemo(void) {
{ // Numeric mode encoding (3.33 bits per digit)
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok = qrcodegen_encodeText("314159265358979323846264338327950288419716939937510", tempBuffer, qrcode,
qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
}
{ // Alphanumeric mode encoding (5.5 bits per character)
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok = qrcodegen_encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", tempBuffer, qrcode,
qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
}
{ // Unicode text as UTF-8
const char *text = "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1wa\xE3\x80\x81"
"\xE4\xB8\x96\xE7\x95\x8C\xEF\xBC\x81\x20\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4";
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
}
{ // Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland)
const char *text =
"Alice was beginning to get very tired of sitting by her sister on the bank, "
"and of having nothing to do: once or twice she had peeped into the book her sister was reading, "
"but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice "
"'without pictures or conversations?' So she was considering in her own mind (as well as she could, "
"for the hot day made her feel very sleepy and stupid), whether the pleasure of making a "
"daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly "
"a White Rabbit with pink eyes ran close by her.";
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
}
}
// Creates QR Codes with manually specified segments for better compactness.
static void doSegmentDemo(void) {
{ // Illustration "silver"
const char *silver0 = "THE SQUARE ROOT OF 2 IS 1.";
const char *silver1 = "41421356237309504880168872420969807856967187537694807317667973799";
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok;
{
char *concat = calloc(strlen(silver0) + strlen(silver1) + 1, sizeof(char));
if (concat == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
strcat(concat, silver0);
strcat(concat, silver1);
ok = qrcodegen_encodeText(concat, tempBuffer, qrcode, qrcodegen_Ecc_LOW,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
free(concat);
}
{
uint8_t *segBuf0 = malloc(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, strlen(silver0)) * sizeof(uint8_t));
uint8_t *segBuf1 = malloc(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, strlen(silver1)) * sizeof(uint8_t));
if (segBuf0 == NULL || segBuf1 == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
struct qrcodegen_Segment segs[] = {
qrcodegen_makeAlphanumeric(silver0, segBuf0),
qrcodegen_makeNumeric(silver1, segBuf1),
};
ok = qrcodegen_encodeSegments(segs, sizeof(segs) / sizeof(segs[0]), qrcodegen_Ecc_LOW, tempBuffer, qrcode);
free(segBuf0);
free(segBuf1);
if (ok)
printQr(qrcode);
}
}
{ // Illustration "golden"
const char *golden0 = "Golden ratio \xCF\x86 = 1.";
const char *golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374";
const char *golden2 = "......";
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok;
{
char *concat = calloc(strlen(golden0) + strlen(golden1) + strlen(golden2) + 1, sizeof(char));
if (concat == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
strcat(concat, golden0);
strcat(concat, golden1);
strcat(concat, golden2);
ok = qrcodegen_encodeText(concat, tempBuffer, qrcode, qrcodegen_Ecc_LOW,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
free(concat);
}
{
uint8_t *bytes = malloc(strlen(golden0) * sizeof(uint8_t));
if (bytes == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
for (size_t i = 0, len = strlen(golden0); i < len; i++)
bytes[i] = (uint8_t)golden0[i];
uint8_t *segBuf0 = malloc(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_BYTE, strlen(golden0)) * sizeof(uint8_t));
uint8_t *segBuf1 = malloc(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, strlen(golden1)) * sizeof(uint8_t));
uint8_t *segBuf2 = malloc(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, strlen(golden2)) * sizeof(uint8_t));
if (segBuf0 == NULL || segBuf1 == NULL || segBuf2 == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
struct qrcodegen_Segment segs[] = {
qrcodegen_makeBytes(bytes, strlen(golden0), segBuf0),
qrcodegen_makeNumeric(golden1, segBuf1),
qrcodegen_makeAlphanumeric(golden2, segBuf2),
};
free(bytes);
ok = qrcodegen_encodeSegments(segs, sizeof(segs) / sizeof(segs[0]), qrcodegen_Ecc_LOW, tempBuffer, qrcode);
free(segBuf0);
free(segBuf1);
free(segBuf2);
if (ok)
printQr(qrcode);
}
}
{ // Illustration "Madoka": kanji, kana, Cyrillic, full-width Latin, Greek characters
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok;
{
const char *madoka = // Encoded in UTF-8
"\xE3\x80\x8C\xE9\xAD\x94\xE6\xB3\x95\xE5"
"\xB0\x91\xE5\xA5\xB3\xE3\x81\xBE\xE3\x81"
"\xA9\xE3\x81\x8B\xE2\x98\x86\xE3\x83\x9E"
"\xE3\x82\xAE\xE3\x82\xAB\xE3\x80\x8D\xE3"
"\x81\xA3\xE3\x81\xA6\xE3\x80\x81\xE3\x80"
"\x80\xD0\x98\xD0\x90\xD0\x98\xE3\x80\x80"
"\xEF\xBD\x84\xEF\xBD\x85\xEF\xBD\x93\xEF"
"\xBD\x95\xE3\x80\x80\xCE\xBA\xCE\xB1\xEF"
"\xBC\x9F";
ok = qrcodegen_encodeText(madoka, tempBuffer, qrcode, qrcodegen_Ecc_LOW,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
}
{
const int kanjiChars[] = { // Kanji mode encoding (13 bits per character)
0x0035, 0x1002, 0x0FC0, 0x0AED, 0x0AD7,
0x015C, 0x0147, 0x0129, 0x0059, 0x01BD,
0x018D, 0x018A, 0x0036, 0x0141, 0x0144,
0x0001, 0x0000, 0x0249, 0x0240, 0x0249,
0x0000, 0x0104, 0x0105, 0x0113, 0x0115,
0x0000, 0x0208, 0x01FF, 0x0008,
};
size_t len = sizeof(kanjiChars) / sizeof(kanjiChars[0]);
uint8_t *segBuf = calloc(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_KANJI, len), sizeof(uint8_t));
if (segBuf == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
struct qrcodegen_Segment seg;
seg.mode = qrcodegen_Mode_KANJI;
seg.numChars = (int)len;
seg.bitLength = 0;
for (size_t i = 0; i < len; i++) {
for (int j = 12; j >= 0; j--, seg.bitLength++)
segBuf[seg.bitLength >> 3] |= ((kanjiChars[i] >> j) & 1) << (7 - (seg.bitLength & 7));
}
seg.data = segBuf;
ok = qrcodegen_encodeSegments(&seg, 1, qrcodegen_Ecc_LOW, tempBuffer, qrcode);
free(segBuf);
if (ok)
printQr(qrcode);
}
}
}
// Creates QR Codes with the same size and contents but different mask patterns.
static void doMaskDemo(void) {
{ // Project Nayuki URL
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok;
ok = qrcodegen_encodeText("https://www.nayuki.io/", tempBuffer, qrcode,
qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText("https://www.nayuki.io/", tempBuffer, qrcode,
qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_3, true);
if (ok)
printQr(qrcode);
}
{ // Chinese text as UTF-8
const char *text =
"\xE7\xB6\xAD\xE5\x9F\xBA\xE7\x99\xBE\xE7\xA7\x91\xEF\xBC\x88\x57\x69\x6B\x69\x70"
"\x65\x64\x69\x61\xEF\xBC\x8C\xE8\x81\x86\xE8\x81\xBD\x69\x2F\xCB\x8C\x77\xC9\xAA"
"\x6B\xE1\xB5\xBB\xCB\x88\x70\x69\xCB\x90\x64\x69\x2E\xC9\x99\x2F\xEF\xBC\x89\xE6"
"\x98\xAF\xE4\xB8\x80\xE5\x80\x8B\xE8\x87\xAA\xE7\x94\xB1\xE5\x85\xA7\xE5\xAE\xB9"
"\xE3\x80\x81\xE5\x85\xAC\xE9\x96\x8B\xE7\xB7\xA8\xE8\xBC\xAF\xE4\xB8\x94\xE5\xA4"
"\x9A\xE8\xAA\x9E\xE8\xA8\x80\xE7\x9A\x84\xE7\xB6\xB2\xE8\xB7\xAF\xE7\x99\xBE\xE7"
"\xA7\x91\xE5\x85\xA8\xE6\x9B\xB8\xE5\x8D\x94\xE4\xBD\x9C\xE8\xA8\x88\xE7\x95\xAB";
uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
bool ok;
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_0, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_1, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_5, true);
if (ok)
printQr(qrcode);
ok = qrcodegen_encodeText(text, tempBuffer, qrcode,
qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_7, true);
if (ok)
printQr(qrcode);
}
}
/*---- Utilities ----*/
// Prints the given QR Code to the console.
static void printQr(const uint8_t qrcode[]) {
int size = qrcodegen_getSize(qrcode);
int border = 4;
for (int y = -border; y < size + border; y++) {
for (int x = -border; x < size + border; x++) {
fputs((qrcodegen_getModule(qrcode, x, y) ? "##" : " "), stdout);
}
fputs("\n", stdout);
}
fputs("\n", stdout);
}

1102
c/qrcodegen-test.c Normal file

File diff suppressed because it is too large Load diff

1027
c/qrcodegen.c Normal file

File diff suppressed because it is too large Load diff

385
c/qrcodegen.h Normal file
View file

@ -0,0 +1,385 @@
/*
* QR Code generator library (C)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* This library creates QR Code symbols, which is a type of two-dimension barcode.
* Invented by Denso Wave and described in the ISO/IEC 18004 standard.
* A QR Code structure is an immutable square grid of dark and light cells.
* The library provides functions to create a QR Code from text or binary data.
* The library covers the QR Code Model 2 specification, supporting all versions (sizes)
* from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
*
* Ways to create a QR Code object:
* - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary().
* - Low level: Custom-make the list of segments and call
* qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced().
* (Note that all ways require supplying the desired error correction level and various byte buffers.)
*/
/*---- Enum and struct types----*/
/*
* The error correction level in a QR Code symbol.
*/
enum qrcodegen_Ecc {
// Must be declared in ascending order of error protection
// so that an internal qrcodegen function works properly
qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords
qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords
qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords
qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords
};
/*
* The mask pattern used in a QR Code symbol.
*/
enum qrcodegen_Mask {
// A special value to tell the QR Code encoder to
// automatically select an appropriate mask pattern
qrcodegen_Mask_AUTO = -1,
// The eight actual mask patterns
qrcodegen_Mask_0 = 0,
qrcodegen_Mask_1,
qrcodegen_Mask_2,
qrcodegen_Mask_3,
qrcodegen_Mask_4,
qrcodegen_Mask_5,
qrcodegen_Mask_6,
qrcodegen_Mask_7,
};
/*
* Describes how a segment's data bits are interpreted.
*/
enum qrcodegen_Mode {
qrcodegen_Mode_NUMERIC = 0x1,
qrcodegen_Mode_ALPHANUMERIC = 0x2,
qrcodegen_Mode_BYTE = 0x4,
qrcodegen_Mode_KANJI = 0x8,
qrcodegen_Mode_ECI = 0x7,
};
/*
* A 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 qrcodegen_makeNumeric().
* The low-level way to create a segment is to custom-make the bit buffer
* and initialize a qrcodegen_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.
* Moreover, the maximum allowed bit length is 32767 because
* the largest QR Code (version 40) has 31329 modules.
*/
struct qrcodegen_Segment {
// The mode indicator of this segment.
enum qrcodegen_Mode mode;
// 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.
int numChars;
// The data bits of this segment, packed in bitwise big endian.
// Can be null if the bit length is zero.
uint8_t *data;
// The number of valid data bits used in the buffer. Requires
// 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8.
// The character count (numChars) must agree with the mode and the bit buffer length.
int bitLength;
};
/*---- Macro constants and functions ----*/
#define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard
#define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard
// Calculates the number of bytes needed to store any QR Code up to and including the given version number,
// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];'
// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16).
// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX.
#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1)
// The worst-case number of bytes needed to store one QR Code, up to and including
// version 40. This value equals 3918, which is just under 4 kilobytes.
// Use this more convenient value to avoid calculating tighter memory bounds for buffers.
#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX)
/*---- Functions (high level) to generate QR Codes ----*/
/*
* Encodes the given text string to a QR Code, returning true if successful.
* If the data is too long to fit in any version in the given range
* at the given ECC level, then false is returned.
*
* The input text must be encoded in UTF-8 and contain no NULs.
* Requires 1 <= minVersion <= maxVersion <= 40.
*
* The 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 qrcodegen_Mask_0 to 7 to force that mask, or
* qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow).
*
* About the arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion):
* - Before calling the function:
* - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow
* reading and writing; hence each array must have a length of at least len.
* - The two ranges must not overlap (aliasing).
* - The initial state of both ranges can be uninitialized
* because the function always writes before reading.
* - After the function returns:
* - Both ranges have no guarantee on which elements are initialized and what values are stored.
* - tempBuffer contains no useful data and should be treated as entirely uninitialized.
* - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule().
*
* If successful, the resulting QR Code may use numeric,
* alphanumeric, or byte mode to encode the text.
*
* 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.
*
* Please consult the QR Code specification for information on
* data capacities per version, ECC level, and text encoding mode.
*/
bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[],
enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl);
/*
* Encodes the given binary data to a QR Code, returning true if successful.
* If the data is too long to fit in any version in the given range
* at the given ECC level, then false is returned.
*
* Requires 1 <= minVersion <= maxVersion <= 40.
*
* The 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 qrcodegen_Mask_0 to 7 to force that mask, or
* qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow).
*
* About the arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion):
* - Before calling the function:
* - The array ranges dataAndTemp[0 : len] and qrcode[0 : len] must allow
* reading and writing; hence each array must have a length of at least len.
* - The two ranges must not overlap (aliasing).
* - The input array range dataAndTemp[0 : dataLen] should normally be
* valid UTF-8 text, but is not required by the QR Code standard.
* - The initial state of dataAndTemp[dataLen : len] and qrcode[0 : len]
* can be uninitialized because the function always writes before reading.
* - After the function returns:
* - Both ranges have no guarantee on which elements are initialized and what values are stored.
* - dataAndTemp contains no useful data and should be treated as entirely uninitialized.
* - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule().
*
* If successful, the resulting QR Code will use byte mode to encode the data.
*
* 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.
*
* Please consult the QR Code specification for information on
* data capacities per version, ECC level, and text encoding mode.
*/
bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[],
enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl);
/*---- Functions (low level) to generate QR Codes ----*/
/*
* Encodes the given segments to a QR Code, returning true if successful.
* If the data is too long to fit in any version at the given ECC level,
* then false is returned.
*
* The smallest possible QR Code version is automatically chosen for
* the output. The ECC level of the result may be higher than the
* ecl argument if it can be done without increasing the version.
*
* About the byte arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX):
* - Before calling the function:
* - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow
* reading and writing; hence each array must have a length of at least len.
* - The two ranges must not overlap (aliasing).
* - The initial state of both ranges can be uninitialized
* because the function always writes before reading.
* - The input array segs can contain segments whose data buffers overlap with tempBuffer.
* - After the function returns:
* - Both ranges have no guarantee on which elements are initialized and what values are stored.
* - tempBuffer contains no useful data and should be treated as entirely uninitialized.
* - Any segment whose data buffer overlaps with tempBuffer[0 : len]
* must be treated as having invalid values in that array.
* - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule().
*
* Please consult the QR Code specification for information on
* data capacities per version, ECC level, and text encoding mode.
*
* This 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.
* This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary().
*/
bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len,
enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]);
/*
* Encodes the given segments to a QR Code, returning true if successful.
* If the data is too long to fit in any version in the given range
* at the given ECC level, then false is returned.
*
* Requires 1 <= minVersion <= maxVersion <= 40.
*
* The 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 qrcodegen_Mask_0 to 7 to force that mask, or
* qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow).
*
* About the byte arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX):
* - Before calling the function:
* - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow
* reading and writing; hence each array must have a length of at least len.
* - The two ranges must not overlap (aliasing).
* - The initial state of both ranges can be uninitialized
* because the function always writes before reading.
* - The input array segs can contain segments whose data buffers overlap with tempBuffer.
* - After the function returns:
* - Both ranges have no guarantee on which elements are initialized and what values are stored.
* - tempBuffer contains no useful data and should be treated as entirely uninitialized.
* - Any segment whose data buffer overlaps with tempBuffer[0 : len]
* must be treated as having invalid values in that array.
* - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule().
*
* Please consult the QR Code specification for information on
* data capacities per version, ECC level, and text encoding mode.
*
* This 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.
* This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary().
*/
bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl,
int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]);
/*
* Tests 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.
*/
bool qrcodegen_isNumeric(const char *text);
/*
* Tests 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.
*/
bool qrcodegen_isAlphanumeric(const char *text);
/*
* Returns the number of bytes (uint8_t) needed for the data buffer of a segment
* containing the given number of characters using the given mode. Notes:
* - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or the internal
* calculation of the number of needed bits exceeds INT16_MAX (i.e. 32767).
* - 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.
* - For byte mode, numChars measures the number of bytes, not Unicode code points.
* - 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.
*/
size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars);
/*
* Returns 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.
*/
struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]);
/*
* Returns a segment representing the given string of decimal digits encoded in numeric mode.
*/
struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]);
/*
* Returns 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.
*/
struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]);
/*
* Returns a segment representing an Extended Channel Interpretation
* (ECI) designator with the given assignment value.
*/
struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]);
/*---- Functions to extract raw data from QR Codes ----*/
/*
* Returns 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_t qrcode[]' must have length at least
* qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1).
*/
int qrcodegen_getSize(const uint8_t qrcode[]);
/*
* Returns the color of the module (pixel) at the given coordinates, which is false
* for light or true for dark. The top left corner has the coordinates (x=0, y=0).
* If the given coordinates are out of bounds, then false (light) is returned.
*/
bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y);
#ifdef __cplusplus
}
#endif