Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Latin-1 in BARCODE-128 #559

Open
iakovmarkov opened this issue Mar 22, 2024 · 4 comments
Open

Support for Latin-1 in BARCODE-128 #559

iakovmarkov opened this issue Mar 22, 2024 · 4 comments

Comments

@iakovmarkov
Copy link

Hello,

we've been using this library to create barcodes in our project. It works well, but we've stumbled upon one limitation - the library explicitly does not support full Latin-1 charset. Some of our clients in scnadinavia use the special characters, and our app can't give them a nice PDF with a readable barcode.

Are there plans to add support for full Latin-1 charset? Maybe there is a workaround we can use?

Appreciate your answer and your work on the library!

@micjahn
Copy link
Owner

micjahn commented Apr 2, 2024

Can you please post a code snippet which shows how you generate the code?

@iakovmarkov
Copy link
Author

Sure thing. This is the whole method that receives user input and returns a byte array with the barcode:

    private static byte[] GetBarCode(string contents)
    {
        byte[] byteArray;
        var codeWriter = new ZXing.BarcodeWriterPixelData
        {
            Format = ZXing.BarcodeFormat.CODE_128,
            Options = new QrCodeEncodingOptions
            {
                Width = 140,
                Height = 40,
                Margin = 0,
                NoPadding = true
            }
        };

        var pixelData = codeWriter.Write(contents);
        var bitmap = new SKBitmap();
        var gcHandle = GCHandle.Alloc(pixelData.Pixels, GCHandleType.Pinned);
        var info = new SKImageInfo(pixelData.Width, pixelData.Height, SKImageInfo.PlatformColorType, SKAlphaType.Unpremul);
        bitmap.InstallPixels(info, gcHandle.AddrOfPinnedObject(), info.RowBytes, delegate { gcHandle.Free(); }, null);

        using var image = SKImage.FromBitmap(bitmap);
        using var data = image.Encode(SKEncodedImageFormat.Png, 100);
        using var writeStream = new MemoryStream();
        data.SaveTo(writeStream);
        byteArray = writeStream.ToArray();

        return byteArray;
    }

@micjahn
Copy link
Owner

micjahn commented Apr 5, 2024

At the moment ZXing.Net doesn't support Latin-1 without manually switching to the FNC4 mode. I fear I will not find enough free time to add that function.
That means you can only use the following "hack". I tested the code only with the german characters 'ä' and 'Ä'.
Perhaps it doesn't work for all Latin-1 characters. ZXing.Net decodes it successfully. But be aware of the perhaps not all readers support FNC4.

        private static byte[] GetBarCode(string contents)
        {
            byte[] byteArray;
            var codeWriter = new ZXing.BarcodeWriterPixelData
            {
                Format = ZXing.BarcodeFormat.CODE_128,
                Options = new ZXing.OneD.Code128EncodingOptions
                {
                    Width = 140,
                    Height = 40,
                    Margin = 0,
                    NoPadding = true
                },
                Renderer = new PixelDataRendererWrapper()
            };
        
            var pixelData = codeWriter.Write(AddFNC4(contents));
            var bitmap = new SKBitmap();
            var gcHandle = GCHandle.Alloc(pixelData.Pixels, GCHandleType.Pinned);
            var info = new SKImageInfo(pixelData.Width, pixelData.Height, SKImageInfo.PlatformColorType, SKAlphaType.Unpremul);
            bitmap.InstallPixels(info, gcHandle.AddrOfPinnedObject(), info.RowBytes, delegate { gcHandle.Free(); }, null);
        
            using var image = SKImage.FromBitmap(bitmap);
            using var data = image.Encode(SKEncodedImageFormat.Png, 100);
            using var writeStream = new MemoryStream();
            data.SaveTo(writeStream);
            byteArray = writeStream.ToArray();
        
            return byteArray;
        }

        private string AddFNC4(string content)
        {
            // zxing doesn't add the FNC4 automatically at the moment
            // it has to be added manually
            var builder = new System.Text.StringBuilder(content.Length);
            foreach (var ch in content)
            {
                if (ch > 128)
                {
                    builder.Append('\u00f4');
                    builder.Append((char)(ch - 128));
                }
                else
                {
                    builder.Append(ch);
                }
            }
            return builder.ToString();
        }

        public class PixelDataRendererWrapper : ZXing.Rendering.IBarcodeRenderer<ZXing.Rendering.PixelData>
        {
            private ZXing.Rendering.PixelDataRenderer renderer = new ZXing.Rendering.PixelDataRenderer();

            public PixelData Render(BitMatrix matrix, BarcodeFormat format, string content)
            {
                return renderer.Render(matrix, format, ReplaceFNC4(content));
            }

            public PixelData Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options)
            {
                return renderer.Render(matrix, format, ReplaceFNC4(content), options);
            }

            private string ReplaceFNC4(string content)
            {
                var builder = new System.Text.StringBuilder(content.Length);
                var fnc4Found = false;
                foreach (var ch in content)
                {
                    if (ch == '\u00f4')
                        fnc4Found = true;
                    else
                    {
                        if (fnc4Found)
                        {
                            builder.Append((char)(ch + 128));
                            fnc4Found = false;
                        }
                        else
                        {
                            builder.Append(ch);
                        }
                    }
                }
                return builder.ToString();
            }
        }

@iakovmarkov
Copy link
Author

Thanks a lot @micjahn, appreciate your workaround! It'll help us a lot. I suppose you can close this issue if you think it's appropriate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants