ایجاد بارکد به همراه یک متن
نویسنده: شریعتی پیام
تاریخ: ۱۴۰۱/۰۴/۱۳ ۲۲:۲۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
- طول عکس خروجی نهایی 250 پیکسل است.
- فونت متن 10 پیکسل هست و عرض هر خط 17 پیکسل.
- حداکثر تعداد خطِ نمایش متن، 3 خط است و اگر متن برای نمایش، به 3 خط بیشتر نیاز داشت، اضافهی متن را به صورت 3 نقطه نمایش میدهیم (مثل عکس بالا).
- عرض بارکد 50 پیکسل است.
- فاصله بین بارکد و متن 5 پیکسل است.
public static class BarcodeHelper
{
public static string GenerateBarcodeWithText(string input, string textBelow)
{
// barcode: 50 pixels
// margin: top 5 pixels
// height of each text line is 17 pixels
// text: maximum 3 lines
// each 30 letters is: 1 line
var eachLineHeight = 17;
var eachLineLetters = 30;
var maximumLines = 3;
var maximumTextHeight = eachLineHeight * maximumLines;
var resultWidth = 250;
var barcodeHeight = 50;
var textY = barcodeHeight + 5;
// each 30 letters is: 1 line for example input length is 150 letters and for show 100 letters we need (150 / 30) 5 lines
// each line is 17 pixels and text height will be (17 * 5) 102 pixels
var textHeight = (textBelow.Length / eachLineLetters) * eachLineHeight;
// if height of text be greater than (eachLineHeight * maximumLines) we use maximum text height (eachLineHeight * maximumLines)
textHeight = textHeight > maximumTextHeight ? maximumTextHeight : textHeight;
// if text height be less than 1 line we set 1 line height (17 pixels) to the text height
// text height minimum is equal 1 linle (17 pixels)
textHeight = textHeight < eachLineHeight ? eachLineHeight : textHeight;
var resultHeight = textY + textHeight;
}
}
چون ما از Bitmap و Image استفاده میکنیم، پس به پکیچ System.Drawing.Common نیاز داریم:
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
</ItemGroup> اولین کاری که انجام میدهیم، یک Bitmap را ایجاد میکنیم و بعد یک مستطیل را به اندازهی خود Bitmap ایجاد میکنیم و با کلاس Graphics، به نارنجی، رنگش میکنیم و داخل Bitmap میریزیم و در نهایت عکس ایجاد شده را در حافظهی رم ذخیره میکنیم.
- Bitmap فضایی را در اختیار ما قرار میدهد که داخلش هر چیزی را ترسیم کنیم.
- Graphics به ما کمک میکند که عملیات گرافیکی را نظیر رنگ آمیزی، ترسیم عکس و ... روی یک شیء انجام دهیم.
- MemoryStream برای ذخیره سازی موقت در حافظهی رم به کار میاد؛ عکس ایجاد شدهی تا این لحظه را که یک مستطیل نارنجی رنگ هست، در داخل رم ذخیره میکنیم.
#region MainBitmap
var mainBitmap = new Bitmap(resultWidth, resultHeight);
using var rectangleGraphics = Graphics.FromImage(mainBitmap);
{
var rectangle = new Rectangle(0, 0, resultWidth, resultHeight);
rectangleGraphics.FillRectangle(Brushes.OrangeRed, rectangle);
}
using var rectangleStream = new MemoryStream();
{
mainBitmap.Save(rectangleStream, ImageFormat.Png);
}
#endregion خروجی تا این لحظه:
حالا باید بارکد را ایجاد کنیم و عکس خروجی بارکد را داخل این مستطیل بریزیم؛ برای اینکار از کتابخانه BarcodeLib استفاده میکنیم:
private static Bitmap GenerateBarcodeImage(string input, int width, int height)
{
var barcodeInstance = new Barcode();
var barcodeImage = barcodeInstance.Encode(BarcodeLib.TYPE.CODE39, input, Color.Black,
Color.OrangeRed, width, height);
using var barcodeStream = new MemoryStream();
{
barcodeImage.Save(barcodeStream, ImageFormat.Png);
}
return (Bitmap)Image.FromStream(barcodeStream);
} و الان این عکس بارکد را داخل مستطیل اصلی میریزیم و هر دو را Merge میکنیم:
#region Barcode
var barcodeImage = GenerateBarcodeImage(input, resultWidth, barcodeHeight);
#endregion
#region MergedRectangleAndBarcode
var newMainBitmap = (Bitmap)Image.FromStream(rectangleStream);
var newBarcodeBitmap = barcodeImage;
using var newRectangleGraphics = Graphics.FromImage(newMainBitmap);
{
newRectangleGraphics.DrawImage(newBarcodeBitmap, 0, 0);
}
using var mergedRectangleAndBarcodeStream = new MemoryStream();
{
newMainBitmap.Save(mergedRectangleAndBarcodeStream, ImageFormat.Png);
}
#endregion خروجی تا این لحظه :
حالا باید 5 پیکسل از پایین بارکد فاصله بگیریم و متن را بنویسیم.
برای اینکار از یک مستطیل کمک میگیریم. یعنی یک مستطیل بدون هیچ رنگ و Border ـی را پایین این بارکد ایجاد میکنیم، چرا؟ دلیل این است که میخواهیم متنمان را به صورت وسط چین، از راست و چپ، و وسط از بالا و پایین قرار بدیم و برای اینکار میگیم این نسبت وسط چین بودن از راست و چپ، وسط بودن از بالا و پایین را از مستطیل پایین بارکد کمک بگیر، خلاصهاش میشود اینکه از مستطیلِ پایینِ بارکد برای وسط چین بودن متن از راست و چپ و وسط بودن از بالا و پایین استفاده میکنیم.
#region WriteText
var barcodeBitmap = (Bitmap)Image.FromStream(mergedRectangleAndBarcodeStream);
using var graphics = Graphics.FromImage(barcodeBitmap);
{
using var font = new Font("Tahoma", 10);
{
var rect = new Rectangle(0, textY, resultWidth, textHeight);
var sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.Trimming = StringTrimming.EllipsisCharacter;
sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;
sf.LineAlignment = StringAlignment.Center;
graphics.DrawString(textBelow, font, Brushes.Black, rect, sf);
//graphics.DrawRectangle(Pens.Green, rect);
}
}
using var finalStream = new MemoryStream();
{
barcodeBitmap.Save(finalStream, ImageFormat.Png);
}
#endregion graphics.DrawString میگوید textBelow را با font تاهوما و با رنگ سیاه، داخل rect (مستطیل) و با این تنظیماتِ متن بریز.
Alignment متن را وسط چین میکند (این وسط چین شدن نسبت به مستطیل پایین بارکد است که هیچ رنگ و Border ـی ندارد) .
LineAlignment متن را از بالا و پایین میارد وسط (این وسط شدن نسبت به مستطیل پایین بارکد است که هیچ رنگ و Border ـی ندارد).
EllipsisCharacter اگر متن طولانی باشد، اضافه متن را به صورت سه نقطه نمایش میدهد.
DirectionRightToLeft متن را RTL میکند.
خروجی نهایی:
عکس نهایی به صورت Stream ذخیره شدهاست، آنرا به فرمت Base64 تبدیل میکنیم و برگشت میزنیم.
return Convert.ToBase64String(finalStream.ToArray());
برای نمایش یک آرایه بایتی که به فرمت Base64 تبدیل شده، به این روش عمل میکنیم:
<img src="data:image/png;base64, @BarcodeHelper.GenerateBarcodeWithText("barcode text", "below text")" /> چون برای ایجاد بارکد از تایپ 39 استفاده کردهایم و تایپ 39 فقط حروف بزرگ انگلیسی را پشتیبانی میکند، پس برای اینکه دچار خطا نشویم، میتوانیم ابتدای متدمان، از این کد استفاده کنیم:
// Type 39 doesn't support lower case letters, for prevent exception, we convert all input letters to upper case // more details: https://www.dntips.ir/newsarchive/details/18019 input = input.ToUpperInvariant();
همچنین جهت تشخیص خودکار راست به چک بودن متن پایین بارکد، میتوان از متد ContainsFarsi در پکیج DNTPersianUtils.Core استفاده کرد:
if (textBelow.ContainsFarsi())
sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;