Apply Custom Layout to Image in DigitalMicrograph GMS3 - dm-script

I have an image in DigitalMicrograph GMS3 (v 3.21.1374.0) which i have applied a custom databar to (trying to learn how to do this via script here: add / apply custom databar to image in DigitalMicrograph GMS3)
I have a custom layout that I can add manually by doing the following:
Right click on the image
Hover on layout (in context menu)
Left click "Apply Layout..."
Select the custom layout in dialog that pops up (the one I want is called "CheckLayout")
Click OK
How do I do this with a script? I know how to get the image and the imagedisplay objects but that is as far as I get.
//main - get front image and apply custom layout
image Img := GetFrontImage()
imageDisplay imgDisplay = Img.ImageGetImageDisplay(0)
//apply custom layout to image here
Any ideas?

The layout is a property of an ImageDocument not an image. The correct way of doing this (provided there exists a layout of name 'MyLayout') is:
ImageDocument doc = GetFrontImageDocument()
doc.ImageDocumentApplyLayout("MyLayout")
You might additionally be interested in the commands:
void ImageDocumentApplyLayout( ImageDocument, String )
void ImageDocumentRemoveDatabar( ImageDocument )
Number ImageDocumentGetLayoutCount( ImageDocument )
String ImageDocumentGetLayoutName( ImageDocument, Number )
as used in
ImageDocument doc = GetFrontImageDocument()
number nLO = doc.ImageDocumentGetLayoutCount()
Result( "\n Layouts in document:" + nLO )
For( number i=0; i<nLO; i++)
{
string layoutName = doc.ImageDocumentGetLayoutName(i)
Result( "\n\t"+i+":"+layoutName)
}

Related

what is the difference between DeleteImage() and closeImage()?

If I use DeleteImage() within a thread versus CloseImage(), there seems to be a difference - but I can only guess. Does anyone have a clear definition?
More detail:
Within the thread, an image A has an ROI. If the user deletes the ROI, I also want to close the image A, but still use it again later in the thread.
It seems that when I use A.deleteImage(), I have to redefine that image, whereas if I use A.CloseImage() - I don't.
It looks like that is what is happening, but if anyone knows for sure, please let me know.
Thanks
In order to undestand the commands you need to understand how memory objects are managed.
Anything will remain a valid memory object as long as there is a valid reference to it.
In case of images, this tanslates to:
An image will stay in memory as long as at least one of the following
is true:
The image is displayed on the screen
A script variable points to the image
Any other DM routine has a variable that points to the image
A single image can have multiple of the above conditions fulfilled at the same time. The only way to remove an image from memory is, to ensure all references to it are removed.
For displayed images this means to "close" the display. As a user, you would click the "X" of the window. The same functionality is invoked by the script command CloseImage(). Note that using this command on an image which isn't displayed, doesn't do anything. Note further, that closing an image does not remove any variables or their references to this image.
For script variables this mean you somehow have to "unlink" the variable from the image. (The opposite from using := to assing it.). This is done with the DeleteImage() command. Alternatively, one could also direclty assign the variable to the NULL-pointer as in img := NULL
For held references from DM there is nothing you can do, and you shouldn't. If a certain routine requires an image to be there, it will remain. You may be able to close the Display, but you can never remove it. That's why you can often 'find' images, and even show them using their label. Camera refernece images are a good example for this, but there are others as well.
Visually:
With the explanation given above, you should be able to understand the different behavior in the following examples:
void CloseTest( number ShowItFirst )
{
image img := realImage( "Test", 4, 100, 100 )
Result( "\n Assignment: Image is valid:" + img.ImageIsValid() )
if ( ShowItFirst )
{
img.ShowImage()
Result( "\n Displaying: Image is valid:" + img.ImageIsValid() )
}
img.CloseImage()
Result( "\n Closing: Image is valid:" + img.ImageIsValid() )
img.ShowImage()
Result( "\n Displaying: Image is valid:" + img.ImageIsValid() )
}
void DeleteTest( number ShowItFirst )
{
image img := realImage( "Test", 4, 100, 100 )
Result( "\n Assignment: Image is valid:" + img.ImageIsValid() )
if ( ShowItFirst )
{
img.ShowImage()
Result( "\n Displaying: Image is valid:" + img.ImageIsValid() )
}
img.DeleteImage() // This is the same as: img := NULL
Result( "\n Deleting: Image is valid:" + img.ImageIsValid() )
// img.ShowImage() // This fails, because image is no longer valid!
}
It should now also be clear, why one can use CloseImage( A ) but not DeleteImage( A ) for a displayed image of label A:
The first command only wants to close the image display of the image which is referenced by the label. The second, however, wants to 'unlink' the script variable from the image. But the label 'A' is not a script-variable!

