{"spec_id":"barcode-code128","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nbarcode-code128: Code 128 Barcode\nLibrary: letsplot 4.10.1 | Python 3.13.13\nQuality: 88/100 | Updated: 2026-05-21\n\"\"\"\n\nimport os\n\nimport pandas as pd\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    element_rect,\n    geom_rect,\n    geom_text,\n    ggplot,\n    ggsave,\n    ggsize,\n    layer_tooltips,\n    scale_fill_identity,\n    theme,\n    theme_void,\n    xlim,\n    ylim,\n)\n\n\nLetsPlot.setup_html()\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n# Code 128 encoding patterns: each digit is the width of alternating bar/space elements\nCODE128_PATTERNS = {\n    0: \"212222\",\n    1: \"222122\",\n    2: \"222221\",\n    3: \"121223\",\n    4: \"121322\",\n    5: \"131222\",\n    6: \"122213\",\n    7: \"122312\",\n    8: \"132212\",\n    9: \"221213\",\n    10: \"221312\",\n    11: \"231212\",\n    12: \"112232\",\n    13: \"122132\",\n    14: \"122231\",\n    15: \"113222\",\n    16: \"123122\",\n    17: \"123221\",\n    18: \"223211\",\n    19: \"221132\",\n    20: \"221231\",\n    21: \"213212\",\n    22: \"223112\",\n    23: \"312131\",\n    24: \"311222\",\n    25: \"321122\",\n    26: \"321221\",\n    27: \"312212\",\n    28: \"322112\",\n    29: \"322211\",\n    30: \"212123\",\n    31: \"212321\",\n    32: \"232121\",\n    33: \"111323\",\n    34: \"131123\",\n    35: \"131321\",\n    36: \"112313\",\n    37: \"132113\",\n    38: \"132311\",\n    39: \"211313\",\n    40: \"231113\",\n    41: \"231311\",\n    42: \"112133\",\n    43: \"112331\",\n    44: \"132131\",\n    45: \"113123\",\n    46: \"113321\",\n    47: \"133121\",\n    48: \"313121\",\n    49: \"211331\",\n    50: \"231131\",\n    51: \"213113\",\n    52: \"213311\",\n    53: \"213131\",\n    54: \"311123\",\n    55: \"311321\",\n    56: \"331121\",\n    57: \"312113\",\n    58: \"312311\",\n    59: \"332111\",\n    60: \"314111\",\n    61: \"221411\",\n    62: \"431111\",\n    63: \"111224\",\n    64: \"111422\",\n    65: \"121124\",\n    66: \"121421\",\n    67: \"141122\",\n    68: \"141221\",\n    69: \"112214\",\n    70: \"112412\",\n    71: \"122114\",\n    72: \"122411\",\n    73: \"142112\",\n    74: \"142211\",\n    75: \"241211\",\n    76: \"221114\",\n    77: \"413111\",\n    78: \"241112\",\n    79: \"134111\",\n    80: \"111242\",\n    81: \"121142\",\n    82: \"121241\",\n    83: \"114212\",\n    84: \"124112\",\n    85: \"124211\",\n    86: \"411212\",\n    87: \"421112\",\n    88: \"421211\",\n    89: \"212141\",\n    90: \"214121\",\n    91: \"412121\",\n    92: \"111143\",\n    93: \"111341\",\n    94: \"131141\",\n    95: \"114113\",\n    96: \"114311\",\n    97: \"411113\",\n    98: \"411311\",\n    99: \"113141\",\n    100: \"114131\",\n    101: \"311141\",\n    102: \"411131\",\n    103: \"211412\",  # Start Code A\n    104: \"211214\",  # Start Code B\n    105: \"211232\",  # Start Code C\n    106: \"2331112\",  # Stop (7 elements, 13 units)\n}\n\n# Code 128B maps ASCII 32–126 (printable chars) to values 0–94\nCODE128B_CHARS = {chr(i + 32): i for i in range(95)}\n\n# Data — shipping label barcode\ncontent = \"SHIP-2024-ABC123\"\n\n# Encode each character to its Code 128B symbol value\nchar_values = [CODE128B_CHARS.get(c, 0) for c in content]\n\n# Checksum: start-B constant (104) plus each value weighted by position (1-indexed)\nchecksum = 104\nfor i, v in enumerate(char_values):\n    checksum += v * (i + 1)\nchecksum = checksum % 103\n\n# Full symbol sequence: start-B + data symbols + check digit + stop\nsequence = [104] + char_values + [checksum, 106]\n\n# Rasterize symbols into bar rectangles; spaces are implicit gaps\nquiet_zone = 10\nx_pos = quiet_zone\nbar_ymin, bar_ymax = 32.0, 98.0\nbars = []\n\nfor sym_idx, code in enumerate(sequence):\n    if sym_idx == 0:\n        sym_label = \"Start Code B\"\n    elif sym_idx == len(sequence) - 1:\n        sym_label = \"Stop\"\n    elif sym_idx == len(sequence) - 2:\n        sym_label = f\"Check digit: {checksum}\"\n    else:\n        char = content[sym_idx - 1]\n        sym_label = f\"'{char}'  pos {sym_idx}  Code 128B value {char_values[sym_idx - 1]}\"\n    is_bar = True\n    for ch in CODE128_PATTERNS[code]:\n        w = int(ch)\n        if is_bar:\n            bars.append(\n                {\n                    \"xmin\": float(x_pos),\n                    \"xmax\": float(x_pos + w),\n                    \"ymin\": bar_ymin,\n                    \"ymax\": bar_ymax,\n                    \"fill\": \"#000000\",\n                    \"symbol\": sym_label,\n                }\n            )\n        x_pos += w\n        is_bar = not is_bar\n\ntotal_width = x_pos + quiet_zone\ncx = total_width / 2\n\ndf_bars = pd.DataFrame(bars)\n\n# White background rectangle ensures barcode contrast on both light and dark themes\ndf_barcode_bg = pd.DataFrame(\n    {\n        \"xmin\": [0.0],\n        \"xmax\": [float(total_width)],\n        \"ymin\": [bar_ymin - 4.0],\n        \"ymax\": [bar_ymax + 4.0],\n        \"fill\": [\"#FFFFFF\"],\n    }\n)\n\ndf_text = pd.DataFrame({\"x\": [cx], \"y\": [18.0], \"label\": [content]})\ndf_annotation = pd.DataFrame(\n    {\"x\": [cx], \"y\": [7.0], \"label\": [f\"{len(content)} chars · Code 128B · check digit: {checksum}\"]}\n)\ndf_subtitle = pd.DataFrame(\n    {\"x\": [cx], \"y\": [118.0], \"label\": [f\"Shipping label · Code 128B · {len(content)} characters\"]}\n)\ndf_title = pd.DataFrame({\"x\": [cx], \"y\": [127.0], \"label\": [\"barcode-code128 · python · letsplot · anyplot.ai\"]})\n\n# Plot\nplot = (\n    ggplot()\n    + geom_rect(\n        aes(xmin=\"xmin\", xmax=\"xmax\", ymin=\"ymin\", ymax=\"ymax\", fill=\"fill\"), data=df_barcode_bg, color=\"#FFFFFF\"\n    )\n    + geom_rect(\n        aes(xmin=\"xmin\", xmax=\"xmax\", ymin=\"ymin\", ymax=\"ymax\", fill=\"fill\"),\n        data=df_bars,\n        tooltips=layer_tooltips().line(\"@{symbol}\"),\n    )\n    + scale_fill_identity()\n    + geom_text(aes(x=\"x\", y=\"y\", label=\"label\"), data=df_text, size=14, color=INK)\n    + geom_text(aes(x=\"x\", y=\"y\", label=\"label\"), data=df_annotation, size=9, color=INK_SOFT)\n    + geom_text(aes(x=\"x\", y=\"y\", label=\"label\"), data=df_subtitle, size=9, color=INK_SOFT)\n    + geom_text(aes(x=\"x\", y=\"y\", label=\"label\"), data=df_title, size=11, color=INK_SOFT)\n    + xlim(0, total_width)\n    + ylim(0, 135)\n    + theme_void()\n    + theme(plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG), panel_background=element_rect(fill=PAGE_BG))\n    + ggsize(800, 450)\n)\n\nggsave(plot, f\"plot-{THEME}.png\", scale=4, path=\".\")\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}