Tuesday, 20 September 2016

Generating 2D Barcodes in C#

Simplified example using ImageProcessorCore and ZXing for .NET Core.

Using StringRenderer will produce a string using the relevant symbols provided and ImageRenderer will return an ImageProcessorCore image.

Gist available at https://gist.github.com/BravoTango86/ca613445c740098e349caf5943b36abb

/*
 * Copyright (C) 2016 BravoTango86
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using ImageProcessorCore;
using System.Text;
using ZXing;
using ZXing.Common;
using ZXing.Rendering;

public class BarcodeGenerator {

    public static T Generate<T>(IBarcodeRenderer<T> renderer, string content, EncodingOptions options,
                                        BarcodeFormat format = BarcodeFormat.QR_CODE) =>
        new ZXing.BarcodeWriterGeneric<T> { Format = format, Options = options, Renderer = renderer }.Write(content);

    public class StringRenderer : IBarcodeRenderer<string> {

        public string Block { get; set; }
        public string Empty { get; set; }
        public string NewLine { get; set; }

        public string Render(BitMatrix matrix, BarcodeFormat format, string content) => Render(matrix, format, content, null);

        public string Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options) {
            StringBuilder SB = new StringBuilder();
            for (int Y = 0; Y < matrix.Height; Y++) {
                if (Y > 0) SB.Append(NewLine);
                for (int X = 0; X < matrix.Width; X++) SB.Append(matrix[X, Y] ? Block : Empty);
            }
            return SB.ToString();
        }
    }

    public class ImageRenderer : IBarcodeRenderer<Image> {

        public Color Background { get; set; } = Color.White;
        public Color Foreground { get; set; } = Color.Black;

        public Image Render(BitMatrix matrix, BarcodeFormat format, string content) => Render(matrix, format, content, null);

        public Image Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options) {
            Image Image = new Image(matrix.Width, matrix.Height);
            using (IPixelAccessor<Color, uint> Lock = Image.Lock()) {
                for (int Y = 0; Y < matrix.Height; Y++) {
                    for (int X = 0; X < matrix.Width; X++) Lock[X, Y] = matrix[X, Y] ? Foreground : Background;
                }
            }
            return Image;
        }
    }

}

StringRenderer works quite nicely with the console...

public static void Main(string[] args) {
    Console.OutputEncoding = Encoding.UTF8;
    Console.WindowWidth = 55;
    Console.WindowHeight = 28;
    StringRenderer Renderer = new StringRenderer() {  Block = "  ", Empty = "\u2588\u2588", NewLine = "\n    ", };
    EncodingOptions Options = new EncodingOptions { Height = 0, Width = 0, Margin = 1 };
    while (true) {
        string Text = DateTime.Now.ToString();
        Console.WriteLine("\n{2}{0}{2}{1}{2}", Generate(Renderer, Text, Options), Text, Renderer.NewLine);
        if (Console.ReadKey().Key == ConsoleKey.Escape) break;
    }
}

...producing this:

No comments:

Post a Comment