Q: applescript faster
Hi there
I create a script which transform a picture at the Gcode
Unfortunately it works very slow. I think that mostly it happens in two "narrow" points:
when script recover all pixels in different colors (marked as "PROBLEM ONE")
and when script try to "wear" sprites at pixels (marked as "MAIN PROBLEM")
any Ideas to make it faster?
set thisFile to choose file with prompt "Выбери файл для обработки в G-Код "
tell application "iMagine Photo"
with timeout of (720 * 60) seconds
set thisImporter to import graphic thisFile
if the component error of thisImporter is not equal to 0 then
close thisImporter
display dialog "Not an image file that quicktime recognizes."
return
end if
set {x, y, xDim, yDim} to the natural bounds of thisImporter
set thisDocument to make new window document with properties {dimensions:{xDim, yDim}}
set the drawing destination of thisImporter to thisDocument
draw thisImporter
close thisImporter
-- The following section is to be replaced depending on the pixel value class
set pixelValueRect to {x, y, xDim, yDim}
set pix_am to (xDim * yDim) as integer --
set pixelValues1 to (get pixel values of thisDocument with properties {pixel value class:pixels in rectangle, bounds rectangle:pixelValueRect}) as list
close thisDocument
--set pixelValues2 to pixelValues1 as list
end timeout
end tell
set pix_am to xDim * yDim
set scany_col to {}
set pixelValues2 to a reference to pixelValues1
repeat 94 times
set a_col to some item of item 2 of pixelValues2 --взял случайный пиксель
if scany_col does not contain {a_col} then copy a_col to the end of scany_col
end repeat
set ttt to count items of scany_col
display dialog ("нашел цветов: " & ttt) buttons "" giving up after 1
set a_c to 1
set b_c to {}
repeat ttt times
set t_r to item a_c of scany_col --t_r это конкретно вытащенный цвет с его положением в списке а_с
copy "(на позиции " & a_c & " " & (((item 1 of t_r as string) / 256) as integer) & ", " & (((item 2 of t_r as string) / 256) as integer) & ", " & (((item 3 of t_r as string) / 256) as integer) & ")" & return to the end of b_c
set a_c to a_c + 1
end repeat
set bb_c to {}
use scripting additions
display dialog (b_c as text) buttons {"оставляю", "меняю очередность"} default button 1 --giving up after 3
copy the result as list to {button_res}
if button_res is "меняю очередность" then
set msg to "ввести номера камор по указанному цвету через запятую " & b_c as text
set delimAnswer to text returned of (display dialog msg default answer "")
set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, ","}
set dialogList to text items of delimAnswer
set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, return}
--set AppleScript's text item delimiters to TID
set aa_bb to 1
repeat count items of scany_col times
set nr_1 to item aa_bb of dialogList
set nr_2 to item nr_1 of scany_col
copy nr_2 to the end of bb_c
set aa_bb to aa_bb + 1
end repeat
set scany_col to bb_c
end if
set abcd to 1
set a2 to {}
repeat ttt times
copy {item abcd of scany_col} to the end of a2
set abcd to abcd + 1
end repeat
set a_c to 1
set scany_col_1 to scany_col
with timeout of (720 * 60) seconds
repeat pix_am times
set r_d to 0
repeat ttt times --PROBLEM ONE
set r_d to r_d + 1
if item r_d of scany_col is (item a_c of item 2 of pixelValues2) then
copy item a_c of item 1 of pixelValues2 to the end of item r_d of a2 --item r_d of scany_col_1
exit repeat
end if
end repeat
set a_c to a_c + 1 -- переход на следущий пиксел
end repeat
end timeout
set g to {}
set g_c to 1
set Diams to {{10, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, {8, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {8, 3}, {9, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {8, 4}, {9, 4}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {8, 5}, {9, 5}, {0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}, {8, 6}, {9, 6}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}, {7, 7}, {8, 7}, {2, 8}, {3, 8}, {4, 8}, {5, 8}, {6, 8}, {7, 8}, {3, 9}, {4, 9}, {5, 9}, {6, 9}}, {9, {3, 0}, {4, 0}, {5, 0}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {8, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {8, 4}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {8, 5}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}, {7, 7}, {3, 8}, {4, 8}, {5, 8}}, {8, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {2, 7}, {3, 7}, {4, 7}, {5, 7}}, {7, {2, 0}, {3, 0}, {4, 0}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {2, 6}, {3, 6}, {4, 6}}, {6, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {1, 5}, {2, 5}, {3, 5}, {4, 5}}, {5, {1, 0}, {2, 0}, {3, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {1, 4}, {2, 4}, {3, 4}}, {4, {1, 0}, {2, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {1, 3}, {2, 3}}, {3, {1, 0}, {0, 1}, {1, 1}, {2, 1}, {1, 2}}}
set kist to "G01 Z0" & return & "G01 Z70" & return
with timeout of (720 * 60) seconds
repeat count items of a2 times
set a to item g_c of a2
set d to {}
set a_vr to {}
set flagg to 1
set t to 2
copy ((("G21" & return & "(" & "R" & (((item 1 of item 1 of a) / 256) as integer)) & " G" & (((item 2 of item 1 of a) / 256) as integer)) & " B" & (((item 3 of item 1 of a) / 256) as integer)) & ")" & return & "Z70" & return & "M00" & return to the end of d
set b to 1
repeat count items of Diams times --MAIN PROBLEM
repeat (count items of a) / (count items of item b of Diams) * 0.7 times
set a_some to some item of a
set x to item 1 of a_some
set y to item 2 of a_some
set kfc to item 1 of item b of Diams
if a contains {(x + kfc) & (y + (kfc / 2) as integer)} and a contains {(x + (kfc / 2) as integer) & (y + kfc)} and a contains {(x + (kfc / 2) as integer) & (y)} and a contains {(x + (kfc / 2) as integer) & (y + (kfc / 2) as integer)} and a contains {x & y} then
set d to d & " Диаметром " & kfc & "pix " & x & " ,Y " & y --тут надо сразу G код писать с формулой окружности - проверку надо откорректировать, порет косяки
repeat with ix from 2 to the count of a
if item b of Diams contains {((item 1 of item ix of a) - x) & ((item 2 of item ix of a) - y)} then
set flagg to flagg + 1
else
copy item ix of a to the end of a_vr
end if
if flagg = ((count items of item b of Diams) - 1) then exit repeat
end repeat
set a to a_vr
end if
set t to t + 1
end repeat
set b to b + 1
set g_c to g_c + 1
copy d to the end of g
end repeat
end repeat
end timeout
tell application "TextEdit"
tell (make new document)
set its text to g as text --as "class utf8"
end tell
end tell
display dialog ("G-KODE как файл лежит открыт в текстовом редакторе") buttons "" giving up after 1 --end timeout
bb_c
MacBook Pro, OS X El Capitan (10.11.2)
Posted on Oct 1, 2016 10:04 PM
Hello
I'm not sure I understand it correctly but here's my revision of your script. I introduced some optimisations and also fixed logic based upon my understanding.
Briefly tested with small images less than 256 x 256 pixels under OS X 10.6.8.
* Circle definitions list (given in property circles) is rather redundant and can be optimised more by using offset ranges.
Good luck,
H
_main()
on _main()
script o
property |NL| : return -- newline character in output
property pp : {} -- list of {x, y} points
property cc : {} -- list of {r, g, b} colours
property scany_col : {} -- list of some auto-selected distinct colours
property scany_col1 : {} -- re-ordered scany_col (promoted partial list)
property tt : {} -- work list for re-orrdering dialogue result
property a2 : {} -- list of {{r, g, b}, {x, y}, {x, y}, ...} for every {r, g, b} in scany_col
property a : {} -- work list for points pool
property a_vr : {} -- work list for points pool (not yet allocated in circle)
property b_c : {} -- work list for re-ordering dialogue
property d : {} -- work list of g-code per colour
property g : {} -- list of g-code
(*
circle = {diameter, list of iternal points offset from reference point (bottom left point)}
circles = {circle, circle, ...}
diameter = 3
-@-
@@@
-@-
diameter = 4
-@@-
@@@@
@@@@
-@@-
diameter = 5
-@@@-
@@@@@
@@@@@
@@@@@
-@@@-
diameter = 6
-@@@@@-
@@@@@@@
@@@@@@@
@@@@@@@
@@@@@@@
-@@@@@-
diameter = 7
--@@@--
-@@@@@-
@@@@@@@
@@@@@@@
@@@@@@@
-@@@@@-
--@@@--
diameter = 8
--@@@@--
-@@@@@@-
@@@@@@@@
@@@@@@@@
@@@@@@@@
-@@@@@@-
--@@@@--
diameter = 9
---@@@---
-@@@@@@@-
-@@@@@@@-
@@@@@@@@@
@@@@@@@@@
@@@@@@@@@
-@@@@@@@-
-@@@@@@@-
---@@@---
diameter = 10
---@@@@---
--@@@@@@--
-@@@@@@@@-
@@@@@@@@@@
@@@@@@@@@@
@@@@@@@@@@
@@@@@@@@@@
-@@@@@@@@-
--@@@@@@--
---@@@@---
*)
property circles : {¬
{10, {3, 0}, {4, 0}, {5, 0}, {6, 0}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, {8, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {8, 3}, {9, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {8, 4}, {9, 4}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {8, 5}, {9, 5}, {0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}, {8, 6}, {9, 6}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}, {7, 7}, {8, 7}, {2, 8}, {3, 8}, {4, 8}, {5, 8}, {6, 8}, {7, 8}, {3, 9}, {4, 9}, {5, 9}, {6, 9}}, ¬
{9, {3, 0}, {4, 0}, {5, 0}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {7, 1}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {8, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {8, 4}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {8, 5}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}, {7, 7}, {3, 8}, {4, 8}, {5, 8}}, ¬
{8, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {7, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {7, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {7, 4}, {0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {2, 7}, {3, 7}, {4, 7}, {5, 7}}, ¬
{7, {2, 0}, {3, 0}, {4, 0}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {2, 6}, {3, 6}, {4, 6}}, ¬
{6, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {1, 5}, {2, 5}, {3, 5}, {4, 5}}, ¬
{5, {1, 0}, {2, 0}, {3, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {1, 4}, {2, 4}, {3, 4}}, ¬
{4, {1, 0}, {2, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {0, 2}, {1, 2}, {2, 2}, {3, 2}, {1, 3}, {2, 3}}, ¬
{3, {1, 0}, {0, 1}, {1, 1}, {2, 1}, {1, 2}}}
set f to choose file with prompt "Выбери файл для обработки в G-Код " (* Select the file for processing in the G-Code *)
tell application "iMagine Photo"
set p to import graphic f
if component error of p ≠ 0 then
close p
display dialog "Not an image file that quicktime recognizes."
error number -128 -- user cancel
end if
set {x, y, w, h} to natural bounds of p
set doc to make new window document with properties {dimensions:{w, h}}
set drawing destination of p to doc
draw p
close p
-- The following section is to be replaced depending on the pixel value class
set pix_am to (w * h)
set pv to (get pixel values of doc with properties {pixel value class:pixels in rectangle, bounds rectangle:{x, y, w, h}})
(* pv = {pixel points:{{x, y}, ...}, pixel colors:{{r, g, b}, ...}} *)
close doc
set pp to pv's pixel points
set cc to pv's pixel colors
end tell
--return pv
set scany_col to {}
repeat 94 times -- select some distinct colours (max 94)
set a_col to some item of my cc --взял случайный пиксель (* I took a random pixel *)
if my scany_col does not contain {a_col} then set my scany_col's end to a_col
end repeat
set scany_col_sz to count my scany_col -- number of selected distinct colours
display dialog ("нашел цветов: " & scany_col_sz) --giving up after 1 -- (* found flowers *)
--(*
(* change order of colours in scany_col *)
repeat
set b_c to {}
repeat with i from 1 to scany_col_sz
set {_r, _g, _b} to my scany_col's item i
(* the position of *)
set my b_c's end to "(на позиции " & i & " " & (_r div 256) & ", " & (_g div 256) & ", " & (_b div 256) & ")" & |NL|
end repeat
display dialog (b_c as text) buttons {"оставляю", "меняю очередность"} default button 1 --giving up after 3
(* {"leave ", "change the order"} *)
set btn to result's button returned
if btn is "меняю очередность" then (* change the order *)
set msg to "ввести номера камор по указанному цвету через запятую " & |NL| & b_c
(* enter the number of cameras to the specified color, separated by commas *)
set txt to text returned of (display dialog msg default answer "")
set {TID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {","}}
set tt to text items of txt
set AppleScript's text item delimiters to TID
-- put colour of specified ordinal numbers to the top
(*
E.g.
Given 4,7,2 in dialogue result, items 4, 7, 2 are moved to top in this order
(Invalid index is ignored)
*)
set scany_col1 to {}
repeat with i from 1 to count my tt
try
set j to my tt's item i as integer
set my scany_col1's end to my scany_col's item j
set my scany_col's item j to false -- promoted thus scratched
end try
end repeat
set scany_col to scany_col1 & my scany_col's lists -- append the rest
else
exit repeat -- done
end if
end repeat
--*)
set a2 to {}
repeat with c in my scany_col
set my a2's end to {c's contents}
end repeat
repeat with i from 1 to pix_am
repeat with j from 1 to scany_col_sz
if my scany_col's item j = my cc's item i then
set my a2's item j's end to my pp's item i
exit repeat
end if
end repeat
end repeat
-- a2 : list of {{r, g, b}, {x, y}, {x, y}, ...} for {r, g, b} in scany_col
--return a2
--set kist to "G01 Z0" & |NL| & "G01 Z70" & |NL| -- # NOT USED ANYWHEER IN SCRIPT
set g to {}
repeat with e in my a2 -- for each colour entry
set a to e's contents -- {{r, g, b}, points pool}
set {_r, _g, _b} to my a's item 1 -- {r, g, b} -- this colour
set a to my a's rest -- this points pool
set d to {}
repeat with c in my circles -- for each circle definition = {diameter, list of internal points offset}
set circle to c's contents -- this circle
set kfc to circle's item 1 -- diameter of this circle
set cnt to (count circle) - 1 -- number of internal points of this circle
repeat (count my a) / cnt * 0.7 times
set a_some to my a's some item -- some point in this points pool
set x to a_some's item 1
set y to a_some's item 2
set x_1 to (x + kfc / 2) as integer
set x_2 to x + kfc
set y_1 to (y + kfc / 2) as integer
set y_2 to y + kfc
if a contains {{x_2, y_1}} and ¬
a contains {{x_1, y_2}} and ¬
a contains {{x_1, y}} and ¬
a contains {{x_1, y_1}} and ¬
a contains {{x, y_1}} then -- 4 boundary points and 1 centre point of this circle are in this points pool
--set my d's end to " Диаметром " & kfc & "pix " & x & " ,Y " & y --тут надо сразу G код писать с формулой окружности - проверку надо откорректировать, порет косяки
(* then you must immediately write to the G code of the circumference formula - checks should be corrected, flogs shoals *)
-- point (x, y) can be the origin of a cirle of diameter d
set my d's end to "# circle of diameter = " & kfc & ", origin = (" & x & ", " & y & ")" & |NL|
(*
# circle of diameter = d, origin = (x, y)
*)
set a_vr to {}
set k to 0
repeat with i from 1 to count my a
set a_i to my a's item i
set dx to (a_i's item 1) - x
set dy to (a_i's item 2) - y
if circle contains {{dx, dy}} then -- in this circle
set k to k + 1
else -- not in this circle
if a_i ≠ a_some then -- unless it is current (x, y), which is already explored
set my a_vr's end to a_i
end if
end if
if k ≥ cnt then exit repeat
end repeat
set a to a_vr -- update points pool to points not chosen in this cicrle
end if
end repeat
end repeat
if (count my d) > 0 then -- only if any circle is allocated for this colour entry
-- set colour and stand by (?)
set my d's beginning to "G21" & |NL| & ¬
"(" & "R" & (_r div 256) & " G" & (_g div 256) & " B" & (_b div 256) & ")" & |NL| & ¬
"Z70" & |NL| & ¬
"M00" & |NL|
(*
G21
(R[0..255] G[0..255] B[0..255])
Z70
M00
*)
set my g's end to d
end if
end repeat
tell application "TextEdit"
tell (make new document)
set its text to g as text --as "class utf8"
end tell
end tell
display dialog ("G-KODE как файл лежит открыт в текстовом редакторе") --giving up after 1
(* G-CODE as the file is opened in a text editor *)
return scany_col
end script
tell o to run
end _main
Posted on Oct 4, 2016 6:44 AM
