Reed-Solomon Algorithmus (für ECC 200 Data Matrix bar code)

Für allgemeine Fragen zur Programmierung mit PureBasic.
andi256
Beiträge: 100
Registriert: 06.11.2004 11:23
Computerausstattung: PB 5.30 (x64) Win7
Wohnort: Österreich

Reed-Solomon Algorithmus (für ECC 200 Data Matrix bar code)

Beitrag von andi256 »

Hi

hab in meiner Arbeit ein neues Projekt ausgefaßt :-)


Wegen eines Kundenwunsches soll auf unseren Produkt-Typenschilder jetzt ein ECC 200 -Code ergänzt werden.
(in unserem Fall müsste zb."1234ABCDEF" codiert werden und als 14x14 2D-Matrix dargestellt werden)

im Prinzip bräuchte ich genau so einen DataMatrix Generator wie hier

hab mir da jetzt einwenig eingelesen ..... wo ich jetzt hänge ist das der ECC200 den Reed-Solomon-Code verwendet um Fehler zu korrigieren ....
(auf dieser Wiki versteh ich nur Bahnhof *lol* ... event. hat da wer was wo auch ich verstehe um was es bei diesen Algo geht)

Frage hat wer da was brauchbares (in PB) / Source codes / Source code snipplets / libs etc... was mir weiterhelfen könnte ?
(die source codes die ich gefunden hab sind wahnsinnig aufgeblasen ... und für mich nicht mehr lesbar ...)

Danke vorab Andi256
andi256
Beiträge: 100
Registriert: 06.11.2004 11:23
Computerausstattung: PB 5.30 (x64) Win7
Wohnort: Österreich

Re: Reed-Solomon Algorithmus (für ECC 200 Data Matrix bar co

Beitrag von andi256 »

so ... hier eine komplett abgespeckte Version (genügt in meinen Fall) für ein ECC200 Data Matrix Generator ...

das Zeug ist gar nicht so ohne !

die Eingabe ist nur gültig für 4 x nummerisch + 6 x Buchstaben .... ala 0000AAAAAA
(weitere Auswertungen / Prüfungen hab ich mir gespart)

falls noch wer Fragen / Ergänzungen hat/braucht ... immer hier rein damit :-)

Code: Alles auswählen

; andi256  PB4.60

#pixel  = 30
Global matrix = 12

#window = 0
#Image  = 0

#modulus_DM = $12d  ; 1 0010 1101 modulus
#gf = $100

Enumeration
 #Gadget_text_Nr 
 #Gadget_String_Nr
 #Gadget_Image 
EndEnumeration

