MusicPDF development

ToDo:

Program source

Please install autoit3 to develop, test and work with the script below.

; MusicPDF, Automatic cleaning and leveling pdf files with Neuratron
; Copyright (C) Oktober 2009 by Marc Nijdam
;
;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;    any later version.
;
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
;
;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>
;
;    Contact details: http://www.nijdam.de/marc.html

#requireadmin ; This program should have proper rights to start external applications. Presumably this behaviour requires user admin rights

#include <Constants.au3> ; Used for registry constants like REG_SZ, REG_DWORD etc.
#include <Process.au3>
#include <file.au3>
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <Math.au3>
#Include <String.au3>

; Current version of MusicPDF is compatible with PhotoScore version Neuratron PhotoScore Ultimate 6
;
; Requires Imagemagick installation from http://www.imagemagick.org (See over there. Choose the dynamic, 16 bit images version)
; Path environment variable should be pointing to imagemagick, (default installation will add this to the %PATH% environment variable, which is persistant)
; If not there, this script adds the following temporarily: %PROGRAMFILES%\imagemagick
;
; This program requires Ghostscript, which may be installed through Photoscore.
; Path environment variable should be pointing to: %PROGRAMFILES%\gs\gs8.56\bin;%PROGRAMFILES%\gs\gs8.56\lib
;
; This solve a R6034 (AutoIt3 related) error:
; http://www.microsoft.com/downloads/details.aspx?familyid=A5C84275-3B97-4AB7-A40D-3802B2AF5FC2
;
; Nb.:
; Write an environment variable: EnvSet ( "envvariable" [, "value"] )
; ControlClick($parentWindowName,"ViewPages", ,2, 12, 81)
; $CmdLine[0] = number of parameters
; $CmdLine[1] = first parameter

Const $NeuratronVersion = "6.0.0"; For which version is this program written and compatibl with?
Const $Version6 = "6.0.0" ; This is Version 6, released in 2009
Const $ThisProgramVersion = "0.9.3" ; Current release of this software
Const $_ERROR_MissingImageMagickObject = -1
Const $_ERROR_PdfInputFileIsNotValid = -2
Const $_ERROR_NeuratronIsNotInstalled = -3
Const $_ERROR_ShowHelp = -4
Const $_ERROR_PdfImageSizeTooLarge = -5
Const $_ERROR_MissingSavedNeuratronPrefs = -6
Const $_ERROR_SavedNeuratronPrefsFileCorrupt = -7
Const $_ERROR_WrongNeuratronVersion = -8
Const $_ERROR_CannotFindGhostscript = -9
Const $_ERROR_imagemagickNotInstalled = -10
Const $_ERROR_Need_ImageMagickObject_OLE = -11
Const $_ERROR_MSVisualCPlusPlus2008RedistNotInstalled = -12

Const $Gui_Title = "PDF Sheetmusic raw scan Processor"
Const $Gui_Xpos = 140
Const $Gui_Ypos = 23
Const $Gui_Width = 518
Const $Gui_Height = 200
Const $Gui_Border = 15
Const $Gui_HeightButton = 20
Const $Gui_WidthButton = 75
Const $Gui_WidthSlider = 20

Const $img_uniquename = "Neuratron6AU3_" ; Unique leading part of filename for temporary files
Const $img_width = 2480 ; constant in pixels, defining what the page width may be at most when portrait modus is used
Const $img_height = 3508 ; constant in pixels, defining what the page height may be at most when portrait modus is used
Const $resolution = 300 ; Resolution in dpi
Const $img_dims[2] = [$img_width,$img_height] ; landscape modus swaps both variables
Const $rastering = 72 ; PDF rastering value
Const $pdf_dims[2] = [String(Int(($rastering*$img_width/$resolution)+0.5)),String(Int(($rastering*$img_height/$resolution)+0.5))] ; Array holding pdf rastering sizes a4 should be 595x842
Dim   $max_dims[2] ; Array holding the largest found dimension (horizontal,vertical)
Dim   $this_dims[2] ; Array holding the actual dimension (horizontal,vertical)

Const $img_empty_name = AddSlash(@TempDir) & $img_uniquename & "_temp.tif"
Const $Pdf_tmp_FileName = AddSlash(@TempDir) & $img_uniquename & "Processed.pdf" ; temporary filename which is used when something had been preprocessed.
Const $QQ = '"'
Const $SQ = "'"
Dim $szDrive, $szDir, $szFName, $szExt
Dim $i , $j

Const $X_firstItem_Sel = 1 ; neuratron buttons window positions
Const $X_firstItem_Del = 2 ; neuratron buttons window positions
Const $Y_firstItem = 3 ; neuratron buttons window positions
Const $NeuratronDelay = 10 ; loop is breaked when it runs for more than 10 seconds

Const $Pdf_ListOfFiles2Proces = AddSlash(@TempDir) & $img_uniquename & "list.txt" ; Maintaing a list with all pdf pages for concatenating.

Const $reg_filename = AddSlash(@TempDir) & $img_uniquename & "RegfilePreferences.csv"
Dim $Param_Command

Const $Neuratron_RegHive1 = "HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate" ; Settings for saving Neuratron preferences before overwriting this with specific settings
Const $Neuratron_RegHive2 = "HKEY_LOCAL_MACHINE\SOFTWARE\Neuratron\PhotoScore\ApplicationPath" ; HKLM path Neuratron
Const $Neuratron_RegGlobalSettings = "Global settings"
Const $Neuratron_RegGeneralSettings = "General settings"
Const $Neuratron_PagesIndexFile = @AppDataDir & "\Neuratron\MusicPages_v5\!Index" ; Folder containing Neuratron Application Settings from user
Const $Neuratron_PendingPagesCleared = "FE,FF,FF,0F,03,00,00,00,00,03,80,04,00" ; The file !Index should contain these bytes to show an empty list of pages
Const $original = 1 ; Selector for location of PendingPagesPreferences
Const $temporary = 2 ; Selector for location of PendingPagesPreferences
Const $MSVC_2008_Redist_RegHive = "HKEY_CLASSES_ROOT\Installer\Products\D20352A90C039D93DBF6126ECE614057" ; Magic key to find whether Microsoft Visual C++ 2008 SP1 is installed
Const $MSVC_2008_Redist_Key = "PackageCode" ; Magic key to find whether Microsoft Visual C++ 2008 SP1 is installed
Const $Ghostscript_name = "gs\gs" ; unique string to search for in %PATH% whether Ghostscript is installed or not
Const $imagemagick_name = "imagemagick" ; unique string to search for in %PATH% whether ImageMagick is installed or not
SetEnvironmentPath(Find_Ghostscript_Path("HKEY_LOCAL_MACHINE\SOFTWARE\GPL Ghostscript","GS_LIB"),$Ghostscript_name) ; retreive path from gs which should be added to %PATH% if it's not there already
SetEnvironmentPath(Find_imagemagick_Path("HKEY_LOCAL_MACHINE\SOFTWARE\ImageMagick\Current","BinPath"),$imagemagick_name) ; retreive path from imagemagick which should be added to %PATH% if it's not there already

