In the spirit of wondering why the obvious doesn't strike you before it does, I've updated the image scaling script to also number the pages so the left and right pages will interleave correctly once both sets of images are copied to a single directory. This avoids using extra software (like the one I used which I described here:
viewtopic.php?f=14&t=3401#p20511) and the inevitable errors with any manual processing and fiddling.
Assumptions about this renumbering script to understand since it was designed to process pages from a single camera scanner.
a) It assumes right hand pages (odd numbered) are scanned from page 1 up to x (i.e. from start of the book to the end, up to a maximum of 9997) and are in their own directory.
b) It assumes left hand pages (even numbered) were scanned from x+1 down to 2 (i.e from the end of the book to the start) and are in their own directory.
c) It checks there are the same number of files in left and right directories (if both are specified), i.e. it assumes you've scanned all pages from 1 up to x and x+1 down to 2.
d) If you don't want to perform image scaling and just number the pages, enter the same pixel value for the first and last pages (i.e. 100% scale).
Code: Select all
#singleinstance, force
; Normalize Scanned Pages Scale V1.3
;
; Autohotkey script using graphics magic library
;
; 1) Rescale pages from a book with varying camera/platen distance (i.e. difference in distance from camera to first page and last page scanned is thickness of book)
; to normalize page scale so content on each page is same as first page (i.e. last page is scaled the most amount).
;
; 2) File modified date and time of each image must increase from first (largest) to last (smallest) page scanned.
;
; a) so for right hand pages (odd numbered), largest and first scanned page should be page 1 and smallest and last scanned should be page x.
; b) and for left hang pages (even numbered), largest and first scanned page should be page x+1 and smallest and last scanned should be page 2.
;
; 3) ALL pages must be scanned (including blank) with equal number of pages in separate directories for left and right hand pages.
;
; 4) Output is placed in a subdirectory of each (calibration pages are not processed or copied).
;
; 5) Filenames of righthand (odd) and lefthand (even) page are also numbered as follows:
;
; a) right hand pages (odd numbered) are scanned from page 1 up to x (i.e. from start of the book to the end, up to a maximum of 9997).
; b) left hand pages (even numbered) were scanned from x+1 down to 2 (i.e from the end of the book to the start).
; c) same number of files in left and right directories (if both are specified), i.e it assumes you've scanned all pages from 1 up to x and x+1 down to 2.
; d) to skip scaling and just number pages, enter the same pixel value for the first and last pages (i.e. 100% scale).
;
; Change log:
; V1.3 -- Added -- Insert page numbering of righthand (odd) and lefthand (even) pages into file name
;
; Full path to graphicsmagick gm.exe
; Example: C:\Program Files\GraphicsMagick-1.3.25-Q8\gm.exe
gm := "C:\Program Files (x86)\GraphicsMagick-1.3.25-Q16\gm.exe"
if !FileExist(gm) {
MsgBox ,,ERROR,graphicsmagick's gm.exe file not found here:`n`n%gm%
exitapp
}
GetImageDirectories:
; Get path to folder with right and/or right hand page jpg images to process
rightOutput := "\right-adjusted"
leftOutput := "\left-adjusted"
rightImagesFolder := ""
leftImagesFolder := ""
FileSelectFolder, rightImagesFolder,,2,Choose folder with all RIGHT hand pages (or enter cancel to skip processing right hand pages).
FileSelectFolder, leftImagesFolder,,2,Choose folder with all LEFT hand pages (or enter cancel to skip processing left hand pages).
If (rightImagesFolder = "" and leftImagesFolder = "") {
ExitApp
}
If (rightImagesFolder = leftImagesFolder) {
MsgBox ,,ERROR,You have chosen the same directory for both left and right hand pages. This is not allowed. Please choose the directories again.
goto GetImageDirectories
}
If (rightImagesFolder <> "") {
if !FileExist(rightImagesFolder) {
MsgBox ,,ERROR,Folder given for right hand images does not exist. Please choose both image directories again.
goto GetImageDirectories
}
; Femove trailing slashes
rightImagesFolder := RegExReplace(rightImagesFolder, "\\$")
if FileExist(rightImagesFolder . rightOutput) {
; need to specify recurse else FileRemoveDir doesn't work.
FileRemoveDir, %rightImagesFolder%%rightOutput%, 1
}
FileCreateDir, %rightImagesFolder%%rightOutput%
Loop, files, %rightImagesFolder%\*.jpg
{
noOfRightFiles++
}
}
If (leftImagesFolder <> "") {
if !FileExist(leftImagesFolder) {
MsgBox ,,ERROR,Folder given for left hand images does not exist. Please choose both image directories again.
goto GetImageDirectories
}
; Femove trailing slashes
leftImagesFolder := RegExReplace(leftImagesFolder, "\\$")
if FileExist(leftImagesFolder . leftOutput) {
; need to specify recurse else FileRemoveDir doesn't work.
FileRemoveDir, %leftImagesFolder%%leftOutput%, 1
}
FileCreateDir, %leftImagesFolder%%leftOutput%
Loop, files, %leftImagesFolder%\*.jpg
{
noOfLeftFiles++
}
}
; check number of left and right files are the same
If (noOfRightFiles <> noOfLeftFiles And leftImagesFolder <> "" And rightImagesFolder <> "") {
MsgBox ,,ERROR, The left and right directories don't have the same number of files`n`nRight directory: %noOfRightFiles%`nLeft directory: %noOfLeftFiles%
ExitApp
}
; Get number of pixels of calibration image (6" ruler) placed on first page and last page of book
GetCalibrationSizes:
firstImageSize := 0
While firstImageSize = 0 Or firstImageSize = "" {
InputBox, firstImageSize, First Calibration Page, Enter number of pixels taken by a 6`" ruler placed on the first page of the book (first callibration page).,,450,150
if (ErrorLevel = 1) {
ExitApp
}
If (firstImageSize = 0 Or firstImageSize = "") {
MsgBox ,,ERROR,Zero or blank is not allowed
}
}
lastImageSize := 0
While lastImageSize = 0 Or lastImageSize = "" {
InputBox, lastImageSize, Last Calibration Page, Enter number of pixels taken by a 6`" ruler placed on the last page of the book (second callibration page). Enter same number as the first page to bypass scaling and only number the files.,,450,150
if (ErrorLevel = 1) {
ExitApp
}
If (lastImageSize = 0 Or lastImageSize = "") {
MsgBox ,,ERROR,Zero or blank is not allowed
}
If (firstImageSize < lastImageSize) {
MsgBox ,,ERROR,Last/smallest image is greater than first/largest image. Please enter the values again.
goto GetCalibrationSizes
}
}
; Calculate scale difference (percentage) between first and last pages
totalScaleFactor := ( firstImageSize / lastImageSize ) * 100
; 8228=4+32+8192
MsgBox, 8228, WARNING, Processing images as follows`n`nRight hand images: %rightImagesFolder%`n`nLeft hand images: %leftImagesFolder%`n`nPixel count (first image): %firstImageSize%`nPixel count (last image): %lastImageSize%`nFirst to last image scale factor: %totalScaleFactor%`n`nOk to proceed?
IfMsgBox, No
ExitApp
If (rightImagesFolder <> "") {
ProcessDirectory(rightImagesFolder, rightImagesFolder . rightOutput, "RIGHT")
}
If (leftImagesFolder <> "") {
ProcessDirectory(leftImagesFolder, leftImagesFolder . leftOutput, "LEFT")
}
exitapp
ProcessDirectory(currentInputImagesFolder, currentOutputImagesFolder, currentPageHand)
{
global totalScaleFactor
global gm
; noOfFiles number of pages in directory to scale can be distributed across all pages
; Create file list sorted by modified date/time so script can be used after renaming and is not depenedent on original image file name.
; Using time stamp also ensures processing is not random if directory listing is not alphabetic
fileList := ""
noOfFiles := 0
Loop, files, %currentInputImagesFolder%\*.jpg
{
; ignore first calibration image
if (noOfFiles <> 0) {
fileList = %FileList%%A_LoopFileTimeModified%`t%A_LoopFileName%`n
}
noOfFiles++
}
; remove last calibration page from file list (search for second `n)
fileList := Substr(fileList,1,Instr(fileList,"`n",false,-1,1))
; reduce count by 2 becuse 2 calibration images removed
noOfFiles := noOfFiles - 2
; Sort file list (date is appeneded to front of each entry of FileList - so list will be sorted by time first and then by file name)
; This lets many files with the same time (i.e. seconds didn't change) still sort in the right order and not dependent on
; Dir listings that may be in random order. Timestamp is not really needed and can be removed.
Sort, FileList
; Initalize the progress bar style
Progress, B2 M FM10 FS10 WM10 WS10 W700, Starting, PROCESSING %currentPageHand% HAND PAGES -- PRESS ESCAPE TO ABORT
If (currentPageHand = "RIGHT") {
currentFileNumber := 1
fileNumberIncrement := 2
} Else {
currentFileNumber := noOfFiles * 2
fileNumberIncrement := -2
}
Loop, Parse, fileList, `n
{
; Omit the last linefeed (blank item) at the end of the list.
If (A_LoopField = "") {
break
}
; Split into two parts at the tab char.
StringSplit, FileItem, A_LoopField, %A_Tab%
currentPageNumber := Format("PAGE#{:04}", currentFileNumber)
; ignore first image coz not to be scaled
If (a_index = 1) {
FileCopy, %currentInputImagesFolder%\%FileItem2%, %currentOutputImagesFolder%\%FileItem2%
} else {
If (totalScaleFactor <> 100) {
thisImageScaleFactor := (totalScaleFactor - 100) * (a_index / noOfFiles) + 100
amountDone := floor(a_index/noOfFiles*100)
; Update the progress bar value
Progress, %amountDone%
; Display the progress bar at the new value with new text
Progress, ,Processing: %a_index%/%noOfFiles% -- Scale: %thisImageScaleFactor% -- %currentPageNumber% -- %FileItem2%
RunWait "%gm%" convert "%currentInputImagesFolder%\%FileItem2%" -resize %thisImageScaleFactor%`% -quality 100 "%currentOutputImagesFolder%\%FileItem2%",,hide
} else {
FileCopy %currentInputImagesFolder%\%FileItem2%, %currentOutputImagesFolder%\%FileItem2%
}
}
FileMove %currentOutputImagesFolder%\%FileItem2%,%currentOutputImagesFolder%\%currentPageNumber% -- %FileItem2%
currentFileNumber := currentFileNumber + fileNumberIncrement
; Just make sure we actually exit when done, just to make sure last file is not processed twice in case don't exit with the blank above (as that seems to fail sometimes)
if (a_index = noOfFiles) {
break
}
}
Progress, Off
return
}
; Allow escape to cancel
Escape::ExitApp