Adobe Photoshop Scripting - How to Select Bounding Box Around Current Selection?

Does anyone know whether it's possible, in Photoshop extend script, to convert an irregular selection (e.g. magic wand tool selection) into a rectangular selection encompassing the top, left, bottom and right bounds of the selection?
Here it is, I have documented the code so you can modify it later if you need. Also, check page 166 and following of Photoshop's JS reference manual, you may read more about selections - you can set feather, extend/intersect/etc. the selection if you need to.
Made for CS6, should work with latter.
#target photoshop
if (documents.length == 0) {
alert("nothing opened");
} else {
// start
//setup
var file = app.activeDocument;
var selec = file.selection;
//run
var bnds = selec.bounds; // get the bounds of current selection
var // save the particular pixel values
xLeft = bnds[0],
yTop = bnds[1],
xRight = bnds[2],
yBottom = bnds[3];
var newRect = [ [xLeft,yTop], [xLeft,yBottom], [xRight,yBottom], [xRight,yTop] ]; // set coords for selection, counter-clockwise
selec.deselect;
selec.select(newRect);
// end
}

Add a footer to an exported OxyPlot plot

I am using OxyPlot to export plots.
When I export them, I want to add a footer to these plots with information like the path it is saved, a time-stamp, and so on...
Right now I am doing this by creating an extra X-axis on a different position-tier and then setting the sizes of all ticks and labels to zero except for the title font-size.
This works, but as you might imagine, this is quite hacky and does not look that good (as you cannot set for example the aligning).
So my question is, is there a possibility to add such a footer to the exported plot?
EDIT:
var xAxis = new OxyPlot.Axes.LinearAxis
{
Position = AxisPosition.Bottom,
PositionTier = 1,
Title = "Footer: i.e. path to my file",
MinorTickSize = 0.0,
MajorTickSize = 0.0,
FontSize = 0.0,
TitleFontSize = 12,
AxisDistance = 10
};
This is the workaround I mentioned.
I create an axis at position-tier 1, which is below the first one and then disable all visuals of it except the title.
And in the end I add it to my plotmodel pm.Axes.Add(xAxis).
To export my plotmodel I use PdfExporter like this:
using (var stream = File.Create(testFile.pdf))
{
PdfExporter.Export(pm, stream, 800, 500);
}
Greetings
Chriz
Just had to do the same thing with my project and thought I'd share how I managed it for anyone else in need of a footer.
I couldn't find any built in OxyPlot methods to add a header or footer but if you use OxyPlot.PDF it's built on top of PDFSharp and you have more options to customize your PDF export.
Remove any previous reference to OxyPlot.Pdf in your project.
Download OxyPlot.Pdf source code from: https://github.com/oxyplot/oxyplot
In your project in VS, right click your solution in 'Solution Explorer' and Add Existing Project.
Navigate to the downloaded source code and add OxyPlot.Pdf.csproj
Right click your project and Add Reference
Select 'Projects' on the left and check the box for OxyPlot.Pdf on the right. Hit OK.
Check that it's working by building and running project.
Go to PdfRenderContext.cs file and find the PdfRenderContext method near the top.
Add the code below then build and run your project.
This code creates a MigraDoc Document and then merges it with the OxyPlot PdfDocument.
public PdfRenderContext(double width, double height, OxyColor background)
{
//*** Original Code - Don't change **//
this.RendersToScreen = false;
this.doc = new PdfDocument();
var page = new PdfPage { Width = new XUnit(width), Height = new XUnit(height) };
this.doc.AddPage(page);
this.g = XGraphics.FromPdfPage(page);
if (background.IsVisible())
{
this.g.DrawRectangle(ToBrush(background), 0, 0, width, height);
}
//*** New Code to add footer **//
Document myDoc = new Document();
Section mySection = myDoc.AddSection();
Paragraph footerParagraph = mySection.Footers.Primary.AddParagraph();
footerParagraph.AddText(DateTime.Now.ToShortDateString());
footerParagraph.Format.Alignment = ParagraphAlignment.Right;
MigraDoc.Rendering.DocumentRenderer docRenderer = new MigraDoc.Rendering.DocumentRenderer(myDoc);
docRenderer.PrepareDocument();
docRenderer.RenderObject(g, XUnit.FromInch(9.5), XUnit.FromInch(8), "1in", footerParagraph);
}
When you export the PDF a date stamp is now added to the lower right corner of the PDF. Note that I was working with landscape 8.5x11 inch paper so you may need to change position if you don't see it on the plot. Upper left corner is 0,0. Once it's working, build the OxyPlot.Pdf project to create the dll and then you can add it as a reference to your project and remove the source code.
Result:

