RWAP / PrinterToPDF

Project for converting captured printer data files to PDF format
GNU General Public License v3.0
85 stars 19 forks source link

Page size and margins #11

Open Mike-DE-RE opened 7 years ago

Mike-DE-RE commented 7 years ago

So far the program pays no respect to page setup. I've prepared a new ESC/P2 sample from our labeling software:

20170510.zip

The lable itself is 45x45mm.

They are arranged on a page with 4 columns and 6 rows, 24 labels on one page.

Distance from the left side of the outmost left label to the right side of the outmost right label it is 186mm.

Page length is 12" = 304.8mm.

Meaning there is a top margin of 2.9mm, a distance between the rable rows of 5.8mm and a bottom margin of 2.9mm again.

Left and right margin is a little difficult, because on line printers you could always move the paper horizontally.

But one can calculate that there is a 2mm distance between the label columns.

Here is a scan of such a page I created with a matrix printer (no ink - for higher precision):

20170510

Scan isn't as good as I thought. I may have to repeat it with higher contrast to show the paper and labels.

Mike-DE-RE commented 7 years ago

Here is a new scan of the same page, showing paper limits (top and right have been enhanced manually):

20170510

Mike-DE-RE commented 7 years ago

To help with page size and margins I have created another document with Word for DOS using EPLQ.DBS and selecting "LQ-series (multifont.) 1.0" as printer modell. It is a colour mix of text and graphic, resolution 360x180:

RETRO.zip

This is on a DIN A4 page (210 x 297mm). Top and bottom margin is 7.5mm, right margin is 20.1mm, left margin is 20mm.

Picture is scaled to 173.4 x 130 mm and centered, it is a screenshot of your website colour reduced to fixed eight colours using Stucki algorithm.

Can be used for testing colour as well, see https://github.com/RWAP/PrinterToPDF/issues/8

RWAP commented 7 years ago

The program currently ignores top and bottom margins and paper size settings passed as ESC ( C command. However, the left and right margins are set.

I have started a method in the initialize() function to set up the paper sizes - standard margins could also be set here - as many printers rely on these being set through DIP switch settings, it is impossible to automate these unless they are passed by the printer program itself.

Mike-DE-RE commented 7 years ago

I completely understand. But as you can see from the RETRO.zip sample an A4 page still splits to three png/pdf files.

I would suggest 12" paper to be default for the program because at the time of ESC/P(2) that was the main page/paper format used.

RWAP commented 7 years ago

The latest beta version of the software adheres to the top, bottom and side margins. You can set them up for the given page size in the initialize() routine. I have added default offsets in there according to the ESC/P2 programming reference manual, along with support for A4, A4 landscape and 12" paper sizes - more can easily be added

As part of the re-consideration of the PNG to PDF conversion routine, we need to look at how to set up the paper sizes passed to the PDF to ensure these are correct - see: http://www.imagemagick.org/script/command-line-options.php#page

We need to pass parameters if we are continuing to use ImageMagick...

Mike-DE-RE commented 7 years ago

Opening the pdf with Adobe Acrobat showes the file like this:

bild01

The document has a size of 2,100.4 x 2,969.3 mm. One could print it using "Fit to Printable Area" but that influences the original size of the print. Trying to print on lables would be completely impossible.

Mike-DE-RE commented 7 years ago

Opening the png in gimp showes that the file is

5954 x 8417px 2100,44 x 2969,33mm with a resolution of 72dpi

Setting resolution to 720dpi will not affect the pixels but will correct the size in mm to

210,04 x 296,93mm

I think that is required here.

RWAP commented 7 years ago

This will need to be looked at once we have decided on the PNG to PDF conversion routine.

For now - we need to add page sizes to the initialize() routine and can then pass that to the convert command.

Mike-DE-RE commented 7 years ago

I have taken gimp to set the original PNG file to 720dpi. After that I used

convert input.png output.pdf

to convert it to PDF. Here is the result:

acrobat-preview

So as far as I see, all you have to do is set the PNG to 720dpi resolution.

Mike-DE-RE commented 7 years ago

Now that I've done above step. I was able to join the PNG with my scan:

layers

I have coloured you PNG in green below that is my original scan. I wouldn't have expected this result.

RWAP commented 7 years ago

The latest source now includes setting the PNG resolution to 720dpi - does this help?

Mike-DE-RE commented 7 years ago

1st - Can confirm that resolution now is 720dpi.

2nd - I am back to black background now.

3rd - It is difficult to match both scan and converted image when conversion result is a black page. ;-)

