I created a tool that generates PDF417 2D barcodes. The output png file is 290x78 pixels.
The reason behind this width and height is a formula used to create this symbol so that it is correctly read by bar code scanners.
My symbol is 13 columns and 39 rows.
This formula is:
Width = ((17 * # of columns) + 69) X + 2 (size of quiet zone)
Height = (# of rows) (row height) + 2 (size of quiet zone)
So:
17 * 13 + 69 = 290px
39 * 2 = 78px
My question is the software I use to create these bar codes allows you to save the file to this size but prints it at a different size.
These print parameters turn out to be as follow but I cannot figure out how to calculate them:
X Dimension (in) :0.0067
Y Dimension (in) :0.0133
Height x Width (in) :0.52 x 1.93
Height x Width (mm) :13.21 x 49.11
Rows x Columns : 39 x 13
Error Correction Level :5
Bytes Encoded :257
SLD Codeword :1
Data Codewords :157
Pad Codewords :285
MPDF Codewords :0
EC Codewords :64
Total Codewords :507
Here's a snapshot of the program I currently use:
This appears to be an issue of DPI and print size.
pixels/dpi=inches
or if you're going the other way
inches x dpi = pixels
You can set the DPI dropdown in your software to the necessary value.
See this calculator to play with the values: http://auctionrepair.com/pixels.html
Related
My Photo Booth application uses code similar to the code below to automatically print.
It works great, however recently when I changed my Dye Sub printer to use 5 x 7 media instead of the usual 4 x 6, as soon as the print code starts, the ribbon error on the printer lights.
I am setting the paper size as shown below but to get the error to go away, I found that I need to set the paper size in the Printer settings:
PrintingSettings->Paper/Quality -> Advanced Options->Paper Output/paperSize
I am setting the paper size in the print document
Is there another setting I can set in code to set the printer page size?
I am setting the paper size as follows:
public static PrintDocument pd = new PrintDocument();
PrintController printController = new StandardPrintController();
pd.PrintController = printController;
//page sizes in hundredths of an inch
if (selectedLayout.LayoutPrintWidthPixels >0) PrintWidth = selectedLayout.LayoutPrintWidthPixels/300 * 100;
if (selectedLayout.LayoutPrintHeightPixels > 0) PrintHeight = selectedLayout.LayoutPrintHeightPixels/300 *100;
pd.PrinterSettings.DefaultPageSettings.PaperSize = new PaperSize("Custom", PrintWidth, PrintHeight);
I am also having trouble understanding page sizes
For example, for 5 x 7 prints, I calculate the sizes as follows:
5 x 7 = 1500 x 2100 px based on 300 dpi
700 x 500 in Milli Inches (pixel size / 300) X 100
But if I look at the page size in the printer properties while debugging,
the paper size shows 713 x 516 or 1548 x 2139 in pixels
Is that the actual page size or are they allowing some extra for margins or bleed?
When printing 4 x 6, I normally design my template based on 1844 x 1240 pixels (instead of 1800 x 1200)
// milliinches=(pixels / 300) X 100
// pixels = (milli inches /100)*300
Im working on inspecting a sheet of paper sized 250mm(width) to 150mm(height).
I grab the image and process it to get the relevant points in mm to send to a robot.
This is how im converting pixel to mm :
decimal paperW = image.Width / 250;
decimal paperH = image.Height / 150;
but this is not accurate, the points are shifted 15mm to the top. Resolution is 96 dpi.
How do I accurately convert image size to mm? Please help.
The general formula to convert a number of pixels in millimeters is the following:
decimal millimeters = (pixels * 25.4d) / dpi;
The constant 25.4 is simply the amount of millimeters in an inch, since we convert from the DPI (Dots per inch) to millimeters.
As an example, with your values of 96 DPIs and a point at 200 pixels, this would mean a corresponding point at (200 * 25.4) / 96 = 52.91mm
If you need to do the opposite, find the the amount of pixels for a length, the formula becomes:
decimal pixels = (millimeters * dpi) / 25.4d;
Say you have a sheet of 250mm of paper still at 96 DPI, this means it is (250 * 96) / 25.4 = 944 pixels long
I write program in C# but hope that C++ and C# in background exactly same.
What i want - take grayscaled image and separate colors over 127 and under 17 to separate images. If i simply get "white" colors and programmatically stretch them from range (127-255) to (0-255) like
// pseudocode
int min = 127, max = 255;
for(int x; x< width; x++)
pixels[x] = pixels[x]/(max-min) * max;
Then here will be not smooth interval.. I mean, that 127 converts to 0 but 128 converts to 2 and colors 1,3,5,... are not exist.
That is original image with alpha:image original
That is image with "extracted white":image original
That is image with "extracted black": snorgg.ru/patchwork/tst_black.png.
I don't clearly understand how it can be realized so exampe code will like:
{
im.MagickImage image = new im.MagickImage("c:/55/11.png");
im.MagickImage imageWhite = ExtractWhite(image);
im.MagickImage imageBlack = ExtractBlack(image);
}
....
public static im.MagickImage ExtractWhite(im.MagickImage img){
im.MagickImage result = new im.MagickImage(img);
?????
?????
return result;
}
thankы in advance ))
I think your calculation is wrong. You are confusing the input range with the output range. The input ranges from min to max and the output ranges from 0 to 255. It is a coincidence that your input max is equal to your output max (255).
If you want to stretch a value in the range of min ... max (= input range) to 0 ... 255 (= output range) then calculate this
int brightness = pixel[x];
if (brightness <= min) {
pixel[x] = 0;
} else if (brightness >= max) {
pixel[x] = 255;
} else {
pixel[x] = 255 * (brightness - min) / (max - min);
}
Where min >= 0 and max <= 255 and min < max.
First you have to make sure the brightness is within the range min ... max, otherwise your result will exceed the range 0 ... 255. You could also limit the range of the output afterwards, but in any case you have to make a range check.
Then subtract min from the brightness. Now you have a value between 0 and (max - min). By dividing by (max - min) you get a value between 0 and 1. Multiply the result by 255 and you get a value in the desired range 0 ... 255.
Also you must be aware of the fact that you are performing integer arithmetic. Therefore multiply by 255 first and then divide. If you start by dividing you get either 0 or 1 as intermediate result (because integer arithmetic does not yield decimals and the final result will either be 0 or 255 and all the gray tones get lost.
The effect you are seeing is called banding or posterisation. It is caused by making contrast stretches to data that is not sampled with sufficient bit-depth. As you only have 8-bit data, you only have 255 grey levels. If you stretch the 50 levels between 100-150 over a range of 255 levels, there will be gaps in your histogram around 5 levels wide. The solution is either to obtain 16-bit data, or make less drastic changes in the contrast.
Alternatively, if like me, you are a photographer, and more interested in the aesthetics of the image than its scientific accuracy, you can add a small amount of random noise to disguise and "smear over" the banding...
There is a nice description here.
I can also show you an example with ImageMagick, first we create two greyscale ramps (gradients), one 8-bit and one 16-bit, both ranging from brightness level 100 to 150 like this:
convert -depth 8 -size 100x500 gradient:"rgb(100,100,100)-rgb(150,150,150)" -rotate 90 gradient8.png
convert -depth 16 -size 100x500 gradient:"rgb(100,100,100)-rgb(150,150,150)" -rotate 90 gradient16.png
They look like this:
If I now stretch them both to the full range of 0-255 you will immediately see the banding effect in the 8-bit version, and the smoothness of the 16-bit version - which, incidentally, is the reason for using RAW format (12-14 bit) on your camera rather than shooting 8-bit JPEGs:
convert gradient8.png -auto-level out8.png
convert gradient16.png -auto-level out16.png
I alluded to using noise to redue the visibility of the banding effect, and you can do that using a technique like this:
convert out8.png -attenuate 0.3 +noise gaussian out.png
which gives you a less marked effect, somewhat similar to film grain:
I am not certain exactly what you are trying to do, but if you just want to spread the brightness levels from 127-255 over the full range of 0-255, you can do that simply at the command-line like this:
convert orig.png -level 50%,100% whites.png
Likewise, if you want the brightness levels from 0-17 spread over the range 0-255, you can do
convert orig.png -level 0,6.66667% blacks.png
Problem:
So I am looking to create bar chart values based on a comparison to an array of values.
Data:
array = [25 , 35 , 55 , 5 , 60 , 200 , 18 , 18 , 30 , 10]
Requirements:
I have a working Bar graph creation using CSS which loads the bar width value 'xx' as a percentage.
I want to allocate the lowest array item value to a percentage value of 100% (full width of CSS bar) The above example would be the fourth array item '5'
Likewise the sixth item in the array is the highest number and I want to allocate 0% to the highest.
(Think of the numbers in the array as time - shortest being the best)
So lowest (fourth) array item '5' = bar width value 100% and the
Highest array item '200' = bar width value 0%
The spread between the highest and lowest values in the array is 195
There are 10x items in the array.
The average value across the array is 45.6 which would for example generate a bar chart value of 50% if represented in the bar chart.
I am struggling to create a formula which dynamically generates the reverse percentage values from the varied array values above into a representational percentage bar chart value of any of the items in the array.
Specific Help Needed:
Can you see the solution in C# so that I can generate percentage bar values based on the requirements outlined above ?
[EDIT] (Including my code which partly works)
int[] array = { 25 , 35 , 55 , 5 , 60 , 200 , 18 , 18 , 30 , 10 };
int selectdVal = 5; //example selection from array
int ratioSpread = 100; //used as 100% CSS width
int responseSlow = array.Max(); //The slowest val within array
decimal ratioAdjust = (ratioSpread / responseSlow);
decimal maxBar = 100 - (selectdVal * ratioAdjust );
int renderBar = Convert.ToInt16(maxBar <= 0 ? 1 : maxBar ); //show min 1% bar width
The above is relatively ok, but I'd prefer to have the shortest time (Min.value) of 5 above actually return 100 for the renderBar, whereas in this example it returns 97.5
int[] array = { 25, 35, 55, 5, 60, 200, 18, 18, 30, 10 };
int selectdVal = 5;
int barMin = 1;
int barMax = 100;
decimal rangeMin = array.Min();
decimal rangeMax = array.Max();
decimal ratio = (barMax - barMin) / (rangeMax - rangeMin);
int bar = barMax - (int)(ratio * (selectdVal - rangeMin));
I am printing using the Windows Compact Framework to a Zebra belt printer using the OpenNetCF serial port class and CPCL. The printed label is pretty much as it should be, but the barcode value is not printing beneath the barcode as it should.
I create an ArrayList of commands to be sent the printer and then pass them one at a time to the serial port. If the controls that supply the values are empty, I use some dummy data, like so:
private void btnPrint_Click(object sender, System.EventArgs e)
{
string listPrice = txtList.Text;
if (listPrice.Trim() == string.Empty)
{
listPrice = "3.14";
}
string description = txtDesc.Text;
if (description.Trim() == string.Empty)
{
description = "The Life of Pi";
}
string barcode = txtUPC.Text;
if (barcode.Trim() == string.Empty)
{
barcode = "01701013992";
}
ArrayList arrList = new ArrayList();
arrList.Add("! 0 200 200 120 1\r\n"); // replace 120 with label height if different than 1.25"/120 pixels (at 96 pixels per inch)
arrList.Add("RIGHT\r\n");
arrList.Add(string.Format("TEXT 0 5 0 0 {0}\r\n", listPrice));
arrList.Add("LEFT\r\n");
arrList.Add(string.Format("TEXT 0 0 0 52 {0}\r\n", description));
arrList.Add("CENTER\r\n");
arrList.Add("BARCODE-TEXT 0 0 5\r\n");
arrList.Add(string.Format("BARCODE 128 1 1 50 0 77 {0}\r\n", barcode));
arrList.Add("FORM\r\n");
arrList.Add("PRINT\r\n");
PrintUtils pu = new PrintUtils();
pu.PrintLabel(arrList);
}
public void PrintLabel(ArrayList linesToSend)
{
using (SerialPort serialPort = new SerialPort())
{
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.DataBits = 8;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
serialPort.PortName = "COM1:";
serialPort.Open();
Thread.Sleep(500); //this may not even be necessary and, if so, a different value may be better
foreach (string line in linesToSend)
{
serialPort.Write(line);
}
serialPort.Close();
}
}
...the problem is that the label (when I allow the dummy data to print) should be:
3.14
The Life of Pi
<barcode here>
01701013992
...and here's what is really printing:
3.14
The Life of Pi
<barcode here>
[blank]
So the problem is that the barcode as text ("01701013992") is not printing beneath the barcode.
Does anybody know why this is occurring even though I've got a BARCODE-TEXT command in there, and how to rectify it?
UPDATE
A key piece of info came my way, namely that the label height (in my case) should be 254, not 120 (for my 1.25" in height label, I was calculating based on 96 pixels == 1 inch, but in actuality this particular printer is 203 dpi, so 1.25 X == 254 (more precisely 253.75, but 254 is close enough).
So the code has changed to this:
// Command args (first line, prepended with a "!": horizontal (X) pos, resolution, resolution, label height, copies
// TEXT args are: fontNumber, fontSizeIdentifier, horizontal (X) pos, vertical (Y) pos
// BARCODE args are: barcodeType, unitWidthOfTheNarrowBar, ratioOfTheWideBarToTheNarrowBar, unitHeightOfTheBarCode,
// horizontal (X) pos, vertical (Y) pos, barcodeValue
// BARCODE-TEXT args are: fontNumber, fontSizeIdentifier, space between barcode and -text
// 1 inch = 203 dots (Zebra QL220 is a 203 dpi printer); font 4,3 == 90 pixels; font 2,0 == 12 pixels
arrList.Add("! 0 200 200 254 1\r\n"); // 203 dpi X 1.25 = 254
arrList.Add("RIGHT\r\n");
arrList.Add(string.Format("TEXT 4 3 0 0 {0}\r\n", listPrice));
arrList.Add("LEFT\r\n");
arrList.Add(string.Format("TEXT 2 0 0 100 {0}\r\n", description));
arrList.Add("BARCODE-TEXT 2 0 5\r\n");
arrList.Add("CENTER\r\n");
arrList.Add(string.Format("BARCODE 128 1 1 50 0 120 {0}\r\n", barcode));
arrList.Add("FORM\r\n");
arrList.Add("PRINT\r\n");
...but I'm STILL not seeing the description label - except for a lonely "P" below the "3" and the "." in the price.
Are my calculations wrong, or what?
Here's what I'm thinking I have:
Label is 254 dots/1.25" high.
First line starts at YPos 0 and prints "3.14" in a 90 pixel font, right-aligned. That prints fine.
Second line starts at YPos 100 (10 dots below the 90-dot first line), left-aligned. All I see is the aforementioned "P" in what seems to be the right size.
Third line is the barcode, at YPos (120), centered; prints fine
Fourth/final line is the barcode as text beneath the barcode proper, centered; prints fine.
NOTE: I can't put a bounty on this yet, but anybody who solves it I will award 100 points as soon as I'm able (in two days, I reckon).
It turns out that the problem was that I was using font # 2 in order to get a font size of 12 (it is the only font that provides that size). The problem with font # 2 is that it is "OCR-A" and as such only prints certain characters. In the string I was passing as a test ("The Life of Pi", to go along with the list price of 3.14), the only character it recognizes in that string is P. So that's why it's the only one I saw.
I had to increase my font size to the next available, namely 24, using font #5 (Manhattan) or 7 (Warwick).
"mk" from zebra provided me with this information ("The OCR font is a special font that doesn’t include all characters that you are trying to print.").
If you look at Appendix D in the CPCL programming manual, it does show font #2 as being "OCR-A," but it didn't dawn on me that that meant it's character set precluded most alpha characters. Even if that's obvious to some, it seems to me that should be emphasized in the manual: When printing text, don't use font #2!
Note: Font #6 (MICR) is also to be avoided for text.