Adding Image to Xaml not rendering with given margin

for (int i = 0; i < length; i++)
{
Image img1 ;
img1 = null;
img1= new Image();
img1.Height = snhei;
img1.Width = snwid;
BitmapImage BitImg = new BitmapImage(new Uri("/Assets/midtail.png", UriKind.Relative));`
img1.VerticalAlignment = VerticalAlignment.Top;
img1.HorizontalAlignment = HorizontalAlignment.Left;
img1.Source = BitImg;
img1.Stretch = Stretch.Fill;
img1.Name = "mid" + i.ToString() ;
img1.Margin = new Thickness(image_width*i, 0, 0, 0);
stackp.Children.Add(img1);
}
after running i get first image at 0,0
then it is render the one image_width below
The problem is your container. The StackPanel will, as it name indicates, try to stack the images. Then you apply the margin, moving the picture farther away.
You have two solutions, depending on what you want:
If you just want the images to be displayed side by side, set the Orientation property of your StackPanel to Horizontal. Then, remove your line of code that sets the margin, since the positioning is automatically handled by the StackPanel
If you still want to position the pictures manually, then you have to use another type of container. Replace your StackPanel by a Canvas or a Grid.

iTextSharp Overlay Image

Hi guys I have an instance where I have a logo image as part of some artwork..
If a user uploads a new logo I have a form field which is larger than the default logo.
I then use that form field to position the new image.
The problem is I need to set the background colour of that form field to white so that it covers the old logo in the event that the new image is smaller than the old logo..
what I have done is:
foreach (var imageField in imageReplacements)
{
fields.SetFieldProperty(imageField.Key, "bgcolor", iTextSharp.text.Color.WHITE, null);
fields.RegenerateField(imageField.Key);
PdfContentByte overContent = stamper.GetOverContent(imageField.Value.PageNumber);
float[] logoArea = fields.GetFieldPositions(imageField.Key);
if (logoArea != null)
{
iTextSharp.text.Rectangle logoRect = new iTextSharp.text.Rectangle(logoArea[1], logoArea[2], logoArea[3], logoArea[4]);
var logo = iTextSharp.text.Image.GetInstance(imageField.Value.Location);
if (logo.Width >= logoRect.Width || logo.Height >= logoRect.Height)
{
logo.ScaleToFit(logoRect.Width, logoRect.Height);
}
logo.Alignment = iTextSharp.text.Image.ALIGN_LEFT;
logo.SetAbsolutePosition(logoRect.Left, logoArea[2] + (logoRect.Height - logo.ScaledHeight) / 2);
// left: logoArea[3] - logo.ScaledWidth + (logoRect.Width - logo.ScaledWidth) / 2
overContent.AddImage(logo);
}
}
The problem with this is that the background colour of the field is set to white and the image then doesn't appear.. i remove the SetFieldProperty and RegenerateField commands and the image replacement works fine..
is there a way to set a stacking order on layers?
Annotations (such as form fields) are always on top of page contents. Annotation Z order is just the order of the annotations array on a given page.
Page content Z order is just the order everything appears in the content stream. New drawing operators go on top of proceeding operators.
If you want to cover your old image, draw a white box over it and then draw the new logo over top that. No need to worry about annotations.
Actually, all you really need to do is not set the background color of the imageField. You're already scaling the new logo to match the size of the old one.
However, if you really must draw that white box, it's fairly simple:
overContent.setColorFill(iTextSharp.text.Color.WHITE);
overContent.rectangle( logoRect );
overcontent.fill();