RWAP commented 7 years ago

I am at a complete loss as to why you sometimes do not get a white background as this is not something I can replicate.

If you add line 554:

if (pixelColour==WHITE) printf("WHITE is %d %d %d \n",red(pixelColour), green(pixelColour), blue(pixelColour)); Do you see lots of output with WHITE is 255 255 255 ?

Mike-DE-RE commented 7 years ago

Had to change that to

for (x=0 ; x<width ; x++) { pixelColour = rgb[ipos + x]; if (pixelColour==WHITE) printf("WHITE is %d %d %d \n",red[pixelColour], green[pixelColour], blue[pixelColour]); row[ppos++] = red[pixelColour]; row[ppos++] = green[pixelColour]; row[ppos++] = blue[pixelColour]; }

because of

gcc PrinterConvert.c sdl-config --cflags --libs -o PrinterConvert -lrt -lpng

PrinterConvert.c: In function ‘write_png’: PrinterConvert.c:554: error: called object ‘red’ is not a function PrinterConvert.c:554: error: called object ‘green’ is not a function PrinterConvert.c:554: error: called object ‘blue’ is not a function

Here is the output:

time ./PrinterConvert 4 3 SIEMENS.C16 1 sdloff ./

delays around ack: t1=0 t2=0 t3=0 t4=0 t5=0 write = png/page1.png command = convert png/page1.png ./pdf/page1.pdf

I am at page 2 write = png/page2.png command = convert png/page2.png ./pdf/page2.pdf

real 0m57.294s user 0m42.819s sys 0m3.736s

RWAP commented 7 years ago

OK sorry for the typo.

However, the output is really odd - as it suggests the page is not getting set to white with erasepage() - called in line 408 and line 2192 (408 is actually overkill).

Just check that the program is actually running line 554 and see what the value of pixelColour is - maybe it is stuck at zero!

Mike-DE-RE commented 7 years ago

First I have amended the source as follows:

for (x=0 ; x<width ; x++) { pixelColour = rgb[ipos + x]; if (x==width) printf("I am here"); if (pixelColour==WHITE) printf("WHITE is %d %d %d \n",red[pixelColour], green[pixelColour], blue[pixelColour]); row[ppos++] = red[pixelColour]; row[ppos++] = green[pixelColour]; row[ppos++] = blue[pixelColour]; }

Result:

I am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am hereI am here...

So that is clear.

Then I tried to print pixelColour:

for (x=0 ; x<width ; x++) { pixelColour = rgb[ipos + x]; printf(pixelColour); if (pixelColour==128) printf("WHITE is %d %d %d \n",red[pixelColour], green[pixelColour], blue[pixelColour]); row[ppos++] = red[pixelColour]; row[ppos++] = green[pixelColour]; row[ppos++] = blue[pixelColour]; }

Result

gcc PrinterConvert.c sdl-config --cflags --libs -o PrinterConvert -lrt -lpng PrinterConvert.c: In function ‘write_png’: PrinterConvert.c:554: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast

So I changed to

for (x=0 ; x<width ; x++) { pixelColour = rgb[ipos + x]; printf("%u ", pixelColour); if (pixelColour==128) printf("WHITE is %d %d %d \n",red[pixelColour], green[pixelColour], blue[pixelColour]); row[ppos++] = red[pixelColour]; row[ppos++] = green[pixelColour]; row[ppos++] = blue[pixelColour]; }

Which printed a lot of integers. And I changed again

for (x=0 ; x<width ; x++) { pixelColour = rgb[ipos + x]; if (pixelColour>=32) printf("%u ", pixelColour); if (pixelColour==128) printf("WHITE is %d %d %d \n",red[pixelColour], green[pixelColour], blue[pixelColour]); row[ppos++] = red[pixelColour]; row[ppos++] = green[pixelColour]; row[ppos++] = blue[pixelColour]; }

Which printed nothing! So that must be C specific. The variable is not what you think.

RWAP commented 7 years ago

Hmm ...

pixelColour does of course depend on what colours you are using - bit 0 = black, bit 1= magenta, bit 2 = cyan, bit 3 = voilet, bit 4 = yellow, bit 5= red, bit 6 = green, bit 7 = white