; Check installation
If Not Neuratron_IsInstalled($Neuratron_RegHive2, "") Then ShowError($_ERROR_NeuratronIsNotInstalled)
If Not Find_MS_Visual_C_PlusPlus_2008_SP1_Redist($MSVC_2008_Redist_RegHive, $MSVC_2008_Redist_Key) Then ShowError($_ERROR_MSVisualCPlusPlus2008RedistNotInstalled)
If Not FileExists(Find_imagemagick_Path("HKEY_LOCAL_MACHINE\SOFTWARE\ImageMagick\Current","BinPath") & "\ImageMagickObject.dll") Then ShowError ($_ERROR_Need_ImageMagickObject_OLE)
If Not FileExists(@SystemDir & "\ImageMagickObject.dll") Then FileInstall("ImageMagickObject.dll",@SystemDir&"\ImageMagickObject.dll",0)
If Not ObjectIsRegistered("HKEY_CLASSES_ROOT\ImageMagickObject.MagickImage\CurVer", "") Then RunWait(@ComSpec & " /c regsvr32 /s MagickObject.dll",@SystemDir,@SW_HIDE)
Dim $oIMG=ObjCreate("ImageMagickObject.MagickImage.1")
If Not IsObj($oIMG) Then ShowError ($_ERROR_MissingImageMagickObject)

; Parse program start options
If @Compiled == 0 Then ; $envDebug == True means Program runs in Debug mode
;	Dim $Pdf_InputFile = "Neuratron_Global_Settings.reg" ; Not a pdf file
;	Dim $Pdf_InputFile = "test_empty.pdf" ; inputfile
;	Dim $Pdf_InputFile = "test_bwpages.pdf" ; inputfile
;	Dim $Pdf_InputFile = "test_4_pages_oversized_grey.pdf" ; inputfile
;	Dim $Pdf_InputFile = "test_4_pages_oversized_mix.pdf"
;	Dim $Pdf_InputFile = "test_1_page_oversized_grey.pdf"
;	Dim $Pdf_InputFile = "test_bw.pdf" ; inputfile
;	Dim $Pdf_InputFile = "test_6 pages.pdf" ; inputfile
;	Dim $Pdf_InputFile = "test_Manual.pdf" ; inputfile
;	Dim $Pdf_InputFile = "test_text.pdf" ; inputfile
;	Dim $Pdf_InputFile = "test_bwpages_tilted.pdf" ; inputfile
;	Dim $Pdf_InputFile = "test_color.pdf"
;	Dim $Pdf_InputFile = "test_largeBW.pdf"
;	Dim $Pdf_InputFile = "test_2_pages_landscape.pdf" ; inputfile
	Dim $Pdf_InputFile = "test_2_pages_landscape_oversized.pdf" ; inputfile
	Dim $Pdf_OutputFile = "test_Processed.pdf" ; outputfile
	$Pdf_InputFile = AddSlash(@WorkingDir) & $Pdf_InputFile ; Add absolute path to filename.
Else ; Program runs in normal mode
	If $CmdLine[0] == 0 Then
		ShowError ($_ERROR_ShowHelp)
		; $InputFile=FileOpenDialog("Select a .pdf file to open", "","PDF files (*.pdf)")
		; IF @error or NOT FileExists($InputFile) Then Exit
	EndIf
	Switch $CmdLine[0]
		Case 1
			Dim $Pdf_InputFile = $CmdLine[1] ; inputfile
			_PathSplit($Pdf_InputFile, $szDrive, $szDir, $szFName, $szExt)
			Dim $Pdf_OutputFile = '"' & $szDrive & $szDir & $szFName & "_Processed" & $szExt & '"'; outputfile
		Case 2
			Dim $Pdf_InputFile = $CmdLine[1] ; inputfile
			Dim $Pdf_OutputFile = $CmdLine[2] ; outputfile
		Case Else
			ShowError ($_ERROR_ShowHelp)
	EndSwitch
EndIf

; Create GUI window with console like output 
Opt("GUIOnEventMode", 1); GUI should be in OnEvent Mode, otherwise our cancelbutton event is not captured
HotKeySet("{Esc}", "CancelButton"); Pressing the Escape button cancels operation
GUICreate($Gui_Title,$Gui_Width,$Gui_Height,$Gui_Xpos,$Gui_Ypos)  ; will create a dialog box that when displayed is centered
$nEdit = GUICtrlCreateEdit ("",$Gui_Border,$Gui_Border,$Gui_Width-$Gui_Border-$Gui_WidthSlider,$Gui_Height-$Gui_Border-2*$Gui_HeightButton, BitOr($ES_AUTOVSCROLL,$ES_READONLY,$ES_MULTILINE))
GUICtrlSetBkColor($nEdit, 0xffffff)
$hButton = GUICtrlCreateButton ("Cancel", ($Gui_Width-$Gui_WidthButton)/2,$Gui_Height-$Gui_HeightButton*1.5, $Gui_WidthButton, $Gui_HeightButton)
GUICtrlSetOnEvent($hButton, "CancelButton") ; Function executed when cancel button is pressed
GUISetState()

; Open pdf document with ghostview and find number of pages given that it's a valid file.
Dim $Path = $QQ & $Pdf_InputFile & $QQ
GUICtrlSetData($nEdit, "Opening " & $Pdf_InputFile & @CRLF & @CRLF, 1)
GUICtrlSetData($nEdit, "Analyzing document..." & @CRLF, 1)

$Param_Command =	$Path & " " & _ ; Use pdf2dsc to find out the number of pages. E.g. %%Pages: 1
					$QQ & AddSlash(@TempDir) & $img_uniquename & "info.dsc" & $QQ
_RunDos("pdf2dsc " & $Param_Command)
$Param_Command = OpenFileAndGrep(AddSlash(@TempDir) & $img_uniquename & "info.dsc", "%%Pages:")
If Not $Param_Command Then ; The supplied file is not an pdf file, exit program
	ShowError ($_ERROR_PdfInputFileIsNotValid)
EndIf

FileDelete(AddSlash(@TempDir) & $img_uniquename & "info.dsc")

Const $PdfPagesCount = Number(StringReplace($Param_Command, "%%Pages: ", ""))
GUICtrlSetData($nEdit, "->Found " & Number($PdfPagesCount) & " Page(s)" & @CRLF, 1)
; ##############################################################################################################
; # Preprocessing scanned pages
; # Extract all pages from a pdf document to single pdf files
; # Convert single pdf files to tiff files
; # If a page is a black and white image, it will be converted to grey with some extra added blurring to
; # improve rotation.
; # If size of one of these pages exceeds the size defined in $img_width and $img_height, all pages will be
; # rescaled to fit within the boundaries set.
; # 
; # Possible values from extracted page from ImageMagick -Identify command are:
; # color: C:\DOCUME~1\admin\LOCALS~1\Temp\Neuratron6AU3_001.pdf PDF 612x792 612x792+0+0 16-bit DirectClass 1.387mb
; # Grayscale: C:\DOCUME~1\admin\LOCALS~1\Temp\Neuratron6AU3_001.pdf PDF 541x775 541x775+0+0 16-bit Grayscale DirectClass 410kb
; # Black & White: C:\DOCUME~1\admin\LOCALS~1\Temp\Neuratron6AU3_001.pdf PDF 541x775 541x775+0+0 16-bit Bilevel DirectClass 51.5kb
; # Empty pages, holding no data, give no output from the Identify command
; ##############################################################################################################
Dim $PagesStats
GUICtrlSetData($nEdit, @CRLF & "Extracting single pages from PDF document..." & @CRLF, 1)

