Goal:
I am aiming to read a bar code that has poor quality. Code works fine if the bar code is in it's highest quality.
Image:
Code:
To crop the barcode code:
private Point LocationXY;
private Point LocationX1Y1;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
LocationXY = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
LocationX1Y1 = e.Location;
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
LocationX1Y1 = e.Location;
pictureBox1.Invalidate();
pictureBox2.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Rectangle currentSelection = GetRect();
if (currentSelection != Rectangle.Empty)
{
e.Graphics.DrawRectangle(Pens.Red, currentSelection);
}
}
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
var src = GetRect();
if (src == Rectangle.Empty) return;
var des = new Rectangle(0, 0, src.Width, src.Height);
e.Graphics.DrawImage(pictureBox1.Image,
des, src, GraphicsUnit.Pixel);
}
private Rectangle GetRect()
{
return new Rectangle(
Math.Min(LocationXY.X, LocationX1Y1.X),
Math.Min(LocationXY.Y, LocationX1Y1.Y),
Math.Abs(LocationXY.X - LocationX1Y1.X),
Math.Abs(LocationXY.Y - LocationX1Y1.Y)
);
}
private Bitmap GetCroppedImage()
{
var des = GetRect();
if (des == Rectangle.Empty) return null;
var b = new Bitmap(des.Width, des.Height);
using (var g = Graphics.FromImage(b))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(pictureBox1.Image, new Rectangle(0, 0, des.Width, des.Height), des, GraphicsUnit.Pixel);
}
return b;
}
Class where the image is saved and able to return the image:
public class BarcodeImage
{
private static Image _image;
public static Image _Image
{
get
{
return _image;
}
set
{
_image = value;
}
}
}
Here I click a button to save the image to class and check the barcode:
private void checkBarcode_Click(object sender, EventArgs e)
{
BarcodeImage._Image = GetCroppedImage();
ZXing.BarcodeReader reader = new ZXing.BarcodeReader();
var result = reader.Decode((Bitmap)BarcodeImage._Image);
if (result != null)
{
MessageBox.Show(result.ToString());
}
}
Using the code:
Here I highlight the barcode and save it into picturebox2
.
Next by clicking checkBarcode_Click
it should show the barcode value - but it doesen't. Becasue of the quality of the image.
I have tested it with high quality barcode images and it works fine!
Question:
How can I improve the quality of the Cropped Image and return me the Barcode value?
Edit: 29/05/2020
I have asked a new question on this community seeing if I can I increase size of the cropped image. But that did not improve anything:
https://stackoverflow.com/a/62068397/12485722
High Quality Barcode:
The image is taken out from specific program.
I print screen the images and they must be specifically like this this:
But it does not detect the barcode.
This is a zoomed in version of the image using 2x on the program:
Unfortunately I cannot use the x2 zoom in option as some of the data will move on the image and not giving an accurate final image. On top of that, the barcode is recognized!
You are seeing too much subpixel data loss here for this barcode to be read with any software.
Barcodes work using the relative width of the bars - they are quite clever about how they do this and there is some room for tolerance, but only a small amount.
Here is your original barcode, a scaled up version and a readable version:
If you look at the farthest right bars on yours vs the readable barcode you can see that they are not equal sizes - they should be, but they are not.
The original image is only adequate if it has enough resolution to correctly capture the relative sizes of all bars.
You need to get better data from whatever your source is.
Edit:
Based on your comments, you say you are taking a print-screen of the bartender label - there's no reason you shouldn't be able to zoom to get a higher resolution print-screen, but if you can't then you can print the label to a file/image (such as a PDF) and use that.
It's also worth noting that BarTender has a .NET API that you can talk to directly if you need to, and that the data for BarTender can be exported as an Excel/CSV format (assuming you are using it as a driver for the barcode output).
You also mention that you want to check if a barcode is already in your database - you might be able to do this using the API instead.
I really can't tell you much more since I don't know what data you are generating labels from or if the labels are all ad-hoc; but I know that what you are trying to achieve is entirely possible if you zoom into the image enough to allow enough pixels for the individual barcode bars to render correctly relative to their full width - that's the important bit!