OneDHelper.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. 
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.Runtime.InteropServices;
  7. //using Curtain.Helpers;
  8. using ZXing;
  9. using ZXing.Common;
  10. using ZXing.OneD;
  11. using ZXing.Rendering;
  12. namespace Dongke.WinForm.Controls.InvoiceLayout.DrawBarcode.OneD
  13. {
  14. /// <summary>
  15. /// 一维码生成
  16. /// </summary>
  17. public sealed class OneDHelper
  18. {
  19. private static readonly Dictionary<OneDFormat, Writer> formatWriter;
  20. private static readonly Dictionary<OneDFormat, BarcodeFormat> formatMap;
  21. static OneDHelper()
  22. {
  23. formatWriter = new Dictionary<OneDFormat, Writer>()
  24. {
  25. { OneDFormat.CODE_128, new Code128Writer() },
  26. { OneDFormat.EAN_13, new EAN13Writer() },
  27. { OneDFormat.EAN_8, new EAN8Writer() },
  28. { OneDFormat.CODABAR, new CodaBarWriter() },
  29. { OneDFormat.CODE_39, new Code39Writer() },
  30. { OneDFormat.CODE_93, new Code93Writer() },
  31. { OneDFormat.ITF, new ITFWriter() },
  32. { OneDFormat.MSI, new MSIWriter() },
  33. { OneDFormat.PLESSEY, new PlesseyWriter() },
  34. { OneDFormat.UPC_A, new UPCAWriter() },
  35. { OneDFormat.UPC_E, new UPCEWriter() },
  36. //formatMap.Add(OneDFormat.CODABAR, new CodaBarWriter());
  37. //formatMap.Add(OneDFormat.CODE_39, new Code39Writer());
  38. //formatMap.Add(OneDFormat.CODE_93, new Code93Writer());
  39. //formatMap.Add(OneDFormat.EAN_8, new EAN8Writer());
  40. //formatMap.Add(OneDFormat.ITF, new ITFWriter());
  41. //formatMap.Add(OneDFormat.MSI, new MSIWriter());
  42. //formatMap.Add(OneDFormat.PLESSEY, new PlesseyWriter());
  43. //formatMap.Add(OneDFormat.UPC_A, new UPCAWriter());
  44. //formatMap.Add(OneDFormat.UPC_E, new UPCEWriter());
  45. // 二维
  46. //formatMap.Add(BarcodeFormat.QR_CODE, new QRCodeWriter());
  47. //formatMap.Add(BarcodeFormat.PDF_417, new PDF417Writer());
  48. //formatMap.Add(BarcodeFormat.DATA_MATRIX, new DataMatrixWriter());
  49. //formatMap.Add(BarcodeFormat.AZTEC, new AztecWriter());
  50. };
  51. formatMap = new Dictionary<OneDFormat, BarcodeFormat>
  52. {
  53. { OneDFormat.CODE_128, BarcodeFormat.CODE_128 },
  54. { OneDFormat.EAN_13, BarcodeFormat.EAN_13 },
  55. { OneDFormat.EAN_8, BarcodeFormat.EAN_8 },
  56. { OneDFormat.CODABAR, BarcodeFormat.CODABAR },
  57. { OneDFormat.CODE_39, BarcodeFormat.CODE_39 },
  58. { OneDFormat.CODE_93, BarcodeFormat.CODE_93 },
  59. { OneDFormat.ITF, BarcodeFormat.ITF },
  60. { OneDFormat.MSI, BarcodeFormat.MSI },
  61. { OneDFormat.PLESSEY, BarcodeFormat.PLESSEY },
  62. { OneDFormat.UPC_A, BarcodeFormat.UPC_A },
  63. { OneDFormat.UPC_E, BarcodeFormat.UPC_E },
  64. };
  65. }
  66. /// <summary>
  67. /// 原始一维码
  68. /// </summary>
  69. /// <param name="contents"></param>
  70. /// <param name="format"></param>
  71. /// <returns></returns>
  72. public static OneDData Encode(string contents, OneDFormat format = OneDFormat.CODE_128)
  73. {
  74. //OneDimensionalCodeWriter writer = null;
  75. Writer writer = null;
  76. if (formatWriter.ContainsKey(format))
  77. {
  78. writer = formatWriter[format];
  79. }
  80. if (writer == null)
  81. {
  82. return null;
  83. }
  84. OneDimensionalCodeWriter codeWriter;
  85. if (format == OneDFormat.UPC_A)
  86. {
  87. codeWriter = new EAN13Writer();
  88. contents = "0" + contents;
  89. }
  90. else
  91. {
  92. codeWriter = writer as OneDimensionalCodeWriter;
  93. }
  94. bool[] code = codeWriter?.encode(contents);
  95. if (code == null || code.Length == 0)
  96. {
  97. return null;
  98. }
  99. OneDData data = new OneDData(code, contents);
  100. return data;
  101. }
  102. /// <summary>
  103. /// 按比例放大的原始一维码
  104. /// </summary>
  105. /// <param name="contents"></param>
  106. /// <param name="format"></param>
  107. /// <param name="width"></param>
  108. /// <returns></returns>
  109. public static OneDData Encode(string contents, int width, OneDFormat format = OneDFormat.CODE_128)
  110. {
  111. OneDData data = Encode(contents, format);
  112. if (data == null)
  113. {
  114. return null;
  115. }
  116. return Encode(data, width);
  117. }
  118. /// <summary>
  119. /// 按比例放大的原始一维码
  120. /// </summary>
  121. /// <param name="data"></param>
  122. /// <param name="width"></param>
  123. /// <returns></returns>
  124. public static OneDData Encode(OneDData data, int width)
  125. {
  126. if (data == null)
  127. {
  128. return null;
  129. }
  130. data.Width = width;
  131. //data.Height = height;
  132. //if (width < data.Size)
  133. //{
  134. // throw new ArgumentOutOfRangeException("barcode width", width, $"data size is {data.Size}");
  135. //}
  136. if (width <= data.Size)
  137. {
  138. return data;
  139. }
  140. int multiple = (width / data.Size);
  141. if (multiple == 1)
  142. {
  143. return data;
  144. }
  145. int dataSize = data.Size * multiple;
  146. OneDData oneData = new OneDData(dataSize)
  147. {
  148. Text = data.Text,
  149. Width = width,
  150. };
  151. for (int x = 0; x < data.Size; x++)
  152. {
  153. int h = x * multiple;
  154. for (int i = h; i < h + multiple; i++)
  155. {
  156. oneData[i] = data[x];
  157. }
  158. }
  159. return oneData;
  160. }
  161. /// <summary>
  162. /// 直接绘制条码
  163. /// </summary>
  164. /// <param name="contents"></param>
  165. /// <param name="options"></param>
  166. /// <param name="format"></param>
  167. public static void DrawOneD(string contents, OneDDrawingOptions options, OneDFormat format = OneDFormat.CODE_128)
  168. {
  169. if (options?.DrawGraphics == null)
  170. {
  171. throw new ArgumentNullException("OneDDrawingOptions.DrawGraphics");
  172. }
  173. if (options.ShowText)
  174. {
  175. /*Writer writer = null;
  176. if (formatWriter.ContainsKey(format))
  177. {
  178. writer = formatWriter[format];
  179. }
  180. if (writer == null)
  181. {
  182. return;
  183. }
  184. BarcodeFormat barcodeFormat = formatMap[format];
  185. EncodingOptions encodingOptions = new EncodingOptions();
  186. encodingOptions.Width = options.ImageWidth - options.Margin.Horizontal;
  187. encodingOptions.Height = options.ImageHeight - options.Margin.Vertical;
  188. if (options.TextMargin.HasValue)
  189. {
  190. encodingOptions.Hints.Add(EncodeHintType.MARGIN, options.TextMargin);
  191. }
  192. AlternateBitmapRenderer render = new AlternateBitmapRenderer();
  193. if (options.TextFont != null)
  194. {
  195. render.TextFont = options.TextFont;
  196. if (format == OneDFormat.EAN_8 ||
  197. format == OneDFormat.EAN_13 ||
  198. format == OneDFormat.UPC_E ||
  199. format == OneDFormat.UPC_A)
  200. {
  201. if (options.DpiX.HasValue)
  202. {
  203. // zxing AlternateBitmapRenderer 创建图片没有设置分辨率
  204. render.TextFont = new Font(options.TextFont.FontFamily, options.TextFont.Size * options.DpiX.Value / 96, options.TextFont.Style);
  205. }
  206. }
  207. }
  208. try
  209. {
  210. BitMatrix m = writer.encode(contents, barcodeFormat, encodingOptions.Width, encodingOptions.Height, encodingOptions.Hints);
  211. using (Image image = render.Render(m, barcodeFormat, contents, encodingOptions))
  212. {
  213. Rectangle rect = new Rectangle(
  214. options.ImageRect.Left + options.Margin.Left,
  215. options.ImageRect.Top + options.Margin.Top,
  216. //imageData.Width,
  217. //imageData.Height);
  218. options.ImageRect.Width - options.Margin.Horizontal,
  219. options.ImageRect.Height - options.Margin.Vertical);
  220. if (options.ShowType == BarcodeShowType.Zoom)
  221. {
  222. options.DrawGraphics.DrawImage(image, rect);
  223. }
  224. else if (options.ShowType == BarcodeShowType.Show)
  225. {
  226. ImageHelper.Show(image, options.DrawGraphics, rect, ContentAlignment.MiddleCenter, false);
  227. }
  228. else
  229. {
  230. ImageHelper.Show(image, options.DrawGraphics, rect, ContentAlignment.TopLeft, false);
  231. }
  232. }
  233. }
  234. catch (Exception ex)
  235. {
  236. Font errorFont = new Font("Courier New", 9f, FontStyle.Regular);
  237. options.DrawGraphics.DrawString(ex.Message, errorFont, Brushes.Red, options.ImageRect);
  238. }*/
  239. using (Image image = GetOneDImage(contents, options, format))
  240. {
  241. Rectangle rect = new Rectangle(
  242. options.ImageRect.Left + options.Margin.Left,
  243. options.ImageRect.Top + options.Margin.Top,
  244. //imageData.Width,
  245. //imageData.Height);
  246. options.ImageRect.Width - options.Margin.Horizontal,
  247. options.ImageRect.Height - options.Margin.Vertical);
  248. if (options.ShowType == BarcodeShowType.Zoom)
  249. {
  250. options.DrawGraphics.DrawImage(image, rect);
  251. }
  252. else if (options.ShowType == BarcodeShowType.Show)
  253. {
  254. ImageHelper.Show(image, options.DrawGraphics, rect, ContentAlignment.MiddleCenter, false);
  255. }
  256. else
  257. {
  258. ImageHelper.Show(image, options.DrawGraphics, rect, ContentAlignment.TopLeft, false);
  259. }
  260. }
  261. return;
  262. }
  263. OneDData data = Encode(contents, format);
  264. if (data == null)
  265. {
  266. return;
  267. }
  268. // 条码范围
  269. int width = options.ImageRect.Width - options.Margin.Horizontal;
  270. int height = options.ImageRect.Height - options.Margin.Vertical;
  271. data = Encode(data, width);
  272. data.Height = height;
  273. DrawOneD(data, options.DrawGraphics, options);
  274. }
  275. /// <summary>
  276. /// 直接绘制条码
  277. /// </summary>
  278. /// <param name="data"></param>
  279. /// <param name="options"></param>
  280. public static void DrawOneD(OneDData data, OneDDrawingOptions options)
  281. {
  282. if (options?.DrawGraphics == null)
  283. {
  284. throw new ArgumentNullException("OneDDrawingOptions.DrawGraphics");
  285. }
  286. //if (options.ShowType != BarcodeShowType.Original)
  287. //{
  288. // // 条码范围
  289. // int width = options.ImageRect.Width - options.Margin.Horizontal;
  290. // int height = options.ImageRect.Height - options.Margin.Vertical;
  291. // if (data.Width != width)
  292. // {
  293. // data = Encode(data, width);
  294. // }
  295. // data.Height = height;
  296. //}
  297. DrawOneD(data, options.DrawGraphics, options);
  298. }
  299. /// <summary>
  300. /// 直接绘制条码
  301. /// </summary>
  302. /// <param name="imageData"></param>
  303. /// <param name="graphics"></param>
  304. /// <param name="options"></param>
  305. private static void DrawOneD(OneDData imageData, Graphics graphics, OneDDrawingOptions options)
  306. {
  307. // 条码范围
  308. using (Image image = GetOneDSource(imageData, options))
  309. {
  310. Rectangle rect = new Rectangle(
  311. options.ImageRect.Left + options.Margin.Left,
  312. options.ImageRect.Top + options.Margin.Top,
  313. //imageData.Width,
  314. //imageData.Height);
  315. options.ImageRect.Width - options.Margin.Horizontal,
  316. options.ImageRect.Height - options.Margin.Vertical);
  317. if (options.ShowType == BarcodeShowType.Zoom)
  318. {
  319. graphics.DrawImage(image, rect);
  320. }
  321. else if (options.ShowType == BarcodeShowType.Show)
  322. {
  323. ImageHelper.Show(image, graphics, rect, ContentAlignment.MiddleCenter, false);
  324. }
  325. else
  326. {
  327. ImageHelper.Show(image, graphics, rect, ContentAlignment.TopLeft, false);
  328. }
  329. }
  330. }
  331. /// <summary>
  332. /// 条码图片
  333. /// </summary>
  334. /// <param name="contents"></param>
  335. /// <param name="options"></param>
  336. /// <param name="format"></param>
  337. /// <returns></returns>
  338. public static Image GetOneDImage(string contents, OneDDrawingOptions options, OneDFormat format = OneDFormat.CODE_128)
  339. {
  340. if (options == null)
  341. {
  342. throw new ArgumentNullException("OneDDrawingOptions");
  343. }
  344. if (options.ShowText)
  345. {
  346. Writer writer = null;
  347. if (formatWriter.ContainsKey(format))
  348. {
  349. writer = formatWriter[format];
  350. }
  351. if (writer == null)
  352. {
  353. return null;
  354. }
  355. BarcodeFormat barcodeFormat = formatMap[format];
  356. EncodingOptions encodingOptions = new EncodingOptions();
  357. encodingOptions.Width = options.ImageWidth - options.Margin.Horizontal;
  358. encodingOptions.Height = options.ImageHeight - options.Margin.Vertical;
  359. encodingOptions.PureBarcode = false;
  360. if (format == OneDFormat.EAN_13)
  361. {
  362. encodingOptions.GS1Format = true;
  363. }
  364. if (options.TextMargin.HasValue)
  365. {
  366. encodingOptions.Hints.Add(EncodeHintType.MARGIN, options.TextMargin);
  367. }
  368. AlternateBitmapRenderer render = new AlternateBitmapRenderer();
  369. if (options.TextFont != null)
  370. {
  371. render.TextFont = options.TextFont;
  372. if (format == OneDFormat.EAN_8 ||
  373. format == OneDFormat.EAN_13 ||
  374. format == OneDFormat.UPC_E ||
  375. format == OneDFormat.UPC_A)
  376. {
  377. if (options.DpiX.HasValue)
  378. {
  379. // zxing AlternateBitmapRenderer 创建图片没有设置分辨率
  380. render.TextFont = new Font(options.TextFont.FontFamily, options.TextFont.Size * options.DpiX.Value / 96, options.TextFont.Style);
  381. }
  382. }
  383. }
  384. try
  385. {
  386. BitMatrix m = writer.encode(contents, barcodeFormat, encodingOptions.Width, encodingOptions.Height, encodingOptions.Hints);
  387. return render.Render(m, barcodeFormat, contents, encodingOptions);
  388. }
  389. catch (Exception ex)
  390. {
  391. //Font errorFont = new Font("Courier New", 9f, FontStyle.Regular);
  392. Font errorFont = render.TextFont ?? new Font("Courier New", 9f * (options.DpiX??96) / 96, FontStyle.Regular);
  393. Bitmap dataImage = new Bitmap(options.ImageWidth, options.ImageHeight);
  394. if (options != null && options.DpiX.HasValue)
  395. {
  396. dataImage.SetResolution(options.DpiX.Value, (options.DpiY) ?? options.DpiX.Value);
  397. }
  398. //Rectangle rectImage = new Rectangle(0, 0, options.ImageWidth, options.ImageHeight);
  399. using (Graphics g = Graphics.FromImage(dataImage))
  400. {
  401. g.DrawString(ex.Message, errorFont, Brushes.Red, options.ImageRect);
  402. }
  403. return dataImage;
  404. }
  405. }
  406. OneDData data = Encode(contents, format);
  407. if (data == null)
  408. {
  409. return null;
  410. }
  411. // 条码范围
  412. int width = options.ImageRect.Width - options.Margin.Horizontal;
  413. int height = options.ImageRect.Height - options.Margin.Vertical;
  414. data = Encode(data, width);
  415. data.Height = height;
  416. return GetOneDImage(data, options);
  417. }
  418. /// <summary>
  419. /// 条码图片
  420. /// </summary>
  421. /// <param name="data"></param>
  422. /// <param name="options"></param>
  423. /// <returns></returns>
  424. public static Image GetOneDImage(OneDData data, OneDDrawingOptions options)
  425. {
  426. if (options == null)
  427. {
  428. throw new ArgumentNullException("OneDDrawingOptions");
  429. }
  430. if (options.ShowType == BarcodeShowType.Original)
  431. {
  432. return GetOneDSource(data, options);
  433. }
  434. Bitmap dataImage = new Bitmap(options.ImageRect.Width, options.ImageRect.Height);
  435. if (options.DpiX.HasValue)
  436. {
  437. dataImage.SetResolution(options.DpiX.Value, (options.DpiY) ?? options.DpiX.Value);
  438. }
  439. using (Graphics graphics = Graphics.FromImage(dataImage))
  440. {
  441. graphics.Clear(options.BackColor);
  442. DrawOneD(data, graphics, options);
  443. }
  444. return dataImage;
  445. }
  446. /// <summary>
  447. /// 原始条码图片
  448. /// </summary>
  449. /// <param name="data"></param>
  450. /// <param name="options"></param>
  451. /// <returns></returns>
  452. public static Image GetOneDSource(OneDData data, OneDDrawingOptions options)
  453. {
  454. if (options == null)
  455. {
  456. throw new ArgumentNullException("OneDDrawingOptions");
  457. }
  458. int height = data.Height;
  459. if (height < 1)
  460. {
  461. height = Math.Max(options.ImageRect.Height - options.Margin.Vertical, 1);
  462. }
  463. Bitmap dataImage = new Bitmap(data.Size, height);
  464. if (options != null && options.DpiX.HasValue)
  465. {
  466. dataImage.SetResolution(options.DpiX.Value, (options.DpiY) ?? options.DpiX.Value);
  467. }
  468. Rectangle rectImage = new Rectangle(0, 0, data.Size, height);
  469. BitmapData bmpData = dataImage.LockBits(rectImage, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
  470. try
  471. {
  472. byte[] pixels = new byte[bmpData.Stride * bmpData.Height];
  473. int index = 0;
  474. for (int x = 0; x < bmpData.Width; x++)
  475. {
  476. Color color = (data[x] ? options.ForeColor : options.BackColor);
  477. pixels[index++] = color.B;
  478. pixels[index++] = color.G;
  479. pixels[index++] = color.R;
  480. pixels[index++] = color.A;
  481. }
  482. for (int y = 1; y < bmpData.Height; y++)
  483. {
  484. Array.Copy(pixels, 0, pixels, y * bmpData.Stride, bmpData.Stride);
  485. }
  486. Marshal.Copy(pixels, 0, bmpData.Scan0, pixels.Length);
  487. }
  488. finally
  489. {
  490. dataImage.UnlockBits(bmpData);
  491. }
  492. return dataImage;
  493. }
  494. }
  495. }