/// <summary>
        /// Найти штрихкод code128 и его ограничивающий п/у
        /// </summary>
        /// <param name="fileName">Имя файла с картинкой png, jpeg</param>
        public static BarcodeResult ScanCode128(Image img, string debugFileName = null)
        {
            BarcodeResult barcodeResult = null;

            Bitmap bmp = new Bitmap(img);

            // create a barcode reader instance
            var reader = new BarcodeReader();

            reader.Options.ReturnCodabarStartEnd = true;
            reader.Options.TryHarder             = true;
            reader.Options.PossibleFormats       = new BarcodeFormat[] { BarcodeFormat.CODE_128 };
            reader.AutoRotate = true;

            // Сейчас код ищет только один штрихкод.
            // Найти несколько штрихкодов можно с помощью метода DecodeMultiple, но по умолчанию возвращаются только разные штрихкоды.
            // Если мы хотим получить положение одного и того же штрихкода вставленного несколько раз, то нужно будет переписывать метод DecodeMultiple.
            // Есть ещё проблема с разноповернутыми штрихкодами если их несколько, то распознаются только однонаправленные,
            // возможно стоит вручную поворачивать и перезапускать алгоритм.
            //
            int scannerOrientation = 0;
            var result             = reader.Decode(bmp);

            if (result != null)
            {
                barcodeResult      = new BarcodeResult();
                barcodeResult.Code = result.Text;
                barcodeResult.Type = BarcodeType.ToString(result.BarcodeFormat);
                try
                {
                    var orient = result.ResultMetadata[ResultMetadataType.ORIENTATION];
                    scannerOrientation = (int)orient; // only vertical/horizontal
                }
                catch (Exception /*ex*/)
                {
                }

                if (result.ResultPoints.Length >= 2)
                {
                    //
                    var luminanceSource = new ZXing.BitmapLuminanceSource(bmp);
                    var binarizer       = new ZXing.Common.HybridBinarizer(luminanceSource);
                    var bitMatrix       = binarizer.BlackMatrix;

                    // result.ResultPoints - точкии линии сканера, для которой был распознан штрих код
                    // для barcode128 эти точки находятся внутри штрихкода видимо за start и stop элементами.
                    // нам нужно получить по этим точкам ограничивающий п/у для всего штрихкода
                    // но это точки в координатах повернутого листа на scannerOrientation градусов,
                    // поэтому преобразуем их в начальную и конечную координату сканера в координатак картинки img
                    Point[] scanLine = GetScanLine(result.ResultPoints, scannerOrientation, img.Width, img.Height, bitMatrix);

                    // Возьмем конечную точку скан линии
                    int x = scanLine[1].X;
                    int y = scanLine[1].Y;

                    // Вычислим магический белый квадрат - предположительное место штрихкода.
                    // Искать будет с точки x,y, возвращает 4 точки, типа ограничивающего штрих код белую п/у.
                    // Использующийся алгоритм не до конца понятен, возвращает п/у содержащий одну, несколько полосок, или весь штрих код.
                    // Поэтому единственная полезная информация которая может быть извлечена высота штрихкода (координаты одной вертикальной полосы)
                    var whiterectDetector = ZXing.Common.Detector.WhiteRectangleDetector.Create(bitMatrix, 1, x, y);
                    var whiteRect         = whiterectDetector.detect();
                    if (whiteRect == null)
                    {
                        return(barcodeResult);                   // не удалось вычислить ограничивающий п/у.
                    }
                    // Посчитаем длину первой черной полоски после правой конечной точки scan линии.
                    int blackLineWidth = CalcBlackLineWidth(bitMatrix, scanLine);

                    // Вычислим по имеющимся данным ограничивающий п/у для штрихкода
                    int           dx          = blackLineWidth * 3; // 3 полоски по бокам добавим (для 128 баркода)
                    ResultPoint[] barcodeRect = GetBarCodeRect(scanLine, whiteRect, dx);

                    // Вычислим п/у для создания штрихкода и его ориентацию(поворот).
                    // (п/у без поворота, от левой нижней точки и его угол поворота в градусах)
                    //barcodeResult.Left = (int)barcodeRect[1].X;
                    //barcodeResult.Bottom = (int)barcodeRect[1].Y;
                    //barcodeResult.Right = barcodeResult.Left + (int)ResultPoint.distance(barcodeRect[0], barcodeRect[2]);
                    //barcodeResult.Top = barcodeResult.Bottom - (int)ResultPoint.distance(barcodeRect[0], barcodeRect[1]);
                    barcodeResult.Left   = (int)barcodeRect[0].X;
                    barcodeResult.Top    = (int)barcodeRect[0].Y;
                    barcodeResult.Right  = barcodeResult.Left + (int)ResultPoint.distance(barcodeRect[0], barcodeRect[2]);
                    barcodeResult.Bottom = barcodeResult.Top + (int)ResultPoint.distance(barcodeRect[0], barcodeRect[1]);

                    /*                    }
                     *                                      else if (scannerOrientation == 180)
                     *                                      {
                     *                                          barcodeResult.Left = (int)barcodeRect[0].X;
                     *                                          barcodeResult.Bottom = (int)barcodeRect[0].Y;
                     *                                          barcodeResult.Right = barcodeResult.Left + (int)ResultPoint.distance(barcodeRect[0], barcodeRect[2]);
                     *                                          barcodeResult.Top = barcodeResult.Bottom - (int)ResultPoint.distance(barcodeRect[0], barcodeRect[1]);
                     *                                      }*/

                    //barcodeResult.Orientation = -Orientation(barcodeRect[0], barcodeRect[2]);
                    barcodeResult.Orientation = Orientation(barcodeRect[0], barcodeRect[2]);

                    if (!string.IsNullOrEmpty(debugFileName))
                    {
                        // Закрасим область белым, чтобы можно было ещё искать barcode
                        var g = Graphics.FromImage(img);
                        g.FillPolygon(new SolidBrush(Color.Pink), ToDrawingRect(barcodeRect));

                        DebugSaveImage(debugFileName,
                                       img,
                                       barcodeRect,
                                       whiteRect,
                                       scanLine);
                    }
                }
            }
            return(barcodeResult);
        }
