Bug 696758 - Vectors are drawn incorrectly resulting in unscanable barcodes
Summary: Vectors are drawn incorrectly resulting in unscanable barcodes
Status: RESOLVED INVALID
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: General (show other bugs)
Version: 9.19
Hardware: PC Windows NT
: P4 normal
Assignee: Default assignee
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-05-08 21:17 UTC by Kyle MacFarlane
Modified: 2016-09-01 23:04 UTC (History)
4 users (show)

See Also:
Customer:
Word Size: ---


Attachments
Comparison of barcode outputs (99.67 KB, image/png)
2016-05-08 21:17 UTC, Kyle MacFarlane
Details
Source PDF (48.55 KB, application/pdf)
2016-05-08 21:18 UTC, Kyle MacFarlane
Details
screenshot.png (15.32 KB, image/png)
2016-05-08 22:06 UTC, Marcos H. Woehrmann
Details
Poppler pdftoppm comparison (16.65 KB, image/png)
2016-05-08 23:34 UTC, Kyle MacFarlane
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Kyle MacFarlane 2016-05-08 21:17:58 UTC
Created attachment 12524 [details]
Comparison of barcode outputs

When I print shipping labels via CUPS the quality of barcodes are greatly reduced and unscanable by most devices. This is not a problem from Windows.

Both CUPS and Windows convert PDFs to an image and then embed that image as a GRF in ZPL. So I made a GRF => PNG converter to check the quality and it's obvious that the GRF from CUPS is wrong. Not low quality but drawn incorrectly.

Then I hooked gs to check what options are being used to generate the PWG so I could generate my own PWG and view it in an app called Rasterview. Doing this confirms that the problem exists in the PWG as well.

Running the same gs command but outputting a PNG shows the same problem. In fact all raster devices show the problem when run with the options CUPS uses to convert PDFs. Ghostscript's options aren't well documented and I am yet to find something that fixes the problem.

The gs command that CUPS runs:

/usr/bin/gs -dQUIET -dPARANOIDSAFER -dNOPAUSE -dBATCH -dNOINTERPOLATE -sDEVICE=cups -sstdout=%stderr -sOutputFile=%stdout -dAdvanceDistance=1000 -r203x203 -dDEVICEWIDTHPOINTS=288 -dDEVICEHEIGHTPOINTS=432 -dcupsBitsPerColor=1 -dcupsColorOrder=0 -dcupsColorSpace=3 -dcupsRowStep=200 -scupsPageSizeName=w288h432 -I/usr/share/cups/fonts -c "<</.HWMargins[0.000000 0.000000 0.000000 0.000000] /Margins[0 0]>>setpagedevice" -f -_
Comment 1 Kyle MacFarlane 2016-05-08 21:18:28 UTC
Created attachment 12525 [details]
Source PDF
Comment 2 Marcos H. Woehrmann 2016-05-08 22:06:35 UTC
Created attachment 12526 [details]
screenshot.png

If I convert the source.pdf file to bitmap at 203 dpi using Acrobat the barcode looks identical to that produced by Ghostscript (the attached screenshot shows the acrobat output on the left and ghostscript output on the right).
Comment 3 Kyle MacFarlane 2016-05-08 22:59:12 UTC
Yeah I see that now too. The problem is with label printers you're stuck at 203dpi as turning up the dpi makes the image bigger rather than higher quality. With the png devices you can reduce the problem with -dDownScaleFactor but it doesn't seem to work for cups plus it really starts to hit performance at high values.

I can understand why Ghostscript wouldn't want to do anything different from Adobe but at the same time if CUPS/GS claim to support label printers then they should try to do it properly.

For reference there's a $200 OSX driver by "Peninsula Group" that claims to fix this problem but I have no idea what they do. They claim that even Apple use their driver instead of CUPS/GS.
Comment 4 Kyle MacFarlane 2016-05-08 23:34:19 UTC
Created attachment 12527 [details]
Poppler pdftoppm comparison

Playing with other tools it seems like with pdftoppm from poppler you can (almost) fix this problem with "-aaVector yes". Is there an equivalent in Ghostscript?

