/* * This macro picks an ROI and makes an expanded version in the corner * The ROI and the expansion have a white border * User can select the size of the ROI, the expansion, the corner and the border size * It is meant to be used for montages but it will work on single square images. * Open 1 image. Run Macro. Pick settings. * Click in the centre of where you want your ROI to be (any panel will work). * There is an option to use foreground color instead of white (default) for borders. * http://github.com/quantixed/imagej-macros/ */ macro "Add ROI Zoom" { if (nImages > 1) exit ("Use a single image or single montage"); if (nImages == 0) exit("No image open"); imageID = getImageID(); title = getTitle(); dir1 = getDirectory("image"); newName = "zooms_" + title; run("Select None"); getDimensions(w, h, c, numSlices, nFrames); // code doesn't work as intended with muli-channel images if (c > 1) exit("Image must be RGB or single channel"); // deal with multiple frames or slices nShots = maxOf(numSlices,nFrames); if (numSlices > 1 && nFrames > 1) exit("Number of slices and frames is greater than one"); if (numSlices == 1) sliceOrFrame = 0; if (numSlices > 1) sliceOrFrame = 1; if (nFrames > 1) sliceOrFrame = 2; // work out grout size if (w == h) { nCol = 1; nRow = 1; grout = 0; nPanel = 1; vChoice = ""; } else if (w > h) { nCol = floor(w/h); nRow = 1; grout = (w - (nCol * h)) / (nCol - 1); if (nCol == 1) { grout = 0; } nPanel = nCol; vChoice = ""; } else { nCol = 1; nRow = floor(h/w); grout = (h - (nRow * w)) / (nRow - 1); if (nRow == 1) { grout = 0; } nPanel = nRow; vChoice = "vert"; } // ask what size ROI and expansion and corner cornerArray = newArray("LT", "RT", "LB", "RB"); labels = newArray(nPanel); defaults = newArray(nPanel); panelDecisions = newArray(nPanel); for (i=0; i h) && lengthOf(vChoice) == 0) exit("Zoom will be too big, use different expansion"); if ((dSize > w) && vChoice == "vert") exit("Zoom will be too big, use different expansion"); // maybe they want to make the zoom the width of panel, let them but limit stroke so it doesn't go into next panel if ((dSize == h && bStroke > grout) && lengthOf(vChoice) == 0) exit("Use different stroke size to do this"); if ((dSize == w && bStroke > grout) && vChoice == "vert") exit("Use different stroke size to do this"); // entered a silly number if (bStroke > 20 * grout && grout > 0) exit("Use a smaller stroke size"); // User defines the centre of the box for expansion setTool(7); // not sure how to force single point vs multi-point waitForUser("Define box", "Click on the image to centre the box for expansion.\n\nTo change position, either drag the point,\nor click again and last point will be used"); if (selectionType == 10) { getBoundingRect(xp, yp, width, height); // print("x="+xp+" y="+yp+" "+width+" "+height); makeRectangle(xp-(bSize/2),yp-(bSize/2),bSize,bSize); selectImage(imageID); } else exit("Works with point selection only"); // figure out which panel the selection is in // each panel is h x h pixels separated by grout for horizontal // and w x w pixels separated by grout for vertical // this is risky but box should not be less than grout away from panel edge // will fail in cases of large grout or many panels. // sp is the panel where selection is, 0-based if (vChoice == "vert") { sp = floor(yp / w); // x and y coords of ROI centre relative to the panel LT xp1 = xp - 0; // --for future dev yp1 = yp - (sp * (w + grout)); // sanity check in case user has clicked too close to the edge if (xp1-(bSize/2) < 0 || yp1-(bSize/2) < 0) exit("Try again, too close to the edge"); if (xp1+(bSize/2) > w || yp1+(bSize/2) > w) exit("Try again, too close to the edge"); } else { sp = floor(xp / h); // x and y coords of ROI centre relative to the panel LT xp1 = xp - (sp * (h + grout)); yp1 = yp - 0; // --for future dev // sanity check in case user has clicked too close to the edge if (xp1-(bSize/2) < 0 || yp1-(bSize/2) < 0) exit("Try again, too close to the edge"); if (xp1+(bSize/2) > h || yp1+(bSize/2) > h) exit("Try again, too close to the edge"); } setBatchMode(true); // border will be white if colorChoice is True if (colorChoice) { if (bitDepth() == 8) setColor(255); if (bitDepth() == 24) setColor(255,255,255); if (bitDepth() == 16) setColor(65535); } else { setColor(getValue("color.foreground")); } if (vChoice == "vert") { if (corner == "RT" || corner == "RB") { dStartx = w - dSize; } else if (corner == "LT" || corner == "LB") { dStartx = 0; } // do the copy/pasting for (i=0; i