BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by Gio » 01 Feb 2016, 18:00

JoeWinograd wrote:I found a command line tool called ZBar bar code reader that has worked in my tests
I also got it to output decoded messages to the CMD and than to AutoHotkey with CMDRet(). Thanks for sharing the link Joe. I added a note about it :thumbup:

Code: Select all

CMD_OUTPUT  := CMDret_RunReturn("cmd /c c:/users/usuario/desktop/zbarimg.exe -q --raw c:/users/usuario/desktop/example.pdf") ; Adjust Zbarimg and the files paths in the string.
msgbox % CMD_OUTPUT
Return
* Code above requires CMDRet() and ZBar.

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 01 Feb 2016, 18:28

Gio,
Thanks for the info on, and link to, CMDRet() — I was not aware of it. Very interesting! I took a much lower tech approach in my script and am simply capturing STDOUT via redirection, as follows:

Code: Select all

RunWait,%comspec% /c ""zbarimg.exe" "%InputFile%">"%OutputFile%"",,Hide
If it doesn't find a QR Code on the image, the line of code above will create a zero-byte output file, which is easy to test for. Regards, Joe

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 01 Feb 2016, 19:38

Hi Gio,
I hope you don't mind, but I took the liberty of generalizing your Example2-QR_Code script. There's a new InputBox that asks for the size, which must be a positive integer, and there are error checks to make sure it is. I also put in a check for clicking the Cancel button on both InputBox dialogs, in which case the script exits (so you don't have to right-click on the tray icon to exit). I tested it against the size 1, 3, and 10 scripts that you posted and the output is identical. I also tested sizes 20 and 50 — both worked fine. The script is below. Regards, Joe

Code: Select all

#SingleInstance, Force
SetBatchLines, -1

START:
inputbox, PixelSize,, Type in a positive integer for the size or click Cancel to Exit.`nA bigger number results in a bigger QR Code.
if (ErrorLevel=1)
  ExitApp
if PixelSize is not integer
{
  Msgbox, 0x10, Error, size must an integer - try again
  Goto START
}
if (PixelSize<0)
{
  Msgbox, 0x10, Error, size must be positive - try again
  Goto START
}
inputbox, Test,, Type in a message and a corresponding QR Code image will be generated and saved in the scripts directory.`nOr click Cancel to Exit.
if (ErrorLevel=1)
  ExitApp
MATRIX_TO_PRINT := BARCODER_GENERATE_QR_CODE(test)
if (MATRIX_TO_PRINT = 1)
{
  Msgbox, 0x10, Error, The input message is blank. Please input a message to successfully generate a QR Code image.
  Goto START
}

If MATRIX_TO_PRINT between 1 and 7
{
  Msgbox, 0x10, Error, ERROR CODE: %MATRIX_TO_PRINT% `n`nERROR CODE TABLE:`n`n1 - Input message is blank.`n2 - The Choosen Code Mode cannot encode all the characters in the input message.`n3 - Choosen Code Mode does not correspond to one of the currently indexed code modes (Automatic, numeric, alphanumeric or byte).`n4 - The choosen forced QR Matrix version (size) cannot encode the entire input message using the choosen ECL Code_Mode. Try forcing a higher version or choosing automated version selection (parameter value 0).`n5 - The input message is exceeding the QR Code standards maximum length for the choosen ECL and Code Mode.`n6 - Choosen Error Correction Level does not correspond to one of the standard ECLs (L, M, Q and H).`n7 - Forced version does not correspond to one of the QR Code standards versions.
  Goto START
}

  ; Start gdi+
  If !pToken := Gdip_Startup()
  {
    MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
    ExitApp
  }

  pBitmap := Gdip_CreateBitmap((MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize, (MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize) ; Adding 8 pixels to the width and height here as a "quiet zone" for the image. This serves to improve the printed code readability. QR Code specs require the quiet zones to surround the whole image and to be at least 4 modules wide (4 on each side = 8 total width added to the image). Don't forget to increase this number accordingly if you plan to change the pixel size of each module.
  G := Gdip_GraphicsFromImage(pBitmap)
  Gdip_SetSmoothingMode(pBitmap, 3)
  pBrush := Gdip_BrushCreateSolid(0xFFFFFFFF)
  Gdip_FillRectangle(G, pBrush, 0, 0, (MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize, (MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize) ; Same as above.
  Gdip_DeleteBrush(pBrush)

  Loop % MATRIX_TO_PRINT.MaxIndex() ; Acess the Rows of the Matrix
  {
    CURRENT_ROW := A_Index
    Loop % MATRIX_TO_PRINT[1].MaxIndex() ; Access the modules (Columns of the Rows).
    {
      CURRENT_COLUMN := A_Index
      If (MATRIX_TO_PRINT[CURRENT_ROW, A_Index] = 1)
      {
        ;Gdip_SetPixel(pBitmap, A_Index + 3, CURRENT_ROW + 3, 0xFF000000) ; Adding 3 to the current column and row to skip the quiet zones.
        Loop %PixelSize%
        {
          CURRENT_REDIMENSION_ROW := A_Index
          Loop %PixelSize%
          {
            Gdip_SetPixel(pBitmap, (CURRENT_COLUMN * PixelSize) + (3*PixelSize) - 1 + A_Index, (CURRENT_ROW * PixelSize) + (3*PixelSize) - 1 + CURRENT_REDIMENSION_ROW, 0xFF000000)
          }
      }
    }
      If (MATRIX_TO_PRINT[CURRENT_ROW, A_Index] = 0) ; White pixels need some more attention too when doing multi pixelwide images.
      {
        Loop %PixelSize%
        {
          CURRENT_REDIMENSION_ROW := A_Index
          Loop %PixelSize%
          {
            Gdip_SetPixel(pBitmap, (CURRENT_COLUMN * PixelSize) + (3*PixelSize) - 1 + A_Index, (CURRENT_ROW * 10) + 29 + CURRENT_REDIMENSION_ROW, 0xFFFFFFFF)
          }
        }
      }
    }
  }
  StringReplace, FILE_NAME_TO_USE, test, `" ; We can't use all the characters that byte mode can encode in the name of the file. So we are replacing them here (if they exist).
  FILE_PATH_AND_NAME := A_ScriptDir . "\" . SubStr(RegExReplace(FILE_NAME_TO_USE, "[\t\r\n\\\/\`:\`?\`*\`|\`>\`<]"), 1, 20) . ".png" ; Same as above.
  Gdip_SaveBitmapToFile(pBitmap, FILE_PATH_AND_NAME)
  Gdip_DisposeImage(pBitmap)
  Gdip_DeleteGraphics(G)
  Gdip_Shutdown(pToken)

msgbox, 0, Success, QR Code image successfully created!
Goto START
Return
#Include %A_ScriptDir%/BARCODER.ahk
#Include %A_ScriptDir%/GDIP.ahk

User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by Gio » 01 Feb 2016, 19:49

Excellent. I've added a link to it on the note about module sizes :thumbup:


User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 04 Feb 2016, 01:25

Hi Gio,
I don't know if this is a bug or was intentional, but it was driving me crazy until I figured it out, so I decided to pass it along. The file name of the PNG file that gets created is being truncated in the Example2-QR_Code script to the first 20 characters. This is because of the following statement near the bottom of the script:

Code: Select all

FILE_PATH_AND_NAME := A_ScriptDir . "\" . SubStr(RegExReplace(FILE_NAME_TO_USE, "[\t\r\n\\\/\`:\`?\`*\`|\`>\`<]"), 1, 20) . ".png"
It's the , 20 that's the culprit. I removed it, although good practice would be check for a length greater than 260 (inluding the length of the script folder plus one for the backslash). Regards, Joe

User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by Gio » 04 Feb 2016, 09:39

JoeWinograd wrote:I don't know if this is a bug or was intentional
It was intended. There is a limit to the number of characters that a file name may have and it is much lower than the number of characters that can be encoded in a QR Code matrix. I whanted the example to be able to output a very big message if the user wished to, but i also whanted the file name to be that of the message so that it could be easily told apart from other files in the same folder.

The number 20 was an arbitrary number i choose because i thought it would be enougth to let the user know which file he had generated and it still wouldnt be that big of a file name.

I should've added a comment about it in the code though. Sorry for that. It's now added.

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 04 Feb 2016, 11:23

Hi Gio,
The problem in my case is that the QR Codes are identical in the first 20 characters — the difference occurs only in the characters beyond 20, so the PNG file was getting overwritten, even though the QR Codes were different.

In researching the maximum length of a file name, it's trickier than I thought. But for purposes of this script, I'm fine with checking for a max total length (path and name) of 256, which these four lines of code do:

Code: Select all

  FILE_PATH_AND_NAME := A_ScriptDir . "\" . SubStr(RegExReplace(FILE_NAME_TO_USE, "[\t\r\n\\\/\`:\`?\`*\`|\`>\`<]"), 1) ; Same as above.
  If (StrLen(FILE_PATH_AND_NAME)>252)
    FILE_PATH_AND_NAME:=SubStr(FILE_PATH_AND_NAME,1,252)
  FILE_PATH_AND_NAME:=FILE_PATH_AND_NAME . ".png"
In the first line, I removed the string length param in the SubStr command and also removed the ".png" file type. In the second and third lines, I check for a total length greater than 252 — not 256, because the ".png" file type will add 4 chars. If it is greater than 252 chars, the SubStr command truncates it to the first 252. The fourth line adds the ".png" file type. Ideally, the code should check for an existing file and then have have an overwrite prompt/warning (perhaps the action taken when a file exists should be controlled by a user-specified param). Regards, Joe

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 04 Feb 2016, 11:55

Gio,
I decided to put in a quick-and-dirty check for an existing file. I'm sure it's not suitable for everyone's purpose with the script, but it's fine for me. I added these lines below the four new lines shown in my previous post:

Code: Select all

  IfExist,%FILE_PATH_AND_NAME%
  {
    MsgBox,4144,Error,%FILE_PATH_AND_NAME%`nalready exists - try again
    Goto START
  }
I also changed the "Success" dialog to include the file name created, as follows:

Code: Select all

MsgBox,4096,Success,Created QR Code in file`n%FILE_PATH_AND_NAME%
As you can see, I like to use System Modal (always on top) — change to suit your tastes. Regards, Joe

User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by Gio » 04 Feb 2016, 12:33

Excellent. I've added it.

The example is very limited because it's sole purpose is to ilustrate in a few lines one possible way to get an image out of the 2D object that the BARCODER_GENERATE_QR_CODE() function outputs. It's great that to see that you're not getting restricted by that method.

In my company, i have some implementations that actually output no image files at all. I simply retrieve the 2D Object from the function and use it to write a QR Code image straight to a bitmap in memory (created using GDIP Library by tic) that represents a pallet label with storage instrunctions. Than, i print it straight from memory using SGDIPrint Library by Zed Gecko.

This may solve the issue on report name handling since AutoHotkey variables can hold even more characters than QR Code Matrixes (also, it may speed up the process on large quantities of reports).
IMG_0250.JPG

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 04 Feb 2016, 13:13

> It's great that to see that you're not getting restricted by that method.

For the current project, creating the PNG file is perfect. But I do like your idea of not creating a file and instead writing it straight to memory, i.e., to an AHK variable. In looking at the Example2-QR_Code script, I guess that means utilizing the pBitmap variable and not calling Gdip_SaveBitmapToFile(pBitmap, FILE_PATH_AND_NAME) — right? Anything else to worry about with the in-memory approach?

User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by Gio » 04 Feb 2016, 15:03

I guess that means utilizing the pBitmap variable and not calling Gdip_SaveBitmapToFile(pBitmap, FILE_PATH_AND_NAME) — right? Anything else to worry about with the in-memory approach?
Basically yes, something like that. There would be more development though as you would be creating a report from scratch using GDI calls (adding the lines, the text, the QR Code, etc). But it doesn't really take that long and the report is completely customised to your needs.

As an alternative, if you already have a prototype report in an image file, you can load it using GDI and just add what you whant (like the QR Code) and than print it using SGDI (this would be the easiest to implement).

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 05 Feb 2016, 12:10

Thanks for the ideas!

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 18 Feb 2016, 03:40

Found a bug in my previously posted code — I failed to change some occurrences of the hard-coded numbers to using the PixelSize variable. The complete script with the bug fix, as well as all the enhancements mentioned in previous posts, is below:

Code: Select all

#SingleInstance, Force
SetBatchLines, -1

START:
inputbox, PixelSize,, Type in a positive integer for the size or click Cancel to Exit.`nA bigger number results in a bigger QR Code.
if (ErrorLevel=1)
  ExitApp
if PixelSize is not integer
{
  Msgbox, 0x10, Error, size must an integer - try again
  Goto START
}
if (PixelSize<0)
{
  Msgbox, 0x10, Error, size must be positive - try again
  Goto START
}
inputbox, Test,, Type in a message and a corresponding QR Code image will be generated and saved in the scripts directory.`nOr click Cancel to Exit.
if (ErrorLevel=1)
  ExitApp
MATRIX_TO_PRINT := BARCODER_GENERATE_QR_CODE(test)
if (MATRIX_TO_PRINT = 1)
{
  Msgbox, 0x10, Error, The input message is blank. Please input a message to succesfully generate a QR Code image.
  Goto START
}

If MATRIX_TO_PRINT between 1 and 7
{
  Msgbox, 0x10, Error, ERROR CODE: %MATRIX_TO_PRINT% `n`nERROR CODE TABLE:`n`n1 - Input message is blank.`n2 - The Choosen Code Mode cannot encode all the characters in the input message.`n3 - Choosen Code Mode does not correspond to one of the currently indexed code modes (Automatic, numeric, alphanumeric or byte).`n4 - The choosen forced QR Matrix version (size) cannot encode the entire input message using the choosen ECL Code_Mode. Try forcing a higher version or choosing automated version selection (parameter value 0).`n5 - The input message is exceeding the QR Code standards maximum length for the choosen ECL and Code Mode.`n6 - Choosen Error Correction Level does not correspond to one of the standard ECLs (L, M, Q and H).`n7 - Forced version does not correspond to one of the QR Code standards versions.
  Goto START
}

  ; Start gdi+
  If !pToken := Gdip_Startup()
  {
    MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
    ExitApp
  }

  pBitmap := Gdip_CreateBitmap((MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize, (MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize) ; Adding 8 pixels to the width and height here as a "quiet zone" for the image. This serves to improve the printed code readability. QR Code specs require the quiet zones to surround the whole image and to be at least 4 modules wide (4 on each side = 8 total width added to the image). Don't forget to increase this number accordingly if you plan to change the pixel size of each module.
  G := Gdip_GraphicsFromImage(pBitmap)
  Gdip_SetSmoothingMode(pBitmap, 3)
  pBrush := Gdip_BrushCreateSolid(0xFFFFFFFF)
  Gdip_FillRectangle(G, pBrush, 0, 0, (MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize, (MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize) ; Same as above.
  Gdip_DeleteBrush(pBrush)

  Loop % MATRIX_TO_PRINT.MaxIndex() ; Acess the Rows of the Matrix
  {
    CURRENT_ROW := A_Index
    Loop % MATRIX_TO_PRINT[1].MaxIndex() ; Access the modules (Columns of the Rows).
    {
      CURRENT_COLUMN := A_Index
      If (MATRIX_TO_PRINT[CURRENT_ROW, A_Index] = 1)
      {
        ;Gdip_SetPixel(pBitmap, A_Index + 3, CURRENT_ROW + 3, 0xFF000000) ; Adding 3 to the current column and row to skip the quiet zones.
        Loop %PixelSize%
        {
          CURRENT_REDIMENSION_ROW := A_Index
          Loop %PixelSize%
          {
            Gdip_SetPixel(pBitmap, (CURRENT_COLUMN * PixelSize) + (3*PixelSize) - 1 + A_Index, (CURRENT_ROW * PixelSize) + (3*PixelSize) - 1 + CURRENT_REDIMENSION_ROW, 0xFF000000)
          }
      }
    }
      If (MATRIX_TO_PRINT[CURRENT_ROW, A_Index] = 0) ; White pixels need some more attention too when doing multi pixelwide images.
      {
        Loop %PixelSize%
        {
          CURRENT_REDIMENSION_ROW := A_Index
          Loop %PixelSize%
          {
            Gdip_SetPixel(pBitmap, (CURRENT_COLUMN * PixelSize) + (3*PixelSize) - 1 + A_Index, (CURRENT_ROW * PixelSize) + (3*PixelSize) -1 + CURRENT_REDIMENSION_ROW, 0xFFFFFFFF)
          }
        }
      }
    }
  }
  StringReplace, FILE_NAME_TO_USE, test, `" ; We can't use all the characters that byte mode can encode in the name of the file. So we are replacing them here (if they exist).
  FILE_PATH_AND_NAME := A_ScriptDir . "\" . SubStr(RegExReplace(FILE_NAME_TO_USE, "[\t\r\n\\\/\`:\`?\`*\`|\`>\`<]"), 1) ; Same as above.
  If (StrLen(FILE_PATH_AND_NAME)>252)
    FILE_PATH_AND_NAME:=SubStr(FILE_PATH_AND_NAME,1,252)
  FILE_PATH_AND_NAME:=FILE_PATH_AND_NAME . ".png"
  IfExist,%FILE_PATH_AND_NAME%
  {
    MsgBox,4144,Error,%FILE_PATH_AND_NAME%`nalready exists - try again
    Goto START
  }
  Gdip_SaveBitmapToFile(pBitmap, FILE_PATH_AND_NAME)
  Gdip_DisposeImage(pBitmap)
  Gdip_DeleteGraphics(G)
  Gdip_Shutdown(pToken)

MsgBox,4096,Success,Created QR Code in file`n%FILE_PATH_AND_NAME%
Goto START
Return
#Include %A_ScriptDir%/BARCODER.ahk
#Include %A_ScriptDir%/GDIP.ahk
Regards, Joe

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 18 Feb 2016, 10:10

Hi Gio,
I hope you can help me with a change to the sample script that calls BARCODER to create a PNG file. I'd like the PNG to contain the contents of the QR Code in text. I don't care about font type/style, but I want the point size to be big enough to be easily read, perhaps 12-point. So I'm looking for something like this:

Image
I don't care if it's placed above or below the QR Code. Thanks very much for your help with this. Regards, Joe

User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by Gio » 18 Feb 2016, 13:29

That shouldn't be a problem.

And since we are using Tics GDIP library in these examples, we may aswell stick to it. Gdip_TextToGraphics() is the function you are looking for.

Simply add these two lines

Code: Select all

Options = x0 y0 cFF000000 r4 s20
Gdip_TextToGraphics(G, test, Options, "Arial")
Right before this line in the examples:

Code: Select all

StringReplace, FILE_NAME_TO_USE, test, `" ; We can't use all the characters that byte mode can encode in the name of the file. So we are replacing them here (if they exist).
You can them run the example to test it (but set the pixelsize to 10 in order to see the message).

There is a catch to this method though. The first line we added contains options on how the text should be written in the canvas (x and y positions in the canvas, color, rendering quality and size of the text to be written) which we have all set to fixed values (and that is why i asked for a pixelsize of 10).

If your code is outputing matrixes of variable sizes, some math will have to be put into use here, calculating the correct values for x, y and font size.

I also suggest you consider changing the math in the Gdip_CreateBitmap() and Gdip_FillRectangle() in order to preserve the quiet zones in the QR Matrix (we are currently writting the text inside the upper sides quiet zone). Always write the text outside the quiet zones if possible (this will require a bigger canvas, thus the adjustments in said functions). The quiet zones are blank areas 4x the size of a module after each of the borders of the QR Matrix. Though seemingly unnecessary with todays readers, they may increase the readability of the QR Code.

You can also check Tic's tutorial on GDIP text messages here. It contains more detailed information on the available options for the Gdip_TextToGraphics() function.

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 18 Feb 2016, 14:21

Gio,
That is perfect! Thanks so much. Btw, it works well at both 10 and 20. Regards, Joe

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 18 Feb 2016, 19:17

Hi Gio,
One more tweak, if possible. My goal is to have this printed out on Letter or A4 paper. I'd like the QR Code to be an inch or so across (which is what PixelSize=10 creates) while the text should be able to run the entire width of the page (8.5inch or 210mm). Something like this:
Image
Placement of the QR Code and text on the page doesn't matter (whatever is easier to do is fine), except to avoid the edges of the page where some printers are unable to print — for that reason I changed the x0 y0 options in your TextToGraphics call to x10 y10. That works well, but I haven't been able to figure out how to get a PixelSize=10 QR Code on a Letter/A4 page. Thanks again, Joe

User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by Gio » 19 Feb 2016, 08:27

Easy. With a catch (as always).

You have to change the pixel size of the whole bitmap canvas, which is set in the Gdip_CreateBitmap() call, to achieve similar proportions to an A4 page. Also, since default pixel color is black, you have to adjust Gdip_FillRectangle() once again to be sure to paint the whole canvas white (not just part of it).

It is important to notice that i said similar proportions (not similar size) because pixels have no set size in real world. You cannot measure an A4 page in pixels. A picture that was printed to be 10cm long in a paper may have a width of 100 pixels in lower resolution and a width of 100,000 pixels in higher resolution before printing. But you can use pixels in similar proportions to get an idea of how the picture will look like once printed in an A4 paper.

So let's make our canvas have a width of 2100 pixels and a height of 2970 pixels. That means a 300x300 pixels picture will take roughly a tenth of the height and a seventh of the width. It will also be in a set proportion of 10 pixels per milimeter of the A4 page, which is fair enougth.

change this line:

Code: Select all

pBitmap := Gdip_CreateBitmap((MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize, (MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize) ; Adding 8 pixels to the width and height here as a "quiet zone" for the image. This serves to improve the printed code readability. QR Code specs require the quiet zones to surround the whole image and to be at least 4 modules wide (4 on each side = 8 total width added to the image). Don't forget to increase this number accordingly if you plan to change the pixel size of each module.
to this:

Code: Select all

pBitmap := Gdip_CreateBitmap( 2100, 2970)


And also this line:

Code: Select all

Gdip_FillRectangle(G, pBrush, 0, 0, (MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize, (MATRIX_TO_PRINT.MaxIndex() + 8) * PixelSize) ; Same as above.
to this:

Code: Select all

Gdip_FillRectangle(G, pBrush, 0, 0, 2100, 2970)
And you should get something close enought to your picture, with the text message being able to take the whole width of the page.

The QR Matrix will be positioned right below it though. To make it go lower or to the right of the page, you have to add the ammount of pixels to jump in each direction to the Gdip_SetPixel()s x and y parameters on each call.

The math to achieve the center of the page is simple.

You take the width of the page, subtract the width of your image and divide the result by 2 (i considered a QR Matrix of 290 pixels total width).
(2100 - 290) / 2 = 905
Add it to the X position of the Gdip_SetPixel calls.

Also, take the height of the page, subtract the height of your image and divide the result by 2 (i considered a QR Matrix of 290 pixels total height).
(2970 - 290) / 2 = 1340

Add it to the Y position of the Gdip_SetPixel calls.

Thus, this line (only 1 line):

Code: Select all

Gdip_SetPixel(pBitmap, (CURRENT_COLUMN * PixelSize) + (3*PixelSize) - 1 + A_Index, (CURRENT_ROW * PixelSize) + (3*PixelSize) - 1 + CURRENT_REDIMENSION_ROW, 0xFF000000)
Should become this:

Code: Select all

Gdip_SetPixel(pBitmap, (CURRENT_COLUMN * PixelSize) + (3*PixelSize) - 1 + A_Index + 905, (CURRENT_ROW * PixelSize) + (3*PixelSize) - 1 + CURRENT_REDIMENSION_ROW + 1340, 0xFF000000)
And this line (yes, this is ANOTHER line!):

Code: Select all

Gdip_SetPixel(pBitmap, (CURRENT_COLUMN * PixelSize) + (3*PixelSize) - 1 + A_Index, (CURRENT_ROW * PixelSize) + (3*PixelSize) -1 + CURRENT_REDIMENSION_ROW, 0xFFFFFFFF)
Should become this:

Code: Select all

Gdip_SetPixel(pBitmap, (CURRENT_COLUMN * PixelSize) + (3*PixelSize) - 1 + A_Index + 905, (CURRENT_ROW * PixelSize) + (3*PixelSize) -1 + CURRENT_REDIMENSION_ROW + 1340, 0xFFFFFFFF)
Those changes should yield something close to what you are looking for.

User avatar
JoeWinograd
Posts: 2179
Joined: 10 Feb 2014, 20:00
Location: U.S. Central Time Zone

Re: BARCODER - Create 1D and 2D Barcodes (QRCode , C39,etc)

Post by JoeWinograd » 19 Feb 2016, 11:39

Hi Gio,
Thank you — exactly what I need! The only thing I had to adjust is that Gdip apparently defaults to 96 DPI, which made the size 556x786mm (21.9x30.9inch). So I changed the DPI to 300 with this call right after creating the bitmap:

Code: Select all

Gdip_BitmapSetResolution(pBitmap,300,300)
That makes the size 178x251mm (7.0x9.9inch). It also makes the fonts too small to read, so I increased the size param from 20 to 40, and moved the text from x0-y0 to x100-y100 so it isn't in the non-printable area (for some printers). So the options statement is now this:

Code: Select all

Options = x100 y100 cFF000000 r4 s40
Btw, what does the rendering value r4 mean? Thanks again! Regards, Joe

Post Reply

Return to “Scripts and Functions (v1)”