imagemon (lx_imagemon.hpp)

From The Foundry MODO SDK wiki
Jump to: navigation, search
There are security restrictions on this page


Image Source

Different monitor view instances may be set to target specific sources of images. Common sources might include clip items or rendered frames. This is stored in the viewport as the imageSource, and is written to the config as part of the viewport state. Only selection packets that also have this imageSource will be processed by the monitor.

The list of available image sources is defined in the configs, with the internal name of the source used as the key of an ImageMonitorSource hash. Usernames are stored in a separate message table with the key "ImageMonitorSource:<sourcename>.<lang>", where <sourcename> is the name of the source and <lang> is the language code as usual. The internal name is used in the selection packet to identify the source of the image, and monitor views will only process images from sources that match their own image source setting.

(1) Image Source Config Example
 <atom type="ImageMonitorSources">
   <hash type="ImageMonitorSource" key="renderWindow"/>
   <hash type="ImageMonitorSource" key="clips"/>
 </atom>
 
 <atom type="Messages">
   <hash type="Table" key="ImageMonitorSource:renderWindow.en_US">
     <hash type="T" key="ImageMonitorUserName">Render Window Images</hash>
     <hash type="T" key="ImageMonitorMonitorDesc">Images selected in the Render Window</hash>
   </hash>
 
   <hash type="Table" key="ImageMonitorSource:clip.en_US">
     <hash type="T" key="UserName">Clip Items</hash>
   </hash>
 </atom>

Selection Packet

The selection packet for the image monitor is an ILxImageID or ILxFrameBufferID buffer index pair and an optional image source name. The ILxImageID is the image to be analyzed by the monitor; if NULL, then the buffer index within the ILxFrameBufferID is to be used. The image source allows different monitors to look at different images from different parts of the system. For example, one viewport might be set to only monitor clip items, while another might be set to analyse images selected in the render window.

x1, y1, x2 and y2 define an area within the image to be analyzed. An extent of 0,0 to 1,1 indicates that the entire image should be analyzed.

The packet also contains an optional ILxImageProcessing object, which clients can use to set image processing operations that the image source will apply to the image for display to the user. The image processing object has its identifier set to the image source, which means that setting its properties will automatically send a notification to the image source, which in turn will apply said processing to the image. If the source doesn't support processing, this will be NULL. Note that although this is a read/write obejct, clients should really only use this for reading unless they are executing a command.

For speed, the packet may also contain a thumbnail image. This image already has image processing applied to it, and is large enough to be useful for monitor analysis. For example, render window sources provide a 256 pixel wide image. Clients should be able to handle cases where the thumbnail is NULL.

(2) SDK: LXtImageMonitorPacket struct
 ILxImageID               image;
 
 ILxFrameBufferID         frameBuffer;
 int                      bufferIndex;
 
 double                   x1, y1, x2, y2;
 
 ILxImageProcessingID     imageProc;
 
 ILxImageID               processedThumbnail;
 
 char                     imageSource[256];

Selection itself is divided into subtypes, which is what the image source is used for. Due to the fact that we're just passing around pointers to images, there is no conventional selection command (we don't have a good way to make those pointers into strings that isn't actually just the pointer as a string), and thus all selection is done through public function calls. The selection type itself is non-undoable, so this should be fine.

ILxImageMonitor

modo supports an extensible set of image analysis monitors. These are essentially blank canvases into which the plug-in can draw a monitor displaying an analysis of the image provided. Common monitors include histograms and vectorscopes.

(3) SDK: Declarations
 #define LXu_IMAGEMONITOR        "5ef021ed-a2e3-48d3-aba1-7cbb815f15b7"
 #define LXa_IMAGEMONITOR        "imagemonitor"

This is called with the image (ILxImageID) or frame buffer (ILxFrameBufferID) to be analyzed. The new image may be NULL if there is not currently an image to be analyzed, and it may be the same image as previously passed in if the image has changed for some reason. If imageToAnalyze is NULL, frameBufferToAnalyze may be non-NULL, in which case bufferIndex is the index of the specific buffer within the frame buffer to be analyzed. If both imageToAnalyze and frameBufferToAnalyze are NULL, no image is selected and the monitor should draw in a default or disabled style.

x1, y1, xc2 and y2 define a region within the image to analyze. If these are 0,0 and 1,1, then the entire image should be analyzed; otherwise, only the specified region should be analyzed.

The ILxImageProcessingRead object is also provided, although this may be NULL if processing options are not available. Clients should use this to read the properties in case they want to apply the effects of said options to the monitor's display; they should use commands to change the properties. It is important to note that the image/frame buffer will be a "clean", unprocessed image, and will not have any image processing options applied to it.

To avoid needing to process the full-sized image repeatedly on an ImageProcChanged() event, this method is also called with a smaller thumbnail image that already has processing applied. The image is large enough to be suitable for image analysis. Note that this may be NULL.

(4) SDK: ILxImageMonitor interface
         LXxMETHOD( LxResult,
 Image) (
         LXtObjectID               self,
         LXtObjectID               imageToAnalyze,
         LXtObjectID               frameBufferToAnalyze,
         int                       bufferIndex,
         double                    x1,
         double                    y1,
         double                    x2,
         double                    y2,
         LXtObjectID               imageProcessingRead,
         LXtObjectID               processedThumbnail);

This method is called when the properties of the ILxImageProcessingRead object have changed. Monitors can use this to refresh themselves using image/frame buffers and the ILxImageProcessingRead object provided to them through their Image() method. Note that Image() is also called with an updated processed thumbnail suitable for analysis whenever the image processing object changes.

(5) SDK: ILxImageMonitor interface
         LXxMETHOD( LxResult,
 ImageProcChanged) (
         LXtObjectID               self);

This returns the minimum and maximum aspect ratio for the monitor. The image provided (to draw the monitor into) will never exceed this aspect. This is useful for monitors like histograms that look better when laid out horizontally, but don't look like much when stretched vertically. If not implemented or if one of the values is set to 0, the aspect is unconstrained.

(6) SDK: ILxImageMonitor interface
         LXxMETHOD( LxResult,
 AspectRange) (
         LXtObjectID               self,
         double                   *minAspect,
         double                   *maxAspect,
         double                   *idealAspect);

This is called to draw the monitor into the ILxImageWriteID provided.

(7) SDK: ILxImageMonitor interface
         LXxMETHOD( LxResult,
 Draw) (
         LXtObjectID               self,
         LXtObjectID               imageForDrawing);

Image monitors accept images from an image source. The image source is set through the viewport, and is provided to the monitor through this method. Clients can use the image source string to execute commands that target the image source, respond to monitor-specific commands (like setting ranges for display) based on image source, and so on.

For example, a histogram monitor for the clip items image source might be embedded in the clip item's properties. A command to change the channels shown in the histogram might include the image source as an argument, so that just that monitor's channel option can be changed, without affecting the other histogram monitors, such as the one used by the Render Window histogram. This argument would also be used when querying the command for a value.

This method will be called whenever the image source changes. The server should make a copy of the string for future reference.

(8) SDK: ILxImageMonitor interface
         LXxMETHOD( LxResult,
 ImageSource) (
         LXtObjectID               self,
         const char               *source);

Mousing

We support limited mousing support through the use of the Mouse...() methods. We have a down/move/up cycle that occurs when the mouse button is clicked over the montior. The server is provided with the down x/y as well as the current x/y of the mosue relative to the top-left corner of the monitor. Only the left mouse button is supported at this time. The dimensions of the drawing monitor are also passed to each method.

(9) SDK: ILxImageMonitor interface
         LXxMETHOD( LxResult,
 MouseDown) (
         LXtObjectID               self,
         int                       startx,
         int                       starty,
         int                       w,
         int                       h );
 
         LXxMETHOD( LxResult,
 MouseMove) (
         LXtObjectID               self,
         int                       startx,
         int                       starty,
         int                       cx,
         int                       cy,
         int                       w,
         int                       h );
 
         LXxMETHOD( LxResult,
 MouseUp) (
         LXtObjectID               self,
         int                       startx,
         int                       starty,
         int                       cx,
         int                       cy,
         int                       w,
         int                       h );

We also support tracking, which is when the mouse is moving over the view but is not being clicked. TrackEnter() is called when the mouse moves into the monitor, and TrackExit() is called when the mouse leaves the monitor. Track() is moved while the mouse moves over the view with the current mouse coordinates and the size of the monitor.

(10) SDK: ILxImageMonitor interface
         LXxMETHOD( LxResult,
 MouseTrackEnter) (
         LXtObjectID               self);
 
         LXxMETHOD( LxResult,
 MouseTrack) (
         LXtObjectID               self,
         int                       cx,
         int                       cy,
         int                       w,
         int                       h );
 
         LXxMETHOD( LxResult,
 MouseTrackExit) (
         LXtObjectID               self);

Tooltips are also supported. As usual, the tooltip should be composed from a message table lookup. Returning LXe_NOTIMPL or any other failure code will result in no tooltip being displayed.

(11) SDK: ILxImageMonitor interface
         LXxMETHOD( LxResult,
 ToolTip) (
         LXtObjectID               self,
         int                       cx,
         int                       cy,
         int                       w,
         int                       h,
         char                     *buf,
         unsigned                  len);

Image Monitor Global Service

The global image monitor service provides a few utility functions to clients.

(12) SDK: Declarations
 #define LXu_IMAGEMONITORSERVICE "f59258f8-3e86-408f-9e92-f81a21d01bde"
 #define LXa_IMAGEMONITORSERVICE "imagemonitorservice"

As with all globals, the first method gets the ILxScriptQueryID interface for the system. This is not currently implemented.

(13) SDK: ILxImageMonitorService interface
         LXxMETHOD(  LxResult,
 ScriptQuery) (
         LXtObjectID              self,
         void                   **ppvObj);

These methods allow the server list to be walked, and allow a server to be looked up by name. When a COM object is returned, the client is responsible for releasing it as usual.

(14) SDK: ILxImageMonitorService interface
         LXxMETHOD(  LxResult,
 ServerCount) (
         LXtObjectID              self,
         int                     *count);
 
         LXxMETHOD(  LxResult,
 ServerByIndex) (
         LXtObjectID               self,
         int                       index,
         void                    **ppvObj);
 
         LXxMETHOD(  LxResult,
 ServerLookup) (
         LXtObjectID               self,
         const char               *name,
         void                    **ppvObj);

These methods return the name and username of a server given an index.

(15) SDK: ILxImageMonitorService interface
         LXxMETHOD(  LxResult,
 ServerNameByIndex) (
         LXtObjectID               self,
         int                       index,
         const char              **name);
 
         LXxMETHOD(  LxResult,
 ServerUserNameByIndex) (
         LXtObjectID               self,
         int                       index,
         const char              **name);

These can be used to get a list of image sources names, as defined through the config system.

(16) SDK: ILxImageMonitorService interface
         LXxMETHOD(  LxResult,
 SourceCount) (
         LXtObjectID              self,
         int                     *count);
 
         LXxMETHOD(  LxResult,
 SourceNameByIndex) (
         LXtObjectID               self,
         int                       index,
         const char              **name);
 
         LXxMETHOD(  LxResult,
 SourceUserNameByIndex) (
         LXtObjectID               self,
         int                       index,
         const char              **username);

Clients can use this to change the current image in an image source. This in turn will ask associated views to analyze the new image. Either the image (ILxImageID) or frameBuffer (ILxFrameBufferID) and bufferIndex should be set; if they're NULL, then no image is to be analyzed. x1/y1 and x2/y2 define a window into the image to the analyzed; if 0,0 and 1,1, the entire image is analyzed. Images are set for a specific image source, and thus only affects views monitoring that source. Note that imageProc is an object with an ILxImageProcessing interface, and is optional. processedThumbnail is also optional, but is recommended.

(17) SDK: ILxImageMonitorService interface
         LXxMETHOD(  LxResult,
 SetImage) (
         LXtObjectID              self,
         const char              *imageSource,
         LXtObjectID              image,
         LXtObjectID              frameBuffer,
         int                      bufferIndex,
         double                   x1,
         double                   y1,
         double                   x2,
         double                   y2,
         LXtObjectID              imageProc,
         LXtObjectID              processedThumbnail );

Clients can use this to get the current image from an image source. If a pointer is NULL, that property won't be returned.

(18) SDK: ILxImageMonitorService interface
         LXxMETHOD(  LxResult,
 GetImage) (
         LXtObjectID               self,
         const char               *imageSource,
         void                    **ppvObj_image,
         void                    **ppvObj_frameBuffer,
         int                      *bufferIndex,
         double                   *x1,
         double                   *y1,
         double                   *x2,
         double                   *y2,
         void                    **ppvObj_imageProc,
         void                    **ppvObj_processedThumbnail );

This can also be returned as a packet.

(19) SDK: ILxImageMonitorService interface
         LXxMETHOD(  LxResult,
 GetImagePacket) (
         LXtObjectID                       self,
         const char                       *imageSource,
         const LXtImageMonitorPacket     **packet );

Sometimes image analysis can take a while. This utility can be used to tell all views with a particular image source to ask their server to redraw their view.

If immediate is true, the view will be redrawn immediately. This is useful for interaction operations using the mousing methods of the monitor. If false, the view will be updated during at the normal redrawing time.

(20) SDK: ILxImageMonitorService interface
         LXxMETHOD(  LxResult,
 RefreshViews) (
         LXtObjectID              self,
         const char              *imageSource,
         int                      immediate );

(21) User Service Class: ImageMonitorService method
         LxResult
 RefreshViews (
         const std::string        imageSource,
         bool                     immediate)
 {
         return CLxLoc_ImageMonitorService::RefreshViews (imageSource.c_str (), immediate);
 }

Empty ImageMonitor service Python user class.

(22) PY: ImageMonitorService method
 pass

Notifier "notifier.imagemonitor.source"

We also define a notifier, "notifier.imagemonitor.source", which sends a notification whenever the image source (as provided through the notifier's argument string) changes with the flags provided. For example, "renderWindow+vd" will send DISABLE and VALUE notifications when the "renderWindow" image source changes.

(23) SDK: Declarations
 #define LXsIMAGEMONITOR_SOURCE_NOTIFIER "notifier.imagemonitor.source"

Notifier "notifier.imageproc"

Another notifier is used to listen for changes to an ILxImageProcessing object, as described in lx_rndjob.hpp. The notifier's argument format is:

<identifier> <attribute>+vdlt

<identifier> is the identifier string (often the an image source) set in the processing object. <attribute> is the specific attribute to listen for, as defined in the text hitns array below. +vdlt are any combination of the LXfCMDNOTIFY_ hints, indicating that when the specific attribute changes, it should send a value, label, disable or datatype invalidation to the UI.

(24) SDK: Declarations
         #define LXsIMAGEPROC_NOTIFIER   "notifier.imageproc"
 
 static LXtTextValueHint  notifierImageProcEventHints[] = {                                      // Events as a text hints array
         /* Event */
         LXiIMAGEPROC_EVENT_CHANGED_SOURCE_IMAGE_GAMMA,                  "sourceImageGamma",
         LXiIMAGEPROC_EVENT_CHANGED_SAVE_PROCESSED,                      "saveProcessed",
         LXiIMAGEPROC_EVENT_CHANGED_BLOOM_ENABLED,                       "bloomEnabled",
         LXiIMAGEPROC_EVENT_CHANGED_BLOOM_THRESHOLD,                     "bloomThreshold",
         LXiIMAGEPROC_EVENT_CHANGED_BLOOM_RADIUS,                        "bloomRadius",
 
         LXiIMAGEPROC_EVENT_CHANGED_VIGNETTE_AMOUNT,                     "vignAmt",
 
         LXiIMAGEPROC_EVENT_CHANGED_RESPECT_RENDER_VIEW_GAMMA_PREF,      "respectRenderViewGammaPref",
 
         LXiIMAGEPROC_EVENT_CHANGED_INPUT_BLACK_LEVEL,                   "inputBlackLevel",
         LXiIMAGEPROC_EVENT_CHANGED_INPUT_GRAY_LEVEL,                    "inputGrayLevel",
         LXiIMAGEPROC_EVENT_CHANGED_INPUT_WHITE_LEVEL,                   "inputWhiteLevel",
 
         LXiIMAGEPROC_EVENT_CHANGED_INPUT_MIN_RGB_LEVEL,                 "inputMinRGBLevel",
         LXiIMAGEPROC_EVENT_CHANGED_INPUT_GRAY_RGB_LEVEL,                "inputGrayRGBLevel",
         LXiIMAGEPROC_EVENT_CHANGED_INPUT_MAX_RGB_LEVEL,                 "inputMaxRGBLevel",
 
         LXiIMAGEPROC_EVENT_CHANGED_TONE_MAPPING,                        "toneMapping",
         LXiIMAGEPROC_EVENT_CHANGED_HUE_OFFSET,                          "hueOffset",
         LXiIMAGEPROC_EVENT_CHANGED_SATURATION,                          "saturation",
         LXiIMAGEPROC_EVENT_CHANGED_COLORIZATION,                        "colorization",
         LXiIMAGEPROC_EVENT_CHANGED_TARGET_COLOR,                        "targetColor",
 
         LXiIMAGEPROC_EVENT_CHANGED_OUTPUT_BLACK_LEVEL,                  "outputBlackLevel",
         LXiIMAGEPROC_EVENT_CHANGED_OUTPUT_WHITE_LEVEL,                  "outputWhiteLevel",
 
         LXiIMAGEPROC_EVENT_CHANGED_OUTPUT_MIN_RGB_LEVEL,                "outputMinRGBLevel",
         LXiIMAGEPROC_EVENT_CHANGED_OUTPUT_MAX_RGB_LEVEL,                "outputMaxRGBLevel",
 
         LXiIMAGEPROC_EVENT_CHANGED_OUTPUT_GAMMA,                        "outputGamma",
 
         /* Invalidation flags for the event */
         LXfCMDNOTIFY_VALUE,                     "+v",
         LXfCMDNOTIFY_LABEL,                     "+l",
         LXfCMDNOTIFY_DISABLE,                   "+d",
         LXfCMDNOTIFY_DATATYPE,                  "+t",
         0,                                       NULL
 };
 
         #define LXfIPEVENT_EVENT                 0xFFFFFFF0                     // Mask off the event
         #define LXfIPEVENT_FLAGS                 0x0000000F                     // Mask off the invalidation flags
 
         #define LXxIPEVENT_EVENT(e)              (LXfIPEVENT_EVENT & (e))       // Macro to mask off the event
         #define LXxIPEVENT_FLAGS(e)              (LXfIPEVENT_FLAGS & (e))       // Macro to mask off the invalidation flags