$max_dims[0] = $img_dims[0]
$max_dims[1] = $img_dims[1]
Dim $img_dimensions
Dim $img_scale = False ; False means scaling is not necessary, because image fits within $img_width and $img_height
Dim $img_greyconverted = False ; False means image has not been converted from black and white to grey scale
Dim $PaperOrientation[$PdfPagesCount] ; Store page orientation for each page, 0 means portrait, 1 means landscape
; Extract all pages from document to single pdf pages
for $i = 1 To $PdfPagesCount
	GUICtrlSetData($nEdit, "->Extracting page " & Number($i) & " out of " & Number($PdfPagesCount) & @CRLF, 1)
	$ThisFileName = AddSlash(@TempDir) & $img_uniquename & Number($i) & ".pdf"
	$ThatFileName = AddSlash(@TempDir) & $img_uniquename & Number($i) & ".tif"

	; From pdf file extract a single pdf page (as pdf)
	$Param_Command =	$QQ & "-sDEVICE=pdfwrite" & $QQ & " " & _ ; Ghostview command to extract a single page from a pdf file.
						$QQ & "-dNOPAUSE" & $QQ & " " & _
						$QQ & "-dQUIET" & $QQ & " " & _
						$QQ & "-dBATCH" & $QQ & " " & _
						$QQ & "-dAutoFilterGrayImages=false" & $QQ & " " & _
						$QQ & "-dGrayImageFilter=/LZWEncode" & $QQ & " " & _ ; To prevent jpeg artifects add -dAutoFilterGrayImages=false -dGrayImageFilter=/LZWEncode
						$QQ & "-dFirstPage=" & Number($i) & $QQ & " " & _
						$QQ & "-dLastPage=" & Number($i) & $QQ & " " & _
						$QQ & "-sOutputFile=" & $ThisFileName & $QQ & " " & _
						$QQ & $Pdf_InputFile & $QQ
	_RunDos("gswin32c " & $Param_Command)

	; Convert pdf to tiff.
	; If image is black and white convert it to grey level with some gaussian blurring.
	$PagesStats = DOSResult("Identify " & $ThisFileName) ; ImageMagick command to retreive image properties
	If StringInStr($PagesStats, "Bilevel") Then ; If a page is only black and white color, convert it to grey with some gaussian blurring
		GUICtrlSetData($nEdit, "-->Converting page " & Number($i) & " out of " & Number($PdfPagesCount) & " to grey" & @CRLF, 1)
		$oIMG.Convert("-density",String($resolution), $ThisFileName, "-depth", "8", "-compress", "LZW", $ThatFileName)
		$oIMG.Mogrify("-gaussian-blur","1x0.5", $ThatFileName) ; Perform gaussian blur to improve ability to rotate, value found experimentally
		$img_greyconverted = True
	Else
		$oIMG.Convert("-density",String($resolution), $ThisFileName, $ThatFileName)
	EndIf
	FileDelete($ThisFileName); Delete pdf file, because we don't need it anymore.
	; Check whether image exceeds size limit.
	$Param_Command =	"-format " & $QQ & "%[fx:w]x%[fx:h]" & $QQ & " " & _ ; ImageMagick command to find page dimensions
						$QQ & $ThatFileName & $QQ

	$img_dimensions = DOSResult("Identify " & $Param_Command)
	$this_dims[0] = Number(StringRegExpReplace($img_dimensions, "([0-9]+)x([0-9]+)", "$1")) ; From string holding dimensions (for example "1800x1600") extract first number
	$this_dims[1] = Number(StringRegExpReplace($img_dimensions, "([0-9]+)x([0-9]+)", "$2")) ; From string holding dimensions (for example "1800x1600") extract second number

	If $this_dims[0] <= $this_dims[1] Then ; Normal portrait modus. 
		$PaperOrientation[$i-1] = 0
	Else
		GUICtrlSetData($nEdit, "-->(Page " & Number($i) & " has paper orientation set to landscape)" & @CRLF, 1)
		$PaperOrientation[$i-1] = 1
	EndIf
	; $this_dims[$PaperOrientation[$i-1]] is always the short side
	; $this_dims[1-$PaperOrientation[$i-1]] is always the long side
	; $max_dims[0] carries always the maximum of the shorter side
	; $max_dims[1] carries always the maximum of the longer side
	; $j = 0 -> find the widest page for the short side 
	; $j = 1 -> find the longest page for the long side
	; The BitXOR function will output only a logical 1 of two arguments are different.
	For $j = 0 To 1
		If $this_dims[BitXOR($j,$PaperOrientation[$i-1])] > $max_dims[$j] Then ; From string holding dimensions (for example "1800x1600") extract first number
			$max_dims[$j] = $this_dims[BitXOR($j,$PaperOrientation[$i-1])]
			$img_scale = True ; Image doesn't fit; scaling will be necessary
		EndIf
	Next

Next

	; # If there were one or more images exceeding size limit, scale them all with the same percentage.
If $img_scale Then
	Dim $resize_scale = Calc_scalingfactor($max_dims[0],$max_dims[1],$img_dims[0],$img_dims[1]); calculate scaling percentage portrait: [0],[1] Landscape: [1],[0]
	If $resize_scale < 50 Then
		; Remove previous orphans
		For $i = 1 To $PdfPagesCount ; Delete all files we don't need anymore
			If FileExists(AddSlash(@TempDir) & $img_uniquename & Number($i) & ".tif") Then FileDelete(AddSlash(@TempDir) & $img_uniquename & Number($i) & ".tif")
		Next
		ShowError($_ERROR_PdfImageSizeTooLarge) ; Resizing to less than 50 % is kind of silly.
	EndIf
	GUICtrlSetData($nEdit, @CRLF & "Some pages exceed maximum size." & @CRLF & "Reducing page size to " & $resize_scale & "% ..." & @CRLF, 1)
	For $i = 1 To $PdfPagesCount ; Delete all files we don't need anymore
		GUICtrlSetData($nEdit, "->Resizing page " & Number($i) & " out of " & Number($PdfPagesCount) & @CRLF, 1)
		$oIMG.Mogrify("-resize", $resize_scale & "%", AddSlash(@TempDir) & $img_uniquename & Number($i) & ".tif") ; ImageMagick command to find page dimensions
	Next
EndIf

If $img_greyconverted or $img_scale Then
	GUICtrlSetData($nEdit, @CRLF & "Some image processing had been done." &@CRLF & "Recreating pdf file..." & @CRLF, 1)

	If FileExists($Pdf_ListOfFiles2Proces) Then FileDelete($Pdf_ListOfFiles2Proces) ; Empty this file before adding filenames as text to it. Will be used to merge several pdf files into one.

	$FHandle = FileOpen($Pdf_ListOfFiles2Proces,1) ; $Pdf_ListOfFiles2Proces is a text file containg file names. (1 = Write mode append to the end of file)

	for $i = 1 To $PdfPagesCount
		$oIMG.Convert("","-size", String($img_dims[$PaperOrientation[$i-1]]) & "x" & String($img_dims[1-$PaperOrientation[$i-1]]), "xc:white", "-depth", "16", $img_empty_name) ; create one empty page with a4 size
		GUICtrlSetData($nEdit, "->Converting page " & Number($i) & " out of " & Number($PdfPagesCount) & " to pdf" & @CRLF, 1)
		$SourceFile = AddSlash(@TempDir) & $img_uniquename & Number($i)
		; Note that the Composite command generates a black and white canvas, therefore the resulting image may lose also any bit depth. Not a problem here, but it's just important to realise this.
		$oIMG.Composite($SourceFile & ".tif", "-density", String($resolution), "-units", "PixelsPerInch", "-compose", "atop", "-gravity", "Center", $img_empty_name, $SourceFile & "_temp.tif")
		$oIMG.Convert("-density",String($rastering),"-units", "PixelsPerInch", $SourceFile & "_temp.tif", "-page", $pdf_dims[$PaperOrientation[$i-1]] & "x" & $pdf_dims[1-$PaperOrientation[$i-1]] & "+0+0", "ps:" & $SourceFile & ".ps")
		_RunDos("gswin32c -sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH -dAutoFilterGrayImages=false -dGrayImageFilter=/LZWEncode -sOutputFile=" & $SourceFile & ".pdf" & " -dDEVICEWIDTHPOINTS=" & $pdf_dims[$PaperOrientation[$i-1]] & " -dDEVICEHEIGHTPOINTS=" & $pdf_dims[1-$PaperOrientation[$i-1]] & " " & $SourceFile & ".ps")

		FileWriteLine($FHandle,$SourceFile & ".pdf" & @CRLF)
		FileDelete($SourceFile & "_temp.tif")
		FileDelete($SourceFile & ".ps")
		FileDelete($SourceFile & ".tif")
	Next
	FileDelete($img_empty_name)
	FileClose($FHandle)
	GUICtrlSetData($nEdit, @CRLF & "Merging " & Number($PdfPagesCount) & " page(s) into one document." & @CRLF, 1)
	; # Merge all pdf files into one pdf file
	MergePDF($Pdf_tmp_FileName, $Pdf_ListOfFiles2Proces)
