/// <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); }
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); }