Simple Code-39 BarcodeGadget()

Share your advanced PureBasic knowledge/code with the community.
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Simple Code-39 BarcodeGadget()

Post by TI-994A »

Following the numerical UPC-A barcode gadget, here's an alpha-numerical Code-39 version. The implementation syntax is as follows:

Code: Select all

BarcodeGadget39(gadgetNo, x, y, width, height, barcodeString$ [, colour [, displayLabelBool]])
gadgetNo = BarcodeGadget39(#PB_Any, x, y, width, height, barcodeString$ [, colour [, displayLabelBool]])
Image

Code: Select all

;==============================================================
;   BarcodeGadget39() converts any given string (43-char max,
;   only upper case A-Z, space, 0-9, and + - / * $ % .) into
;   a valid Code39 barcode and displays it in an image gadget.
;   Compressing the widths of longer barcodes would severely 
;   compromise the readability by barcode readers/scanners.
;
;   credit to Poshu for the Code-39 barcode algorithm.
;
;   Tested & working on Windows 8.1 & 10 and OSX Lion,
;   running PureBasic v5.60, v5.41, v5.40 respectively. 
;
;   by TI-994A - free to use, improve, share...
;
;   27th April 2017
;==============================================================

;self-contained BarcodeGadget39() procedure
Procedure BarcodeGadget39(gadgetNo.i, x.i, y.i, bcWidth.i, bcHeight.i, 
                          bcText.s, bcColor.i = 0, bcLabel = #True)
  Static gadgetInitialised, bcTextFont
  Protected gNo, i, ii, mf, *tb.byte
  Protected invalidChar, charWidth, bcCharAsc, bcTextChar.s
  Protected bcImage, bcTextLen, bcRawWidth, bcTextWidth, bcTextHeight
    
  bcText = UCase(bcText)
  For i = 1 To Len(bcText)
    bcCharAsc = Asc(Mid(bcText, i, 1))
    If bcCharAsc = 32 Or  
       (bcCharAsc >= 36 And bcCharAsc <= 37) Or 
       (bcCharAsc >= 42 And bcCharAsc <= 43) Or
       (bcCharAsc >= 48 And bcCharAsc <= 57) Or
       (bcCharAsc >= 45 And bcCharAsc <= 47) Or
       (bcCharAsc >= 65 And bcCharAsc <= 90)
      Continue
    Else
      invalidChar = #True
      Break
    EndIf
  Next
  
  If Not gadgetInitialised
    Protected asc, bin, asc$
    bcTextFont = LoadFont(#PB_Any, "Arial", 10)
    Static NewMap binDec.i()
    Restore ascBinData
    For i = 0 To 43
      Read asc
      Read bin
      asc$ = Chr(asc)
      binDec(asc$) = AllocateMemory(32) 
      PokeL(binDec(asc$), bin)
    Next
    gadgetInitialised = #True
  EndIf
  
  charWidth = 19
  bcTextLen = Len(bcText) + 1
  bcText = "*" + bcText + "*"
  bcRawWidth = bcTextLen * charWidth + 18
  bcImage = CreateImage(#PB_Any, bcRawWidth, bcHeight, 32, #White)
  
  If bcImage
    StartDrawing(ImageOutput(bcImage))
      If invalidChar
        DrawText(10, 10, "> INVALID CHARACTER IN BARCODE <", #White, #Red)
      Else
        For i = 0 To bcTextLen
          bcTextChar = Mid(bcText, i + 1, 1)
          For ii = 0 To 18
            mf = (ii % 8)
            *tb = binDec(bcTextChar) + (ii >> 3)
            If (*tb\b & (1 << mf)) >> mf
              Line(i * charWidth + ii, 0, 1, bcHeight, bcColor)
            EndIf
          Next
        Next
        If bcLabel
          bcTextChar = ""
          For i = 1 To Len(bcText)
            bcTextChar + Mid(bcText, i, 1) + " "
          Next i
          bcText = "  " + bcTextChar + " "
          DrawingFont(FontID(bcTextFont))
          bcTextWidth = TextWidth(bcText)
          bcTextHeight = TextHeight(bcText)
          DrawText((bcRawWidth - bcTextWidth) / 2, bcHeight - bcTextHeight, 
                   bcText, bcColor, RGB(255, 255, 255))
        EndIf      
      EndIf      
    StopDrawing()
  EndIf
  
  ;compressing the widths of longer barcodes corrupts scanner-readability
  ;uncomment this line to size the barcode according to the gadget width
  ;ResizeImage(bcImage, bcWidth, bcHeight)
  
  gNo = ImageGadget(gadgetNo, x, y, bcWidth, bcHeight, ImageID(bcImage))
  If gadgetNo = #PB_Any
    gadgetNo = gNo
  EndIf   
  
  ProcedureReturn gadgetNo
  
  ;the data block is included within the procedure for portability - can be positioned anywhere in the code
  DataSection 
  ascBinData:
    Data.i 65, 250031, 66, 250045, 67, 181743, 68, 250341, 69, 182191, 70, 182205, 71, 252965, 72, 159919
    Data.i 73, 159933, 74, 192997, 75, 246959, 76, 246973, 77, 136687, 78, 247269, 79, 137135, 80, 137149
    Data.i 81, 247717, 82, 138415, 83, 138429, 84, 138725, 85, 251023, 86, 251361, 87, 186255, 88, 251809
    Data.i 89, 155279, 90, 188385, 48, 194437, 49, 250927, 50, 250941, 51, 184815, 52, 251781, 53, 187951
    Data.i 54, 187965, 55, 253061, 56, 193583, 57, 193597, 32, 194017, 36, 181281, 37, 135301, 42, 194465
    Data.i 43, 135329, 45, 253089, 46, 160911, 47, 136225
  EndDataSection  
  
EndProcedure

;implementation demo
wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered 
win = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 950, 450,
                 "Simple Code-39 Barcode Gadget", wFlags)

;default options - black barcode with barcode number overlaid
bcg = BarcodeGadget39(#PB_Any, 50, 50, 500, 50, "code39 barcode generator")

;blue barcode without barcode number overlaid
BarcodeGadget39(0, 50, 150, 600, 50, "code39 barcode generator", #Blue, #False)

;green barcode with barcode number overlaid
BarcodeGadget39(1, 50, 250, 300, 50, "short descriptor", RGB(00, 99, 33))

;very long 43-char barcode in red with number overlaid
BarcodeGadget39(2, 50, 350, 800, 50, "up to 43 chars long but proportionate width", #Red)

While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
It accepts only uppercase alpha-numeric strings and a handful of special characters. The width of the generated barcode is proportionate to the length of the given string. Compressing the width too much would compromise scanner readability.

Any and all feedback welcome. Thank you. :D
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: Simple Code-39 BarcodeGadget()

Post by RSBasic »

Works fine, thank you for your code. Image
Image
Image
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5352
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Simple Code-39 BarcodeGadget()

Post by Kwai chang caine »

Here too, thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: Simple Code-39 BarcodeGadget()

Post by RSBasic »

Can you write a code to decrypt from barcode image?
Image
Image
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Simple Code-39 BarcodeGadget()

Post by TI-994A »

Thank you for the kind feedback. Truly appreciated. :D

In all honesty, generating the barcodes are more of an emulation than anything else. Knowing the encoding, the bars are simply drawn based on the binary values.

Reading and translating the barcode images back to their original values would be a slightly bigger task, which might be beyond me. :lol:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Marc56us
Addict
Addict
Posts: 1479
Joined: Sat Feb 08, 2014 3:26 pm

Re: Simple Code-39 BarcodeGadget()

Post by Marc56us »

Thanks for sharing :)

Barcodes are increasingly used, even for small businesses. It would be nice if Fred would add that to the image lib :idea:
(At least the main: Code-39, Code-128, QRCode, Datamatrix)

:wink:
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Simple Code-39 BarcodeGadget()

Post by TI-994A »

Marc56us wrote:Thanks for sharing :)

Barcodes are increasingly used, even for small businesses. It would be nice if Fred would add that to the image lib :idea:
(At least the main: Code-39, Code-128, QRCode, Datamatrix)

:wink:
Just a Q&D solution. Clearly, a native PureBasic implementation would be ultimate. :D
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Simple Code-39 BarcodeGadget()

Post by Fangbeast »

TI-994A wrote:
Marc56us wrote:Thanks for sharing :)

Barcodes are increasingly used, even for small businesses. It would be nice if Fred would add that to the image lib :idea:
(At least the main: Code-39, Code-128, QRCode, Datamatrix)

:wink:
Just a Q&D solution. Clearly, a native PureBasic implementation would be ultimate. :D
Nothing wrong with your solution. Now if only my wife would go to sleep so I could play with it undisturbed:):)

Don't tell her I said that!!!!
Amateur Radio, D-STAR/VK3HAF
Post Reply