So, pixelColour >=32 is only valid for printing green and white or mixed colours including green.

I wonder if pixelColour == 0 on your system for some reason when it should be a white background - this could be overcome by changing the start of lookupColour() to read:

int * lookupColour(unsigned char colourValue)
{
    // Convert printer colour (0 to 7 stored in bits of colourValue) to RGB value
    // Routine uses averaging to get colours such as pink (red + white)
    static int rgb1[3];
    int colourMixMethod = 2; // 1 = RGB simple addition method, 2 = Standard CMYK Mix with conversion -
    int *mixedColour;
    int mixedColour_red, mixedColour_green, mixedColour_blue;
    rgb1[0]=0;
    rgb1[1]=0;
    rgb1[2]=0;
    int mixColour = 0;
    if (colourValue == 1) return rgb1; // Black
    if (colourValue == 0 || colourValue == WHITE) {
        // Bit 7 is set for white - not supported on printers
        rgb1[0]=255;
        rgb1[1]=255;
        rgb1[2]=255;
        return rgb1;
    }

This should not actually happen unless it is a bug in your version of gcc causing an issue with the erasepage() function (which should have set bit 7 in all of the memory values initially)

RWAP commented 7 years ago

Of course, it could also be a bug in the new CMYK lookup method for colour mixing - is the problem fixed by altering line 186 to read:

int colourMixMethod = 1;

If so then at least we know where to look for a bug....

I have just noticed that line 177 ( rgb_result[3] = rgb_lookups[3];) is not required and might cause an issue

Mike-DE-RE commented 7 years ago

is the problem fixed by altering line 186 to read:

int colourMixMethod = 1;

No!

I have just noticed that line 177 ( rgb_result[3] = rgb_lookups[3];) is not required and might cause an issue

// rgb_result[3] = rgb_lookups[3];

No difference! (still black)

Tried your amended

lookupColour

from above. No difference! (still black)

Mike-DE-RE commented 7 years ago

Remember, we were on white background. What happened after that?

RWAP commented 7 years ago

Nothing that I can find in the history of the code - that is what is confusing!

Did you try the change to the lookupColour() function?

Mike-DE-RE commented 7 years ago

Did you try the change to the lookupColour() function?

Yes, as written above.

Sorry, but I did not archive the version that produces proper white background. I have only found the version that creates green background.

RWAP commented 7 years ago

If you go to : https://github.com/RWAP/PrinterToPDF/blob/master/PrinterConvert.c

You can then click on history and will see the various update history on github. Click on the title of one (say "Improvements to colour and TIFF compression" on 11th May which is when I know the white background was working).

This shows the changes made in that version.

Click on browse files (top right) and that will take you to a snapshot of the code at that version - you can then access the full printerconvert.c at that time.

My guess is that this issue has come back in the commit of 14th May ( 720dpi Delta Row Compression ) although that is a pure guess

Mike-DE-RE commented 7 years ago

This

Commits on May 11, 2017 "Correction of Delta Row Compression"

https://raw.githubusercontent.com/RWAP/PrinterToPDF/76a89ccde0f810e05f6d5ebcf40d4edafecb5cf9/PrinterConvert.c

produces WHITE background.

This

Commits on May 12, 2017 "Colour Lookup & Page Size"

https://raw.githubusercontent.com/RWAP/PrinterToPDF/c008fc5a72299203735f64dd5a04aa7780d78289/PrinterConvert.c

produces BLACK background again.

Mike-DE-RE commented 7 years ago

That solves the Problem!

Changing line 471 from

int pixelColour;

to read

unsigned char pixelColour;

RWAP commented 7 years ago

OK the black background is now fixed by changing line 471 from :

int pixelColour;

to read:

unsigned char pixelColour;

Not quite sure why this was needed on some versions of gcc

Mike-DE-RE commented 7 years ago

Now that I can "see" again, I've repeated my above test:

2017

Green is the result of the conversion, black is my scan. The conversion in comparison to the printer showes a wider and higher picture.

I've done some measurements and found that the conversion is about 20% bigger than the original. I think it must have to do with the resolution?

720/120*100=600, where 720dpi is conversion and 600dpi is scan. I'll try to resize and overlay tomorrow.

Mike-DE-RE commented 7 years ago

Ok, so what I've done now comes closer to what is required. But I am a little puzzled about how I reached the result:

testprn

Changing the scan to 720dpi with gimp did not work. In fact I had to scale the scan to 120% of it's original size. But 120% seems not to be perfect value as you can see on above picture.

Any idea why?

Mike-DE-RE commented 7 years ago

Next step I did was to scale the converted (green) layer down to fit the scan.

Original size 5954 x 8417

fitted 5971 x 8394

testprn

Not very much, but this way scan and conversion matches. What I recognized doing this is that the converted png has a resolution of 719.998dpi:

information

Can that cause the problem?

RWAP commented 7 years ago

Possibly the converted png resolution might have a bearing - we tell it to use 720dpi, but obviously libpng is not using that exact figure... However, at 720dpi, A4 paper (11.69") gives a vertical number of pixels of 11.69 * 720 = 8416.8 (slightly less using 719.988dpi but still more than 8416)

At 5971 x 8394 this gives an original paper size of 8.293" x 11.658" - which could of course be down to the physical size of your fanfold paper

I think it is a matter of working out the exact paper size - you said your paper is 12" fanfold, yet it measures (looking at your image) 205mm x 305mm = 8.07" x 12.0079" so you need to ensure that in initialize() you set the pageSize=2 and probably finetune the values in:

        // 12" Paper - Fanfold
        pageSetWidth = 5954; // 720 * 8.27"
        pageSetHeight = 8640; // 720 * 12"
        defaultMarginLeftp = 85; // 720 x 3mm
        defaultMarginRightp = pageSetWidth - 85; // 720 x 3mm
        defaultMarginTopp = 255; // 720 x 9mm
        defaultMarginBottomp = pageSetHeight - 355; // 720 x 9mm
        break;

Maybe to

        // 12" Paper - Fanfold
        pageSetWidth = 5811; // 720 * 8.07"
        pageSetHeight = 8640; // 720 * 12"
        defaultMarginLeftp = 85; // 720 x 3mm
        defaultMarginRightp = pageSetWidth - 85; // 720 x 3mm
        defaultMarginTopp = 255; // 720 x 9mm
        defaultMarginBottomp = pageSetHeight - 355; // 720 x 9mm
        break;
Mike-DE-RE commented 7 years ago

Made a big mistake in my above posting!

I've repeated the operation for the converted image. Before that I rescaled both scan and converted picture to have exactly 720dpi.

Original size 5954 x 8417

fitted 4977 x 6995

so converted print it is still about 20% bigger than the scan. I will try above suggestions.

Mike-DE-RE commented 7 years ago

Have set

pageSize = 2;

and adopted

// 12" Paper - Fanfold pageSetWidth = 5811; // 720 205mm pageSetHeight = 8640; // 720 12" defaultMarginLeftp = 283; // 720 x 2.5mm defaultMarginRightp = pageSetWidth - 283; // 720 x 2.5mm defaultMarginTopp = 71; // 720 x 10mm defaultMarginBottomp = pageSetHeight - 71; // 720 x 10mm

Conversion showes everything on on page now. Looks fine. Still does not fit on scan. But now I have actually measured the scan and seen that the ruler on 100mm is only 83,1mm, which must be the result from setting this page to 720dpi. When I check that on the 600dpi original, it is in fact 100mm.

Mike-DE-RE commented 7 years ago

Now I've prepared the scan first to be 8433 x 11933 pixels (~ x 1.202) and 720dpi. I have calculated this and checked it with gimp so that the vertical rules is exactly 100mm at 10cm and the horizontal ruler is 100.4mm at 10cm. After that I have inserted the green layer that I had scaled to exactly 720dpi first:

testx

As you can see, conversion and scan still does not match for 100%. Scan is horizontally little smaller and vertically a little longer.

Next is: I will get the conversion printed on an A3 page (without scaling it) and compare it to the original print.

Mike-DE-RE commented 7 years ago

Ok, this is confusing indeed. Doing on paper as described, there is nearly no visible difference. Should that come from the last conversion step (png2pdf)? I did not use the PDF on digital compares, because I tried to be as close to the original conversion result as possible.

Right now I have no explanation for that.

RWAP commented 7 years ago

png2pdf should not affect this so I guess it is something to do with the scanning process