Marquee bisection

Anyone, especially newbies, asking for help with Photoshop Scripting and Photoshop Automation - as opposed to those contributing to discussion about an aspect of Photoshop Scripting

Moderators: Tom, Kukurykus

HiKO

Marquee bisection

Post by HiKO »

Hi,
Can someone help me please with this nasty problem? I am trying to locate the x coordinate of the closest layer to 0 in a marquee. I don’t want to loop trough all layers, layer sets etc. – so I made a script which make a bisection of the actual marquee and tries to copy merged part A and part B (actual marquee will be split in part A and B). If one Part is true, there will be an other bisection of these actual Parts and so on.

I have tested this with a transparent document (512 x 512 px) with only a small dot inside to locate it.

My problem is to set the X offset called “bisX” the right way – because of the changing A part and B part.

This part of the Code is wrong (bisX = bisA;) – but something happened

Code: Select alliniDoc = app.activeDocument;
iniLay = iniDoc.activeLayer;

iniMarX = 0;
iniMarY = 0;
iniMarWid = 512;
iniMarHgt = 512;

bisA = Math.round(iniMarWid / 2);
bisB = (iniMarWid - bisA);
bisX = iniMarX;
bisY = iniMarY;


// tries to copy A and B bisection
function colBis() {

   function cpyColBis() {

      var colA = [[bisX,bisY],[(bisX + bisA),bisY],[(bisX + bisA),iniMarHgt],[bisX,iniMarHgt]];
      iniDoc.selection.select(colA);
      try {iniDoc.selection.copy(true);
      //iniDoc.selection.deselect();
      cpyA = true;
      } catch(e) {
      cpyA = false;
      };

      if (cpyA == false) {
         var colB = [[(bisX + bisA),bisY],[(bisX + bisA + bisB),bisY],[(bisX + bisA + bisB),iniMarHgt],[(bisX + bisA),iniMarHgt]];
         iniDoc.selection.select(colB);
         try {iniDoc.selection.copy(true);
          //iniDoc.selection.deselect();
         } catch(e) {
         };
      };

      // bisection of A
      if (cpyA == true) {
         bisB = (bisA - (Math.round(bisA / 2)));
         bisA = Math.round(bisA / 2);
      };

      // bisection of B
      if (cpyA == false) {
         bisX = bisA;
         bisA = Math.round(bisB / 2);
         bisB = (bisB - bisA);
      };

   };

   // while loop for column bisection
   while ((bisA >= 2) || (bisB >= 2)) {
   alert (bisX);
      cpyColBis();
   };
};


colBis();


Sorry for my confused english description
Thanks in advance

HiKO
User avatar
Kukurykus
Posts: 528
Joined: Mon Jul 25, 2016 12:36 pm

Re: Marquee bisection

Post by Kukurykus »

There is no need to use this (bisection) method to find the most bounding layer of the left side image. You simply can use copy merged layers in try...catch statement like you did in your script, but with a preceding history state taken to memory, you call after you flat all layer to check activeDcoument.activeLayer.bounds[0]

I thought what could be point of using this method, but only one thought came to me was you could activate most bounding layer without looping them all. Problem is that I don't have idea how that could be done :( So this method loses with traditional checking bounds of document.

Anyway I tried my best and here is finished script working your way (I got inspired yours but used it only as a scratch to write my version):

Code: Select all

prU = preferences.rulerUnits, preferences.rulerUnits = Units.PIXELS;
hst = 'aHS = aD.activeHistoryState, aD.artLayers.add(), sel.fill(foregroundColor)'
cpy = 'sel.copy(true)'; (r = (aD = activeDocument).width); var brk, o, l, R; $.level = 0;

(function col() {
l = (l || 0)
while(r > l) {
(sel = aD.selection).select([[l, 0], [r = (l + (r - l) / 2), 0], [r, h = aD.height], [l, h]])
if (BRK = r - l == 1) try{eval(cpy), brk = BRK; break} catch (e1) {}
try{eval(cpy), eval(hst), R = aD.activeLayer.bounds[2], aD.activeHistoryState = aHS}
catch (e2) {
if (R) {
eval(hst), l = (bnd = aD.activeLayer.bounds)[2], o = (bnd[2] - bnd[0] == 1) - 1
aD.activeHistoryState = aHS, r = R; break
}
}
}
if (brk) {}; else if(o) col()
})()

if (R) alert('The left edge of layer nearest to left edge of document is at: ' + UnitValue(r.value - 1 + ' px'))
else alert('Lack of layers on left part of document!'); preferences.rulerUnits = prU
If anyone else want to test it, just create empty document, duplicate background then delete background. Make selection on whole copy of background and delete it, so it becomes transparent. At the end add one or few little layers on the left part of document, that there still remains empty space around layer(s).


And now what is the biggest riddle to me:

There are many visible layers in the document, each without contact with each other (the background is set to transparent layer). Can someone tell me how without looping (by a script of course) make active only that layer which has been selected (even manually). I ticked in Photoshop 'Auto Select Layer', then I LMB clicked on some layer. Checked what ScriptListener wrote, but unfortunetelly there was name of layer in the code. So that wouldn't help as I had to loop all layers to check which layer is that I made selection over.

Well anyone know how to do it witout looping layers? If so then the script I wrote would be useful let's say if there are 100 'island-layers' (without any order) in different positions of document. Then after fast scanning by (modified version of above) script I could select from those 100 layers that one I'm looking for.
Attachments
Marquee Bisection.zip
(938 Bytes) Downloaded 312 times