Giter Club home page Giter Club logo

Comments (6)

micjahn avatar micjahn commented on July 20, 2024

There is no trick and there is no implementation.
And, as far as I know, it isn't that easy. You do not only have to replace the FNC1 character, you also need to know the structure of the code. There are fixed length and variable length elements which depend on the used identifiers.

You can write a wrapper around the Renderer class which replaces the FNC1 elements and adds the brackets before generating the image.

      private class GS1Renderer : BitmapRenderer
      {
         public override Bitmap Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options)
         {
            // modify the content before rendering the image
            // it doesn't change the bitmatrix, it's only for the text beneath the code
            // following replace is only a sample
            // add a more complex algorithm here
            content = content.Replace($"{(char)0x00F1}", "(");

            // call the base class to render the barcode image
            return base.Render(matrix, format, content, options);
         }
      }

and use it with the BarcodeWriter

         var writer = new BarcodeWriter
         {
            Format = BarcodeFormat.CODE_128,
            Renderer = new GS1Renderer()
         };
         var barcodeImage = writer.Write($"{(char)0x00F1}0123454689");

from zxing.net.

wgrudda avatar wgrudda commented on July 20, 2024

okay, I try it later.
Is it right, that the content is Change before the Barcode is rendered?
The Barcode must have the FNC1-char, but the text under the Barcode must human-readable.
So when I change it before rendering, than I change the Barcode too.

from zxing.net.

micjahn avatar micjahn commented on July 20, 2024

What do you mean with "Didn't work for me."?
As I said before if you modify the content parameter in the method "Render" than only the readable text will be modified. The barcode contains the original, unmodified content.

from zxing.net.

micjahn avatar micjahn commented on July 20, 2024

Does it work now?

from zxing.net.

xrisdoc avatar xrisdoc commented on July 20, 2024

I too have just encountered this issue and the suggestion made by @micjahn to write a wrapper around the Render method of the BitmapRenderer class put me on the right track to come up with a solution for what I was wanting to achieve.

I thought I would document this here, in the hope that this will also help others that find themselves facing this issue or similar.

This basically expands on the content.Replace($"{(char)0x00F1}", "("); code that @micjahn used in his example. It seems it's easy enough to get the first ( in place, but trying to figure out where to put the closing ) seemed to be a bit more complicated.

In my case, I was trying to create Barcode images (on the fly) and serve them up via HTTP. The data for the barcode is supplied through a querystring parameter named data along with other parameters, which is used to generate the relevant barcode image.

The problem I faced here was trying to identify where the separation of items should occur within the value supplied through data.

So, within the data string value, I am separating each item with a hyphen - or dot/period ..

  • Occurrences of the - character indicate where a field separator should be inserted
  • Occurrences of the . character indicate a separation of fields but does NOT require a field separator to be inserted.

An example of the URL I would call to generate a barcode image and serve back to the browser:

http://mysite.com/Barcode/?data=0200000000000023.11171115.3700456000-10664202&type=code128&margin=70

This results in the following barcode:

(02)00000000000023 (11)171115 (37)00456000 (10)664202

I created an MVC application and created a controller and action to handle this as well as a custom renderer class GS1Renderer to handle the generation of the barcode number that is placed at the bottom of the image.

The code for this is provided below:

    public class BarcodeController : Controller
    {
        /// <summary>
        /// Generates a barcode and returns it to the browser as a PNG image
        /// </summary>
        /// <param name="data">The data that is to be used on the barcode</param>
        /// <param name="width">The width that is to be used when generating the barcode</param>
        /// <param name="height">The height that is to be used when generating the barcode</param>
        /// <param name="margin">The size that is to be set around the barcode</param>
        /// <param name="type">Specifies the type of barcode that is to be generated</param>
        /// <returns>A byte array that will be streamed to the browser</returns>
        [HttpGet]
        public ActionResult Index(string data, int width = 200, int height = 200, int margin = 0, string type = "qr")
        {
            // Defne a byte array.
            // This is the varaible that we will use to return the data back to the browser.
            byte[] fileContent;

            // Set the options that we will use for creatung the barcode
            var options = new QrCodeEncodingOptions
            {
                Width = width,
                Height = height,
                Margin = margin
            };

            // We need to to determine what format the barcode is to be.
            // This will default to the QR Code format
            var format = BarcodeFormat.QR_CODE;
            switch (type.ToLower())
            {
                case "qr":
                    format = BarcodeFormat.QR_CODE;
                    break;

                case "code128":
                    format = BarcodeFormat.CODE_128;
                    break;

                default:
                    format = BarcodeFormat.QR_CODE;
                    break;
            }

            // Create an istance of the BarcodeWriter, setting the relevant Options and Format
            var bw = new BarcodeWriter { Format = format, Options = options };

            // If the type of barcode being rendered is GS1-128,
            // Then assign an instance of GS1Renderer to the Renderer property.
            // This will allow us to perform custom logic just before the barcode image is generated.
            if (type.ToLower() == "code128")
            {
                bw.Renderer = new GS1Renderer();
                ((GS1Renderer)bw.Renderer).SetFriendlyContent(data);

                char fnc1 = (char)0x00F1;
                data = $"{fnc1}{data}";

                // NOTE:
                //  - Occurrences of the '-' character indicate where a field separtor should be inserted
                //  - Occurrences of the '.' character indicate a separation of fields but does NOT require a field separator to be inserted

                data = data.Replace("-", $"{fnc1}");
                data = data.Replace(".", "");
            }

            // Create the relevant Barcode as a Bitmap
            // We will use this later to convert it to a PNG file.
            var bitmapBarcode = bw.Write(data);

            // Create a MemoryStream and save the bitmap to it using the PNG format.
            // then get the Byte array from the stream, as this is the data we want to send back to the browser.
            using (var ms = new MemoryStream())
            {
                bitmapBarcode.Save(ms, ImageFormat.Png);
                fileContent = ms.ToArray();
            }
            
            // Send the Byte array back to the browser.
            // This will serve the barcode up as a PNG image.
            return File(fileContent, "image/png");
        }
    }

The code for the Custom Renderer class is provided below:

    public class GS1Renderer : BitmapRenderer
    {
        /// <summary>
        /// Will contain a value used for number at the bottom of the barcode image
        /// </summary>
        private string _friendlyContent;

        public override Bitmap Render(BitMatrix matrix, BarcodeFormat format, string content, EncodingOptions options)
        {
            // If the _friendlyContent has been set, then we will use this value for the content.
            // Otherwise, we will just use the original content.
            content = (!string.IsNullOrWhiteSpace(_friendlyContent)) ? _friendlyContent : content;

            // Call the base class to render the barcode image
            return base.Render(matrix, format, content, options);
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data">The data content that is to be modified to be in a more user friendly and readable format</param>
        public void SetFriendlyContent(string data)
        {
            string newContent = string.Empty;

            // Define a list of Application Identifier Values.
            // We will use this list to identify strings that contain data for the relevant Application Identifiers.
            List<string> appIds = new List<string> { "00", "02", "11", "10", "37" };

            // TODO:
            // Add the relevant Application Identifier Values to the appIds list as required

            // Split the data string at each occurrence of the '-' and '.' characters.
            // This should give us a list of strings, each one representing data relating to a specific Application Identifier.
            var barcodeItems = data.Split(new char[] { '-' , '.' }, StringSplitOptions.RemoveEmptyEntries).ToList();

            if(barcodeItems != null & barcodeItems.Any())
            {
                // Loop through each of the items and check if it starts with one of the Application Identifiers in out list.
                // If it does, then we will extract the relevant data value from the item.
                // We will use the extracted data to bulid a string for the current item to be in a more readable format that clearly separates Application Identifier and it's assiciated data.
                // e.g. (11)171115
                foreach (var item in barcodeItems)
                {
                    appIds.ForEach(id =>
                    {
                        if (item.StartsWith(id))
                        {
                            string itemValue = item.Substring(id.Length);
                            newContent += $"({id}){itemValue}";
                        }
                    });
                }
            }

            // Only assign a value to _friendlyContent if the newContent has been set.
            if (!string.IsNullOrWhiteSpace(newContent))
            {
                _friendlyContent = newContent;
            }
        }
    }

from zxing.net.

micjahn avatar micjahn commented on July 20, 2024

Thanks for sharing your solution.

from zxing.net.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.