|
Hello.
I am trying to run this algorithm for Code39 using the code that was provided by Cyos in this thread. But it does not work for me, as usually - I have a bad luck
I don't understand why both algorithms use property System.Drawing.Imaging.BitmapData.Stride and what it means. My image has dimension 226 x 80, but the Stride (which should represent a line of an image) has size of 32. Why not complete rows are scanned by ScanRow() method?
data = bmp.LockBits( ... )
For y = 0 To bmp.Height - 1
For x = 0 To data.Stride - 1
ScanRow(x) = System.Runtime.InteropServices.Marshal.ReadByte(data.Scan0, data.Stride * y + x)
Next
Scan(ScanRow, 0, bmp.Width)
Next
And can anyone explain the overall idea of methods in this algorithm? It is not commented, plus uses non-descriptive variable names. I have spent with it a few hours and still do not understand.
modified 29-Aug-14 5:40am.
|
|
|
|
|
Ok, so the problem probably was in method CreateSymbolTable() in class that decodes Code39. After row:
StartSymbol = New gmseNWBarcodeSymbol(-1, "Start", "NWNNWNWNN")
You have to add this line:
hash.Add(StartSymbol.Encoding, StartSymbol)
The reason is, that in method Decode1() is correctly solved situation when the start-character of a barcode is read:
If String.Compare(sym, StartSymbol.Encoding, True) <> 0 Then
Return ""
End If
... but the same character, when used as trailing character, is searched in an "array" named "hash". If it is not found, then all so far decoded content is discarded. Maybe the whole comparison is useless.
|
|
|
|
|
how to read EAN8 or EAN13 barcode from an image using c#/.net?
plz help me...
|
|
|
|
|
And what about reading barcode type 39? Have you developed the algoritm to read it too?
Thank you.
bye
|
|
|
|
|
Just found this code the other week and actually wanted it to do code 39 i am posting my edit of the code that will read code 39
|
|
|
|
|
' Original Author: Georg Mackenbrock (c) 2006
' Barcode Reader for code 39
' Edited by 39412
Imports System.Text
Imports System.Drawing
Imports System.Drawing.Imaging
#Region "Barcode Structures"
Public Class gmseNWResult
Public Text As String
Public Count As Integer
End Class
Public Class gmseNWResultCollection
Implements IEnumerable
Dim hash As New Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default)
ReadOnly Property Count() As Integer
Get
Return hash.Count
End Get
End Property
ReadOnly Property Item(ByVal Index As Integer) As gmseNWResult
Get
Return hash(Index)
End Get
End Property
Public Sub Add(ByVal Text As String)
Dim r As gmseNWResult
r = hash(Text)
If r Is Nothing Then
r = New gmseNWResult
r.Text = Text
hash.Add(r.Text, r)
End If
r.Count += 1
End Sub
Public Sub Remove(ByVal MinHeight As Integer)
Dim r As gmseNWResult
Dim tmp As New Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default)
For Each r In hash.Values
If r.Count >= MinHeight Then
tmp.Add(r.Text, r)
End If
Next
hash = tmp
End Sub
Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
Return hash.Values.GetEnumerator
End Function
End Class
#End Region
' Definition of one Symbol
Public Class gmseNWBarcodeSymbol
Public Value As Integer
Public Text As String
' Encoding of Symbol in NW notation
Public Encoding As String
Public Sub New(ByVal Value As Integer, ByVal Text As String, ByVal Encoding As String)
Me.Value = Value
Me.Text = Text
Me.Encoding = Encoding
End Sub
End Class
' Abstract parameters für barcode decoding for further extensions (2 of 5 standard,...)
Public MustInherit Class gmseNWBarcodeDef
' Minimum count of bars for a valid barcode.
MustOverride ReadOnly Property MinBarCount() As Integer
' Decode nw representation to text.
Public MustOverride Function Decode(ByVal symbol As String) As String
' NWidth * Fkt <WWidth (relation between narrow width and wide width.
Overridable ReadOnly Property MaxFktNW() As Integer
Get
Return 10
End Get
End Property
' upped the tolerance to 67% due to bad scans 39412
Overridable ReadOnly Property PctNWTolerance() As Double
Get
Return 0.67
End Get
End Property
' Min length of white space before first bar and after last bar in percent of wide bar (Quiet zone).
Overridable ReadOnly Property PctMinWhiteSpace() As Double
Get
Return 0
End Get
End Property
' Barcode must be at least MinHeight height.
Overridable ReadOnly Property MinHeight() As Integer
Get
Return 2
End Get
End Property
End Class
' Definition 2 of 5 interleaved
Public Class gmseBarcodeDef2of5interleaved
Inherits gmseNWBarcodeDef
Dim StartSymbol As gmseNWBarcodeSymbol
Dim StopSymbol As gmseNWBarcodeSymbol
Dim hash As New Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default)
' We only accept barcodes with at least 23 bars.
Public Overrides ReadOnly Property MinBarCount() As Integer
Get
Return 23
End Get
End Property
Private Sub CreateSymbolTable()
'in code 39 there are 43 chars
Dim BaseSymbol(43) As gmseNWBarcodeSymbol
Dim sym As gmseNWBarcodeSymbol
Dim x As Integer
Dim Text As String
Dim i As Integer
'code 39 symbols
BaseSymbol(0) = New gmseNWBarcodeSymbol(0, "0", "NNNWWNWNN")
BaseSymbol(1) = New gmseNWBarcodeSymbol(1, "1", "WNNWNNNNW")
BaseSymbol(2) = New gmseNWBarcodeSymbol(2, "2", "NNWWNNNNW")
BaseSymbol(3) = New gmseNWBarcodeSymbol(3, "3", "WNWWNNNNN")
BaseSymbol(4) = New gmseNWBarcodeSymbol(4, "4", "NNNWWNNNW")
BaseSymbol(5) = New gmseNWBarcodeSymbol(5, "5", "WNNWWNNNN")
BaseSymbol(6) = New gmseNWBarcodeSymbol(6, "6", "NNWWWNNNN")
BaseSymbol(7) = New gmseNWBarcodeSymbol(7, "7", "NNNWNNWNW")
BaseSymbol(8) = New gmseNWBarcodeSymbol(8, "8", "WNNWNNWNN")
BaseSymbol(9) = New gmseNWBarcodeSymbol(9, "9", "NNWWNNWNN")
BaseSymbol(10) = New gmseNWBarcodeSymbol(10, "A", "WNNNNWNNW")
BaseSymbol(11) = New gmseNWBarcodeSymbol(11, "B", "NNWNNWNNW")
BaseSymbol(12) = New gmseNWBarcodeSymbol(12, "C", "WNWNNWNNN")
BaseSymbol(13) = New gmseNWBarcodeSymbol(13, "D", "NNNNWWNNW")
BaseSymbol(14) = New gmseNWBarcodeSymbol(14, "E", "WNNNWWNNN")
BaseSymbol(15) = New gmseNWBarcodeSymbol(15, "F", "NNWNWWNNN")
BaseSymbol(16) = New gmseNWBarcodeSymbol(16, "G", "NNNNNWWNW")
BaseSymbol(17) = New gmseNWBarcodeSymbol(17, "H", "WNNNNWWNN")
BaseSymbol(18) = New gmseNWBarcodeSymbol(18, "I", "NNWNNWWNN")
BaseSymbol(19) = New gmseNWBarcodeSymbol(19, "J", "NNNNWWWNN")
BaseSymbol(20) = New gmseNWBarcodeSymbol(20, "K", "WNNNNNNWW")
BaseSymbol(21) = New gmseNWBarcodeSymbol(21, "L", "NNWNNNNWW")
BaseSymbol(22) = New gmseNWBarcodeSymbol(22, "M", "WNWNNNNWN")
BaseSymbol(23) = New gmseNWBarcodeSymbol(23, "N", "NNNNWNNWW")
BaseSymbol(24) = New gmseNWBarcodeSymbol(24, "O", "WNNNWNNWN")
BaseSymbol(25) = New gmseNWBarcodeSymbol(25, "P", "NNWNWNNWN")
BaseSymbol(26) = New gmseNWBarcodeSymbol(26, "Q", "NNNNNNWWW")
BaseSymbol(27) = New gmseNWBarcodeSymbol(27, "R", "WNNNNNWWN")
BaseSymbol(28) = New gmseNWBarcodeSymbol(28, "S", "NNWNNNWWN")
BaseSymbol(29) = New gmseNWBarcodeSymbol(29, "T", "NNNNWNWWN")
BaseSymbol(30) = New gmseNWBarcodeSymbol(30, "U", "WWNNNNNNW")
BaseSymbol(31) = New gmseNWBarcodeSymbol(31, "V", "NWWNNNNNW")
BaseSymbol(32) = New gmseNWBarcodeSymbol(32, "W", "WWWNNNNNN")
BaseSymbol(33) = New gmseNWBarcodeSymbol(33, "X", "NWNNWNNNW")
BaseSymbol(34) = New gmseNWBarcodeSymbol(34, "Y", "WWNNWNNNN")
BaseSymbol(35) = New gmseNWBarcodeSymbol(35, "Z", "NWWNWNNNN")
BaseSymbol(36) = New gmseNWBarcodeSymbol(36, "-", "NWNNNNWNW")
BaseSymbol(37) = New gmseNWBarcodeSymbol(37, ".", "WWNNNNWNN")
BaseSymbol(38) = New gmseNWBarcodeSymbol(38, " ", "NWWNNNWNN")
BaseSymbol(39) = New gmseNWBarcodeSymbol(39, "$", "NWNWNWNNN")
BaseSymbol(40) = New gmseNWBarcodeSymbol(40, "/", "NWNWNNNWN")
BaseSymbol(41) = New gmseNWBarcodeSymbol(41, "+", "NWNNNWNWN")
BaseSymbol(42) = New gmseNWBarcodeSymbol(42, "%", "NNNWNWNWN")
' Buildung the hash for decoding:
For x = 0 To 42
Text = ""
For i = 0 To 8
Text &= BaseSymbol(x).Encoding.Chars(i)
Next
sym = New gmseNWBarcodeSymbol(x, BaseSymbol(x).Text, Text)
hash.Add(sym.Encoding, sym)
Next
StartSymbol = New gmseNWBarcodeSymbol(-1, "Start", "NWNNWNWNN")
'in code 39 the start and stop symbols are the same
End Sub
Public Sub New()
CreateSymbolTable()
End Sub
Public Overrides Function Decode(ByVal symbol As String) As String
Return Decode1(symbol, 0)
End Function
' Get human readable text from the barcode.
Public Function Decode1(ByVal symbol As String, ByVal offset As Integer) As String
Dim sym As String
Dim sb As New StringBuilder
Dim Pos As Integer = offset
Dim bi As gmseNWBarcodeSymbol
sym = symbol.Substring(Pos, StartSymbol.Encoding.Length)
' Make sure that the first symbol is the start symbol
If String.Compare(sym, StartSymbol.Encoding, True) <> 0 Then
Return ""
End If
' Get past the start symbol so we can start decoding.
Pos += StartSymbol.Encoding.Length + 1
' Data
While Pos < symbol.Length
'symbols are 9 bars long plus the narrow whitespace
If symbol.Length - Pos > 10 Then
sym = symbol.Substring(Pos, 9)
bi = hash(sym)
If bi Is Nothing Then
Return ""
End If
sb.Append(bi.Text)
Pos += 10
ElseIf String.Compare(sym, StartSymbol.Encoding, True) <> 0 Then ' StopSymbol and start symbol are the same
sym = symbol.Substring(Pos, 9)
bi = hash(sym)
If bi Is Nothing Then
Return ""
Else
Return sb.ToString
End If
Else
Return ""
End If
End While
Return ""
End Function
End Class
' Scanning algorithm:
Public Class gmseNWScanner
Dim cBitMask(7) As Byte
Dim cScanRow() As Byte
Dim nBar As Integer
Dim cBarWidth() As Integer
Dim cBarBlack() As Boolean
Dim cOffset As Integer
Dim cLength As Integer
Dim cNWidth As Integer
Dim cWWidth As Integer
Dim cBCDef As gmseNWBarcodeDef
Dim cResult As gmseNWResultCollection
ReadOnly Property Result() As gmseNWResultCollection
Get
Return cResult
End Get
End Property
' Find all Code 39 barcodes in Bitmap
Public Sub Scan(ByVal bmp As Bitmap)
Dim data As BitmapData
Dim ScanRow() As Byte
Dim y As Integer
Dim x As Integer
data = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed)
Try
cResult = New gmseNWResultCollection
ReDim ScanRow(data.Stride - 1)
' Scan all rows of bitmap.
For y = 0 To bmp.Height - 1
For x = 0 To data.Stride - 1
ScanRow(x) = System.Runtime.InteropServices.Marshal.ReadByte(data.Scan0, data.Stride * y + x)
Next
Scan(ScanRow, 0, bmp.Width)
Next
cResult.Remove(cBCDef.MinHeight)
Finally
bmp.UnlockBits(data)
End Try
End Sub
' ScanRow must be 1bppp format.
Private Sub Scan(ByVal ScanRow() As Byte, ByVal offset As Integer, ByVal Length As Integer)
cScanRow = ScanRow
cLength = Length
cOffset = offset
CalcBars()
Scan()
End Sub
' Calculate bars
Private Sub CalcBars()
Dim x As Integer
Dim bl As Boolean
nBar = 0
ReDim cBarWidth(10)
ReDim cBarBlack(10)
cBarBlack(0) = IsBlack(cOffset)
For x = 0 To cLength - 1
If nBar >= cBarWidth.Length - 1 Then
ReDim Preserve cBarWidth(nBar * 2)
ReDim Preserve cBarBlack(nBar * 2)
End If
bl = IsBlack(cOffset + x)
If cBarBlack(nBar) = bl Then
cBarWidth(nBar) += 1
Else
nBar += 1
cBarBlack(nBar) = bl
cBarWidth(nBar) = 1
End If
Next
nBar += 1
End Sub
' The scan
Private Sub Scan()
Dim Pos As Integer
Dim ValidNW As Boolean
Dim BCStart As Integer
Dim BCEnde As Integer
Dim Text As String
Dim sb As StringBuilder
Dim nwt As Integer
' We want a leading white space, so we start at position 1
Pos = 1
While Pos < nBar - cBCDef.MinBarCount
' Start with a black bar
If cBarBlack(Pos) Then
' Try to validate with a sample set, if we can classify the bars in N and W bars within a tolerance of 25%.
ValidNW = CalcNWWidth(Pos, cBCDef.MinBarCount)
If ValidNW Then ' n und w are OK.
sb = New StringBuilder
BCStart = Pos
BCEnde = Pos
' Start to decode, until no more valid bars are found.
While Pos < nBar
nwt = NWBarType(cBarWidth(Pos))
If nwt = -1 Then
Exit While
ElseIf nwt = 0 Then
sb.Append("n")
Else
sb.Append("w")
End If
BCEnde += 1
Pos += 1
End While
BCEnde -= 1
Text = cBCDef.Decode(sb.ToString)
If Text <> "" Then
cResult.Add(Text)
Debug.WriteLine(Text)
End If
Else
Pos += 1
End If
Else
Pos += 1
End If
End While
End Sub
' Classify width of a bar in -1: invalid, 0 N(arrow), 1 W(ide).
Private Function NWBarType(ByVal Width As Integer) As Integer
Dim MaxAbweichung As Double
Dim Abweichung As Integer
Abweichung = Math.Min(Math.Abs(Width - cNWidth), Math.Abs(Width - cWWidth))
MaxAbweichung = (cWWidth - cNWidth) * cBCDef.PctNWTolerance
If Abweichung > MaxAbweichung Then
Return -1
ElseIf Math.Abs(Width - cNWidth) < Math.Abs(Width - cWWidth) Then
Return 0
Else
Return 1
End If
End Function
' Calculate Narrow and Wide bar width.
Private Function CalcNWWidth(ByVal Pos As Integer, ByVal Length As Integer) As Boolean
Dim NWidth As Integer
Dim WWidth As Integer
Dim tmp As Integer
Dim Abweichung As Double
Dim MaxAbweichung As Double
Dim i As Integer
' Calc Min and Max.
NWidth = cBarWidth(Pos)
WWidth = cBarWidth(Pos)
For i = 0 To Length - 1
tmp = cBarWidth(Pos + i)
If tmp > WWidth Then
WWidth = tmp
End If
If tmp < NWidth Then
NWidth = tmp
End If
Next
' As wide we accept as maximum NWidth * cBCDef.MaxFktNW
If NWidth * cBCDef.MaxFktNW < WWidth Then
cWWidth = 0
cNWidth = 0
Return False
End If
Abweichung = 0
' Calculate Tolerance
For i = 0 To Length - 1
tmp = Math.Min(Math.Abs(cBarWidth(Pos + i) - NWidth), Math.Abs(cBarWidth(Pos + i) - WWidth))
If tmp > Abweichung Then
Abweichung = tmp
End If
Next
MaxAbweichung = (WWidth - NWidth) * cBCDef.PctNWTolerance
If Abweichung > MaxAbweichung Then
cWWidth = 0
cNWidth = 0
Return False
Else
cWWidth = WWidth
cNWidth = NWidth
Return True
End If
End Function
' Is the pixel black?
Private ReadOnly Property IsBlack(ByVal x As Integer) As Boolean
Get
Return (cScanRow(x \ 8) And cBitMask(x Mod 8)) = 0
End Get
End Property
' Hepler for calculating pixel color.
Private Sub CreateBitMask()
Dim b As Byte = 1
Dim i As Integer
For i = 0 To 7
cBitMask(7 - i) = b
If i < 7 Then
b = b * 2
End If
Next
End Sub
Public Sub New(ByVal bcd As gmseNWBarcodeDef)
cBCDef = bcd
CreateBitMask()
End Sub
End Class
|
|
|
|
|
i did choose the lazy way out and didn't verify that the barcode was tall enough to be considered a barcode by the code 39 standard.
|
|
|
|
|
Hi,
i found that the performance of "System.Runtime.InteropServices.Marshal.ReadByte"
is show... anyone can give me a suggestion what method can replace this function so the performance can be improved?
thanks
Jack
|
|
|
|
|
There was happened Error when i changed another BMP File
bmp.LockBits(...) 'Error :System.ArgumentException
Benjamin Zhou
|
|
|
|
|
Can you post the code, that causes the error?
|
|
|
|
|
The Solution would be to use the right parameter for format.
If it has 32Bit depth, then use PixelFormat.Format32bpp*...I'm not quiet sure if this would work.
Or you convert each pic to BW, means 1 Bit Color depth.
Bobby
modified on Monday, March 23, 2009 11:04 AM
|
|
|
|
|
Just change the code line #238 in the gmseNWScanner.vb file to
data = bmp.LockBits(New Rectangle(0,0, bmp.Width, bmp.Height), ImageLockMode.Readonly, bmp.PixelFormat)
|
|
|
|
|
I've got some problems to solve barcode recognition.
I can't detect barcode region in a large image.
If the image is too bad i don't know how to recover it.
Please answer me
Handsome + Rich = Amorous
|
|
|
|
|
Can i use this read barcodes from an image application to read or scan barcode with font code 128?
Thanks Mackenb
angela
|
|
|
|
|
Code 128 is not a two width barcode. For that reason the algorithm in this article can not be used to detect Code 128.
|
|
|
|
|
ok, i get it.
Anyway thanks a lot for your explaination
angela
|
|
|
|
|
Hi
i'm trying to send an email using vb.net/html
the problem comes when i have to use a hyperlink to send an email
on the click of the button the mail does go to the reciepient. the problem is that on that mail there is a hyperlink <rejected> that the reciepient should click on and that should too send mail to certain reciepients
my code looks something like this
Private Sub btnSubmit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
Dim MailSender As New System.Web.Mail.MailMessage
With MailSender
.To = txtEmail.Text
'retrieve managers email address
.From = txtUserMail.Text
'retrieve users email address
.Subject = "Request For Rights"
.BodyFormat = MailFormat.Html
.Body = "Request for rights
" + txtFirstName.Text + " " + txtLastName.Text + " has requested for " + cblAccess.SelectedValue + " on" & _
" Database: " + txtDB.Text + ", Projects: " + txtProject.Text + "
" & _
" Do you appove or reject the request? If you approve click here" & _
"If you reject click hereRejectedRejected "
End With
SmtpMail.SmtpServer = "00172MSGJNB0057"
SmtpMail.Send(MailSender)
Response.Redirect("Approved.aspx")
End Sub
katli
|
|
|
|
|
I have barcode of machine is TR550 of PROMAX proceduce and connect to computer by COM gate, but i don't know anyway to connect with computer ,please show me the way detaily, (i have vb.net for this project),if you have source code is you give me,please. thank you very much.
- My email: quoc20042002@yahoo.com
4aaaa
|
|
|
|
|
First of all, this is the wrong place to ask about this.
You should first contact the manufacturer of your machine(I think it is a barcode reader)and ask him about the messages your device sends on the com port and the wiring of the com port.
Secondly you could use a microsoft activex called mscomm (it has a phone as icon)to receive/send com port messages. You might also want to set up windows hyperterminal(Start/programs/accessories/communications) and use it to make tests.
|
|
|
|
|