1//////////////////////////////////////////////////////////////////////////////////// 2//////////////////////////////////////////////////////////////////////////////////// 3Frame_item = class 4 Menupullright "Picture _Frame" "working with images of frames" 5 { 6 //////////////////////////////////////////////////////////////////////////////////// 7 Build_frame_item = class 8 Menupullright "_Build Frame From" "builds a new frame from image a and places it around image b" 9 { 10 //////////////////////////////////////////////////////////////////////////////////// 11 Frame_corner_item = class 12 Menuaction "_Frame Corner" 13 "copies and extends a frame corner, a, to produce a complete frame to fit round a given image, b" 14 { 15 prefs = Workspaces.Preferences; 16 17 action a b = class 18 _result 19 { 20 _check_args = [ 21 [a, "a", check_Image], 22 [b, "b", check_Image] 23 ]; 24 _check_all = [ 25 [a.coding == b.coding && a.bands == b.bands, 26 "a.coding == b.coding && a.bands == b.bands"] 27 ]; 28 _vislevel = 3; 29 30 ppcm = Expression "Number of pixels per cm" 25; 31 32 /* Given the value of ppcm, distance between the inner edge of the frame 33 * and the outer edge of the image. +ve values mean the frame overlaps 34 * the image. 35 */ 36 overlap = Expression "Size of frame overlap in cm" 0; 37 variables = class 38 { 39 scale_factor = Expression "scale the size of the frame by" 1; 40 41 /* These sliders define the fraction of the frames width or height is extracted 42 * to produce each of the particular regions. 43 */ 44 corner_section = Slider 0.1 1 0.5; 45 middle_section = Slider 0.1 1 0.2; 46 blend_fraction = Slider 0.1 0.9 0.1; 47 } 48 49 _type = Image_type.colour_spaces.get_name b.type; 50 51 //If applied the count colour be seen for -ve values of overlap 52 mount_options = class 53 { 54 apply = Toggle "Apply mount options" false; 55 ls = Expression "Lower mount section bigger by (cm)" 0; 56 mount_colour = Colour _type [0, 0, 0]; 57 _los = ls.expr * ppcm.expr; 58 } 59 60 _cs = variables.corner_section.value; 61 _ms = variables.middle_section.value; 62 _ov = ppcm.expr * overlap.expr; 63 _sf = variables.scale_factor.expr; 64 _bf = variables.blend_fraction.value; 65 66 //Scale frame image if required. 67 _a = a, _sf == 1; 68 = a, _sf == 0; 69 = Image (resize _sf _sf Interpolate.BILINEAR a.value); 70 71 _im_w = b.width; 72 _im_h = b.height + mount_options._los, mount_options.apply 73 = b.height; 74 _os = mount_options._los, mount_options.apply 75 = 0; 76 _cl = Vector mount_options.mount_colour.value, mount_options.apply 77 = 0; 78 79 //Produce scaled and resized frame. 80 frame = corner_frame _a _im_w _im_h _ov _cs _ms _bf; 81 //Resize image canvas and applied mount colour as required. 82 _pos_im = frame_position_image b frame _os _cl; 83 //Wrap frame round image. 84 _result = if (frame == 0) then _pos_im else frame; 85 } 86 } 87 88 //////////////////////////////////////////////////////////////////////////////////// 89 Simple_frame_item = class 90 Menuaction "_Simple Frame" 91 "extends or shortens the central sections of a simple frame, a, to fit round a given image, b" 92 { 93 prefs = Workspaces.Preferences; 94 95 action a b = class 96 _result 97 { 98 _check_args = [ 99 [a, "a", check_Image], 100 [b, "b", check_Image] 101 ]; 102 _check_all = [ 103 [a.coding == b.coding && a.bands == b.bands, 104 "a.coding == b.coding && a.bands == b.bands"] 105 ]; 106 _vislevel = 3; 107 108 109 ppcm = Expression "Number of pixels per cm" 25; 110 111 /* Given the value of ppcm, distance between the inner edge of the frame 112 * and the outer edge of the image. +ve values mean the frame overlaps 113 * the image. 114 */ 115 overlap = Expression "Size of frame overlap in cm" 0; 116 117 variables = class 118 { 119 scale_factor = Expression "scale the size of the frame by" 1; 120 121 /* These sliders define the fraction of the frames width or height that 122 * is extracted to produce each of the particular regions. 123 */ 124 corner_section = Slider 0.1 1 0.5; 125 middle_section = Slider 0.1 1 0.3; 126 blend_fraction = Slider 0.1 0.9 0.1; 127 option = Toggle "Use mirror of left-side to make right" true; 128 } 129 130 _type = Image_type.colour_spaces.get_name b.type; 131 //If applied the count colour be seen for -ve values of overlap 132 mount_options = class 133 { 134 apply = Toggle "Apply mount options" false; 135 ls = Expression "Lower mount section bigger by (cm)" 0; 136 mount_colour = Colour _type [0, 0, 0]; 137 _los = ls.expr * ppcm.expr; 138 } 139 140 _cs = variables.corner_section.value; 141 _ms = variables.middle_section.value; 142 _ov = ppcm.expr * overlap.expr; 143 _sf = variables.scale_factor.expr; 144 _bf = variables.blend_fraction.value; 145 146 //Scale frame image if required. 147 _a = a, _sf == 1; 148 = a, _sf == 0; 149 = Image (resize _sf _sf Interpolate.BILINEAR a.value); 150 151 _im_w = b.width; 152 _im_h = b.height + mount_options._los, mount_options.apply 153 = b.height; 154 _os = mount_options._los, mount_options.apply 155 = 0; 156 _cl = Vector mount_options.mount_colour.value, mount_options.apply 157 = 0; 158 159 //Produce scaled and resized frame. 160 frame = simple_frame _a _im_w _im_h _ov _cs _ms _bf variables.option; 161 //Resize image canvas and applied mount colour as required. 162 _pos_im = frame_position_image b frame _os _cl; 163 //Wrap frame round image. 164 _result = if (frame == 0) then _pos_im else frame; 165 } 166 } 167 168 //////////////////////////////////////////////////////////////////////////////////// 169 Complex_frame_item = class 170 Menuaction "_Complex Frame" 171 "extends or shortens the central sections of a frame a, preserving any central edge details, to fit image b" { 172 prefs = Workspaces.Preferences; 173 174 action a b = class 175 _result 176 { 177 _check_args = [ 178 [a, "a", check_Image], 179 [b, "b", check_Image] 180 ]; 181 _check_all = [ 182 [a.coding == b.coding && a.bands == b.bands, 183 "a.coding == b.coding && a.bands == b.bands"] 184 ]; 185 _vislevel = 3; 186 187 ppcm = Expression "Number of pixels per cm" 25; 188 189 /* Given the value of ppcm, distance between the inner edge of the frame 190 * and the outer edge of the image. +ve values mean the frame overlaps 191 * the image. 192 */ 193 overlap = Expression "Size of frame overlap in cm" 0; 194 195 variables = class 196 { 197 scale_factor = Expression "scale the size of the frame by" 1; 198 199 /* These sliders define the fraction of the frames width or height is extracted 200 * to produce each of the particular regions. 201 */ 202 corner_section = Slider 0.1 1 0.4; 203 edge_section = Slider 0.1 1 0.1; 204 middle_section = Slider 0.1 0.5 0.3; 205 blend_fraction = Slider 0.1 0.9 0.1; 206 option = Toggle "Use mirror of left-side to make right" true; 207 } 208 209 210 _type = Image_type.colour_spaces.get_name b.type; 211 212 //If applied the count colour be seen for -ve values of overlap 213 mount_options = class 214 { 215 apply = Toggle "Apply mount color" false; 216 ls = Expression "Lower mount section bigger by (cm)" 0; 217 colour = Colour _type [0, 0, 0]; 218 _los = ls.expr * ppcm.expr; 219 } 220 221 _cs = variables.corner_section.value; 222 _es = variables.edge_section.value; 223 _ms = variables.middle_section.value; 224 _ov = ppcm.expr * overlap.expr; 225 _sf = variables.scale_factor.expr; 226 _bf = variables.blend_fraction.value; 227 228 _a = a, _sf == 1; 229 = a, _sf == 0; 230 = Image (resize _sf _sf Interpolate.BILINEAR a.value); 231 232 _im_w = b.width; 233 _im_h = b.height + mount_options._los, mount_options.apply 234 = b.height; 235 _os = mount_options._los, mount_options.apply 236 = 0; 237 _cl = Vector mount_options.colour.value, mount_options.apply 238 = 0; 239 240 241 //Produce scaled and resized frame. 242 frame = complex_frame _a _im_w _im_h _ov _cs _es _ms _bf variables.option; 243 //Resize image canvas and applied mount colour as required. 244 _pos_im = frame_position_image b frame _os _cl; 245 //Wrap frame round image. 246 _result = if (frame == 0) then _pos_im else frame; 247 } 248 } 249 } 250//////////////////////////////////////////////////////////////////////////////////// 251 Straighten_frame_item = class 252 Menuaction "_Straighten Frame" "uses four points to square up distorted images of frames" { 253 action a = Perspective_item.action a; 254 } 255}; 256 257//////////////////////////////////////////////////////////////////////////////////// 258//////////////////////////////////////////////////////////////////////////////////// 259Select_item = class 260 Menupullright "_Select" 261 "select user defined areas of an image" { 262 prefs = Workspaces.Preferences; 263 264 /* Option toggle used to define whether the user is replacing a 265 * dark or a light area. 266 */ 267 _control = Option "Make" [ 268 "Selection Brighter", 269 "Selection Darker", 270 "Selection Black", 271 "Selection White", 272 "Background Black", 273 "Background White", 274 "Mask" ] 6; 275 276 277 control_selection mask im no 278 = (if mask then im * 1.2 else im * 1), no == 0 279 = (if mask then im * 0.8 else im * 1), no == 1 280 = (if mask then 0 else im), no == 2 281 = (if mask then 255 else im), no == 3 282 = (if mask then im else 0), no == 4 283 = (if mask then im else 255), no == 5 284 = mask; 285 286 Elipse = class 287 Menuaction "_Ellipse" 288 "use a line/arrow x to define the center point radius and direction of an ellipse" 289 { 290 action x = class 291 _result { 292 _vislevel = 3; 293 294 control = _control; 295 width = Slider 0.01 1 0.5; 296 297 _result = control_selection mask im control 298 { 299 mask = select_ellipse x width.value; 300 im = x.image; 301 } 302 } 303 } 304 305 Tetragon = class 306 Menuaction "_Tetragon" 307 "selects the convex area defined by four points" 308 { 309 action a b c d = class 310 _result { 311 _vislevel = 3; 312 313 control = _control; 314 315 _result = control_selection mask im control 316 { 317 mask = select_tetragon a b c d; 318 im = a.image; 319 } 320 } 321 322 } 323 324 Polygon = class 325 Menuaction "_Polygon" 326 "selects a polygon from an ordered group of points" 327 { 328 action pt_list = class 329 _result { 330 _vislevel = 3; 331 332 control = _control; 333 334 _result = control_selection mask im control 335 { 336 mask = select_polygon pt_list; 337 im = ((pt_list.value)?0).image; 338 } 339 } 340 } 341 }; 342//////////////////////////////////////////////////////////////////////////////////// 343//////////////////////////////////////////////////////////////////////////////////// 344 345Perspective_match_item = class 346 Menuaction "_Perspective Match" 347 "rotate, scale and skew one image to match another" { 348 action x y = class 349 _result { 350 _vislevel = 3; 351 352 // try to find an image ... for a group, get the first item 353 find_image x 354 = x, is_Image x 355 = find_image x?0, is_list x 356 = find_image x.value, is_class x && has_value x 357 = error "unable to find image"; 358 359 _a = find_image x; 360 _b = find_image y; 361 362 ap1 = Mark_relative _a 0.1 0.1; 363 ap2 = Mark_relative _a 0.9 0.1; 364 ap3 = Mark_relative _a 0.1 0.9; 365 ap4 = Mark_relative _a 0.9 0.9; 366 367 bp1 = Mark_relative _b 0.1 0.1; 368 bp2 = Mark_relative _b 0.9 0.1; 369 bp3 = Mark_relative _b 0.1 0.9; 370 bp4 = Mark_relative _b 0.9 0.9; 371 372 _result = map_binary process x y 373 { 374 f1 = _a.width / _b.width; 375 f2 = _a.height / _b.height; 376 377 rl = sort_pts_clockwise [ap1, ap2, ap3, ap4]; 378 pl = sort_pts_clockwise [bp1, bp2, bp3, bp4]; 379 380 to = [ 381 rl?0.left, rl?0.top, 382 rl?1.left, rl?1.top, 383 rl?2.left, rl?2.top, 384 rl?3.left, rl?3.top 385 ]; 386 387 from = [ 388 pl?0.left * f1, pl?0.top * f2, 389 pl?1.left * f1, pl?1.top * f2, 390 pl?2.left * f1, pl?2.top * f2, 391 pl?3.left * f1, pl?3.top * f2 392 ]; 393 394 trans = perspective_transform to from; 395 396 process a b = transform 1 0 trans b2 397 { 398 b2 = resize f1 f2 1 b, (f1 >= 1 && f2 >= 1) || (f1 >= 1 && f2 >= 1) 399 = resize f1 1 1 b1 400 {b1 = resize 1 f2 1 b;} 401 } 402 } 403 } 404 } 405 406//////////////////////////////////////////////////////////////////////////////////// 407//////////////////////////////////////////////////////////////////////////////////// 408Perspective_item = class 409 Menuaction "Pe_rspective Distort" 410 "rotate, scale and skew an image with respect to defined points" { 411 action x = class 412 _result { 413 _vislevel = 3; 414 415 // try to find an image ... for a group, get the first item 416 find_image x 417 = x, is_Image x 418 = find_image x?0, is_list x 419 = find_image x.value, is_class x && has_value x 420 = error "unable to find image"; 421 422 _a = find_image x; 423 424 dir = Option "Select distort direction" [ "Distort to points", "Distort to corners" ] 1; 425 ap1 = Mark_relative _a 0.1 0.1; 426 ap2 = Mark_relative _a 0.9 0.1; 427 ap3 = Mark_relative _a 0.9 0.9; 428 ap4 = Mark_relative _a 0.1 0.9; 429 430 _result = map_unary process x 431 { 432 trans = [perspective_transform to from, perspective_transform from to]?(dir.value) 433 { 434 rl = sort_pts_clockwise [ap1, ap2, ap3, ap4]; 435 to = [(rl?0).left, (rl?0).top, (rl?1).left, (rl?1).top, 436 (rl?2).left, (rl?2).top, (rl?3).left, (rl?3).top]; 437 from=[0, 0, (_a.width - 1), 0, 438 (_a.width - 1), (_a.height - 1), 0, (_a.height - 1)]; 439 } 440 441 process a = transform 1 0 trans a; 442 } 443 } 444 }; 445 446