Else
	for $i = 1 To $PdfPagesCount ; Delete all files we don't need anymore
			FileDelete(AddSlash(@TempDir) & $img_uniquename & Number($i) & ".tif")
	Next
EndIf

; ##############################################################################################################
; # Neuratron processing
; #
; ##############################################################################################################
; Save Preferences from Neuratron
SaveNeuratronPrefs()
; Overwrite Preferences with custom values
SetNeuratronPrefs()
RemoveSomeTempFiles() ; Before writing to temp directory with files, first remove possible reminiscents

; Neuratron 6 specific details like its Window Name. Execute the program as well.
; the title of the window
$parentWindowName = "Neuratron PhotoScore Ultimate 6"   
; the name of the application to run
Const $programRunName = "C:\Program Files\Neuratron PhotoScore Ultimate\Neuratron PhotoScore.exe"   
; run the application
GUICtrlSetData($nEdit, @CRLF & "Starting Neuratron PhotoScore Ultimate 6" & @CRLF, 1)
run($programRunName) 
WinWaitNotActive ($Gui_Title) ; wait for Neuratron to become initialized
sleep(250) 
; wait until the window is showing, time out in 3 secs
WinWaitActive($parentWindowName,"",3)   
; get the handle of the window
; $mainHwnd = WinGetHandle($parentWindowName)

; open pdf file ...
GUICtrlSetData($nEdit, "Open document in Neuratron..." & @CRLF, 1)
Send("!f")
WinWaitActive($parentWindowName,"",5)
Send("n")
WinWaitActive("Open","",5) ; Wait for the Open window to become active
; # If there had been no processing before, we can send the original file, otherwise send the processed file.
If $img_greyconverted or $img_scale Then
	Const $Pdf2Open = $Pdf_tmp_FileName
Else
	Const $Pdf2Open = $Pdf_InputFile
EndIf
Send($Pdf2Open)
Send("{ENTER}")
WinWaitNotActive("Open","",4) ; Wait for the Open window to dissapear

;WinWaitActive($parentWindowName,"",6)  
	_PathSplit($Pdf2Open, $szDrive, $szDir, $szFName, $szExt)
;WinWaitActive("Processing " & $SQ & $szFName & $szExt & $SQ & "...","",5)
WinWaitActive("Processing ","",8)
; ... and confirm 300 dpi resolution
Send("{ENTER}")
; Now wait for Progress Report window to get finished
WinWaitNotActive("Processing","",8)

GUICtrlSetData($nEdit, "Waiting for Neuratron image processing..." & @CRLF, 1)
; Check whether Windowfocus is stable: Count timer, reset if window is not active and exitloop if timer exceeds $NeuratronDelay.
;WinWaitActive($parentWindowName,"",8)
$begin = TimerInit()
While 1
	If Not WinActive($parentWindowName) Then $begin = TimerInit()
	If TimerDiff($begin)/1000 > $NeuratronDelay Then ExitLoop
WEnd
WinWaitActive($parentWindowName,"",8)
; move slider to the top.
Opt("MouseCoordMode", 0)
Opt('PixelCoordMode', 0)
$POS = ControlGetPos($parentWindowName, "", "")
$x1 = $POS[0]
$y1 = $POS[1]
for $i = 1 To $PdfPagesCount
	MouseClick("left", $x1-9, $y1+50, 1)
Next

;doubleclick on first page
Opt("MouseCoordMode", 0)
Opt('PixelCoordMode', 0)
$POS = ControlGetPos($parentWindowName, "", "")
$x1 = $POS[0]
$y1 = $POS[1]
MouseClick("left", $x1-NeuratronObjPos($X_firstItem_Sel) , $y1+NeuratronObjPos($Y_firstItem) , 2)

Sleep(1000)
; save from all pdf pages, each image as tiff ...
for $i = 1 To $PdfPagesCount
	GUICtrlSetData($nEdit, "->Saving page " & Number($i) & " out of " & Number($PdfPagesCount) & @CRLF, 1)
	Send("!f"); Send Save as... tiff command
	sleep(400)
	Send("a")
	sleep(400)
	Send(AddSlash(@TempDir) & $img_uniquename & $i)
	Send("!s")
	sleep(400)
	If $i < $PdfPagesCount Then ; last time clicking is not needed
		MouseClick("left", $x1+178, $y1+50, 1)
		$begin = TimerInit()
		While Not WinActive($parentWindowName)
			if TimerDiff($begin)/1000 > $NeuratronDelay Then
				ExitLoop
			EndIf
		WEnd
		WinWaitActive($parentWindowName, "", 4)
		MouseClick("left", $x1+178, $y1+72, 1) ; Click one time extra on the window with the staves. Otherwise keyboard shortcuts don't work. This seems a bug to me...
	EndIf
Next
; Go to the first page in order to delete
for $i = 1 To $PdfPagesCount
	MouseClick("left", $x1-9, $y1+50, 1)
Next

; delete pdf pages from batch in Neuratron
for $i = 1 To $PdfPagesCount
	GUICtrlSetData($nEdit, "->Removing page " & Number($i) & " out of " & Number($PdfPagesCount) & @CRLF, 1)
	MouseClick("left", $x1-NeuratronObjPos($X_firstItem_Del) , $y1+NeuratronObjPos($Y_firstItem) , 1)
	sleep(800)
	MouseClick("left", $x1-NeuratronObjPos($X_firstItem_Del)-2 , $y1+NeuratronObjPos($Y_firstItem) , 1)
	Send("y")
	sleep(300)
Next	
	GUICtrlSetData($nEdit, "Exiting Neuratron" & @CRLF & @CRLF, 1)
	Send("!f")
	sleep(400)
	Send("x")

RevertNeuratronPrefs()

; #################################################################################################################
; # Finished with Neuratron
; #################################################################################################################
; Below is for portrait paper orientation:
; Convert each tiff page to a pdf page.
; Convert -size 2480x3508 xc:white miff:- 
; composite -density 300 -units PixelsPerInch -compose atop -gravity Center /tmp/$ptmpf.pbm - miff:-
; convert -monochrome -density 300 -units PixelsPerInch - ps:-
; ps2pdf13 -sPAPERSIZE=a4 - "/tmp/$ptmpf-$nmb.pdf"
;
; There is a problem with ImageMagick writing directly to pdf, not outputting in the proper colorspace (grey instead of black and white). A solution is to write first to ps and then use ps2pdf.
; The solution to specify the page size is done with the following example:
; gswin32c.exe -sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH -sOutputFile=outgsr.pdf -dDEVICEWIDTHPOINTS=842 -dDEVICEHEIGHTPOINTS=595 outr.ps
; See: http://www.groupsrv.com/computers/about63231.html
If FileExists($Pdf_ListOfFiles2Proces) Then
	FileDelete($Pdf_ListOfFiles2Proces)