See the attached image for the difference between aaVector no and yes.
Comment 5 Ken Sharp 2016-05-09 00:19:21 UTC
(In reply to Kyle MacFarlane from comment #4)
> Created attachment 12527 [details]
> Poppler pdftoppm comparison
> 
> Playing with other tools it seems like with pdftoppm from poppler you can
> (almost) fix this problem with "-aaVector yes". Is there an equivalent in
> Ghostscript?

There is -dGraphicsAlphaBits or you can use one of the 'scaled' devices, which also produce anti-aliased output using a different method. Of course, anti-aliased output can't produce gray scales, so the gray areas will be halftoned in the tiffscaled output. There is no scaled version of the CUPS device.

All the Ghostscript options are (extensively) documented in ghostpdl/doc/*.htm. If you are trying to use the man pages, we don't write those, don't support them and don't recommend you use them. Use our documentation.

As far as I can tell this is simply due to the low resolution combined with the precise pixel placement of the rectangles forming the bar code. The bar code is drawn as a series of often thin (1.68/72nds of an inch) often placed close together. 1.68 units works out (at 203 dpi) as 4.736666 pixels. Clearly this is going to result in progressive approximations to the desired actual widths of the black and white areas. Exactly which pixels are elided depends on the graphics library, the fact that we match Adobe is good enough for me.
Comment 6 Ken Sharp 2016-05-09 00:21:08 UTC
Using a bar code font instead of drawing the codes 'might' also give better output.
Comment 7 Kyle MacFarlane 2016-05-09 01:25:21 UTC
I did try barcode fonts but had difficulty getting them to match the Deutsche Post requirements. I didn't even get to the printing stage yet but I can try again.

Similar problem with drawing the barcode and meeting DP's spec. It has to be 46mm wide and setting each bar to a nice round width ends up with a barcode that is either too long or too short.

What would be the smallest bar width you could get away with at 203dpi?

Currently pdftoraster converts the PDF to a mono PWG and then rastertolabel converts that to GRF/ZPL (which is mono only). I'm thinking wouldn't it be better if pdftoraster returned a greyscale PWG and then rastertolabel decides how to convert that to mono suitable for label printers? With a thermal printer you want to use a much higher threshold than a laser as the very nature of thermal often results in bleeding that makes any rounding errors even worse.

Going with the above I'm thinking I could write my own CUPS filter but I'm not sure how I could hijack the PDF mimetypes for label printers without affecting laser printers.
Comment 8 Ken Sharp 2016-05-09 02:08:34 UTC
(In reply to Kyle MacFarlane from comment #7)

> Similar problem with drawing the barcode and meeting DP's spec. It has to be
> 46mm wide and setting each bar to a nice round width ends up with a barcode
> that is either too long or too short.
> 
> What would be the smallest bar width you could get away with at 203dpi?

The width is not the problem, as such, except possibly for unreasonably tight requirements from Deutsche Post for low resolution devices. Not knowing those requirements I can't comment on them. The smallest width you could 'get away with' would, obviously, be 1/203 = 0.0049 inches = 0.3546 PostScript points. (actually, see later, you could potentially use half that)

The point is the width *and* the placement. There are two rules for determining whether a pixel is black or not; any portion of pixel, and pixel centre. In the first, if any portion of the pixel is touched by a marking operation then the pixel is marked, in the second, the pixel is marked only if the centre of the pixel is covered (ie the mark covers at least half a pixel).

Depending on the rule used (which depends on whether this is a stroke, image or fill operation), and the precise placement in user space of the operation, a pixel may or may not be marked in black. Note; user space is a theoretical infinitely divisible co-ordinate system, when rendering we convert that into the actual pixels of the device.

Looking at the rectangles in the PDF you sent (this is actually a form XObject, so there is additional translation to consider, but this will do for illustration purposes), the first rectangle is:

0 0 1.68 20.63 re

So that's starting at 0,0 (bottom left) draw a rectangle 1.68 wide by 20.63 units (1/72 inch) high. So that's 0.23333 inches by 0.28657222 inches. At 203 dpi that works out at 4.7366 pixels by 58.16 pixels. Which is either 5x58 or 5x59 depending which rule we are using.

Either way, you can see that we have considerable error no matter which we do. there's an inaccuracy of 6% there in the width, and it could easily be worse. Consider the case where we had 4.5 pixels, that's a 9% inaccuracy, no matter which way we go. Spacing (which appears to be the main problem) can be even worse, consider if we finish a feature at slightly more than 0.5 of a pixel, and start the next at slightly less than 0.5 of a pixel. If there were expected to be (say) 2.5 pixels gap, there might now be a single pixel gap.

The second rectangle is :

2.52 0 0.84 20.63 re

Converting into the actual device space, that starts at pixel 7.1 and is 2.36 pixels wide. Assuming we use pixel centres, that means we mark pixels 7, 8 and 9.

Consider if we had started the rectangle at 7.2 instead. Now the rectangle would extend from 7.2 to 9.56. Still assuming pixel centres, we now mark pixels 7, 8, 9 and 10. The line is 33% wider just by shifting the starting point by 0.1 pixels.

The pixel rendering rules we use are (mostly) the same as Adobe for obvious reasons.

 
> Currently pdftoraster converts the PDF to a mono PWG and then rastertolabel
> converts that to GRF/ZPL (which is mono only). I'm thinking wouldn't it be
> better if pdftoraster returned a greyscale PWG and then rastertolabel
> decides how to convert that to mono suitable for label printers?

No idea, and none of this is really anything to do with Ghostscript. NB for a further comparison you could try MuPDF, which applies anti-aliasing by default. Of course it only works with PDF input, but that seems to be what you are using.


> Going with the above I'm thinking I could write my own CUPS filter but I'm
> not sure how I could hijack the PDF mimetypes for label printers without
> affecting laser printers.

Again, this seems to be a question for CUPS developers, not really Ghostscript. Unless of course you were to write a device for Ghostscript which implemented the changes you require for this type of printer. As long as you are using a generic bitmap output you aren't going to get any kind of control specific to your device.
Comment 9 Kyle MacFarlane 2016-05-09 02:30:40 UTC
I reported the issue to CUPS before coming here but they closed the ticket and blamed Ghostscript. I've gone back there now so let's see what happens.
Comment 10 Ken Sharp 2016-05-09 02:36:22 UTC
(In reply to Kyle MacFarlane from comment #9)
> I reported the issue to CUPS before coming here but they closed the ticket
> and blamed Ghostscript. I've gone back there now so let's see what happens.

I wasn't suggesting this was a CUPS 'problem' as such, simply that if you want to alter the way CUPS works, or builds pipelines, we can't help you.
Comment 11 jsmeix 2016-05-09 04:49:23 UTC
FYI:

This is the mentioned CUPS issue:
https://github.com/apple/cups/issues/4820

I agree that this is not an issue "inside" CUPS
but - if at all - it could be an issue in any
of the various filtering programs that are called
by the cupsd for processing print job data.

In general with PDF input the root cause of issues
is often not in a print job data processing program
but "inside" the original PDF input (but I am
not at all a PDF expert to make any authoritative
statement about this particular issue here).
Comment 12 Kyle MacFarlane 2016-05-10 02:25:42 UTC
For reference barcode fonts do bypass the problem but you can't change their size without them going crazy. They're also very expensive for a server license.

For our self generated labels I managed to fix the problem by merely making the black bars thinner. On a thermal printer a 1px black line comes out well but a 1px white line almost disappears. Less is more when printing on thermal paper.
Comment 13 Robin Watts 2016-05-10 05:28:51 UTC
(In reply to Kyle MacFarlane from comment #12)
> For reference barcode fonts do bypass the problem but you can't change their
> size without them going crazy. They're also very expensive for a server
> license.
> 
> For our self generated labels I managed to fix the problem by merely making
> the black bars thinner. On a thermal printer a 1px black line comes out well
> but a 1px white line almost disappears. Less is more when printing on
> thermal paper.

The smartest way to solve this then, is probably to draw a solid black block for the barcode, then draw the gaps in.

The 'any part of a pixel' rule, will cause the white gaps to 'expand' slightly.

Of course, the larger you draw the barcode, the smaller the variations will be (as a proportion of the total size).
Comment 14 Kyle MacFarlane 2016-05-10 05:48:48 UTC
I've actually tried that and it worked best. So far I tried the following methods:

1) I wondered if the downscaling doesn't care about colours but merely shapes. If this is true then whiting out a black box should work best for a thermal printer. However merely whiting things out doesn't quite work as expected and minor adjustments are needed. You have to be careful not to create too large white areas that cause scanners to crop the code.

2) Since I had to adjust the size of the white bars to make #1 work then I also tried the opposite of adjusting black bars.

3) I tried to draw the bars snapped to a grid at a target DPI.

#1 seems to produce the highest quality prints even with the slight adjustments. So was I correct in assuming that the downscaler looks for shapes rather than colours?

#2 works well and is very simple but isn't quite as high quality as #1.

#3 didn't work very well but I only tried it in a pretty simple way.

I also had a look to see if GS has a negative option but apparently such a thing doesn't exist. I wanted to see what might happen if you combined a negative of vectors with a positive of fonts.
Comment 15 Ken Sharp 2016-05-10 06:02:32 UTC
(In reply to Kyle MacFarlane from comment #14)

> 1) I wondered if the downscaling doesn't care about colours but merely
> shapes. 

We are not performing 'downscaling', we are rendering the requested operation to the target device. The problem isn't 'downsampling' its the low resolution.

A true 'write white' device might suit your purposes better, given the apparent properties of the printer. However, that would mean creating a specific device type for that printer, instead of using the generic bitmap routines.


> #1 seems to produce the highest quality prints even with the slight
> adjustments. So was I correct in assuming that the downscaler looks for
> shapes rather than colours?

There is no downscaler (unless you are using one of the *scaled devices). The rendering routines do not care about colour though, except in as much as colour may need to be converted to other spaces, and obviously the colour determines which planes are marked.

> I also had a look to see if GS has a negative option but apparently such a
> thing doesn't exist.

In PostScript, the NegativePrint page device parameter.

> I wanted to see what might happen if you combined a
> negative of vectors with a positive of fonts.

I don't see how NegativePrint would help that really, since the entire output would be in negative.

In any event, for testing purposes, you can get the same effect by loading the output of Ghostscript into your favourite image editor and negating the output.
Comment 16 Kyle MacFarlane 2016-05-10 06:40:33 UTC
So where is the problem starting? Is it in the rastertolabel filter from CUPS or the cups device in Ghostscript?

The way I see it is that CUPS offers support for label printers and 99.99% of label printers are 203dpi. To claim to support label printers you need to support 203dpi and it can't be dismissed as too low resolution.

My thinking all along is that the problem is how rastertolabel converts a PWG to a GRF which is inserted into ZPL (label printers don't use Postscript) without any consideration for how label printers work. That's why I started over on their issue tracker. But now I'm being told that a new Ghostscript device could solve the problem? Wouldn't that mean that the existing cups device could also solve the problem?

So in conclusion, if CUPS offers support for label printers then shouldn't the cups device in Ghostscript also support label printers? (Assuming that the cups device is where the problem starts.)
Comment 17 Robin Watts 2016-05-10 07:12:40 UTC
The issue, AIUI, is to do with Postscript. It's independent of CUPS or label printers or even ghostscript.

Any conforming postscript interpreter (i.e. the bit that takes postscript in, and produces an "image" out that can be printed) is bound by the postscript specification to render lines in a particular way.

Imagine that you have some graph paper with divisions at 203dpi.

Now draw your barcode onto that. Some of the bars in the bar code are not going to line up exactly with the divisions in the graph paper, and so the question is what to do in those cases.

The Postscript specification (which Ghostscript implements) says that if ANY PART of a pixel (i.e. a division of the graph paper) is touched, then the WHOLE pixel gets filled.

So if you draw your barcode as a white background with black stripes, the black stripes will 'spread' left and right by up to 1 full pixel.

If you draw your barcode as a black background with white stripes, the white stripes will 'spread' left and right by up to 1 full pixel.

Now, if you're working at 600dpi, 1 pixel is neither here nor there. If you're working at 203 dpi, then it's a much more significant proportion.

Finally, you're saying that your label printers (being thermal) cause black lines to spread even more. That's a completely separate problem. In theory it would be possible to produce a device in ghostscript to 'adjust' the output image so that this 'thermal spreading' is allowed for, but that'll be a large amount of work.

If the thermal spreading is large (i.e. > 1 pixel) then you may be able to construct the initial postscript files so as to correct for this. But I really doubt that it's that large.

So, how can you solve this problem? Well, there are some steps that would make sense to me.

1) Check to see if you can adjust the size of the barcode in such a way that at 203dpi, the edges of the lines match up better with the pixel grid. I have no idea if this is possible.

2) If not, make the barcode as large as possible subject to your printing area. The larger the barcode, the smaller the percentage errors will be.

3) I'd suspect that drawing the barcode as a white background with black lines on it will render better; the spaces will tend to grow, which will be slightly compensated for by the thermal spread.

4) One alternative would be to generate the bar codes as images. Images follow a different rule in Postscript (and hence in Ghostscript). Rather than a pixel being set if "any part" of it is touched they are only set if the "centre point" of the pixel is touched. This MAY give you better results.

You've mentioned the idea of 'downscaling'. We do offer some devices in ghostscript that do downscaling, but I don't think these will help you. For these, we literally render at a larger resolution, and then downscale, taking the average of pixel values. This means that rather than getting an exact black/white image you'll either get a greyscale image or a dithered image. Neither one of those will help with a barcode where you really want an exact black/white result.
Comment 18 Ken Sharp 2016-05-10 07:18:30 UTC
(In reply to Kyle MacFarlane from comment #16)

> So where is the problem starting? Is it in the rastertolabel filter from
> CUPS or the cups device in Ghostscript?

The problem is that you are trying to print quite tightly defined sized objects on a low resolution device, using a high level language. Even worse is the mixing of metric requirements with imperial resolution/language (millimetres vs dpi).


> > The way I see it is that CUPS offers support for label printers and 99.99%
> of label printers are 203dpi. To claim to support label printers you need to
> support 203dpi and it can't be dismissed as too low resolution.

Well, that's a CUPS decision, Ghostscript doesn't specifically support this kind of printer. Of course, since the printer can accept a bitmap, and that's what we produce, its quite reasonable to argue that the printer should sort this out, and arrange that thin areas don't vanish.

Its also true to say that as labels your printout is adequate, its the printing of bar codes which is the problem, and the tight tolerances are difficult to match (as you have discovered) with a low resolution printer. There's nothing wrong IMO with CUPS saying it supports label printers, but bar codes are a different matter.

This doesn't mean I am dismissing the printer as 'too low resolution', but you are going to find it hard to match 46 millimeters at 203 dpi, as I tried to explain in comment #8 the problem is that your rectangle definitions do not match the underlying pixels of the device, so the rendering code needs to make decisions about which pixels to mark. The result is (I would say) entirely adequate for a label, if not for a bar code. If you want the output to match your desired outcome better then you have a number of choices, as already discussed. Perhaps the simplest is to design your bar codes so that they lie precisely on the printers pixels. I could readily enough write that in PostScript, but you are using PDF (produced by 'PDFium'), I have no idea what you use to generate the PDF files.


> My thinking all along is that the problem is how rastertolabel converts a
> PWG to a GRF which is inserted into ZPL (label printers don't use
> Postscript) without any consideration for how label printers work. That's
> why I started over on their issue tracker. But now I'm being told that a new
> Ghostscript device could solve the problem? Wouldn't that mean that the
> existing cups device could also solve the problem?

I cannot comment on CUPS or rastertolabel. A Ghostscript device, written specifically to cater for the characteristics of this kind of printer, *could* do a better job than a generic bitmap device, obviously, since it could take account of the peculiarities of the hardware. Essentially building the intelligence you feel is missing from rastertolabel into the Ghostscript device. That's not an offer to write such a thing by the way, just an observation that it could be done.

 
> So in conclusion, if CUPS offers support for label printers then shouldn't
> the cups device in Ghostscript also support label printers?

No. The Ghostscript CUPS device produces a generic bitmap, it does not target any specific device. CUPS sends that raster to the device, manipulating it as required, we have no input into any of that.

My conclusion is that there is no bug in Ghostscript, it is operating exactly as designed and expected. I'm aware that doesn't help you, but it is nevertheless true. Your basic problem remains that you are using a high level language to describe the printed output, and not taking sufficient care to match the co-ordinate system to the pixel of the target device. Bluntly put you are using a device-independent language and complaining about device-dependent results.
Comment 19 Ken Sharp 2016-05-10 07:29:20 UTC
(In reply to Robin Watts from comment #17)

> 4) One alternative would be to generate the bar codes as images. Images
> follow a different rule in Postscript (and hence in Ghostscript). Rather
> than a pixel being set if "any part" of it is touched they are only set if
> the "centre point" of the pixel is touched. This MAY give you better results.

Making the barcode as a full page bitmap, 203 dpi, and then drawing the remaining objects on top of it might work well.
Comment 20 jsmeix 2016-05-10 08:09:18 UTC
Shouldn't it mitigate the issue when the
dimensions of the barcode rectangles are
specified in units that match excatly 203 dpi
(i.e. 1/203 = 0.0049 inches = 0.3546 PostScript points)?

I think this way the "rounding error" for a barcode rectangle
with width of N * 0.3546 PostScript points could be at most
0.3546 PostScript points and not up to 2 * 0.3546 PostScript points.

I think if width are specified in 0.3546 PostScript point units
it results mainly a small shift (up to 0.3546 PostScript point)
of the whole barcode.
Comment 21 Ken Sharp 2016-05-10 08:40:26 UTC
(In reply to jsmeix from comment #20)
> Shouldn't it mitigate the issue when the
> dimensions of the barcode rectangles are
> specified in units that match excatly 203 dpi
> (i.e. 1/203 = 0.0049 inches = 0.3546 PostScript points)?

Dimensions *and* positions, and yes this is one of the points made in earlier comments.

 
> I think this way the "rounding error" for a barcode rectangle
> with width of N * 0.3546 PostScript points could be at most
> 0.3546 PostScript points and not up to 2 * 0.3546 PostScript points.

Its not rounding errors, its the fact that when you do the arithmetic to convert from user space to device space, the result (not a rounding error, the actual result) is fractional pixels. In comment #8 I point out, for example, that the second barcode rectangle is defined as starting at pixel position 7.1; that isn't a rounding error, its the actual result of doing the arithmetic from the co-ordinate in user space.

If the rectangle is defined in user space so that the vertices lie on pixel boundaries in device space, then there is no rounding error, and the rectangle will be drawn as expected.

There is *some* scope for error, since we use a fixed point representation internally for performance, but this is unlikely to cause real problems.
Comment 22 Kyle MacFarlane 2016-05-10 09:43:34 UTC
Just to be clear, for all intents and (our) purposes I have fixed this problem. However this is only because we're allowed by our couriers to generate our own labels and smaller businesses or personal users would still run into this problem.

Also this discussion would be better on the CUPS ticket but this is where the action is.


>I think this way the "rounding error" for a barcode rectangle
with width of N * 0.3546 PostScript points could be at most
0.3546 PostScript points and not up to 2 * 0.3546 PostScript points.

That was the #3 I tried above. It didn't work out very well because I still have to stay within the total 46mm width. All I did was round the position and width of each bar up and down depending on the adjacent gaps but a smarter attempt would shave off large gaps and add to small gaps across the whole barcode.

>Of course, since the printer can accept a bitmap, and that's what we produce, its quite reasonable to argue that the printer should sort this out, and arrange that thin areas don't vanish.

Label printers can only accept 1bit bitmaps. The proper way to use ZPL (label printers aren't PS) is to write everything by hand in raw ZPL as vector and use the built in fonts and barcodes (yes built in barcode generation!). However it's been a long time since a courier has provided raw ZPL and these days it's all PDF. The only PDF => ZPL route that exists (and Windows does this too) is to convert the PDF to a bitmap and embed that in the ZPL.

The ZPL bitmaps are only really meant for logos and the like but this is the path history has lead us down. The built in fonts are also often not suitable for international shipping labels as international addresses can use all types of glyphs so PDF is a safer option. Plus nobody has a ZPL viewer installed and users will think you sent them a virus if they opened ZPL in a text editor.

A PDF => ZPL device would probably be worth a bit of money. I did briefly consider trying to create a vector to ZPL generator but the SVG output of GS is deprecated and I'm not as familiar with the other vector formats. Maybe in the future I'll have a go at creating a subset of PS => ZPL converter.

>Its also true to say that as labels your printout is adequate, its the printing of bar codes which is the problem, and the tight tolerances are difficult to match (as you have discovered) with a low resolution printer. There's nothing wrong IMO with CUPS saying it supports label printers, but bar codes are a different matter.

I would say that nearly everyone using a label printer is printing barcodes. When I say "label printer" I don't mean those Dymo things for overly organised people, I mean the Zebra things that print the 4"x6" (or longer) labels that are on every package you receive from Amazon. The rastertolabel source mentions being tested on such 4"x6" models.

They're expensive to personal users but couriers give them (and the rolls of paper) away like candy to account holders. They do this because they want sharp labels that can be reliably scanned and OCRd and laser printers aren't reliable enough to do this 1000s of times a day every day. They also have a ~1s first page time which is good for time sensitive tasks. However it would seem that some couriers only test printing their labels from Windows.

>produced by 'PDFium'

That is actually Chrome overwriting the metadata. When you print from Chrome it modifies the PDF before it's sent to the printer. I believe it's so as much as possible can be done in the client and reduce the requirements for printers to support Cloud Print.
Comment 23 jsmeix 2016-05-11 03:59:23 UTC
Only for clarification about my "rounding errors":

I know that this are not actual "rounding errors"
but I don't know the right technical/mathematical term
for the resulting "differences" when one has to convert
real (fractional) numbers into integer numbers
(independent of the used algorithm).

When user space uses units which match the units of device space
and also the position matches, then those "differences" are zero.

What I liked to tell was that when user space uses units
which match the units of device space but the position
does not match, then the "differences" in dimensions
are at most one such unit (i.e. one pixel in printout).
Comment 24 James Cloos 2016-05-11 12:13:38 UTC
BTW:

One point which may make things easier when generating the original pdf:

Think of the printer as 8/mm rather than 203/in.

So, for instance, your note that the bars need to be 46mm wide means they should be 368 pixels wide.

Also, you may want to look at what https://github.com/bwipp/postscriptbarcode does to see how to make a good barcode using postscript's rendering choices.
Comment 25 Kyle MacFarlane 2016-05-11 22:16:32 UTC
So I was on the wrong track with this.

I noticed that barcodes on portrait labels are much higher quality than barcodes on landscape levels. Royal Mail's spec requires an even smaller barcode at 39mm but it prints out higher quality than Deutsche Post's.

I think that it's probably due to the fact that for a portrait barcode the printer can just leave the heat on but in landscape it has to turn the heat on and off and residual heat lowers the achievable DPI.

I used poppler with "-aa no -aaVector yes" to create a PNG with (almost) monoscale text and greyscale vectors. Then running up from the bottom of the label I transform grey pixels depending on whether or not the heat might need to be turned off early. Something so simple greatly increases the quality but still needs a few tweaks for particularly slim white areas.

The remaining problem is that even with aa off poppler still has some blurring on text and I end up making a lot of it look bad. There's a particularly bad effect on larger bold text but a similar effect appears on Windows which I hope means I'm on the right track.

What I'd like to be able to do now is convert a PDF to a PNG (and eventually a PWG to integrate with CUPS) with completely monoscale text and images but greyscale vectors.
Comment 26 Chunlin Yao 2016-09-01 23:04:34 UTC
Maybe it is because gstoraster use any-part-of-pixel rule when fill path. It can print better barcode by set '-c 0 .setfilladjust'. I created a related feature request in cups-filters project   https://bugs.linuxfoundation.org/show_bug.cgi?id=1373