As part of the food management system my group made this semester, we wrote bindings for ZBar and based on those a bar scanning widget for Gtk#. Anyway, I figured it might be useful somebody else, so I’ve been using a few days cleaning up the ZBar bindings, extracting the Gtk# widget from our UI-mess and writing a simple example of how to use it.
The result is bindings for a subset of ZBar and a Gtk# bar scanning widget. I don’t intend to maintain the source, but if you find any bugs etc. or wish to start a project for the bindings, please leave a comment…
The example application using the bar code scanning widget can be seen on to right. Note: this was a really lousy webcam
. The check-mark appears when a bar code have been recognized and then fades away.
In Foodolini we used HAL to detect webcams as they were plugged, however, having heard that Ubuntu will be deprecating HAL, I didn’t care to clean up the source for this feature. If you interested it can be found in the source for Foodolini. And if anybody should happen to know how to detect webcams, distro independently, without HAL, please leave a comment…
[...] the time or the reason… Anyway, as I discovered a minor bug in the zbar-sharp bindings I recently released… I figured this might just be the kind of project I could push to github, and either forget [...]
Pingback by Jopsen.dk/blog — January 31, 2010 @ 08:02
Hi Jopsen,
This is very useful. Do you know how to build ZBar in Visual Studio? I could not find any information. The main reason that I am asking is that I want to make a Pocket PC program.
Best regards,
Alper
Comment by Alper Yaman — May 11, 2010 @ 05:17
zbar no… but just use the binaries the project ship… Or ask them…
zbar-sharp can probably be opened directly in VS… Haven’t tried though…
You can download the source from: http://github.com/jopsen/zbar-sharp
Comment by Jonas Finnemann Jensen — May 11, 2010 @ 05:32
Hey
I’ve just spend 30mins or so trying to use your bindings in windows / visual studio but am yet to be successful.
Any help you can give? example C# windows code perhaps?
Thanks
NB: Im trying to use your bindings to enable me to run ZBAR with C#, and to make an app to achieve something similar to that of yours above, ie shows web cam picture, detects barcode and then use that in the app. (bascially make the output of ZBAR usable in a c# proggy)
Comment by birdi3 — July 9, 2010 @ 07:09
The example given should work with VS, but requires gtk-sharp, if you don’t want to play install that I’ve pushed a new example (bmp-scanner) to github.com/jopsen/zbar-sharp.
The bmp-scanner example is hard coded to the image it distributed with… But it works and shows how zbar-sharp can also be used.
Remember to link against zbar-sharp in your project file, and put libzbar-sharp.dll and libzbar.dll next to the binary when running it.
Note the binary libzbar.dll (the one from zbar.sf.net) may be named zbar.dll or libzbar-1.dll or something, but it needs to be renamed to libzbar.dll
Let me know if have any problems building it… I don’t have time to test it on a Windows VM right now…
Comment by Jonas Finnemann Jensen — July 9, 2010 @ 11:01
Thanks for your reply!
I had a play further yesterday (before reading your comment) and only got as far as hitting an error such as ‘Unable to load DLL libzbar”, despite having it renamed and in line with the binary, (ie in the debug folder, as well as in other locations as I tried to test it), but then managed to get this working by moving in the other dll’s from ZBAR (..really should have done that first time round)
With this in mind and your help above, I have since been able to get your example working! Huge thanks for the swift reply and good example, hopefully it will be very useful for others! Next challenge is to get it reading directly from the cam in Windows. Wish me luck and I hopefully wont be back too soon!
Thanks Again
Comment by birdi3 — July 10, 2010 @ 07:43
Any advice how to discover the PixelFormat of a bmp image and how to discover the video device string?
Comment by Varro — July 28, 2010 @ 07:58
If you’re on Windows:
The video capture in zbar on Windows uses Video For Windows. A very old legacy API, you may wish to write your own capturing code that uses whatever is hot in Windows, probably DirectShow. And give the captured images to zbar…
I have an example where I read a barcode in a BMP:
http://github.com/jopsen/zbar-sharp/tree/master/example/bmp-scanner/
If you write such code please share…
If you’re on Linux, you can get the video device string from HAL. I did this using dbus, the code is available at http://jopsen.dk/blog/2009/12/foodolini-a-food-management-system/
However, HAL is being deprecated… So it’s probably better to get it elsewhere. If you find out how, let me know…
I don’t know how to discover the PixelFormat, if you’re talking about bmp from files, I suggest you find a bmp reader/parser or read the specification…
- Best of luck…
Comment by Jonas Finnemann Jensen — July 28, 2010 @ 14:50
Thank you for the fast reply.
Currently i’m working on windows system, trying to create a piece of code which makes the bmp and jpeg scanning (like bmp-scanner you made).
Thank you for the advice and thank you for your library.
Regards.
Comment by Varro — August 1, 2010 @ 03:09
Hello,
thanks a lot for programming a c# version of zbar.
I hope i can use ist in a Visual Studio c# Program.
But In any way i try to run it, I fail.
Now I tried MonoDevelop to Build a runnable Version.
I failed too and I don’t understand the error. Its something
about the Form Builder or probably somthing about me…
Actually I Have a running Application which use Zbar in a very bad way.
The zbar download for Windows includes a zbarimg.exe to scan images for
Barcodes. Now my Program takes an image out of an Webcam Video Stream and
Saves it on harddrive. Then I scan it with zbarimg.exe and read back the
console output. Its very slow. Now I hope i can use zbar-sharp.
Iam sitting here a whole day and it doesnt run yet…
MFG.: Lars
Comment by Lars — September 17, 2010 @ 05:56
@Lars:
zbar-sharp is not a C# version/clone of zbar, it’s just C# bindings for zbar.
Regarding your issues you should make clone of:
http://github.com/jopsen/zbar-sharp
E.g. make sure you’re using the latest development version, not that there’s a lof of active development… But it might have some fixes…
Second, you must have the libzbar.dll placed next to your .exe file along with the zbar-sharp.dll. During this you’ll notice that they binary zbar dll distributed for windows is called libzbar0.dll or something, if so you MUST rename it to libzbar.dll
Also remember to copy the other .dlls that is distributed with libzbar.dll next to your .exe file…
Are you having any problems building zbar-sharp.dll ? In visual studio ?
And if not have you tried to make a VS.Net project for the bmp-scanner example ? Can you build it ? Can you run it ? At what point does it fail…
By the way, if you think this turns into a longer discussion you should consider opening an issue at: http://github.com/jopsen/zbar-sharp/issues
Regards Jonas Finnemann Jensen.
Comment by Jonas Finnemann Jensen — September 17, 2010 @ 11:43
Hello again,
now I can build the projects with VS.net
And Iam able to run the bmp-scanner, too.
I dont know what I had done the first Time but now it works.
Iam very glad
Now I wonna ask you for a tip:
I need a Zbar.Image (binary) I have a System.Drawing.Bitmap
How can I become my bitmap in the Zbar.Image?
I testet:
System.IO.MemoryStream MS = new System.IO.MemoryStream();
Bitmap.Save(MS, Bildformat);
MS.Seek(54, SeekOrigin.Begin);
byte[] data = new byte[Bild.Width * Bild.Height * 3];
MS.Read(data, 0, data.Length);
Zbarimage.Data = data;
When I run it, zbar doesnt find any Barcodes
MFG.: Lars
Comment by Lars — September 24, 2010 @ 04:07
Hi Lars,
I think the Bitmap needs to be in the right format (RGB3), afaik System.Drawing.Bitmap can have different underlying representations… And then you need to run ZBar.Image.Convert(0×30303859) after copying the data to ZBar.Image…
Also note that some a BMP is header file… The conversation I did in BMPScanner is hardcoded and won’t work in general cases… So you probably need to read something about Bitmap and GREY/Y800 format.
I think it’s fairly simple, but I don’t have time to hack it these days…
But please do send me an example if you come up with something better, so that others may also benefit from it…
Comment by Jonas Finnemann Jensen — September 24, 2010 @ 04:23
Hi,
Here is my code:
I chnaged my Original-Code a little. I hope there arent too many mistakes…
Public Function ScanBitmap(ByVal Image As System.Drawing.Bitmap, ByRef Seriennummer As String, ByRef typ As String, ByRef qual As Integer)
Dim NewBitmap As New Bitmap(Image.Width, Image.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb)
Dim NewGraphics As Graphics = Graphics.FromImage(NewBitmap)
NewGraphics.DrawImage(Image, New System.Drawing.Rectangle(0, 0, Image.Width, Image.Height), 0, 0, Image.Width, Image.Height, GraphicsUnit.Pixel)
Dim width As UInteger = Image.Width
Dim height As UInteger = Image.Height
Dim data As Byte() = New Byte(width * height * 3 – 1) {}
Using fs As New IO.MemoryStream
NewBitmap.Save(fs, System.Drawing.Imaging.ImageFormat.Bmp)
‘Skip the header
fs.Seek(54, SeekOrigin.Begin)
fs.Read(data, 0, data.Length)
End Using
‘Create an empty image instance
Dim img As New ZBar.Image()
img.Data = data
‘Set the data property
img.Width = width
‘Set width and height
img.Height = height
img.Format = &H33424752
‘Trying with RGB3, as I know it’s 24bit BMP
Dim grey As ZBar.Image = img.Convert(&H30303859)
‘Convert to GREY/Y800
‘Create a scanner
Using scanner As New ImageScanner()
scanner.Cache = False
‘Scan the image
scanner.Scan(grey)
End Using
ScanBitmap = False
qual = 0
typ = “”
Seriennummer = “”
For Each sym As Symbol In grey.Symbols
qual = sym.Quality
typ = sym.Type
Seriennummer = sym.Data.ToString
ScanBitmap = True
Next
grey.Dispose()
NewBitmap.Dispose()
img.Dispose()
End Function
Comment by Lars — October 14, 2010 @ 00:27
@Lars,
It looks good to me… I’ll consider using the Bitmap class for scanning in my example code.
When I get around to updating it someday…
– Thanks for figuring it out
Comment by Jonas Finnemann Jensen — October 14, 2010 @ 02:05
I have a problem when I have to destroy the image.
in C#
zbar_image_destroy(this.handle);
ERROR –>Invalid access to memory location. (Exception from HRESULT: 0x800703E6)
in VB
zbar_image_destroy(this.handle);
ERROR –>A callback was made on a garbage collected delegate of type ‘BCReader!BCReader.ZBar.Image+zbar_image_cleanup_handler::Invoke’. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
pls help
Comment by thedarkking — November 22, 2010 @ 23:59
@thedarkking,
I knew this bug would come back and haunt me… But I haven’t been able to reproduce it reliably, and I never suspected that it was the delegate that was the issue.
Anyway, having looked at [1], I’m starting to think it was the delegate, I’ve tried to make a fix, and pushed it to github you can find it here:
https://github.com/jopsen/zbar-sharp/tree/delegate-fix
Please do confirm if this fix works, so I can merge it into master branch, and next release…
[1] http://www.mono-project.com/Interop_with_Native_Libraries#Memory_Boundaries
Comment by Jonas Finnemann Jensen — November 23, 2010 @ 10:55
Hey
I was wondering if you could help clear up some confusing im having using your project!
Image img = new Image();
img.Data = data; //Set the data property
img.Width = width; //Set width and height
img.Height = height;
// Fine up to here…
img.Format = 0×33524742; // Whats this? As far as I can work out its the “format” of the file, and can be obtained from the headers…?
// can you advise on how to obtain it from the header? and what it actually does? or where there is a list of sensible things->hex? is that just for rgb3 24bit?
// i found what I thought was a list and tried the hex value that matched up to a 32bit rbg3 and it threw an error…
Image grey = img.Convert(0×30303859); //Convert to GREY/Y800
Thanks
PS: im a big fan of the work you did with zbar
Comment by bob — November 23, 2010 @ 12:58
@bob,
The format is a FOURCC code, I think, take a look at: http://fourcc.org
Ideally, we should probably have some enum with these codes in… But I never really cared to figure out how they worked…
zbar can only read images of format GREY/Y800 (fourcc code: 0×30303859).
But zbar can convert from RGB3 (0×33524742) to GREY/Y800. It can also do other conversations, but I haven’t tried any of that.
What I mean by “obtained from header” is that in the header of the BMP file it should say what format it’s in… But how to read that I don’t know or care…
I recommend using System.Drawing.Bitmap to load custom images, and then convert to RGB3 using that, before creating an instance of ZBar.Image (see Lars’ code above)
But I’m sure it can be done more efficiently…
Comment by Jonas Finnemann Jensen — November 23, 2010 @ 13:45
Thanks @bob,
This bug is fixed.
Now works very well.
I use it to read barcodes from images that are in the database, for this I needed to free memory.
Comment by thedarkking — November 24, 2010 @ 04:38
Thanks for the confirmation…
I’ll merge the patch into master… It’s really great to fix this one bug that’s been hiding for so long…
Comment by Jonas Finnemann Jensen — November 24, 2010 @ 08:24
Here is how to convert a tiff
private byte[] ConvertBitmap(Bitmap bitmap)
{
//Code excerpted from Microsoft Robotics Studio v1.5
BitmapData raw = null; //used to get attributes of the image
byte[] rawImage = null; //the image as a byte[]
try
{
//Freeze the image in memory
raw = bitmap.LockBits(
new Rectangle(0, 0, (int)bitmap.Width, (int)bitmap.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format24bppRgb
);
int size = raw.Height * raw.Stride;
rawImage = new byte[size];
//Copy the image into the byte[]
System.Runtime.InteropServices.Marshal.Copy(raw.Scan0, rawImage, 0, size);
}
finally
{
if (raw != null)
{
//Unfreeze the memory for the image
bitmap.UnlockBits(raw);
}
}
return rawImage;
}
private void button2_Click(object sender, EventArgs e)
{
System.Drawing.Image image = System.Drawing.Image.FromFile(“test.tif”);
Byte[] data = ConvertBitmap((Bitmap)image);
ZBar.Image zimage = new ZBar.Image();
zimage.Data = data;
zimage.Width = (uint)image.Width;
zimage.Height = (uint)image.Height;
zimage.Format = ZBar.Image.FourCC(‘R’, ‘G’, ‘B’, ’3′);
using (ZBar.ImageScanner scanner = new ImageScanner())
{
using (ZBar.Image grey = zimage.Convert(ZBar.Image.FourCC(‘Y’, ’8′, ’0′, ’0′)))
{
scanner.Scan(grey);
List symbols = new List(grey.Symbols);
}
}
}
Hope this helps
Comment by Justin — January 13, 2011 @ 12:21
Nice… I recently pushed a new method that lets you create an image from an instance of System.Drawing.Image, but it uses some drawing stuff and is rather expensive…
The UnlockBits thing look really neat… I’ll try that and add a specific overload for System.Drawing.Bitmap
In case anybody wonders the source is maintained here:
http://github.com/jopsen/zbar-sharp
Comment by Jonas Finnemann Jensen — January 13, 2011 @ 14:22
Hi,
i like this approach a lot and would also like to use it. I am facing some problems. I am using the bitmap scanner and was expecting similar results to what zbarimg is producing. But the result i am getting are rather frustrating. I use another component to capture a video stream and take an image and scan it afterwards. Uploaded an image which is working fine in a zbarimg and does not have a result with the bitmap scanner http://dl.dropbox.com/u/17637020/test.bmp.
am i missing something here?
Comment by Daniel — January 19, 2011 @ 09:18
@Daniel,
I assume you’re using latest version of zbar (0.10), right? and zbar-sharp master from github (not the one available for download as tarball).
Support for QR codes is very new, I haven’t tested it, and it’s only recently made it to master branch at github.com/jopsen/zbar-sharp
When, you say the bitmap scanner, is that the one in example/bmp-scanner ?
And what is the result? Does find anything, or what? bmp-scanner, doesn’t really print anything useful, it’s just an example…
Comment by Jonas Finnemann Jensen — January 20, 2011 @ 03:47
Hi thank you for your reply,
i took the latest master version from github from the link you have posted (13. January). in combination with the latest zbar (0.10).
The Bitmap scanner is the example you published at github as well. The core code is this:
System.Drawing.Image img = System.Drawing.Image.FromFile(file);
List symbols = scanner.Scan(img);
foreach (Symbol symbol in symbols)
Console.WriteLine(“\t” + symbol.ToString());
the file is the bitmap i send. The output is empty, so no symbols where found. The zbarimg.exe detects it and i also looked into that code (zbarimg.exe) and did not see any fancy stuff like configuration settings or similar things. so i assume the only different thing is the way how the image is converted. i was also not able to scan the following image too (an example image from zbar which also works with zbarimg which is an normal bar code): http://dl.dropbox.com/u/17637020/Just_right.png
besides the image conversion i do not see where the problem might be.
Comment by Daniel — January 20, 2011 @ 09:18
@Daniel,
Sorry, for the reply time…
I’m thinking that maybe zbar can consume color images… Maybe even RGB3 (24bit BMP), see:
http://sourceforge.net/apps/mediawiki/zbar/index.php?title=Supported_image_formats
Update: I had a look at the code and zbarimg uses ImageMagick for conversation to greyscale… Which is better than the greyscale conversation in zbar…
Comment by Jonas Finnemann Jensen — January 29, 2011 @ 05:59
I just finished a project for work that batch scans 3 of 9 barcodes from jpg files.
1. try to read zbar installdir key from the regestry
2. if i can read it, show message that zbar isnt installed and launch zbar installer.
3. use that information to make a path from zbarimg.exe
4. have a way to select a folder on the UI.
5. for each file in the selected folder.
6. if its a jpg
7. make a new process
8. set the path to zbar that we worked out from the regestry
9. create the command line arguments including filename of the current file (including –raw command)
10. redirect both standard output and error output to textboxes on the form.
I guess i could have just used this…. oh well, i might rewrite it tomorrow at work to see if there is any speed increase.
Comment by steveo — February 16, 2011 @ 04:15
@steveo
zbar is LGPL, I don’t see why you don’t just distribute it with your application. LGPL is easy to comply with (zbar-sharp is also LGPL).
Also, if you performance in an issue why don’t you do it in C? Or at least the core functionality… Using ImageMagick for gray conversation might also yield better results.
But you’ll probably also experience a small performance improvement from using zbar-sharp… Because, unlike Linux, launching process on Windows is inherently slow.
(Do consider using latest sources from the master branch at github, they have fewer bugs).
Comment by Jonas Finnemann Jensen — February 16, 2011 @ 12:55
@Jonas
I did manage to we write my program.
Using the same 5 600dpi jpg images.
1. My program using command line zbar = 20 seconds.
2. My program using your library = 27 seconds.
3. My program using your library with cropping = 10 seconds.
Because we are feeding the documents through a document feeder the barcode is always aprox in the same spot in the images.
so 10 hours of processing will now be 5 hours hopefully
Comment by steveo — February 16, 2011 @ 20:58
@steveo
Okay, if you’re running that high resolution I see that performance might be an issue…
But there’s a lot of memory copying in zbar-sharp, so you might want to do the croping in zbar-img.exe, and then maybe extend the program to loop through all files in the folder (to avoid spawning new processes).
Comment by Jonas Finnemann Jensen — February 17, 2011 @ 03:22
[...] previously caused applications to crash at random. A thanks to the nameless commentor by the name thedarkking, who’s comment finally gave me a clue as to where the bug [...]
Pingback by Jopsen.dk/blog — March 19, 2011 @ 09:51