EndIf
$FHandle = FileOpen($Pdf_ListOfFiles2Proces,1) ; Write mode append to the end of file
GUICtrlSetData($nEdit, "Converting and combining images to PDF" & @CRLF, 1)
for $i = 1 To $PdfPagesCount
	$oIMG.Convert("","-size", String($img_dims[$PaperOrientation[$i-1]]) & "x" & String($img_dims[1-$PaperOrientation[$i-1]]), "xc:white", $img_empty_name) ; create one empty page with a4 size
	GUICtrlSetData($nEdit, "->Converting page " & Number($i) & " out of " & Number($PdfPagesCount) & @CRLF, 1)
	$SourceFile = AddSlash(@TempDir) & $img_uniquename & Number($i)
	$oIMG.Composite($SourceFile & ".tif", "-density", String($resolution), "-units", "PixelsPerInch", "-compose", "atop", "-gravity", "Center", $img_empty_name, $SourceFile & "_temp.tif")
	$oIMG.Convert("-monochrome", "-density",String($rastering),"-units", "PixelsPerInch", $SourceFile & "_temp.tif", "-page", $pdf_dims[$PaperOrientation[$i-1]] & "x" & $pdf_dims[1-$PaperOrientation[$i-1]] & "+0+0", "ps:" & $SourceFile & ".ps")
	_RunDos("gswin32c -sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH -sOutputFile=" & $SourceFile & ".pdf" & " -dDEVICEWIDTHPOINTS=" & $pdf_dims[$PaperOrientation[$i-1]] & " -dDEVICEHEIGHTPOINTS=" & $pdf_dims[1-$PaperOrientation[$i-1]] & " " & $SourceFile & ".ps")
	FileWriteLine($FHandle,$SourceFile & ".pdf" & @CRLF)
	FileDelete($SourceFile & ".tif")
	FileDelete($SourceFile & ".ps")
	FileDelete($SourceFile & "_temp.tif")
	
Next
FileDelete($img_empty_name)
If $img_greyconverted or $img_scale Then FileDelete($Pdf_tmp_FileName)
FileClose($FHandle)
GUICtrlSetData($nEdit, @CRLF & "Merging " & Number($PdfPagesCount) & " page(s) into one document." & @CRLF, 1)
MergePDF(UniqueFileName($Pdf_OutputFile) ,$Pdf_ListOfFiles2Proces)
Sleep(1500)
GUIDelete()
Exit

; ##############################################################################################################
; # Below are functions etc. 
; #
; ##############################################################################################################

Func DOSResult(Const $DR_LINE)
	_RunDOS($DR_LINE & " > " & @TempDir & "\DosResult.txt") ;==> Did you take into consideration the working path?
	Local $DR_FILE = FileOpen(@TempDir & "\DosResult.txt",0)
	Local $DR_RESULT = FileRead($DR_FILE)
	FileDelete(@TempDir & "\DosResult.txt")
	FileClose($DR_FILE)
	Return $DR_RESULT
EndFunc

