The following journal will create a screenshot of the current NX graphics window (using a white background) and place the resulting image on the Windows clipboard. After running the journal, you can immediately paste the image into another application (email message, powerpoint deck, paint program, etc.). The resulting image is cropped,except for a user-specified amount of white space around the image.
'NXJournaling.com
'August 11, 2015
'Export a screenshot from NX with a white background
'place the image data on the Windows clipboard so you can immediately
'"paste" the image to a new location (email, powerpoint, etc).
'This version will crop the image and provide a user supplied amount of "whitespace" on each side of the image.
Option Strict Off
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF
Module Module2
Dim theSession As Session = Session.GetSession()
Dim theUfSession As UFSession = UFSession.GetUFSession()
Sub Main()
If IsNothing(theSession.Parts.BaseWork) Then
'active part required
Return
End If
Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()
Dim tempScreenshot As String
Dim tempLocation As String = IO.Path.GetTempPath
tempScreenshot = IO.Path.Combine(tempLocation, "NXscreenshot.png")
Try
ExportScreenshot(tempScreenshot)
Catch ex As Exception
lw.WriteLine("Error: " & ex.Message)
Return
End Try
'crop the screenshot (filename, amount of whitespace on each side of image [integer value, number of pixels])
CropScreenshot(tempScreenshot, 5)
'copy image to clipboard
Dim theImage As Bitmap = CType(Image.FromFile(tempScreenshot), Bitmap)
Clipboard.SetImage(theImage)
lw.Close()
End Sub
Sub ExportScreenshot(ByVal filename As String)
'save user preference for visibility of WCS, triad, view name, and view border
Dim wcsVisible As Boolean = theSession.Parts.BaseDisplay.WCS.Visibility
Dim triadVisible As Integer = theSession.Preferences.ScreenVisualization.TriadVisibility
Dim displayModelViewNames As Boolean = theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewNames
Dim displayModelViewBorders As Boolean = theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewBorders
'turn off the WCS, triad, view name, and view border
theSession.Parts.BaseDisplay.WCS.Visibility = False
theSession.Preferences.ScreenVisualization.TriadVisibility = 0
theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewBorders = False
theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewNames = False
Try
theUfSession.Disp.CreateImage(filename, UFDisp.ImageFormat.Png, UFDisp.BackgroundColor.White)
Catch ex As Exception
MsgBox(ex.Message & ControlChars.NewLine & _
"'" & filename & "' could not be created")
Throw New Exception("Screenshot could not be created")
Finally
'reset visibility of WCS, triad, view name, and view border to user's preference
theSession.Parts.BaseDisplay.WCS.Visibility = wcsVisible
theSession.Preferences.ScreenVisualization.TriadVisibility = triadVisible
theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewBorders = displayModelViewBorders
theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewNames = displayModelViewNames
End Try
End Sub
Sub CropScreenshot(ByVal theImageFile As String, ByVal borderWidth As Integer)
'borderWidth = whitespace to leave around the border of the image
Dim original As New Bitmap(theImageFile)
Dim JPGminX As Integer = original.Width
Dim JPGminY As Integer = original.Height
Dim JPGmaxX As Integer = 0
Dim JPGmaxY As Integer = 0
Dim bckgrndColor As Color = Color.White
For y As Integer = 0 To original.Height - 1
For x As Integer = 0 To original.Width - 1
If original.GetPixel(x, y).ToArgb <> bckgrndColor.ToArgb Then
If x < JPGminX Then
JPGminX = x
ElseIf x > JPGmaxX Then
JPGmaxX = x
End If
If y < JPGminY Then
JPGminY = y
ElseIf y > JPGmaxY Then
JPGmaxY = y
End If
End If
Next
Next
Dim rect As New Rectangle(JPGminX, JPGminY, JPGmaxX - JPGminX, JPGmaxY - JPGminY)
Dim cropped As Bitmap = original.Clone(rect, original.PixelFormat)
'create new image sized to add border around cropped image
Dim border As New Bitmap(cropped.Width + (2 * borderWidth), cropped.Height + (2 * borderWidth), cropped.PixelFormat)
'create a new graphics object
Dim g As Graphics = Graphics.FromImage(border)
'fill the graphics object with white color (for background)
Using myBrush As Brush = New SolidBrush(Color.White)
g.FillRectangle(myBrush, 0, 0, border.Width, border.Height)
End Using
'calculate position to place cropped image onto background image
Dim xImage As Integer = border.Width - cropped.Width - borderWidth
Dim yImage As Integer = border.Height - cropped.Height - borderWidth
'draw cropped image onto white background
g.CompositingMode = Drawing2D.CompositingMode.SourceOver
g.DrawImage(cropped, New Drawing.Point(xImage, yImage))
'dispose of unneeded graphics objects
original.Dispose()
cropped.Dispose()
g.Dispose()
'save our finished graphics file
border.Save(theImageFile, Imaging.ImageFormat.Png)
End Sub
Public Function GetUnloadOption(ByVal dummy As String) As Integer
'Unloads the image immediately after execution within NX
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
End Function
End Module
Comments
code speed
This is great functionality but it's slow. Has anyone created something in c# or any tips to make this execute faster?
nxvicente
re: code speed
I agree that it is a bit slow, but porting directly to C# (or any other language, for that matter) won't provide a significant improvement. The bottleneck is the algorithm used to search through the image. To make a real improvement, we'd need to find a faster way to search through the image and remove the whitespace.
That said, there is something you can do to provide a small speed improvement without changing the algorithm: resize the graphics window close to the desired final size of the image and do a 100% 'fit view' before running the journal. This will minimize the amount of whitespace that the journal needs to search through and trim away.
Very usefull, thank you very
Very usefull, thank you very much
Hi, if you want a faster
Hi, if you want a faster cropping method, using a third parts app:
google it: imagemagick crop
I used it many times, fast and easy.
-------
kukelyk
change Image Size
Dear all,
This code is very usefull, and now a colleague asked if it would be possible to add a option to have the copied image a smaller size then the original.
E.g. 450 pixels wide
Is there anybody who could modify this code to have this image resized available?
Best regards.
P.
I have modified this journal
I have modified this journal some weeks ago to copy a high resolution screenshot to the clipboard. I have added also the possibility to reduce the width to an user defined size:
'Original from NXJournaling.com
'Export a HIGH RESOLUTION screenshot from NX with a white background
'place the image data on the Windows clipboard so you can immediately
'"paste" the image to a new location (email, powerpoint, etc).
'This version will crop the image and provide a user supplied amount of "whitespace" on each side of the image.
'The Image size can be reduced to a uderdefined value
Option Strict Off
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF
Module Module2
Dim theSession As Session = Session.GetSession()
Dim theUfSession As UFSession = UFSession.GetUFSession()
Dim workPart As NXOpen.Part = theSession.Parts.Work
Dim displayPart As NXOpen.Part = theSession.Parts.Display
Sub Main()
If IsNothing(theSession.Parts.BaseWork) Then
'active part required
Return
End If
Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()
Dim tempScreenshot As String
Dim tempLocation As String = IO.Path.GetTempPath
tempScreenshot = IO.Path.Combine(tempLocation, "NXscreenshot.png")
Try
ExportScreenshot(tempScreenshot)
Catch ex As Exception
lw.WriteLine("Error: " & ex.Message)
Return
End Try
'crop the screenshot (filename, amount of whitespace on each side of image [integer value, number of pixels])
CropScreenshot(tempScreenshot, 5)
'copy image to clipboard
Dim theImage As Bitmap = CType(Image.FromFile(tempScreenshot), Bitmap)
Clipboard.SetImage(theImage)
'Resize the Image to new width
Dim newWidth As Integer = 400
ResizeImageFromClipboard(newWidth)
lw.Close()
End Sub
Sub ExportScreenshot(ByVal filename As String)
'save user preference for visibility of WCS, triad, view name, and view border
Dim wcsVisible As Boolean = theSession.Parts.BaseDisplay.WCS.Visibility
Dim triadVisible As Integer = theSession.Preferences.ScreenVisualization.TriadVisibility
Dim displayModelViewNames As Boolean = theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewNames
Dim displayModelViewBorders As Boolean = theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewBorders
'turn off the WCS, triad, view name, and view border
theSession.Parts.BaseDisplay.WCS.Visibility = False
theSession.Preferences.ScreenVisualization.TriadVisibility = 0
theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewBorders = False
theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewNames = False
Try
'theUfSession.Disp.CreateImage(filename, UFDisp.ImageFormat.tiff, UFDisp.BackgroundColor.White)
'######################### Create High Res Image #########################
Dim studioImageCaptureBuilder1 As NXOpen.Display.StudioImageCaptureBuilder = Nothing
studioImageCaptureBuilder1 = workPart.Views.CreateStudioImageCaptureBuilder()
studioImageCaptureBuilder1.DrawingSizeEnum = NXOpen.Display.StudioImageCaptureBuilder.DrawingSizeEnumType.Isoa0
studioImageCaptureBuilder1.DpiEnum = NXOpen.Display.StudioImageCaptureBuilder.DPIEnumType.Dpi150
studioImageCaptureBuilder1.AASamplesEnum = NXOpen.Display.StudioImageCaptureBuilder.AASamplesEnumType.Sam8X
studioImageCaptureBuilder1.NativeFileBrowser = filename
studioImageCaptureBuilder1.BackgroundOption = NXOpen.Display.StudioImageCaptureBuilder.BackgroundOptions.CustomColor
Dim custombackgroundcolor1(2) As Double
custombackgroundcolor1(0) = 1.0
custombackgroundcolor1(1) = 1.0
custombackgroundcolor1(2) = 1.0
studioImageCaptureBuilder1.SetCustomBackgroundColor(custombackgroundcolor1)
Dim nXObject13 As NXOpen.NXObject = Nothing
nXObject13 = studioImageCaptureBuilder1.Commit()
studioImageCaptureBuilder1.Destroy()
'#####################
Catch ex As Exception
MsgBox(ex.Message & ControlChars.NewLine & _
"'" & filename & "' could not be created")
Throw New Exception("Screenshot could not be created")
Finally
'reset visibility of WCS, triad, view name, and view border to user's preference
theSession.Parts.BaseDisplay.WCS.Visibility = wcsVisible
theSession.Preferences.ScreenVisualization.TriadVisibility = triadVisible
theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewBorders = displayModelViewBorders
theSession.Parts.BaseDisplay.Preferences.NamesBorderVisualization.ShowModelViewNames = displayModelViewNames
End Try
End Sub
Sub CropScreenshot(ByVal theImageFile As String, ByVal borderWidth As Integer)
'borderWidth = whitespace to leave around the border of the image
Dim original As New Bitmap(theImageFile)
Dim JPGminX As Integer = original.Width
Dim JPGminY As Integer = original.Height
Dim JPGmaxX As Integer = 0
Dim JPGmaxY As Integer = 0
Dim bckgrndColor As Color = Color.White
For y As Integer = 0 To original.Height - 1
For x As Integer = 0 To original.Width - 1
If original.GetPixel(x, y).ToArgb <> bckgrndColor.ToArgb Then
If x < JPGminX Then
JPGminX = x
ElseIf x > JPGmaxX Then
JPGmaxX = x
End If
If y < JPGminY Then
JPGminY = y
ElseIf y > JPGmaxY Then
JPGmaxY = y
End If
End If
Next
Next
Dim rect As New Rectangle(JPGminX, JPGminY, JPGmaxX - JPGminX, JPGmaxY - JPGminY)
Dim cropped As Bitmap = original.Clone(rect, original.PixelFormat)
'create new image sized to add border around cropped image
Dim border As New Bitmap(cropped.Width + (2 * borderWidth), cropped.Height + (2 * borderWidth), cropped.PixelFormat)
'create a new graphics object
Dim g As Graphics = Graphics.FromImage(border)
'fill the graphics object with white color (for background)
Using myBrush As Brush = New SolidBrush(Color.White)
g.FillRectangle(myBrush, 0, 0, border.Width, border.Height)
End Using
'calculate position to place cropped image onto background image
Dim xImage As Integer = border.Width - cropped.Width - borderWidth
Dim yImage As Integer = border.Height - cropped.Height - borderWidth
'draw cropped image onto white background
g.CompositingMode = Drawing2D.CompositingMode.SourceOver
g.DrawImage(cropped, New Drawing.Point(xImage, yImage))
'dispose of unneeded graphics objects
original.Dispose()
cropped.Dispose()
g.Dispose()
'save our finished graphics file
border.Save(theImageFile, Imaging.ImageFormat.Png)
End Sub
Public Function GetUnloadOption(ByVal dummy As String) As Integer
'Unloads the image immediately after execution within NX
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
End Function
Sub ResizeImageFromClipboard(newWidth As Integer)
If Clipboard.ContainsImage() Then
Dim originalImage As Image = Clipboard.GetImage()
Dim newHeight As Integer = CInt(originalImage.Height * (newWidth / originalImage.Width))
Dim resizedImage As New Bitmap(originalImage, new Size(newWidth, newHeight))
Clipboard.SetImage(resizedImage)
Else
MessageBox.Show("Clipboard does not contain an image.")
End If
End Sub
End Module