using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Media;
using System.Threading.Tasks;
using System.Windows.Forms;
using AForge.Video.DirectShow;
using TableMagic.Properties;
using ZXing;
using ZXing.Common;
using Excel = Microsoft.Office.Interop.Excel;
namespace TableMagic
{
public partial class Form5 : Form
{
DataTable dt = new DataTable();
public Form5()
{
InitializeComponent();
picture_radioButton.Checked = true;
folder_path_label.Text = string.Empty;
dt.Columns.Add("fold_path", typeof(string));
dt.Columns.Add("file_name", typeof(string));
dt.Columns.Add("qr_sequence", typeof(string));
dt.Columns.Add("qr_content", typeof(string));
videoSourcePlayer1.Paint += videoSourcePlayer1_Paint;
}
private void quit_button_Click(object sender, EventArgs e)
{
this.Close();
}
List<string> files_fullname = new List<string>();
private int currentCameraIndex = 0;
private FilterInfoCollection videoDevices;
private List<Rectangle> qrRectangles = new List<Rectangle>();
private Pen qrBoxPen = new Pen(Color.LimeGreen, 3);
private int frameWidth = 0;
private int frameHeight = 0;
private VideoCaptureDevice videoDevice;
private bool isProcessing = false;
private Bitmap frame;
private readonly object _lockObject = new object();
private void switchCamera_button_Click(object sender, EventArgs e)
{
if (videoDevices == null || videoDevices.Count < 2) return;
if (videoDevice != null && videoDevice.IsRunning)
{
videoDevice.SignalToStop();
videoDevice.WaitForStop();
}
currentCameraIndex = (currentCameraIndex + 1) % videoDevices.Count;
videoDevice = new VideoCaptureDevice(videoDevices[currentCameraIndex].MonikerString);
videoDevice.VideoResolution = videoDevice.VideoCapabilities[0];
videoSourcePlayer1.VideoSource = videoDevice;
videoDevice.Start();
videoSourcePlayer1.Start();
folder_path_label.Text = $"已切换摄像头: {videoDevices[currentCameraIndex].Name}";
}
private async void scan_button_Click(object sender, EventArgs e)
{
if (picture_radioButton.Checked)
{
openFileDialog1.Filter = "图片文件(*.jpg;*.jpeg;*.png;*.bmp)|*.jpg;*.jpeg;*.png;*.bmp";
openFileDialog1.Title = "请选择包含二维码的图片";
openFileDialog1.Multiselect = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK && openFileDialog1.FileNames.Length > 0)
{
picture_radioButton.Enabled = false;
webcam_radioButton.Enabled = false;
quit_button.Enabled = false;
scan_button.Enabled = false;
files_fullname = openFileDialog1.FileNames.ToList();
string folderPath = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
this.Invoke((MethodInvoker)delegate
{
folder_path_label.Text = $"已选文件夹:{folderPath}。正在读取中......";
});
await Task.Run(() =>
{
foreach (string item in files_fullname)
{
using (Bitmap bitmap = new Bitmap(item))
{
Bitmap gray_bitmap = PreprocessImage(bitmap);
List<string> results = ReadQRCode(gray_bitmap);
if (results != null && results.Count > 0)
{
for (int i = 0; i < results.Count; i++)
{
string[] details = new string[4]
{
Path.GetDirectoryName(item),
Path.GetFileName(item),
(i + 1).ToString(),
results[i]
};
dt.Rows.Add(details);
}
}
}
}
});
this.Invoke((MethodInvoker)delegate
{
folder_path_label.Text = $"读取完成!成功读取{dt.Rows.Count.ToString()}个二维码";
if (dt.Rows.Count > 0)
{
WriteToExcel(dt);
dt.Clear();
}
});
this.Invoke((MethodInvoker)delegate
{
picture_radioButton.Enabled = true;
webcam_radioButton.Enabled = true;
quit_button.Enabled = true;
scan_button.Enabled = true;
});
}
}
else if (webcam_radioButton.Checked)
{
isProcessing = false;
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (videoDevices.Count > 0)
{
switchCamera_button.Visible = videoDevices.Count > 1;
currentCameraIndex = 0;
frame = null;
picture_radioButton.Enabled = false;
webcam_radioButton.Enabled = false;
quit_button.Enabled = false;
scan_button.Enabled = false;
cancel_button.Enabled = true;
folder_path_label.Text = "开始扫描二维码......";
videoDevice = new VideoCaptureDevice(videoDevices[0].MonikerString);
videoDevice.VideoResolution = videoDevice.VideoCapabilities[0];
videoSourcePlayer1.VideoSource = videoDevice;
videoDevice.Start();
videoSourcePlayer1.Start();
timer1.Interval = 100;
timer1.Enabled = true;
}
else
{
MessageBox.Show("未检测到摄像头设备!请使用图片识别方式扫描二维码");
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (isProcessing) return;
isProcessing = true;
Task.Run(() =>
{
frame = videoSourcePlayer1.GetCurrentVideoFrame();
if (frame == null)
{
isProcessing = false;
return;
}
using (Bitmap gray_bitmap = PreprocessImage(frame))
{
List<Rectangle> rects;
List<string> results = ReadQRCode(gray_bitmap, out rects);
this.Invoke((MethodInvoker)delegate
{
qrRectangles = rects;
if (frame != null)
{
frameWidth = frame.Width;
frameHeight = frame.Height;
}
videoSourcePlayer1.Invalidate();
});
if (results != null && results.Count > 0)
{
this.Invoke((MethodInvoker)delegate
{
using (SoundPlayer scan_player = new SoundPlayer(Resources.ScanSound))
{
scan_player.Play();
}
videoDevice.SignalToStop();
videoDevice.WaitForStop();
videoSourcePlayer1.SignalToStop();
videoSourcePlayer1.WaitForStop();
timer1.Enabled = false;
});
foreach (var result in results)
{
lock (_lockObject)
{
string[] details = new string[4]
{
"webcam",
"webcam",
(results.IndexOf(result) + 1).ToString(),
result.ToString()
};
dt.Rows.Add(details);
}
}
if (dt.Rows.Count > 0)
{
WriteToExcel(dt);
dt.Clear();
this.Invoke((MethodInvoker)delegate
{
picture_radioButton.Enabled = true;
webcam_radioButton.Enabled = true;
quit_button.Enabled = true;
scan_button.Enabled = true;
cancel_button.Enabled = false;
folder_path_label.Text = "二维码读取完毕!";
qrRectangles.Clear();
});
}
}
}
isProcessing = false;
});
}
private List<string> ReadQRCode(Bitmap bitmap)
{
List<Rectangle> dummy;
return ReadQRCode(bitmap, out dummy);
}
private List<string> ReadQRCode(Bitmap bitmap, out List<Rectangle> rectangles)
{
rectangles = new List<Rectangle>();
List<string> qrCodeContents = new List<string>();
BarcodeReader reader = new BarcodeReader()
{
Options = new DecodingOptions
{
TryHarder = true,
PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE },
CharacterSet = null
}
};
try
{
var results = reader.DecodeMultiple(bitmap);
if (results == null) return null;
foreach (var result in results)
{
if (result != null && !string.IsNullOrEmpty(result.Text))
{
qrCodeContents.Add(result.Text);
if (result.ResultPoints != null && result.ResultPoints.Length >= 3)
{
float minX = float.MaxValue;
float minY = float.MaxValue;
float maxX = float.MinValue;
float maxY = float.MinValue;
foreach (var point in result.ResultPoints)
{
minX = Math.Min(minX, point.X);
minY = Math.Min(minY, point.Y);
maxX = Math.Max(maxX, point.X);
maxY = Math.Max(maxY, point.Y);
}
rectangles.Add(new Rectangle(
(int)minX, (int)minY,
(int)(maxX - minX), (int)(maxY - minY)));
}
}
}
return qrCodeContents;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}
private void videoSourcePlayer1_Paint(object sender, PaintEventArgs e)
{
if (qrRectangles == null || qrRectangles.Count == 0 || frameWidth == 0 || frameHeight == 0)
return;
float scaleX = (float)videoSourcePlayer1.Width / frameWidth;
float scaleY = (float)videoSourcePlayer1.Height / frameHeight;
foreach (var rect in qrRectangles)
{
Rectangle scaledRect = new Rectangle(
(int)(rect.X * scaleX),
(int)(rect.Y * scaleY),
(int)(rect.Width * scaleX),
(int)(rect.Height * scaleY)
);
e.Graphics.DrawRectangle(qrBoxPen, scaledRect);
using (var brush = new SolidBrush(Color.FromArgb(50, Color.LimeGreen)))
{
e.Graphics.FillRectangle(brush, scaledRect);
}
}
}
private int CountQRCodes(Bitmap bitmap)
{
if (bitmap == null)
{
return -1;
}
try
{
BarcodeReader reader = new BarcodeReader()
{
Options = new DecodingOptions
{
TryHarder = true,
PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE },
CharacterSet = null
}
};
var results = reader.DecodeMultiple(bitmap);
if (results != null && results.Any())
{
foreach (var result in results)
{
if (result != null && !string.IsNullOrEmpty(result.Text))
{
Console.WriteLine(result.Text);
}
}
return results.Count();
}
else
{
return 0;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return -1;
}
}
private bool IsQR(Bitmap bitmap)
{
BarcodeReader reader = new BarcodeReader();
Result result = reader.Decode(bitmap);
if (result != null)
{
Console.WriteLine(result.Text);
return true;
}
else
{
Console.WriteLine("No QR Code Found");
return false;
}
}
private Bitmap PreprocessImage(Bitmap bitmap)
{
Bitmap grayBitmap = new Bitmap(bitmap.Width, bitmap.Height);
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
Color pixel = bitmap.GetPixel(x, y);
int grayValue = (int)(pixel.R * 0.299 + pixel.G * 0.587 + pixel.B * 0.114);
grayBitmap.SetPixel(x, y, Color.FromArgb(grayValue, grayValue, grayValue));
}
}
return grayBitmap;
}
Excel.Workbook workbook = Globals.ThisAddIn.Application.ActiveWorkbook;
private void WriteToExcel(System.Data.DataTable data)
{
ThisAddIn.app.Application.ScreenUpdating = false;
ThisAddIn.app.Application.DisplayAlerts = false;
if (!ThisAddIn.Global.created_qr_sheet)
{
Excel.Worksheet worksheet = workbook.Worksheets.Add(Before: workbook.Worksheets[1]);
foreach (Excel.Worksheet item in workbook.Worksheets)
{
if (item.Name == "_QR_Scan")
{
item.Name = "_QR_Scan_备份";
break;
}
}
worksheet.Name = "_QR_Scan";
worksheet.Activate();
worksheet.Range["A1"].Value = "目录";
worksheet.Range["B1"].Value = "文件名称";
worksheet.Range["C1"].Value = "二维码编号";
worksheet.Range["D1"].Value = "二维码内容";
ThisAddIn.Global.created_qr_sheet = true;
}
else
{
workbook.Worksheets["_QR_Scan"].Activate();
}
Excel.Worksheet sheet = workbook.Worksheets["_QR_Scan"];
try
{
int row = sheet.UsedRange.Rows.Count + 1;
for (int i = 0; i < data.Rows.Count; i++)
{
for (int j = 0; j < data.Columns.Count; j++)
{
string str = data.Rows[i][j].ToString();
sheet.Cells[row + i, j + 1].NumberFormat = "@";
sheet.Cells[row + i, j + 1].Value = str;
if (j == 1 && sheet.Cells[row + i, j + 1].Value != "webcam")
{
sheet.Hyperlinks.Add(sheet.Cells[row + i, j + 1], Path.Combine(data.Rows[i][0].ToString(), str), Type.Missing, Type.Missing, str);
}
if (str.StartsWith("http") || str.StartsWith("mailto:"))
{
sheet.Hyperlinks.Add(sheet.Cells[row + i, j + 1], str, Type.Missing, Type.Missing, str);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
ThisAddIn.app.Application.ScreenUpdating = true;
ThisAddIn.app.Application.DisplayAlerts = true;
}
}
private void webcam_radioButton_CheckedChanged(object sender, EventArgs e)
{
if (webcam_radioButton.Checked)
{
videoSourcePlayer1.Visible = true;
}
}
private void picture_radioButton_CheckedChanged(object sender, EventArgs e)
{
if (picture_radioButton.Checked)
{
videoSourcePlayer1.Visible = false;
cancel_button.Enabled = false;
}
}
private void cancel_button_Click(object sender, EventArgs e)
{
if (videoSourcePlayer1.IsRunning)
{
videoSourcePlayer1.SignalToStop();
videoSourcePlayer1.WaitForStop();
}
if (videoDevice != null && videoDevice.IsRunning)
{
videoDevice.SignalToStop();
videoDevice.WaitForStop();
}
scan_button.Enabled = true;
quit_button.Enabled = true;
cancel_button.Enabled = false;
isProcessing = false;
qrRectangles.Clear();
folder_path_label.Text = "";
}
private void Form5_FormClosing(object sender, FormClosingEventArgs e)
{
if (videoSourcePlayer1.IsRunning)
{
videoSourcePlayer1.SignalToStop();
videoSourcePlayer1.WaitForStop();
videoSourcePlayer1.VideoSource = null;
}
if (videoDevice != null && videoDevice.IsRunning)
{
videoDevice.SignalToStop();
videoDevice.WaitForStop();
}
if (qrBoxPen != null) qrBoxPen.Dispose();
}
}
}