Structure BYTEARRAY
 b.a[#gf]
EndStructure

DataSection
 ; 14x14  -> 12x12 pixel -> 18 Byte   -> 8 Daten 10 Fehler
 Matrix12x12:
 Data.l 2,1 , 2,2 ,  3,6 ,  3,7 ,  3,8 ,  4,3 ,  4,4 ,  4,5 , 13,1 , 13,2 ,  8,4 ,  8,5
 Data.l 2,3 , 2,4 ,  2,5 ,  5,1 ,  5,2 ,  4,6 ,  4,7 ,  4,8 , 13,3 , 13,4 , 13,5 ,  8,6
 Data.l 2,6 , 2,7 ,  2,8 ,  5,3 ,  5,4 ,  5,5 , 12,1 , 12,2 , 13,6 , 13,7 , 13,8 ,  8,7
 Data.l 1,5 , 6,1 ,  6,2 ,  5,6 ,  5,7 ,  5,8 , 12,3 , 12,4 , 12,5 , 14,1 , 14,2 ,  8,8
 Data.l 1,8 , 6,3 ,  6,4 ,  6,5 , 11,1 , 11,2 , 12,6 , 12,7 , 12,8 , 14,3 , 14,4 , 14,5
 Data.l 7,2 , 6,6 ,  6,7 ,  6,8 , 11,3 , 11,4 , 11,5 , 15,1 , 15,2 , 14,6 , 14,7 , 14,8
 Data.l 7,4 , 7,5 , 10,1 , 10,2 , 11,6 , 11,7 , 11,8 , 15,3 , 15,4 , 15,5 ,  1,1 ,  1,2
 Data.l 7,7 , 7,8 , 10,3 , 10,4 , 10,5 , 16,1 , 16,2 , 15,6 , 15,7 , 15,8 ,  1,3 ,  1,4
 Data.l 9,1 , 9,2 , 10,6 , 10,7 , 10,8 , 16,3 , 16,4 , 16,5 , 18,1 , 18,2 ,  1,6 ,  1,7
 Data.l 9,3 , 9,4 ,  9,5 , 17,1 , 17,2 , 16,6 , 16,7 , 16,8 , 18,3 , 18,4 , 18,5 ,  7,1
 Data.l 9,6 , 9,7 ,  9,8 , 17,3 , 17,4 , 17,5 ,  3,1 ,  3,2 , 18,6 , 18,7 , 18,8 ,  7,3
 Data.l 8,1 , 8,2 ,  8,3 , 17,6 , 17,7 , 17,8 ,  3,3 ,  3,4 ,  3,5 ,  4,1 ,  4,2 ,  7,6
EndDataSection

Procedure clearimage() 
 StartDrawing(ImageOutput(#Image))
 Box(0,0,ImageWidth(#Image),ImageHeight(#Image),$FFFFFF)
 StopDrawing() 
EndProcedure

Procedure drawborder()
 StartDrawing(ImageOutput(#Image))
 Box(0,0,#pixel,matrix*#pixel+2*#pixel,RGB($00,$00,$00))
 Box(#pixel,matrix*#pixel+#pixel,matrix*#pixel+#pixel,#pixel,RGB($00,$00,$00))
 For i = 1 To matrix Step 2
  Box(        #pixel+#pixel*i,0       ,#pixel,#pixel,RGB($00,$00,$00))
  Box(matrix*#pixel+#pixel  ,i*#pixel,#pixel,#pixel,RGB($00,$00,$00))
 Next
 StopDrawing()
EndProcedure

Procedure drawbytes(*byte.BYTEARRAY)
 StartDrawing(ImageOutput(#Image))
 For i = 1 To (matrix*matrix/8)
  For k = 1 To 8 
   bit =  (*byte\b[i-1] >> (8-k)) & 1
    Restore Matrix12x12  
    For ze = 1 To matrix
     For sp = 1 To matrix
      Read.l a
      Read.l b
      If a = i And b = k
       Break 2
      EndIf
     Next
    Next
    If bit = 1
     Box(#pixel*sp,#pixel*ze,#pixel,#pixel,RGB($00,$00,$00))
    EndIf 
  Next
 Next 
 StopDrawing()
EndProcedure

Procedure decode_databytes(*wd.BYTEARRAY) 
 input$ = UCase(GetGadgetText(#Gadget_String_Nr))
 ; ersten 4 Zeichen müssen numerisch sein!!
 *wd\b[0] = Val(Mid(input$,1,2)) + 130  
 *wd\b[1] = Val(Mid(input$,3,2)) + 130
 ; switch C40 decoding , nächsten 6 Zeichen müssen Buchstaben (A-Z) sein!!
 *wd\b[2] = 230  
  a1 = Asc(Mid(input$,5,1)) - 51             ; A - ASCII = 65    A - C40 = 14  65-14 = 51
  a2 = Asc(Mid(input$,6,1)) - 51 
  a3 = Asc(Mid(input$,7,1)) - 51  
  a = 1600*a1 + 40*a2 + a3 + 1
 *wd\b[3] = a / 256
 *wd\b[4] = a % 256
  a1 = Asc(Mid(input$, 8,1)) - 51           
  a2 = Asc(Mid(input$, 9,1)) - 51 
  a3 = Asc(Mid(input$,10,1)) - 51  
  a = 1600*a1 + 40*a2 + a3 + 1
 *wd\b[5] = a / 256
 *wd\b[6] = a % 256
 *wd\b[7] = 129  ; -> Padding
EndProcedure

; "prod(x,y,log,alog,gf)" returns the product "x" times "y" 
Procedure prod(x,y,*log.BYTEARRAY,*alog.BYTEARRAY) 
 If x=0 Or y=0 
  ProcedureReturn 0
 Else 
  ProcedureReturn *alog\b[(*log\b[x] + *log\b[y]) % (#gf-1)]
 EndIf
EndProcedure

Procedure ReedSolomon(*wd.BYTEARRAY,nd,nc) 
 ; allocate, then generate the log & antilog arrays: 
 *log.BYTEARRAY  = AllocateMemory(512)
 *alog.BYTEARRAY = AllocateMemory(512)
 *log\b[0] = 0;1-gf
 *alog\b[0] = 1
 For i = 1 To #gf -2
  wert = *alog\b[i-1] * 2
  If wert >= #gf 
   *alog\b[i] = (wert ! #modulus_DM) &$FF
  Else 
   *alog\b[i] = wert & $FF
  EndIf 
  *log\b[*alog\b[i]] = i
 Next
  ; allocate, then generate the generator polynomial coefficients: 
 *c.BYTEARRAY = AllocateMemory(nd+nc)
 For i=1 To nc
  *c\b[i] = 0
 Next
 *c\b[0] = 1
 For i=1 To nc 
  *c\b[i] = *c\b[i-1]
  For j = i-1 To 1 Step -1
   *c\b[j] = *c\b[j-1] ! prod(*c\b[j],*alog\b[i],*log,*alog)
  Next
  *c\b[0] = prod(*c\b[0],*alog\b[i],*log,*alog)
 Next
 ; clear, then generate "nc" checkwords in the Array wd[] : 
 For i=nd To nd+nc
  *wd\b[i] = 0
 Next
 For i=0 To nd -1 
  k = (*wd\b[nd] ! *wd\b[i] ) & $FF
  For j=0 To nc - 1 
  *wd\b[nd+j] = *wd\b[nd+j+1] ! prod(k,*c\b[nc-j-1],*log,*alog)
  Next
 Next
 FreeMemory(*c)
 FreeMemory(*alog)
 FreeMemory(*log)
EndProcedure 

Procedure generate() 
 clearimage() 
 *wd = AllocateMemory(180)
 decode_databytes(*wd)
 reedSolomon(*wd,8,10) 
 drawborder()
 drawbytes(*wd)
 SetGadgetState(#Gadget_Image ,ImageID(#Image))
 FreeMemory(*wd)
EndProcedure

; Main
CreateImage(#Image,matrix*#pixel+2*#pixel,matrix*#pixel+2*#pixel,32)
OpenWindow(#window,500,500,matrix*#pixel+2*#pixel+20,matrix*#pixel+2*#pixel+50,"Barcode ECC 200")
TextGadget  (#Gadget_text_Nr    ,10, 12, 70,20,"Code.:")
StringGadget(#Gadget_String_Nr  ,80, 10,130,20,"0001ZNEAME")
ImageGadget (#Gadget_Image      ,10, 32,matrix*#pixel+2*#pixel,matrix*#pixel+2*#pixel,ImageID(#Image)) 

Repeat
 Select WindowEvent()
  Case 0 
   Delay(1)
  Case #PB_Event_CloseWindow
   End
  Case #PB_Event_Gadget  
   Select EventGadget()
    Case #Gadget_String_Nr
     generate()    
    EndSelect
  EndSelect 
ForEver 
andi256
andi256
Beiträge: 100
Registriert: 06.11.2004 11:23
Computerausstattung: PB 5.30 (x64) Win7
Wohnort: Österreich

Re: Reed-Solomon Algorithmus (für ECC 200 Data Matrix bar co

Beitrag von andi256 »

Hallo muss nochmals lästig sein...

im obigen Code werden in der Procedure "decode_databytes" bei einen 14x14 Matrix 8 Bytes für die Eingabe übergeben...

Code: Alles auswählen

Procedure decode_databytes(*wd.BYTEARRAY)
 input$ = UCase(GetGadgetText(#Gadget_String_Nr))
 *wd\b[0] = 
 *wd\b[1] =
 *wd\b[2] = 
 *wd\b[3] = 
 *wd\b[4] = 
 *wd\b[5] = 
 *wd\b[6] = 
 *wd\b[7] = 
EndProcedure
soweit so gut ... nur gibt es mehrere Möglichkeiten die Daten zu codieren:

Mein Problem liegt darin das ich nicht wirklich verstanden habe, nach welcher Methodik der Eingangs-String aufgeteilt wird.

Möglichkeiten zu codieren:
1) als ASCII

Code: Alles auswählen

*wd\b[0] = Asc(Mid(input$,1,1)) + 1    ; 
2) als zweistelliges Zahlenpaar

Code: Alles auswählen

*wd\b[0] = Val(Mid(input$, 1,2)) + 130  ; 
3) als C40 - Code

Code: Alles auswählen

 *wd\b[0] = 230                                  ; switch to C40
  a1 = Asc(Mid(input$,1,1)) - 51             ; (A - ASCII = 65    A - C40 = 14  65-14 = 51)
  a2 = Asc(Mid(input$,2,1)) - 51
  a3 = Asc(Mid(input$,3,1)) - 51 
  a = 1600*a1 + 40*a2 + a3 + 1
 *wd\b[1] = a / 256
 *wd\b[2] = a % 256
Die Codierung ist zwar in der ISO/IEC 16022 beschrieben aber nicht wann welche üblich verwendet wird.

so erhält man zb. als Eingabestring "12345678901" mehrere Möglichkeiten ...

Variante 1

Code: Alles auswählen

 *wd\b[0] = Val(Mid(input$, 1,2)) + 130  ; 12  (Zahlenpaar)
 *wd\b[1] = Val(Mid(input$, 3,2)) + 130  ; 34
 *wd\b[2] = Val(Mid(input$, 5,2)) + 130  ; 56
 *wd\b[3] = Asc(Mid(input$, 7,1)) + 1    ; 7    (ASCII)
 *wd\b[4] = Asc(Mid(input$, 8,1)) + 1    ; 8
 *wd\b[5] = Asc(Mid(input$, 9,1)) + 1    ; 9
 *wd\b[6] = Asc(Mid(input$,10,1)) + 1    ; 0
 *wd\b[7] = Asc(Mid(input$,11,1)) + 1    ; 1
Variante 2

Code: Alles auswählen

 *wd\b[0] = Val(Mid(input$, 1,2)) + 130  ; 12  
 *wd\b[1] = Val(Mid(input$, 3,2)) + 130  ; 34
 *wd\b[2] = Val(Mid(input$, 5,2)) + 130  ; 56
 *wd\b[3] = Val(Mid(input$, 7,2)) + 130  ; 78
 *wd\b[4] = Asc(Mid(input$, 9,1)) + 1    ; 9
 *wd\b[5] = Asc(Mid(input$,10,1)) + 1    ; 0
 *wd\b[6] = Asc(Mid(input$,11,1)) + 1    ; 1
 *wd\b[7] = 129  ; -> Padding
Variante 3

Code: Alles auswählen

 *wd\b[0] = Val(Mid(input$, 1,2)) + 130  ; 12  
 *wd\b[1] = Val(Mid(input$, 3,2)) + 130  ; 34
 *wd\b[2] = Val(Mid(input$, 5,2)) + 130  ; 56
 *wd\b[3] = Val(Mid(input$, 7,2)) + 130  ; 78
 *wd\b[4] = Val(Mid(input$, 9,2)) + 130  ; 90
 *wd\b[5] = Asc(Mid(input$,11,1)) + 1    ; 1
 *wd\b[6] = 129  ; -> Padding
 *wd\b[7] = 56   ; -> ?????
alle drei liefen ein anderes Bild Ergebnis ...

der generierte ECC-Code liefert zwar ein richtiges Ergebnis wenn man ihn scannt,
jedoch muss es ja da eine Methodik geben wie man das richtig erstellt, um auf die gleichen Ergebnisse zu kommen wie professionelle Code Generatoren.

PS.
Professionelle Code-Generatoren erzeugen die 8 Bytes nach Variante 3 ...wobei mir hier das 8.Byte "*wd\b[7] = 56" auch rätselhaft ist ?

Danke Andi
Benutzeravatar
dige
Beiträge: 1239
Registriert: 08.09.2004 08:53

Re: Reed-Solomon Algorithmus (für ECC 200 Data Matrix bar code)

Beitrag von dige »

Hallöchen, ich suche gerade nach einer Möglichkeit, einen DataMatrix Barcode zu erstellen. @Andi256: konntest du denn dein Problem noch lösen?
"Papa, ich laufe schneller - dann ist es nicht so weit."
Antworten