לברקוד על תווית משלוח או חשבונית יש תפקיד אחד, והוא להיקרא על ידי סורק בניסיון הראשון. השאלה אם הוא ישרוד את הניסיון הזה מוכרעת הרבה לפני שהחבילה מגיעה לרציף. היא מוכרעת לפי האופן שבו הסמל הונח על העמוד. הטעות הנפוצה ביותר בתהליך הפקת דוחות ב-Delphi היא לרנדר את הברקוד כמפת סיביות (bitmap) במקום אחר ולהציב את התמונה הזו בתוך ה-PDF. זה נראה בסדר על המסך ברמת זום אחת ואז נשחק בכל מקום אחר.
החלופה היא לצייר את הסמל כתוכן וקטורי, ישירות לתוך העמוד. PDFlibPas חושף משפחה של קריאות ציור בדיוק עבור זה, המכסה את סמלי המטריצה הדו-ממדיים QR, PDF417 ו-DataMatrix, המשפחות הקוויות דרך Code128 ו-GS1-128, ו-USPS Intelligent Mail לאוטומציית דואר. הטיעון לטובת וקטור אינו אסתטי. הוא עוסק בשאלה אם הקווים נוחתים היכן שהסורק מצפה להם.
מדוע וקטור מנצח מפת סיביות ממוקמת
ברקוד הוא תבנית של פסים ומרווחים, או בדו-ממד גריד של מודולים כהים ובהירים. המפענח עובד על ידי מדידת היחס בין הרוחבים הללו. כל מה שמעוות את היחסים הוא רעש האוכל מתקציב השגיאות של הסמל. תמונת ברקוד שעברה רסטריזציה נושאת פיקסלים קבועים. כאשר ה-PDF מרונדר למדפסת שהנקודות שלה אינן מתחלקות באופן שווה לתוך גריד התמונה, הרסטרייזר חייב לדגום מחדש, וקצוות מודול שאמורים להיות חדים נפרסים על פני שני פיקסלים של המכשיר. פס צר יכול להתרחב, מרווח סמוך יכול להצטמצם, והיחס בין הרוחבים שהמפענח מסתמך עליו נודד.
כאשר הוא מצויר כתוכן וקטורי, אותו סמל הוא קבוצה של מלבנים מלאים המתוארים בקואורדינטות מרחב המשתמש של PDF. אין גריד פיקסלים קבוע להילחם בו. בזמן ההדפסה המכשיר מרנדר כל מלבן ברזולוציה שיש לו בפועל, כך שכל קצה מודול חד ככל שהחומרה מאפשרת, בכל קנה מידה ובכל גודל הדפסה. הגדל סמל וקטורי עבור תווית משטחים או כווץ אותו עבור חבילה והגיאומטריה נשארת מדויקת. דיוק זה הוא מה ששומר על שיעור קריאה גבוה בניסיון הראשון, וזה כל הרעיון של הצבת ברקוד על העמוד.
קודי QR וארבע רמות התיקון
QR הוא סמל מטריצה דו-ממדי הנקרא בשני הצירים בו-זמנית, ולכן הוא דוחס הרבה נתונים לתוך ריבוע קטן. עמידותו בפני נזקים מגיעה מתיקון שגיאות של ריד-סולומון (Reed-Solomon), המוצע בארבע רמות. רמה L משחזרת כ-7 אחוזים ממילות הקוד, M כ-15 אחוזים, Q כ-25 אחוזים, ו-H כ-30 אחוזים. תיקון גבוה יותר אינו בחינם. מילות הקוד לשחזור תופסות מקיבולת המודול, כך שעבור כמות נתונים קבועה רמה גבוהה יותר מאלצת סמל צפוף יותר או גדול יותר פיזית.
הפשרה היא שאלה לגבי הסביבה שבה הסמל יחיה. מסמך דיגיטלי נקי שייסרק רק ממסך יכול להישאר ברמה L ולהישאר קומפקטי. תווית שתודפס, תטופל, תישחק, ואולי תכוסה בחלקה בסרט הדבקה דורשת Q או H, מכיוון שהיתירות הנוספת היא מה שמאפשר למפענח לשחזר את הנתונים מסמל שכבר אינו מושלם. DrawQRCode מקבל את המיקום ו-SymbolSize שקובע את הרוחב והגובה המצוירים, בתוספת ערך EncodeOptions הבוחר את מצב הנתונים (0 לאוטומטי, או גרסאות מספריות, אלפא-נומריות, ISO-8859-1 ו-UTF-8) וערך DrawOptions עבור כיוון התצוגה.
var
Pdf: TPDFlib;
begin
Pdf := TPDFlib.Create(nil);
try
Pdf.NewDocument;
Pdf.SetPageSize('A4');
Pdf.SetMeasurementUnits(1); // 1 = millimetres
Pdf.NewPage;
// 30 mm square QR, automatic encoding, normal orientation
Pdf.DrawQRCode(20, 20, 30, 'https://www.loslab.com/', 0, 0);
Pdf.SaveToFile('Label_QR.pdf');
finally
Pdf.Free;
end;
end;
רמת התיקון עצמה נבחרת על ידי המקודד כדי להתאים את הנתונים לתוך הסמל שביקשת. אם אתה צריך רמה גבוהה מובטחת עבור סביבה קשה, קבע גודל נדיב לסמל כך שלמקודד יהיה תקציב מודול להוציא על יתירות במקום להיאלץ לרדת ברמת התיקון כדי להתאים.
PDF417 לתעודות זהות ותוויות משלוח
PDF417 הוא סמל קווי מיושר (stacked linear symbol). כל שורה היא ברקוד קווי קצר, והשורות נערמות ליצירת בלוק, וזו הסיבה שהוא מופיע ברישיונות נהיגה, כרטיסי עלייה למטוס ותוויות משלוח של מובילים שבהם רצועה רחבה יותר של נתונים צריכה לשבת בתוך שטח מלבני. תיקון השגיאות שלו פועל על סולם של 0 עד 8. כל שלב מכפיל בערך את מספר מילות הקוד לתיקון, כך שרמה 5 נושאת הרבה יותר יתירות מרמה 1, במחיר של יותר מילות קוד בעמוד.
צורת בלוק PDF417 ניתנת להתאמה, וזה משנה מכיוון שלתווית יש שטח קבוע למילוי. DrawPDF417SymbolEx חושף את הבקרות שהקריאה הבסיסית אינה כוללת. FixedColumns ו-FixedRows נועלים את ספירת עמודות הנתונים וספירת השורות, כאשר 0 פירושו לתת למקודד להחליט. ErrorLevel מקבל -1 לאוטומטי או ערך מפורש של 0 עד 8. ModuleSize הוא הרוחב של האלמנט הצר ביותר ביחידת המדידה הנוכחית, ו-HeightWidthRatio קובע כמה גבוה כל מודול ביחס לרוחבו, וכך אתה הופך את הבלוק לקצר ורחב או לגבוה וצר כדי להתאים לשטח שיש לך.
// Fixed 10 data columns, automatic rows, error level 5,
// module 0.30 mm wide, rows three times the module width tall
Pdf.DrawPDF417SymbolEx(20, 60, 'PDF417 PAYLOAD 0123456789',
0, // Options: 0 = normal orientation
10, // FixedColumns
0, // FixedRows: 0 = automatic
5, // ErrorLevel: 0 to 8
0.30, // ModuleSize, in the current measurement unit
3.0); // HeightWidthRatio
נעילת עמודות היא המנוף הרגיל בתבנית תווית. ספירת עמודות קבועה מעניקה לבלוק רוחב צפוי, כך שהפריסה מסביב אינה משתנה כאשר עומס הנתונים המקודד משנה את אורכו ממסמך אחד למשנהו, בעוד המקודד מוסיף שורות כלפי מטה כדי לספוג את ההפרש.
DataMatrix לסימונים קטנים
DataMatrix הוא הסמל לפנות אליו כאשר הסימון חייב להיות קטן. זהו גריד דו-ממדי קומפקטי המשתמש ב-ECC 200, שיטת הריד-סולומון המודרנית, והוא נשאר קריא בגדלים שבהם סמל QR של אותם נתונים היה מגושם. זה הופך אותו לבחירה הסטנדרטית לסימון חלקים ישיר, רכיבים אלקטרוניים קטנים ותוויות לוגיסטיקה צפופות.
הפונקציה DrawDataMatrixSymbol מקבלת ModuleSize עבור מרווח הנקודות, Encoding של 1 עבור ASCII, ו-SymbolSize שהוא 0 לאוטומטי או אחד הממדים הריבועיים והמלבניים הסטנדרטיים, מ-10x10 ועד 132x132. הפרמטר Options משלב כיוון תצוגה עם רוחב האזור השקט (quiet-zone), כאשר הוספת 100 עד 400 קובעת גבול לבן של אחד עד ארבעה מודולים. האזור השקט אינו קישוט. מפענח צריך את המרווח הנקי הזה כדי למצוא את תבנית הזיהוי של הסמל, וסמל הדחוס מול דיו אחר הוא סמל שנכשל בזיהוי.
// Auto-sized ASCII DataMatrix, 0.5 mm module, normal orientation
// with a one-module quiet zone (Options 0 + 100)
Pdf.DrawDataMatrixSymbol(20, 110, 0.5, 'DMX-SN-4408812',
1, // Encoding: 1 = ASCII
0, // SymbolSize: 0 = automatic
100); // Options: normal + one-module quiet zone
היכן שברקודים חד-ממדיים (1D) עדיין שולטים
סמלים דו-ממדיים מושכים את תשומת הלב, אך ברקודים קוויים עדיין מחזיקים בחלקים גדולים מהקמעונאות והלוגיסטיקה, והסיבה היא בסיס סורקי הלייזר המותקן שקורא סריקה יחידה. Code128 הוא סוס העבודה לנתונים אלפא-נומריים, והיעילות שלו מגיעה משלוש ערכות תווים. ערכה A מכסה תווי בקרה ואותיות גדולות, ערכה B מכסה את טווח ה-ASCII המלא להדפסה, וערכה C היא זו שמשנה עבור מספרים. תת-ערכה C מקודדת זוג ספרות בתו סמל בודד, כך שרצף של נתונים מספריים לוקח חצי מתווי הסמל שהוא היה לוקח בערכה A או B. זוהי הדרך הקומפקטית ביותר להציב ברקוד מספרי ארוך, ומימוש ה-Code128 של PDFlibPas משלב את ערכות B ו-C באופן אוטומצטי כדי להגיע לכך.
GS1-128, התקן שנקרא בעבר EAN-128, מתבסס על Code128 על ידי נשיאת מזהי יישום (Application Identifiers), הקידומות בסוגריים שאומרות למערכת המקבלת אם הספרות הבאות הן מספר סידורי, קוד אצווה או תאריך תפוגה. המבנה מסומן על ידי FNC1, תו מיוחד שאינו תו נתונים המסמן את הסמל כקידוד GS1 ומפריד בין שדות באורך משתנה. ב-PDFlibPas אתה מצייר סמל GS1-128 עם DrawBarcode תוך שימוש בטיפוס Code128 והסימן המילולי [FNC1] הממוקם במחרוזת הנתונים שבה מתחיל כל מזהה יישום.
var
W: Double;
begin
// Code128, with FNC1 markers this becomes a GS1-128 symbol.
// AI 21 (serial) = ABC123, AI 20 (variant) = 13
Pdf.DrawBarcode(20, 150, 60, 18, '[FNC1]21ABC123[FNC1]2013',
3, // Barcode: 3 = Code128
0); // Options: 0 = default drawing
// Measure the rendered width for a 0.30 mm narrow bar before laying out
W := Pdf.GetBarcodeWidth(0.30, '[FNC1]21ABC123[FNC1]2013', 3);
end;
עבור דואר, USPS Intelligent Mail, הנקרא גם OneCode, מקודד נתוני ניתוב ומעקב בברקוד יחיד מבוסס גובה לאוטומציית דואר. DrawIntelligentMailBarcode מקבל גיאומטריה מפורשת עבור רוחב הפס, גובה הפס המלא, גובה הגשש (tracker) ורוחב המרווח, כאשר הנתונים מסופקים כמחרוזת של 20, 25, 29 או 31 ספרות בלבד. גבהי הפס והגשש המפורשים קיימים מכיוון שהסמל נושא מידע בשאלה אם כל פס הוא פס מלא, עולה (ascender) או יורד (descender), וקורא הדואר תלוי בכך שגבהים אלה יישמרו בהתאם למפרט.
ציור לתוך העמוד ומדידה עבור פריסה (layout)
כל קריאה המוצגת כאן מציירת לתוך התוכן של העמוד שנבחר כעת, אותו משטח שמקבל את הטקסט והתמונות שלך, כך שברקוד מופק כחלק מהפקת מסמך רגילה במקום להיות מיובא כנכס נפרד. מכיוון שהסמלים הם תוכן וקטורי, הנתונים שהם מקודדים והגיאומטריה שהם תופסים ידועים שניהם בזמן הציור, וזה מה שמאפשר לך למקם אותם בצורה דטרמיניסטית.
פריסה עבור המשפחות הקוויות מרוויחה ממדידה מוקדמת. GetBarcodeWidth מחזירה את רוחב הציור הכולל של ברקוד עבור רוחב פס צר וטיפוס ברקוד נתונים, כך שתוכל לשריין את המרחב האופקי המדויק לפני שאתה מבצע את הציור, במקום לנחש ולגלות חפיפה לאחר שהעמוד נבנה. סמלים דו-ממדיים פשוטים יותר למיקום מכיוון שאתה קובע את גודל הציור שלהם ישירות דרך SymbolSize או ModuleSize, והסמל ממלא את השטח הזה. בשני המקרים המשמעת זהה. קבע את הגודל הפיזי מסביבת הסריקה, ודא שהסמל מתאים למשבצת שיש לך, ותן לגיאומטריה הוקטורית לשמור על כל קצה חד מתצוגה מקדימה במסך ועד להדפסה הסופית.
עבור זרימת העבודה הרחבה יותר של בניית עמודים שברקודים אלה נופלים לתוכה, הטכניקות ב-מאמר שלנו על חילוץ טקסט, תמונות וגופנים מכסות קריאת תוכן בחזרה מתוך PDF, ו-המדריך למיזוג ופיצול קובצי PDF גדולים עם גישה ישירה מציג כיצד להרכיב מסמכים בנפח גבוה ביעילות. שניהם משתלבים באופן טבעי עם ממשק ה-API לציור המתואר כאן, אשר נשלח כחלק מ- Delphi PDF Library עבור Delphi ו-C++Builder לצד ממשקי ה-API לטקסט, גרפיקה, טפסים וחתימות המכוסים במקומות אחרים בבלוג זה.