Skip to content

Instantly share code, notes, and snippets.

@SugoiDev
Last active December 26, 2015 15:00
Show Gist options
  • Save SugoiDev/168dc48887adf9f68994 to your computer and use it in GitHub Desktop.
Save SugoiDev/168dc48887adf9f68994 to your computer and use it in GitHub Desktop.
This script uses ImageMagick to generate PNG files from PSD/Ai files so that they can compared using the P4Merge, from Perfoce. #autohotkey #windows
#SingleInstance force
#NoEnv
#Warn
; This script uses ImageMagick to generate PNG files from PSD/Ai files so that they can compared using the P4Merge, from Perfoce.
; We mainly use this inside PlasticSCM as our default diff for images and Illustrator files.
; History
; 2015/10/23: released version 0.0.1
; License: The MIT License (MIT)
; Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
; The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
; Requirements
; PlasticSCM https://www.plasticscm.com/download/
; P4Merge http://www.perforce.com/downloads/helix (look for from P4Merge: Visual Merge Tool)
; ImageMagick from http://www.imagemagick.org/script/download.php
; AutoHotkey http://ahkscript.org/download/
; Usage (PlasticSCM)
; 1. Edit the paths in the "user configuration" section below
; 2. In PlasticSCM, go to Preferences -> Diff Tools -> Add
; Select "External diff tool" and "Use this tool for binary files"
; And add this for command line:
; <THIS> @sourcefile @destinationfile
; where <THIS> is this script's full path (e.g., c:\ImagesDiffWithP4Merge.ahk)
; -------------------------------------------------------------
; --------------------- user configuration --------------------
; -------------------------------------------------------------
global imageMagicConvertExe := "T:\ImageMagick\convert.exe"
global p4MergeExe := "T:\P4Merge\p4merge.exe"
global P4MergeLNKName := "P4Merge.lnk"
;this suffix makes it easier for us to cleanup later
;this is also used to match a running P4Merge that we created (it will show in the Window Title)
global suffix_for_converted_files := "ImagesDiffWithP4Merge"
; -------------------------------------------------------------
; ------------------------- variables -------------------------
; -------------------------------------------------------------
global dir_for_converted_files = A_Temp . "\" . suffix_for_converted_files
; we can't declare those global and assign them in the same statement, as we would have to use 1 and 2,
; and they would be seem as normal numbers
global file_a :=
global file_b :=
file_a = %1%
file_b = %2%
; -------------------------------------------------------------
; ---------------------- initialization -----------------------
; -------------------------------------------------------------
; This seems weird but is correct. 0 is the variable containing the amount of parameters passed to this script.
If 0 <> 2
{
MsgBox, 48, Error, This script takes exactly 2 parameters, but %0% were passed.
ExitApp
}
Diff_then_Cleanup(file_a, file_b)
; -------------------------------------------------------------
; ---------------------- functions ----------------------------
; -------------------------------------------------------------
Diff_then_Cleanup(file1, file2) {
TrayTip, , Generating files..., 1, 1
cleanup() ; we run cleanup before to remove files that could have been left over from a previous run
FileCreateDir, %dir_for_converted_files% ; this will do nothing if the dir already exists
sleep, 1000
diff(file1, file2)
sleep, 1000
cleanup()
}
Diff(file1, file2) {
file1 := Get_Supported_File_From_Source_If_Possible(file1)
file2 := Get_Supported_File_From_Source_If_Possible(file2)
; Check if there converted files named like filename-0.png, filename-1.png, filename-3.png
; If there are, it means we just converted a multi-artboart illustrator file and
; we need to open one P4Merge instance for each pair of files
if (FileExist(file1) && FileExist(file2)) {
; no multi-page illustrator files detected, continuing normally
RunWait, %p4MergeExe% "%file1%" "%file2%",, Max UseErrorLevel
; removeme: ErrorLevel is useless as it seems p4merge doesn't set this properly
If (A_LastError > 0)
{
TrayTip, , ERROR Opening P4Merge!, 2, 3
ExitApp
}
} else {
user_wants_manual_compare = 0
MsgBox, 51, Attention, Multiple artboards/pages detected.`n`nCompare manually?
IfMsgBox, Yes
{
user_wants_manual_compare = 1
} else IfMsgBox, Cancel
{
ExitApp
}
SplitPath, file1, , , , file_1_name_no_ext
SplitPath, file2, , , , file_2_name_no_ext
file_1_artboards := get_artboards_array(file_1_name_no_ext)
file_2_artboards := get_artboards_array(file_2_name_no_ext)
multi_page_diff(file_1_artboards, file_2_artboards, user_wants_manual_compare)
}
}
; multi page ai/pdf files diff
multi_page_diff(file_1_artboards, file_2_artboards, user_wants_manual_compare) {
file_1_total_artboards := file_1_artboards._MaxIndex()
file_2_total_artboards := file_2_artboards._MaxIndex()
If ((file_1_total_artboards <> file_2_total_artboards) || user_wants_manual_compare ) {
multi_page_manual_diff(user_wants_manual_compare)
return
}
multi_page_automatic_diff(file_1_artboards, file_2_artboards)
}
; Runs a diff for each of the artboards in the ai files (one PNG for each artboard)
; Waits until the user finishes diffing one artboard to open the next diff
; Asks questions to continue
multi_page_automatic_diff(file_1_artboards, file_2_artboards) {
Loop % file_1_artboards._MaxIndex()
{
MsgBox, 3, , Artboard %A_Index% `n`nCompare?
IfMsgBox, No
{
;skip current artboard
Continue
} else IfMsgBox, Cancel
{
ExitApp
}
f1 := file_1_artboards[A_Index]
f2 := file_2_artboards[A_Index]
RunWait, %p4MergeExe% "%f1%" "%f2%",, Max
}
}
; if the user wants to compare manually (maybe because of files with non-corresponding artboards) we'll
; simply show them an Explorer window with the converted files and a shortcut to the P4Merge exe
; If this routine is called with parameter False, it means we tried to automatic compare files with
; different number of artboards. In this case, a manual compare will be forced
multi_page_manual_diff(user_wants_manual_compare) {
if (!user_wants_manual_compare) {
MsgBox, 48, Impossible to compare automatically!, The files have different number of pages/artboards. Only files with the same number of pages/artboards can be compared automatically. `n`nAn explorer Window will be open with the converted files and a shortcut to P4Merge. Use the lnk manually compare.
}
FileCreateShortcut, %p4MergeExe%, %dir_for_converted_files%\%P4MergeLNKName%
RunWait, explore %dir_for_converted_files%, Max
MsgBox, 48, Attention, The temporary files will be removed when you click OK.
Return
}
; Returns the full path for a file with typed supported by P4Merge.
; Does this by either converting the source using ImageMagick or by copying the source itself to the proper diff dir
Get_Supported_File_From_Source_If_Possible(source) {
SplitPath, source, file_name,, source_ext
ConvertedFileName = %dir_for_converted_files%\%suffix_for_converted_files%_%file_name%.png
if (source_ext = "ai") {
imageMagickParameters = -colorspace RGB
} else if (source_ext = "psd") {
imageMagickParameters = -flatten -quality 100
} else if ((source_ext = "png") || (source_ext = "jpg") || (source_ext = "bmp")) {
; In this case, we can simply use the own source file, as it is nativelly supported.
; We'll copy it to the diff dir so it can be used in manual comparisons, if needed.
copied_file = %dir_for_converted_files%\%suffix_for_converted_files%_%file_name%
FileCopy, %source%, %copied_file%
Return %copied_file%
} else {
MsgBox,16 , Error!, Unsupported format: %source_ext%! Exiting...
ExitApp
}
RunWait, %imageMagicConvertExe% %imageMagickParameters% "%source%" "%ConvertedFileName%",, Hide UseErrorLevel
If (A_LastError > 0)
{
TrayTip, , ERROR in Imagemagick conversion! Source: %source_ext%..., 2, 3
ExitApp
}
Return %ConvertedFileName%
}
; returns an array with the file paths of a PNG for each artboard
get_artboards_array(file_without_ext) {
artboards_array := Object()
; we parse up to 100 artboards (!)
Loop, 100
{
current_index := A_Index - 1 ; 1-indexed madness
file_candidate = %dir_for_converted_files%\%file_without_ext%-%current_index%.png
If (FileExist(file_candidate)) {
artboards_array.Insert(file_candidate)
} else {
return artboards_array
}
}
return artboards_array
}
Cleanup() {
SplitPath, file_a, file_a_name
SplitPath, file_b, file_b_name
TrayTip, , cleaning up..., 1, 1
FileDelete, %dir_for_converted_files%\%suffix_for_converted_files%*.png
FileDelete, %dir_for_converted_files%\%suffix_for_converted_files%*.png
FileDelete, %dir_for_converted_files%\%file_a_name%
FileDelete, %dir_for_converted_files%\%file_b_name%
FileDelete, %dir_for_converted_files%\%P4MergeLNKName%
FileRemoveDir, %dir_for_converted_files%
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment