Rhino.Display.ViewCapture.CaptureToBitmap over Windows RDP

Hello Rhino friends :wave: I’m running into an issue when trying to capture a viewport via RhinoCommon method CaptureToBitmap while using Windows RDP. It returns a blank black image, I’m assuming this is well known? Even the command ViewCaptureToFile seems to have issues with this over RDP.

I saw this discussion about openGL over RDP and I’m wondering if it’s even possible to view capture on an RDP PC?

Here is my python code below if you want to try and reproduce. I’m just wondering if anyone has a workaround for getting this to work even if it’s relatively hacky? :thinking:

Cheers!

Special thanks to @AndersDeleuran for the capture method from this post: A way to screencapture and send to print with one button? - #6 by AndersDeleuran

import rhinoscriptsyntax as rs
import Rhino
from System.Drawing import Bitmap
from System.Drawing.Imaging import ImageFormat
import os
import traceback



def capture_active_view(save_filepath, width, height):
    """ 
    Captures the active viewport and saves it to the specified filepath
    
    Args
    ----------
        save_filepath (str): The filepath to save the image to
        scale (float): The scale of the image relative to the viewport size (1.0 = 100%)

    Returns:
    ----------
        str: The filepath of the saved image
        None: If the image was not saved successfully

    """

    active_view = Rhino.RhinoDoc.ActiveDoc.Views.ActiveView

    # capture image
    try:
        view_capture = Rhino.Display.ViewCapture(
            DrawAxes = False,
            DrawGrid = False,
            DrawGridAxes = False,
            Height = height,
            Width = width,
            ScaleScreenItems = False
            )
        
        image_capture = view_capture.CaptureToBitmap(active_view)
        Bitmap.Save(image_capture, save_filepath, ImageFormat.Png)

        if os.path.exists(save_filepath):
            return save_filepath
        else:
            return None
    except Exception as e:
        tb = traceback.format_exc()
        rs.MessageBox("An error occurred capturing the image: {}\n\nTraceback:\n{}".format(e, tb), 0|16, "Viewport Capture Error")
        exit()
        
        
if __name__ == "__main__":
    width = 800
    height = 800
    computer_name = 'your_pc_name'
    image_path = r'C:\Users\{}\Desktop\test_img.png'.format(computer_name)
    
    saved_filepath = capture_active_view(image_path, width, height)
    
    if os.path.exists(saved_filepath):
        rs.MessageBox("Image succesfully created: {}".format(saved_filepath), 0|64, "Image Saved")
        


1 Like

I’m assuming there’s not really a workaround given Rhino doesn’t officially support RDP: Rhino - System Requirements

That is correct. All of the view capture code uses Rhino’s display architecture to generate a bitmap image. If the display for Rhino over RDP is not working well, then capturing will also not work well.

Thank you for the explanation that totally makes sense.

Hi @bfrederick

FWIW:
I resolved this by rendering an image, as that does work over RDP.

-Willem

1 Like

@Willem interesting thank you! :pray:

Just so i’m clear, are you suggesting using the RenderPipeline.Render method?

I implemented this through scripted commands:

def render_web_preview(preview_path):

    rs.UnselectAllObjects()

    rs.ViewProjection(mode=2)
    rs.Command('!-ViewportProperties CameraTarget w-10,-10,10 w0,0,0 _Enter')
    rs.Command('!ZEA ')

    # RENDERING
    sc.doc.Lights.Skylight.Enabled = True
    # sc.doc.GroundPlane.AutoAltitude = True
    sc.doc.GroundPlane.Enabled = False

    rs.Command('!_-DocumentProperties Render Resolution Type=Custom Width=640 Height=360 _Enter _Enter _Enter')
    rs.Command('!_Render ')
    rs.Command('!_-SaveRenderWindowAs "{}" '.format(preview_path))
    rs.Command('!_-CloseRenderWindow ')

    sc.doc.Lights.Skylight.Enabled = False
1 Like

Thank you @Willem this is super helpful!

1 Like