Diese QRCode UDF ermöglicht es, QRCodes zu generieren und als Bild oder Ausgabe in der Konsole darzustellen.
Sie bietet Funktionen um ein 2D-Boolean-Array des QRCodes zu erhalten, dieses als Bitmap (_GDIPlus) zu erhalten, oder direkt auf eine GraphicsContext (_GDIPlus) zu zeichnen.
Dabei wird eine von mir mit Rust erstellte .dll genutzt, welche die "QR Code generator library (Rust)" von Project Nayuki (https://www.nayuki.io/page/qr-code-generator-library) verwendet.
Aktuell sind folgende Funktionen in der UDF erhalten:
_QRCode_StartUp - Startup needed before using most other functions (Includes _GDIPlus_Startup)
_QRCode_Shutdown - Shutdown should be called at the and to clean up (Includes _GDIPlus_Shutdown)
_QRCode_GetQRCode - Generate a QRCode as 2D-Boolean-Array, where the first index = lines, the second index=cols, normally False=White, True=Black
_QRCode_GetBitmap - Creates a GDIPlus-Bitmap with the QRCode
_QRCode_DrawQRCode - Draws a QRCode on a provides GDIPlus-GraphicsContext
_QRCode_DrawQRCodeFast - Same as _QRCode_DrawQRCode, but without error checks and requires brushes for the colors to be provided (=> higher FPS)
_QRCode_ConsoleWrite - Print the QRCode to the console
_QRCode_GetSize - Get the size of the generated QRCode
_QRCode_GetECLMaxLoss - Get the maximum allowed loss before the qrcode becomes unreadable (decimal multiplier)
Possible error correction levels:
$_QRCode_ECL_LOW = 1
$_QRCode_ECL_MEDIUM = 2
$_QRCode_ECL_QUARTILE = 3
$_QRCode_ECL_HIGH = 4 - Default
Alles anzeigen
Hier ist ein Beispiel, wie die UDF verwendet werden kann:
#cs ----------------------------------------------------------------------------
AutoIt Version: 3.3.16.1
Author: Kanashius
Script Function:
Example script to show the usages of the QRCode UDF.
#ce ----------------------------------------------------------------------------
#include <Array.au3>
#include "QRCode.au3"
; Startup to initialize the dll and call _GDIPlus_Startup
_QRCode_StartUp()
If @error Then
ConsoleWrite("Error QRCode startup: "&@error&" >> "&@extended&@crlf)
Exit
EndIf
; Generate a 2D-Array with boolean values representing the QRCode
; The $_QRCode_ECL_HIGH provides a high error correction level. But a higher ECL also creates larger QRCodes and allows for less characters. So if any of that is an issue, try decreasing the ECL.
; The $_QRCode_ECL_HIGH is the default to be more robust and allow for images to be placed on top of the qrcode (like a logo in the middle) without making the qrcode unreadable.
;Local $arQRCode = _QRCode_GetQRCode("A very long String to test", $_QRCode_ECL_HIGH)
Local $arQRCode = _QRCode_GetQRCode(Binary("0xFEED1337"), $_QRCode_ECL_HIGH)
If @error Then
ConsoleWrite("Error creating QRCode: "&@error&" >> "&@extended&@crlf)
Exit
EndIf
; Print the QRCode to the console.
_QRCode_ConsoleWrite($arQrCode, "#", " ", @crlf)
; Create a Bitmap with the QRCode and a 50 pixel border.
Local $hBitmap = _QRCode_GetBitmap($arQRCode, 4, 50, 50, 50, 50)
; _GDIPlus_ImageSaveToFile($hBitmap, "qrcode.png")
_GDIPlus_BitmapDispose($hBitmap)
; ==> GuiExample drawing directly on the graphics context
_guiExample()
; Shutdown to close the dll, free memory of structs and call _GDIPlus_Shutdown
_QRCode_Shutdown()
If @error Then ConsoleWrite("Error QRCode shutdown: "&@error&" >> "&@extended&@crlf)
Func _guiExample()
Local $iWidth = 800, $iHeight = @DesktopHeight-100, $iSpace = 10, $iQRCodePixelSize = 4
Local $hGui = GUICreate("QRCode example", $iWidth, $iHeight)
Local $iInput = GUICtrlCreateInput("This is a text example", $iSpace, $iSpace, $iWidth-$iSpace*2, 25)
; create buffer image
Local $iQRCodeAreaLeft = $iSpace, $iQRCodeAreaTop = $iSpace*2+25, $iQRCodeAreaWidth = $iWidth-$iSpace*2, $iQRCodeAreaHeight = $iHeight-$iSpace*3-25
Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
Local $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iQRCodeAreaWidth, $iQRCodeAreaHeight, $hGraphics)
Local $hBitmapGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsClear($hBitmapGraphics, 0xFFFFFFFF)
GUISetState(@SW_SHOW, $hGui)
; create brushes for the rectangles
Local $hBrushBlack = _GDIPlus_BrushCreateSolid(0xFF000000)
Local $hBrushWhite = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
Local $hPenBlack = _GDIPlus_PenCreate(0xFF000000, 2)
_GDIPlus_GraphicsSetSmoothingMode($hBitmapGraphics, 2)
; generate the first bottom qrcode
Local $arQRCodeFast = _QRCode_GetQRCode("Current date and time: "&@YEAR&"/"&@MON&"/"&@MDAY&" "&@HOUR&":"&@MIN&":"&@SEC, $_QRCode_ECL_HIGH)
If @error Then
MsgBox(16, "Error", "QRCode generation failed."&@crlf&"Most probable error is the qrcode.exe not being in the correct directory: "&@error&" >> "&@extended)
return false
EndIf
; save the size of the bottom qrcode
Local $arSizeQRCodeFast = _QRCode_GetSize($arQRCodeFast, $iQRCodePixelSize*2)
; initialize loop variables
Local $iMsg, $sQRCodeText = "", $arSizeQRCode = [0, 0], $PI = 3.141592653589793
While 1
$iMsg = GUIGetMsg()
If $iMsg = -3 Then ExitLoop
; ==> Top QRCode
; draw the top qrcode, if the input changes
If GUICtrlRead($iInput)<>$sQRCodeText Then
; clear the area of the old qrcode
_GDIPlus_GraphicsSetClipRect($hBitmapGraphics, ($iQRCodeAreaWidth-$arSizeQRCode[0])/2, 0, $arSizeQRCode[0], $arSizeQRCode[1])
_GDIPlus_GraphicsClear($hBitmapGraphics, 0xFFFFFFFF)
_GDIPlus_GraphicsResetClip($hBitmapGraphics)
; generate the new qrcode
$sQRCodeText = GUICtrlRead($iInput)
Local $arQRCode = _QRCode_GetQRCode($sQRCodeText, $_QRCode_ECL_HIGH)
if @error Then
Local $iErr = @error, $iExt = @extended
_GDIPlus_GraphicsClear($hBitmapGraphics, 0xFFFFFFFF)
If $iErr=5 Then
MsgBox(16, "Error", "QRCode generation failed."&@crlf&"The given Text is ~"&($iExt/8)&" characters to long")
Else
MsgBox(16, "Error", "QRCode generation failed."&@crlf&"Most probable errors are a to long text or the qrcode.exe not being in the correct directory: "&$iErr&" >> "&$iExt)
EndIf
Else
; save the size of the new qrcode
$arSizeQRCode = _QRCode_GetSize($arQRCode, $iQRCodePixelSize)
; draw the new qrcode
Local $iQRCodeLeft = ($iQRCodeAreaWidth-$arSizeQRCode[0])/2
_QRCode_DrawQRCode($hBitmapGraphics, $arQRCode, $iQRCodePixelSize, $iQRCodeLeft, 0)
If @error Then
MsgBox(16, "Error", "QRCode drawing failed: "&@error&" "&@extended)
_GDIPlus_GraphicsClear($hBitmapGraphics, 0xFFFFFFFF)
EndIf
EndIf
EndIf
; ==> Bottom QRCode
Local $sText = "Current date and time: "&@YEAR&"/"&@MON&"/"&@MDAY&" "&@HOUR&":"&@MIN&":"&@SEC&":"&@MSEC
Local $iTime = @SEC+@MSEC*0.001
; generate the qrcode for the new time
$arQRCodeFast = _QRCode_GetQRCode($sText, $_QRCode_ECL_HIGH)
If @error Then
MsgBox(16, "Error", "QRCode generation failed."&@crlf&"Most probable error is the qrcode.exe not being in the correct directory: "&@error&" >> "&@extended)
ExitLoop
EndIf
Local $iTextHeight = 20
; clear the area of the old qrcode
_GDIPlus_GraphicsSetClipRect($hBitmapGraphics, ($iQRCodeAreaWidth-$arSizeQRCodeFast[0])/2, $iQRCodeAreaHeight-$arSizeQRCodeFast[1]-$iTextHeight, $arSizeQRCodeFast[0], $arSizeQRCodeFast[1]+$iTextHeight)
_GDIPlus_GraphicsClear($hBitmapGraphics, 0xFFFFFFFF)
_GDIPlus_GraphicsResetClip($hBitmapGraphics)
; save the size of the new qrcode
$arSizeQRCodeFast = _QRCode_GetSize($arQRCodeFast, $iQRCodePixelSize*2)
; draw the time as string above the qrcode
_GDIPlus_GraphicsDrawString($hBitmapGraphics, $sText, ($iQRCodeAreaWidth-$arSizeQRCodeFast[0])/2+15, $iQRCodeAreaHeight-$arSizeQRCodeFast[1]-$iTextHeight)
; Draw the second qrcode
Local $iLeft = ($iQRCodeAreaWidth-$arSizeQRCodeFast[0])/2, $iTop = $iQRCodeAreaHeight-$arSizeQRCodeFast[1]
_QRCode_DrawQRCodeFast($hBitmapGraphics, $arQRCodeFast, $hBrushBlack, $hBrushWhite, $iQRCodePixelSize*2, $iLeft, $iTop)
; draw the white rectangle in the middle of the qrcode
Local $iRectSize = $arSizeQRCodeFast[0]*0.25, $iRectMidX = $iLeft+$arSizeQRCodeFast[0]/2, $iRectMidY = $iTop+$arSizeQRCodeFast[1]/2
_GDIPlus_GraphicsFillRect($hBitmapGraphics, $iRectMidX-$iRectSize/2, $iRectMidY-$iRectSize/2, $iRectSize, $iRectSize, $hBrushWhite)
; draw the line in the rectangle
Local $iTimeSec = Mod($iTime+45, 60)
Local $iRad = (360/60*$iTimeSec)*$PI/180
_GDIPlus_GraphicsDrawLine($hBitmapGraphics, $iRectMidX, $iRectMidY, $iRectMidX+$iRectSize/2*Cos($iRad), $iRectMidY+$iRectSize/2*Sin($iRad), $hPenBlack)
; draw bitmap to gui
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, $iQRCodeAreaLeft, $iQRCodeAreaTop, $iQRCodeAreaWidth, $iQRCodeAreaHeight)
WEnd
; cleanup time
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_PenDispose($hPenBlack)
_GDIPlus_BrushDispose($hBrushWhite)
_GDIPlus_BrushDispose($hBrushBlack)
GUIDelete($hGui)
EndFunc
Alles anzeigen
Und ein weiteres Beispiel findet sich in der QRCodeGenerator-CLI: QRCode generator cli
Das ist eine Konsolenanwendung mit umfangreichen Einstellungsmöglichkeiten zum generieren von QRCodes.
Ich habe während der Entwicklung in Rust erst eine .exe statt der .dll erstellt. Die war aber langsamer (String parsing in AutoIt,...), deshalb hab ich das verworfen.
Die in Rust entstandene .exe findet ihr aber bei den Dateien als Rust-Executable (QRCode-Wrapper-Console-Rust-Exe.zip).
Sie kann in der Konsole mit einem Text aufgerufen werden und gibt den QRCode als 0 (weiß), 1 (schwarz), 2(neue zeile) aus.
Mit --human wird der QRCode Menschenlesbar ausgegeben und mit --errorlvl low/medium/quartile/high kann das "error correction level" angegeben werden.
Aber diese Anwendung hat weniger Möglichkeiten, als die vorher erwähnte QRCodeGenerator-cli und ist nur zur Vollständigkeit hier.
Dateien:
Die UDF mit allen benötigten Dateien: qrcode.zip
Der Rust-Quellcode der .dll und .exe: QRCode-Dll-Exe-Rust-Src.zip
Die Rust-Executable: QRCode-Wrapper-Console-Rust.zip