; merge pdf pages into one pdf page and deletes intermediate files
Func MergePDF(Const $PDFFILE, Const $PDFFILE_list)
	_RunDos("gswin32c -sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH -dAutoFilterGrayImages=false -dGrayImageFilter=/LZWEncode -sOutputFile=" & $PDFFILE & " " & "@" & $PDFFILE_list)
	FileDelete(@TempDir & "\" & $img_uniquename & "???.pdf") ; Delete only pdf files whose name contain an index.
	FileDelete($PDFFILE_list)	
EndFunc

; Opens a file and returns a line which contains a specified keyword
Func OpenFileAndGrep(Const $OFAG_path,Const $OFAG_query)
	Local $OFAG_file = FileOpen($OFAG_path,0)
	Local $OFAG_result = FileRead($OFAG_file)
	FileClose($OFAG_file)

	If $OFAG_result = "" Then ; If string is empty, return empty string as well
		Return
	Else
		Local $OFAG_q = ""
		Local $OFAG_stdinArray = StringSplit($OFAG_result, @LF, 1) ; put read data, separated by LineFeed characters, in an array
		Local $OFAG_i
		For $OFAG_i In $OFAG_stdinArray
			If StringInStr($OFAG_i,$OFAG_query) Then
				$OFAG_q &= $OFAG_i
				ExitLoop
			EndIf
		Next
	EndIf
	return $OFAG_q
EndFunc

; Find scaling factor to a4
Func Calc_scalingfactor(Const $img_width, Const $img_height, Const $img_width_max, Const $img_height_max)
	Local $scaleimgfactor_hor = 1
	Local $scaleimgfactor_vert = 1

	If $img_width > $img_width_max Then
		$scaleimgfactor_hor = ($img_width_max) / $img_width
	EndIf
	
	If $img_height > $img_height_max Then
		$scaleimgfactor_vert = ($img_height_max) / $img_height
	EndIf

	Return Int((_Min( $scaleimgfactor_hor, $scaleimgfactor_vert ))*100) ; Scalingfactor is between 0 and 100; 100 means no change.
EndFunc

; This function writes all registry keys, values and types from a certain path to a ".csv" file. If $file_append == true, data will not be overwritten but appended.
Func reg2file(Const $reg_string,Const $reg_filename,Const $file_append)
	Local $i = 1
	Local $var_read ; Variable which reads the data from a key
	Local $var_read_stringed ; Variable which is used after conversion to string
	Local $var_read_type ; Sort of registry entry : REG_SZ, REG_DWORD etc.
	Local $var_read_new ; Flag which prohibits invalid data written to file
	Local $FHandle
	Local $var

	If Not $file_append And FileExists($reg_filename) Then
			FileDelete($reg_filename)
	EndIf

	$FHandle = FileOpen($reg_filename,1) ; Write mode append to the end of file

	While 1
		$var = RegEnumVal($reg_string, $i)
		If @error <> 0 Then ExitLoop
		$var_read = RegRead($reg_string , $var)
		$var_read_new = True

		Switch @extended
			Case $REG_NONE ;
				$var_read_stringed = $var_read
				$var_read_type = "REG_NONE"

			Case $REG_SZ ; 
				$var_read_stringed = String($var_read) ; This code does not take into account unicode aspects. ToDo
				$var_read_type = "REG_SZ"

			Case $REG_EXPAND_SZ;
				$var_read_stringed = $var_read
				$var_read_type = "REG_EXPAND_SZ"

			Case $REG_BINARY ;
				$var_read_stringed = String($var_read)
				$var_read_type = "REG_BINARY"

			Case $REG_DWORD ;
				$var_read_stringed = String($var_read)
				$var_read_type = "REG_DWORD"

			Case $REG_DWORD_BIG_ENDIAN ;
				$var_read_stringed = String($var_read)
				$var_read_type = "REG_DWORD_BIG_ENDIAN"

			Case $REG_LINK ;
				$var_read_stringed = String($var_read)
				$var_read_type = "REG_LINK"

			Case $REG_MULTI_SZ ;
				$var_read_stringed = String($var_read)
				$var_read_type = "REG_MULTI_SZ"

			Case $REG_RESOURCE_LIST ;
				$var_read_stringed = String($var_read)
				$var_read_type = "REG_RESOURCE_LIST"

			Case $REG_FULL_RESOURCE_DESCRIPTOR ;
				$var_read_stringed = String($var_read)
				$var_read_type = "REG_FULL_RESOURCE_DESCRIPTOR"

			Case $REG_RESOURCE_REQUIREMENTS_LIST ;
				$var_read_stringed = String($var_read)
				$var_read_type = "REG_RESOURCE_REQUIREMENTS_LIST"

			Case Else
				$var_read_new = False
		EndSwitch
	FileWriteLine($FHandle,$QQ & $reg_string & $QQ & "," & $QQ & $var & $QQ & "," & $QQ & $var_read_type & $QQ & "," & $QQ & $var_read_stringed & $QQ & @CRLF)
;		ConsoleWrite($var & @CRLF & " " & $var_read & @CRLF & "  Type: " & @extended & @CRLF)
		$i+=1 ; Increase i with 1

	WEnd
	FileClose($FHandle)
	Return
EndFunc

; This function reads a file with saved registry settings from a certain path. For safety reasons it will only overwrite keys which are already present
Func file2reg_read_mod_write(Const $reg_filename)
	Local $i = 1
	Local $file_line ; read line from a file
	Local $var_read ; Variable which reads the data from a key
	Local $var_read_stringed ; Variable which is used after conversion to string
	Local $var_read_type ; Sort of registry entry : REG_SZ, REG_DWORD etc.
	Local $FHandle
	Local $csv[4] ; This array will hold a line with csv data

	If Not FileExists($reg_filename) Then
			ShowError ($_ERROR_MissingSavedNeuratronPrefs)
	EndIf

	$FHandle = FileOpen($reg_filename,0) ; Read mode

	While 1
		$file_line = FileReadLine($FHandle)
		If @error <> 0 Then ExitLoop
		ReDim $csv = StringRegExp($file_line & ",", '(".*?",|.*?,|,)', 3) ; Idea from http://www.autoitscript.com/forum/index.php?showtopic=36785
		If UBound($csv) == 4 Then ; Make sure we read 4 elements, otherwise our data is not valid
			; Remove trailing comma and surrounding quotes
			For $i = 0 To 3
				If StringLen($csv[$i]) > 0 Then
					$csv[$i] = StringTrimLeft(StringTrimRight($csv[$i],2),1)
				EndIf
			Next
			
			If RegRead( $csv[0], $csv[1]) == "" And @error <> 0 Then
;				ConsoleWrite("Can't find original data, skipping this one." & @CRLF)
			Else
				; $csv[0] contains the path. E.g. HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings
				; $csv[1] contains the key. E.g. Detail width
				; $csv[2] contains the value. E.g. 132
				; $csv[3] contains the type. E.g. REG_DWORD
				; Currently only REG_SZ, REG_BINARY, REG_DWORD are supported
				Switch $csv[2]
					Case "REG_NONE"
					Case "REG_SZ"
						RegWrite($csv[0],$csv[1],$csv[2],$csv[3])
					Case "REG_EXPAND_SZ"
					Case "REG_BINARY"
						RegWrite($csv[0],$csv[1],$csv[2],Binary($csv[3]))
					Case "REG_DWORD"
						RegWrite($csv[0],$csv[1],$csv[2],Int($csv[3]))
					Case "REG_DWORD_BIG_ENDIAN"
					Case "REG_LINK"
					Case "REG_MULTI_SZ"
					Case "REG_RESOURCE_LIST"
					Case "REG_FULL_RESOURCE_DESCRIPTOR"
					Case "REG_RESOURCE_REQUIREMENTS_LIST"
					Case Else
				EndSwitch
			EndIf

		Else
			FileClose($FHandle)
			ShowError ($_ERROR_SavedNeuratronPrefsFileCorrupt)
		EndIf

	WEnd
	FileClose($FHandle)
	Return
EndFunc

; This saves the registry contents which contains Neuratron personal settings to a file.
Func SaveNeuratronPrefs()
	If Not FileExists($reg_filename) Then ; Program started with still some temporarily Neuratron preferences setting present. The file should have been deleted last time, but since it is there we will use it.
		reg2file(AddSlash($Neuratron_RegHive1) & $Neuratron_RegGlobalSettings,$reg_filename,False) ; False means data will not be appended but newly written
		reg2file(AddSlash($Neuratron_RegHive1) & $Neuratron_RegGeneralSettings,$reg_filename,True) ; True means data will be appended.
	EndIf
	SaveNeuratronAppDirSettings()
	Return
EndFunc

; This overwrites Neuratron preferences (registry and pendingpages file) with set values for the automating proces.
Func SetNeuratronPrefs()
		SetNeuratronRegPrefs()
		EmptyPendingPagesFile()
Return
EndFunc

; This writes Neuratron preferences (registry and pendingpages file) back from their temporary location to where they had been originally.
Func RevertNeuratronPrefs()
	If FileExists($reg_filename) Then
		file2reg_read_mod_write($reg_filename) ; Revert to settings previously stored
		FileDelete($reg_filename)
	EndIf
	If $NeuratronVersion == $Version6 Then
		RevertNeuratronFilePrefs()
	Else
		ShowError ($_ERROR_WrongNeuratronVersion)
	EndIf

	Return
EndFunc

; This file contains all necessary Neuratron registry setting
Func SetNeuratronRegPrefs()
	If $NeuratronVersion == $Version6 Then
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Detail width","REG_DWORD",Int("132"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Detail height","REG_DWORD",Int("194"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Rhythm errors width","REG_DWORD",Int("200"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Rhythm errors height","REG_DWORD",Int("300"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show bad timing","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show attachment","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show voice numbers","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Shade unhighlighted music","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Translucent Windows","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Open Filter","REG_DWORD",Int("1"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Save Filter","REG_DWORD",Int("1"))
	;	RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Open Directory","REG_SZ","C:\Documents and Settings\admin\Desktop\NeuratronAutomater\")
	;	RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Save Directory","REG_SZ","C:\DOCUME~1\admin\LOCALS~1\Temp\")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Print guitar tab rhythm","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Main window position","REG_BINARY",Binary("0x2C0000000000000001000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C000000F8000000980200004C020000"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show BPPWarning dialog","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Scanning preview area","REG_BINARY",Binary("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Preview resolution","REG_DWORD",Int("50"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","View palette","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","View full detail","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","View rhythm errors","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Detail x-offset","REG_DWORD",Int("4294967294"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Detail y-offset","REG_DWORD",Int("2"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Palette x-offset","REG_DWORD",Int("4294967273"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Palette y-offset","REG_DWORD",Int("119"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Rhythm errors x-offset","REG_DWORD",Int("82"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Rhythm errors y-offset","REG_DWORD",Int("4294967273"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Detail anchor","REG_DWORD",Int("1"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Palette anchor","REG_DWORD",Int("3"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Rhythm errors anchor","REG_DWORD",Int("2"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Scan resolution","REG_DWORD",Int("300"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show BWWarning dialog","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show PBWarning dialog","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show Win2000 256 Colour Warning dialog","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Optimise MIDI for playback","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","One voice per MIDI track","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show BTWarning dialog","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show AccuracyWarning dialog","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show HandwrittenWarning dialog","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show DottedStavesWarning dialog","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show BadStavesWarning dialog","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Bracket tuplets","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Number of recent files","REG_DWORD",Int("1"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","View Pages Pane Size X","REG_DWORD",Int("260"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Scan in grey shades","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show startup dialog","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Show Scanned Page Warning dialog","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\Global settings","Recent file 0","REG_SZ","C:\Documents and Settings\admin\Desktop\Mozart.opt")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read slurs, hairpins and ties","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 0","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 1","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 2","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 3","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 4","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 5","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 6","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 7","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 8","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 9","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 10","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 11","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 12","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 13","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 14","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read text type 15","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read articulation","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read small notes","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read guitar frames","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read handwritten music","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Transposing staves","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","HNP Narrow strokes","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","HNP Bidirectional beams","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","HNP Current Style","REG_DWORD",Int("0"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Advanced Correction","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Auto Read Always","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Read in one voice only","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Auto rotate","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Move output scan","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Instrument language","REG_DWORD",Int("0"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Scanning interface","REG_DWORD",Int("2"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Selected scanner","REG_SZ","")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Scanner resolution","REG_DWORD",Int("300"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Scanner pixel type","REG_DWORD",Int("1"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Faster automatic scan 2","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Output Drag Mode","REG_DWORD",Int("0"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Quick Prefs","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Splash screen","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Playback Ignores repeats","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Playback systems","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Use PhotoScore Keypad","REG_SZ","False")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Automatic page margins","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Auto save period","REG_DWORD",Int("5"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","AS MIDI Playback Device","REG_DWORD",Int("2"))
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Anti aliase image","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Wait for user before scanning","REG_SZ","True")
		RegWrite("HKEY_CURRENT_USER\Software\Neuratron\PhotoScore\Ultimate\General settings","Use G7 Keypad","REG_SZ","False")
	Else
		ShowError ($_ERROR_WrongNeuratronVersion) ; Wrong version number, program incompatible.
	EndIf
Return
EndFunc

; Find imagemagick Path
Func Find_imagemagick_Path(Const $imagemagick_RegHive, Const $imagemagick_EnvKey)
	Local $var
	$var = RegRead($imagemagick_RegHive,$imagemagick_EnvKey)
	If @error <> 0 Or $var == "" Or StringInStr($var,$imagemagick_name) == 0 Then ShowError ($_ERROR_imagemagickNotInstalled)
Return $var
EndFunc

; Find Microsoft Visual C++ 2008 SP1 Redistributable Package
Func Find_MS_Visual_C_PlusPlus_2008_SP1_Redist(Const $MSV_RegHive, Const $MSV_Key)
	Local $var
	$var = RegRead($MSV_RegHive,$MSV_Key)
	If @error <> 0 Or $var == "" Then Return False
Return True
EndFunc

; Find if object is already registered
Func ObjectIsRegistered(Const $Obj_RegHive, Const $Obj_Key)
	Local $var
	$var = RegRead($Obj_RegHive,$Obj_Key)
	If @error <> 0 Or $var <> "ImageMagickObject.MagickImage.1" Then Return False
	Return True
EndFunc

; Find if Neuratron is already installed
Func Neuratron_IsInstalled(Const $Reg_Path, Const $Reg_Key)
	Local $var
	$var = RegRead($Reg_Path,$Reg_Key)
	If @error <> 0 Or $var == "" Then Return False
	Return True
EndFunc

; Find Ghostscript Path
Func Find_Ghostscript_Path(Const $Ghostscript_RegHive, Const $Ghostscript_EnvKey)
	Local $var
	Local $var_read
	Local $i = 1
	Local $GhostscriptVersion
	Local $GhostscriptPath
	Local $GhostscriptFound = False
	Local $GhostscriptPathFound = False

	While 1
		$var = RegEnumKey($Ghostscript_RegHive, $i)
		If @error <> 0 Then ExitLoop
			If StringRegExp($var,"^[0-9]+\.[0-9]+") Then
				$GhostscriptVersion = String($var)
				$GhostscriptFound = True
			EndIf
		$i += 1
	WEnd

	$i = 1
	If $GhostscriptFound Then
		While 1
			$var = RegEnumVal($Ghostscript_RegHive & "\" & $GhostscriptVersion, $i)
			If @error <> 0 Then ExitLoop
				If $var == $Ghostscript_EnvKey Then
					$GhostscriptPath = RegRead($Ghostscript_RegHive & "\" & $GhostscriptVersion, $Ghostscript_EnvKey) & ";"
					$GhostscriptPath &= StringRegExpReplace($GhostscriptPath, "(?i)(.*)(c:\\.*)lib;.*", "$2bin") ; Add also the ghostscript bin path
					$GhostscriptPathFound = True
					ExitLoop
				EndIf
			$i += 1
		WEnd
	EndIf
	
	If $GhostscriptPathFound Then
		Return $GhostscriptPath
	Else
		ShowError ($_ERROR_CannotFindGhostscript)
	EndIf
Return
EndFunc

; This function makes sure that the to be added $EnvironmentVariablePath is only added once to the environment path. For this it differentiates between Ghostscript and ImageMagick
Func SetEnvironmentPath(Const $EnvironmentVariablePath, Const $EnvironmentVariableApplication)
	If StringRight(EnvGet("PATH"),1) <> ";" Then EnvSet("PATH",EnvGet("PATH") & ";") ; Add a ; separator between path if it's not there already
	Switch $EnvironmentVariableApplication
		Case $Ghostscript_name ; If the Ghostscript path is not already there, add it.
			If not StringInStr(EnvGet("PATH"), $Ghostscript_name) Then EnvSet("PATH", EnvGet("PATH") & $EnvironmentVariablePath)
		Case $imagemagick_name ; If the imagemagick path is not already there, add it.
			If not StringInStr(EnvGet("PATH"), $imagemagick_name) Then EnvSet("PATH", EnvGet("PATH") & $EnvironmentVariablePath)
		Case Else
	EndSwitch	
	Return
EndFunc

; This function saves the Preferences Settings to a temporary folder, by moving the user profile Application Settings.
Func SaveNeuratronAppDirSettings()
	If $NeuratronVersion == $Version6 Then
		If Not FileExists(NeuratronPrefsFile($temporary)) Then ; only move directory if it's not there already.
			DirCopy(NeuratronPrefsFile($original),NeuratronPrefsFile($temporary)) ; Don't overwrite this file, if it is already in the temp dir.
			Sleep(500) ; Some delay is necessary otherwise files are not updated.
		EndIf
	Else
		ShowError($_ERROR_WrongNeuratronVersion)
	EndIf
	Return
EndFunc

; This function returns either the filename from Neuratron's pending pages preferences in the $original location or in the $temporary location
Func NeuratronPrefsFile(Const $selection)
	Local $szDrive, $szDir, $szFName, $szExt
	_PathSplit($Neuratron_PagesIndexFile, $szDrive, $szDir, $szFName, $szExt)
	Switch $selection
		Case $original
			Return RemoveSlash($szDrive & $szDir)
		Case $temporary
			Return RemoveSlash($szDrive & $szDir) & "_temp"
		Case Else
	EndSwitch
	Return
EndFunc

; This function writes a sequence of bytes (defined in string $Neuratron_PendingPagesCleared) to a file. Specifically this will make sure that no Pending Page appears in Neuratron.
Func EmptyPendingPagesFile()
	If $NeuratronVersion == $Version6 Then
		Local $FHandle = FileOpen($Neuratron_PagesIndexFile,18) ; Write Binary mode
		Local $Bytes = StringSplit($Neuratron_PendingPagesCleared,",")
		Local $i
		For $i = 1 to UBound($Bytes)-1
			FileWrite($FHandle,Chr(Dec($Bytes[$i])))
		Next
		FileClose($FHandle)
		Sleep(500) ; Some delay is necessary otherwise files are not updated.

	Else
		ShowError ($_ERROR_WrongNeuratronVersion)
	EndIf
	Return
EndFunc

; Copy the whole temporary folder which contains the original Application User Preferences Files and Folders back to the orginal location.
Func RevertNeuratronFilePrefs()
	If FileExists(NeuratronPrefsFile($temporary)) Then ; check if directory exists
		If FileExists(NeuratronPrefsFile($original)) Then
			DirRemove(NeuratronPrefsFile($original),1)
			sleep(200) ; Always wait shortly, otherwise system did not manage to update everything apparently.
			emptyfolder(NeuratronPrefsFile($original))
			sleep(200)
			DirMove(NeuratronPrefsFile($temporary),NeuratronPrefsFile($original),1)
			sleep(200)
			DirRemove(NeuratronPrefsFile($temporary),1)
			sleep(200)
			emptyfolder(NeuratronPrefsFile($temporary))
			sleep(200)
		EndIf
	EndIf
	Return
EndFunc

; Cancel button had been pressed. A few cleanup steps should take place.
Func CancelButton()
	GUIDelete()
	RevertNeuratronPrefs()
	If FileExists(AddSlash(@TempDir) & $img_uniquename & "*") Then FileDelete(AddSlash(@TempDir) & $img_uniquename & "*") ; Delete temporary files
Exit
EndFunc

; This function will add a trailing slash to a windows file path
Func AddSlash(Const $var)
	Return StringRegExpReplace($var, "(.)\\*$","$1\\")
EndFunc

; This function will remove a trailing slash to a windows file path
Func RemoveSlash(Const $var)
	Return StringRegExpReplace($var, "(.)\\*$","$1")
EndFunc

; This function will remove a trailing slash to a windows file path
Func RemoveDoubleQuotes(Const $var)
	Return StringRegExpReplace($var, "^""(.*)""$","$1")
EndFunc

; Remove Empty folders in a dir
Func emptyfolder(Const $dir)
	Local $search, $file, $mdir, $dsize
    $search = FileFindFirstFile($dir & '\*')
    If Not ($search = -1) Then
        While 1
            $file = FileFindNextFile($search)
            If @error Then ExitLoop
            $mdir = $dir & '\' & $file
            If StringInStr(FileGetAttrib($mdir), 'D') > 0 Then
                $dsize = DirGetSize($mdir, 1)
                If $dsize[1] == 0 Then
                    ConsoleWrite($mdir & @CRLF)
                    DirRemove($mdir, 1)
                Else
                    emptyfolder($mdir)
                EndIf
            EndIf
        WEnd
    EndIf
    FileClose($search)
EndFunc

; Function gives the position of window items like buttons and sliders etc., depending on Neuratron version number
Func NeuratronObjPos(Const $Item)
	Switch $NeuratronVersion
		Case $Version6
			Switch $Item
				Case $X_firstItem_Sel
					Return 140 ; neuratron buttons window positions
				Case $X_firstItem_Del
					Return 75 ; neuratron buttons window positions
				Case $Y_firstItem
					Return 106 ; neuratron buttons window positions
				Case Else
			EndSwitch
		Case Else
	EndSwitch
	ShowError($_ERROR_WrongNeuratronVersion)
	Return
EndFunc

Func RemoveSomeTempFiles()
	If FileExists(AddSlash(@TempDir) & $img_uniquename & "*") Then FileDelete(AddSlash(@TempDir) & $img_uniquename & "?????????????") ; only delete files with 13 or added characters
EndFunc

; Prevent overwriting a file, when it already exists. This function will find the 'first' free filename.
Func UniqueFileName(Const $Pdf_OutputFile)
	If FileExists(RemoveDoubleQuotes($Pdf_OutputFile)) Then
		Local $i = 1
		Local $szDrive, $szDir, $szFName, $szExt
		_PathSplit(RemoveDoubleQuotes($Pdf_OutputFile), $szDrive, $szDir, $szFName, $szExt)
		While FileExists($szDrive & $szDir & $szFName & "(" & String($i) & ")" & $szExt)
			$i += 1
		WEnd
		Return $QQ & $szDrive & $szDir & $szFName & "(" & String($i) & ")" & $szExt & $QQ
	Else
		Return $Pdf_OutputFile
	EndIf
EndFunc

Func ShowError(Const $_ERROR_Number)
	Switch $_ERROR_Number
		Case $_ERROR_ShowHelp
		MsgBox(0,"Help",	"PDF Sheetmusic raw scan Processor v" & $ThisProgramVersion & @CRLF & _
							"Written by Marc Nijdam, Okt. 2009" & @CRLF & @CRLF & _
							"Usage:" & @CRLF & _
							StringRegExpReplace(@ScriptName, "(?i)(.*)(\.)(au3|exe)(.*)", "$1$4 ") & "<inputfile> [<outputfile>]"& @CRLF & _
							"[...] is optional")
		Case $_ERROR_Need_ImageMagickObject_OLE
		MsgBox(0,"Error", 	"ImageMagickObject.dll is not available." & @CRLF & @CRLF & _
							"Please reinstall ImageMagick (windows-dll) and enable" & @CRLF & _
							"the option " & $QQ & "Install ImageMagickObject OLE Control" & @CRLF & _
							"for VBscript, Visual Basic, and WSH." & $QQ)
		Case $_ERROR_MSVisualCPlusPlus2008RedistNotInstalled
		MsgBox(0,"Error", 	"Microsoft Visual C++ 2008 SP1 is not available." & @CRLF & @CRLF & _
							"Please go to:" & @CRLF & _
							"http://www.microsoft.com/downloads/details.aspx?familyid=A5C84275-3B97-4AB7-A40D-3802B2AF5FC2" & @CRLF & @CRLF & _
							"From there, download and install vcredist_x86.")
		Case $_ERROR_MissingImageMagickObject
		MsgBox(0,"Error", 	"ImageMagickObject cannot be registered." & _
							"Maybe it is already registered.")
		Case $_ERROR_NeuratronIsNotInstalled
		MsgBox(0,"Error", 	"Neuratron Photoscore Ultimate is not installed." & @CRLF & @CRLF & _
							"Please go to:" & @CRLF & _
							"http://www.neuratron.com/" & @CRLF & @CRLF & _
							"From there, download and install Photoscore v6 Ultimate.")
		Case $_ERROR_CannotFindGhostscript
		MsgBox(0,"Error", 	"Ghostscript is not installed." & @CRLF & @CRLF & _
							"Please go to:" & @CRLF & _
							"http://sourceforge.net/projects/ghostscript/" & @CRLF & @CRLF & _
							"From there, download and install Ghostscript.")
		Case $_ERROR_PdfInputFileIsNotValid
		MsgBox(0,"Error", 	"Supplied PDF file is invalid." & @CRLF & @CRLF & _
							"Please check your pdf file.")
		Case $_ERROR_WrongNeuratronVersion
		MsgBox(0,"Error", 	"Current Neuratron Version is not supported." & @CRLF & @CRLF & _
							"Please install Photoscore version 6.")
		Case $_ERROR_PdfImageSizeTooLarge
		MsgBox(0,"Error", 	"Image size of PDF file is too large." & @CRLF & @CRLF & _
							"Processing would not make much sense.")
		Case $_ERROR_MissingSavedNeuratronPrefs
		MsgBox(0,"Error", 	"The preferences file in the temp directory is missing." & @CRLF & @CRLF & _
							"Please restart program.")
		Case $_ERROR_SavedNeuratronPrefsFileCorrupt
		MsgBox(0,"Error", 	"The preferences file in the temp directory is corrupt." & @CRLF & @CRLF & _
							"Please restart program.")
		Case $_ERROR_imagemagickNotInstalled
		MsgBox(0,"Error", 	"ImageMagick is missing." & @CRLF & @CRLF & _
							"Please go to:" & @CRLF & _
							"http://www.imagemagick.org/script/binary-releases.php#windows" & @CRLF & @CRLF & _
							"From there, download the Q16-windows-dll version." & @CRLF & @CRLF & _
							"Make sure the installation option " & $QQ & "Install ImageMagickObject" & @CRLF & _
							"OLE Control for VBscript, Visual Basic, and WSH." & $QQ & " is enabled.")
		Case Else
		MsgBox(0,"Error", "Error number: " & String($_ERROR_Number))
	EndSwitch
	RevertNeuratronPrefs()
	RemoveSomeTempFiles()
Exit
EndFunc