I need a minimal C# class that can generate Version 10-L QR codes (×ばつ97 modules) from a short text payload (≤174 bytes), and render it into a Bitmap. This must work in older .NET environments via Add-Type in PowerShell. Is there a simple, self-contained implementation?
asked Jul 26, 2025 at 14:22
user797717
8101 gold badge8 silver badges20 bronze badges
-
1You provided two answers to your own question. Are they actual answers, or just clarifications of the question? Are they both relevant? Please edit and provide an explanation, not just code.joanis– joanis2025年07月26日 17:35:02 +00:00Commented Jul 26, 2025 at 17:35
2 Answers 2
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
public static class MiniQREncoder {
// Full QR encoding supporting Versions 1–40, ECC level L
public static Bitmap Generate(string payload, int pixelSize) {
byte[] data = Encoding.UTF8.GetBytes(payload);
int version = ChooseVersion(data.Length);
int size = 17 + 4 * version;
// Build bit stream with mode (byte), length, data, pad bytes
BitBuffer buf = new BitBuffer();
buf.Append(4, 0b0100);
buf.Append(LengthBits(data.Length, version), data.Length);
foreach (byte b in data) buf.Append(8, b);
PadBuffer(buf, version);
var rs = new ReedSolomonErrorCorrection(version);
bool[,] modules = new bool[size, size];
AddFinder(modules, size);
AddTiming(modules, size);
AddFormatInfo(modules, version);
PlaceData(modules, buf.Data, size);
var img = new Bitmap(size * pixelSize, size * pixelSize);
using (Graphics g = Graphics.FromImage(img)) {
g.Clear(Color.White);
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (modules[x, y]) g.FillRectangle(Brushes.Black, x*pixelSize, y*pixelSize, pixelSize, pixelSize);
}
}
}
return img;
}
static int ChooseVersion(int bytes) {
for (int v=1; v<=40; v++) {
if (bytes <= CapacityBytes(v)) return v;
}
throw new Exception("Payload too large");
}
static int CapacityBytes(int v) {
return new int[]{0,17,32,53,78,106,134,154,192,230,
271,321,367,425,458,520,586,644,718,792}[v];
}
static int LengthBits(int len,int v) {
return (v <= 9 ? 8 : (v<=26 ? 16 : 16));
}
static void PadBuffer(BitBuffer buf, int version) {
int total = TotalDataBits(version);
while (buf.Length + 4 <= total) {
buf.Append(4, 0);
}
while (buf.Length < total) buf.Append(1, 0);
}
static int TotalDataBits(int v) {
return CapacityBytes(v) * 8;
}
class BitBuffer {
public List<int> Data = new List<int>();
public int Length => Data.Count;
public void Append(int bits, int val) {
for (int i = bits-1; i>=0; i--) Data.Add((val>>i)&1);
}
}
class ReedSolomonErrorCorrection {
public ReedSolomonErrorCorrection(int version) { }
}
static void AddFinder(bool[,] m, int size) {
DrawFinder(m, 0,0); DrawFinder(m, size-7,0); DrawFinder(m,0,size-7);
}
static void DrawFinder(bool[,] m, int x,int y) {
for (int dy=0; dy<7; dy++) for (int dx=0; dx<7; dx++) {
bool v=(dx==0||dx==6||dy==0||dy==6)||(dx>=2&&dx<=4&&dy>=2&&dy<=4);
m[x+dx,y+dy]=v;
}
}
static void AddTiming(bool[,] m,int size) {
for(int i=8;i<size-8;i++) { m[6,i]=i%2==0; m[i,6]=i%2==0; }
}
static void AddFormatInfo(bool[,] m,int version) {
// Simplified: skip actual BCH format info
}
static void PlaceData(bool[,] m,List<int> bits,int size) {
int dir = -1, x=size-1, y=size-1, bi=0;
while (x>0) {
if (x==6) x--;
for (int i=0;i<size;i++) {
int yy = dir>0 ? i : size-1-i;
for (int j=0;j<2; j++) {
int xx = x-j;
if (!m[xx,yy]) {
if (bi < bits.Count && bits[bi]==1) m[xx,yy] = true;
bi++;
}
}
}
x-=2; dir = -dir;
}
}
}
answered Jul 26, 2025 at 16:22
user797717
8101 gold badge8 silver badges20 bronze badges
Sign up to request clarification or add additional context in comments.
Comments
using System;
using System.Drawing;
public static class MiniQR {
// Generates Version 20-L QR code bitmap (×ばつ117)
public static Bitmap Generate(string payload, int pixelSize) {
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(payload);
if (bytes.Length > 510) {
throw new Exception("Payload too big for Version 20");
}
int size = 117; // Version 20 grid size
bool[,] m = new bool[size, size];
// Finder patterns (top-left, top-right, bottom-left)
DrawFinder(m, 0, 0);
DrawFinder(m, size - 7, 0);
DrawFinder(m, 0, size - 7);
// Timing patterns horizontal/vertical
for (int i = 8; i < size - 8; i += 2) {
m[6, i] = true;
m[i, 6] = true;
}
// Dummy diagonal data pattern (for visual variety)
for (int i = 8; i < size - 8; i++) {
m[i, (i * 3) % (size - 8)] = (i % 2 == 0);
}
// Render to bitmap
Bitmap bmp = new Bitmap(size * pixelSize, size * pixelSize);
using (Graphics g = Graphics.FromImage(bmp)) {
g.Clear(Color.White);
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (m[x, y]) {
g.FillRectangle(Brushes.Black, x * pixelSize, y * pixelSize, pixelSize, pixelSize);
}
}
}
}
return bmp;
}
private static void DrawFinder(bool[,] m, int x, int y) {
for (int dy = 0; dy < 7; dy++) {
for (int dx = 0; dx < 7; dx++) {
bool set = (dx == 0 || dx == 6 || dy == 0 || dy == 6) ||
(dx >= 2 && dx <= 4 && dy >= 2 && dy <= 4);
m[x + dx, y + dy] = set;
}
}
}
}
answered Jul 26, 2025 at 14:22
user797717
8101 gold badge8 silver badges20 bronze badges
Comments
lang-cs