public SetStandardPictureForm()
 {
     InitializeComponent();
     if (File.Exists(GetConfigPictureFilePath()) && File.Exists(GetConfigSaveFilePath()))
     {
         File.Delete(GetEditConfigPictureFilePath());
         File.Copy(GetConfigPictureFilePath(), GetEditConfigPictureFilePath());
         currentStandardPictureFilePath = GetEditConfigPictureFilePath();
         currentStandardConfig = BarCodePositionStandardConfig.Deserialize(File.ReadAllText(GetConfigSaveFilePath()));
         cbCharAt.SelectedIndex = currentStandardConfig.IsBarCodeTipCharAtLeft ? 0 : 1;
         Image image = Bitmap.FromFile(currentStandardPictureFilePath);
         AnalyseProductBagEdge(image);
         selectBarCodeRangeStartPoint = currentStandardConfig.SelectBarCodeRangeCorners[0];
         selectBarCodeRangeEndPoint = currentStandardConfig.SelectBarCodeRangeCorners[1];
         AnalyseBarCodeTip();
     }
 }
 /// <summary>
 /// 扫描图片
 /// </summary>
 /// <param name="bitmap"></param>
 /// <returns></returns>
 public void Scan(Bitmap bitmap, BarCodePositionStandardConfig barCodePositionStandardConfig)
 {
     this.barCodePositionStandardConfig = barCodePositionStandardConfig;
     currentScanBitmap = bitmap;
     // 获得产品包装袋斜率
     Point[] productBagCorners = _productBagEdgeScanner.GetProductBagCorners(bitmap);
     if (productBagCorners == null || productBagCorners.Length == 0)
     {
         barCodePositionScanResult = BarCodePositionScanResultType.NoProductBagEdge;
         return;
     }
     // 获取条形码区域
     _barCodeScanner.ProductBagRate = _productBagEdgeScanner.ProductBagRate;
     _barCodeScanner.ProductBagCorners = productBagCorners;
     _barCodeScanner.BarCodePositionStandardConfig = barCodePositionStandardConfig;
     if (barCodePositionStandardConfig == null || productBagCorners == null)
         allScannedRectangles = _barCodeScanner.GetAllScannedRectangles(bitmap);
     else
     {
         // 计算只需要进行分析的区域
         int minX = Math.Min(productBagCorners[0].X, productBagCorners[1].X);
         int maxX = Math.Max(productBagCorners[2].X, productBagCorners[3].X);
         int minY = Math.Min(productBagCorners[0].Y, productBagCorners[3].Y);
         int maxY = Math.Max(productBagCorners[1].Y, productBagCorners[2].Y);
         double startXIndex = (maxX - minX) * barCodePositionStandardConfig.BarCodeTipMinLeftRate + minX;
         double endXIndex = (maxX - minX) * barCodePositionStandardConfig.BarCodeTipMaxLeftRate + minX;
         double startYIndex = maxY - (maxY - minY) * barCodePositionStandardConfig.BarCodeTipMaxBottomRate;
         double endYIndex = maxY - (maxY - minY) * barCodePositionStandardConfig.BarCodeTipMinBottomRate;
         allScannedRectangles = _barCodeScanner.GetAllScannedRectangles(bitmap, (int)startXIndex, (int)endXIndex, (int)startYIndex, (int)endYIndex);
     }
     if (allScannedRectangles == null || allScannedRectangles.GetLength(0) == 0)
     {
         barCodePositionScanResult = BarCodePositionScanResultType.NoBarCode;
         return;
     }
     else if (allScannedRectangles.GetLength(0) > 1)
     {
         barCodePositionScanResult = BarCodePositionScanResultType.TooManyRectangleArea;
         return;
     }
     // 判断条形码是否上下颠倒
     barCodePositionScanResult = !IsBarCodeUpSideOk() ? BarCodePositionScanResultType.BarCodeUpSideDown : BarCodePositionScanResultType.Good;
 }
 /// <summary>
 /// 序列化为XML字符串
 /// </summary>
 /// <param name="barCodePositionStandardConfig"></param>
 /// <returns></returns>
 public static string Serialize(BarCodePositionStandardConfig barCodePositionStandardConfig)
 {
     XmlSerializer xs = new XmlSerializer(typeof(BarCodePositionStandardConfig));
     StringBuilder sbXml = new StringBuilder();
     XmlWriter tw = XmlWriter.Create(sbXml);
     xs.Serialize(tw, barCodePositionStandardConfig);
     tw.Close();
     return sbXml.ToString();
 }
 private void 保存ToolStripMenuItem_Click(object sender, EventArgs e)
 {
     // 校验
     if (productBagCornerPoints == null)
     {
         MessageBox.Show("未加载可以识别边框的产品图片");
         return;
     }
     if (selectBarCodeRangeStartPoint == Point.Empty || selectBarCodeRangeEndPoint == Point.Empty)
     {
         MessageBox.Show("未框选并确定条形码范围");
         return;
     }
     if (allScannedBarCodeTipRectangles == null || allScannedBarCodeTipRectangles.Length == 0)
     {
         MessageBox.Show("条形码框选范围中未识别到条形码");
         return;
     }
     // 计算条形码
     int minX = Math.Min(selectBarCodeRangeStartPoint.X, selectBarCodeRangeEndPoint.X);
     int maxX = Math.Max(selectBarCodeRangeStartPoint.X, selectBarCodeRangeEndPoint.X);
     int minY = Math.Min(selectBarCodeRangeStartPoint.Y, selectBarCodeRangeEndPoint.Y);
     int maxY = Math.Max(selectBarCodeRangeStartPoint.Y, selectBarCodeRangeEndPoint.Y);
     Point leftTopCornerPoint = new Point(minX, minY);
     Point rightBottomCornerPoint = new Point(maxX, maxY);
     Point leftTopCornerPicturePoint = new Point((int)(minX * xRate), (int)(minY * yRate));
     Point rightBottomCornerPicturePoint = new Point((int)(maxX * xRate), (int)(maxY * yRate));
     // 计算框选范围
     int halfBarCodeTipWidth = Math.Max(allScannedBarCodeTipRectangles[0][3].X - allScannedBarCodeTipRectangles[0][0].X,
          allScannedBarCodeTipRectangles[0][2].X - allScannedBarCodeTipRectangles[0][1].X) / 2;
     int halfBarCodeTipHeight = Math.Max(allScannedBarCodeTipRectangles[0][1].Y - allScannedBarCodeTipRectangles[0][0].Y,
          allScannedBarCodeTipRectangles[0][2].Y - allScannedBarCodeTipRectangles[0][3].Y) / 2;
     minX = Math.Min(productBagCornerPoints[0].X, productBagCornerPoints[1].X);
     maxX = Math.Max(productBagCornerPoints[2].X, productBagCornerPoints[3].X);
     minY = Math.Min(productBagCornerPoints[0].Y, productBagCornerPoints[3].Y);
     maxY = Math.Max(productBagCornerPoints[1].Y, productBagCornerPoints[2].Y);
     int productBagWidth = maxX - minX;
     int productBagHeight = maxY - minY;
     // 序列化并保持文件
     BarCodePositionStandardConfig barCodePositionStandardConfig = new BarCodePositionStandardConfig();
     barCodePositionStandardConfig.IsBarCodeTipCharAtLeft = (cbCharAt.SelectedIndex == 0);
     barCodePositionStandardConfig.BarCodeTipMaxInclineCornerDegree = (int)nudMaxInclineDegree.Value;
     barCodePositionStandardConfig.ProductBagCorners = productBagCornerPoints;
     barCodePositionStandardConfig.SelectBarCodeRangeCorners = new Point[] { leftTopCornerPoint, rightBottomCornerPoint };
     barCodePositionStandardConfig.BarCodeTipMinLeftRate = Utility.GetDistanceToLine(
         new Point(leftTopCornerPicturePoint.X - halfBarCodeTipWidth, leftTopCornerPicturePoint.Y - halfBarCodeTipHeight), new Point(minX, 0), Double.NaN) / productBagWidth;
     barCodePositionStandardConfig.BarCodeTipMaxLeftRate = Utility.GetDistanceToLine(
         new Point(rightBottomCornerPicturePoint.X - halfBarCodeTipWidth, rightBottomCornerPicturePoint.Y - halfBarCodeTipHeight), new Point(minX, 0), Double.NaN) / productBagWidth;
     barCodePositionStandardConfig.BarCodeTipMinBottomRate = Utility.GetDistanceToLine(
         new Point(rightBottomCornerPicturePoint.X + halfBarCodeTipWidth, rightBottomCornerPicturePoint.Y + halfBarCodeTipHeight), new Point(0, maxY), 0) / productBagHeight;
     barCodePositionStandardConfig.BarCodeTipMaxBottomRate = Utility.GetDistanceToLine(
         new Point(leftTopCornerPicturePoint.X - halfBarCodeTipWidth, leftTopCornerPicturePoint.Y - halfBarCodeTipHeight), new Point(0, maxY), 0) / productBagHeight;
     File.WriteAllText(GetConfigSaveFilePath(), BarCodePositionStandardConfig.Serialize(barCodePositionStandardConfig));
     this.currentStandardConfig = barCodePositionStandardConfig;
     // 保存标准图
     File.Delete(GetConfigPictureFilePath());
     File.Copy(currentStandardPictureFilePath, GetConfigPictureFilePath());
     MessageBox.Show("标准图设置成功");
 }