Example #2
0
        static public bool ReplaceBarcode128(string input, string output, int page, string sourceCode, string newCode, bool displayText, int maxBarCodeCount = 5)
        {
            float scale = 3;
            float dpi   = 300;

            bool barCodeFinded = false;

            Barcode       barcodeNew = CreateBarcode(BarcodeType.Code128, newCode, displayText);
            BarcodeResult barcode    = null;

            using (var fs = new FileStream(output, FileMode.Create))
                using (var pdfReader = new iTextSharp.text.pdf.PdfReader(input))
                    using (var document = PdfiumViewer.PdfDocument.Load(input))
                    {
                        PdfStamper stamper = new PdfStamper(pdfReader, fs);

                        var           info  = document.GetInformation();
                        IList <SizeF> sizes = document.PageSizes;

                        // Если задана страница, то только в нёё вставим штрихкод, если не задана, то для всех страниц документа
                        int count;
                        if (page <= 0)
                        {
                            page  = 0;
                            count = document.PageCount;
                        }
                        else
                        {
                            // В Pdfium нумерация с 0-ля, а у нас приходит с 1-цы.
                            count = page;
                            page -= 1;
                        }
                        for (; page < count; page++)
                        {
                            int imageWidth           = (int)(sizes[page].Width * scale);
                            int imageHeight          = (int)(sizes[page].Height * scale);
                            System.Drawing.Image img = document.Render(page, imageWidth, imageHeight, dpi, dpi, PdfiumViewer.PdfRenderFlags.Grayscale);

                            for (int i = 0; i < maxBarCodeCount; i++)
                            {
                                barcode = BarcodeOperations.ScanCode128(img, input + ".png");
                                if (barcode != null)
                                {
                                    barCodeFinded = true;
                                    if (barcode.Code == sourceCode)
                                    {
                                        float offsetX       = barcode.Left / scale;
                                        float offsetY       = barcode.Top / scale;
                                        float width         = (barcode.Right - barcode.Left) / scale;
                                        float rotateDegrees = barcode.Orientation;

                                        // Преобразуем к 0-360 и уберем минимальные отклонения
                                        // if (rotateDegrees < 0) rotateDegrees += 360;
                                        // else if (rotateDegrees >= 360) rotateDegrees -= 360;
                                        // if (Math.Abs(rotateDegrees - 0) <= 4) rotateDegrees = 0;
                                        // if (Math.Abs(rotateDegrees - 90) <= 4) rotateDegrees = 90;
                                        // if (Math.Abs(rotateDegrees - 180) <= 4) rotateDegrees = 180;
                                        // if (Math.Abs(rotateDegrees - 270) <= 4) rotateDegrees = 270;

                                        iTextSharp.text.Rectangle pagesize = pdfReader.GetPageSizeWithRotation(page + 1);

                                        // Поскольку ось координат Y для img,bmp сверху вниз направлена и начало в верхнем левом угле,
                                        // а в pdf снизу вверх и в нижним левом угле, то преобразуем координаты
                                        offsetY       = pagesize.Height - offsetY;
                                        rotateDegrees = -rotateDegrees;

                                        PdfOperations.PlaceBarcode(stamper, barcodeNew, page + 1, offsetX, offsetY, width, rotateDegrees);
                                    }
                                    else
                                    {
                                        Console.WriteLine(BARCODE_DIFFERENT_FOUND + barcode.Code);
                                    }
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                        stamper.Close();
                    }

            return(barCodeFinded);
        }