Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Introduction

The DevWare application has a dialog plug-in API whereby an externally written and compiled module (DLL) can integrate with DevWare, present a dialog window to the user, and have access to sensor registers and image data.

The diagram below illustrates the main modules in DevWare that have call-backs into the plug-in DLL.

Features of the Dialog Plug-in API

Plug-ins can be used to create a UI for new sensor registers or third party or prototype hardware not supported by Sensor Control pages in DevWare, or for image processing or image data capture. The Plug-in API provides:

  1.  Read and write access to any register and/or any field within a register, including registers on companion chips.
  2.  Notification when another part of DevWare changes a register the plug-in is interested in so on-screen controls can be updated.
  3.  Read and write access to captured image data, both raw data and the final RGB image that DevWare will display in the main window.
  4.  Control of DevWare's software color pipeline features such as auto exposure, software color correction, etc.

DevWare supports up to 24 plug-in dialogs simultaneously. If plug-ins are present, DevWare will add a “Plug-ins” menu to its main window. The user can activate and deactivate plug-in windows at will.


Dialog Plugin API Details

These sections describe the API specifications. The API is rather simple. There are three functions you must export to DevWare, and DevWare will provide functions to you to access the sensor and control DevWare. Also, DevWare may send messages to your window, and you can send messages to DevWare's window.


DevWare creates the plug-in windows when it starts and doesn't destroy them until the user switches to a new camera or exits the application. DevWare will show and hide your window when the user selects it on the Plug-in menu. If the user clicks your Close button, you should hide your window, not close it. Therefore you can continue processing image data even when your window is hidden, if desired.

Include Files

Include files are provided that will work for C and C++. You need to include the following files in your code for the API definitions:

 

#include "ApBase.h"
#include "DlgImport.h"

The files are in the include directory where the Aptina Imaging software is installed, typically C:\Aptina Imaging\include.

DLL Exported Functions

A plug-in dialog must be compiled into a DLL. The DLL file must have the extension “.dll” and should export the functions described below. The exported functions must use the standard WIN32 calling convention, normally indicated with the __stdcall keyword. (Parameters passed right to left, called function restores the stack.) The exported function names can be undecorated (e.g. “OpenDialog”) or decorated with _ prefix and @ suffix with number of parameter bytes (e.g. “_OpenDialog@16”). The three functions you export are as follows. The first two are required, the last is optional.

 

Function

Details

Calling Thread
OpenDialog

__declspec(dllexport) HWND CALLBACK
OpenDialog(DWORD dwApiVersion,
HWND hwndParent,
DEVW_Camera *pCamera,
DEVW_Callbacks *pCallbacks);

DevWare calls this function when it's starting up a camera or switching cameras. You should create the window but not show it. Also copy the passed-in data structures into your own variables. (Don't just copy the pointers, copy the whole structures.) Return the Windows window handle for your window. DevWare will use the handle to show and hide your window, and to send you window messages. Do only basic initialization here. Do not access registers yet; you will have an opportunity to do that later.

Parameters:

  • dwApiVersion: Compare this against the constant PLUGIN_DLG_API to make sure you and DevWare are using the same version of the API.
  • hwndParent: The Windows window handle of the main DevWare window. Normally your window would be a WS_POPUP style window with DevWare as its parent (but this is not strictly necessary). Also you can use this handle to send messages to DevWare.
  • pCamera: Information about the sensor and camera. See the header files for details. The pointer does not remain valid after OpenDialog() returns, you must copy the contents of the structure into your own variable.
  • pCallbacks: Pointers to the callback functions in DevWare. See below. The pointer does not remain valid after OpenDialog() returns, you must copy the contents of the structure into your own variable. (The pointers to functions within the structure do remain valid.)

If something goes wrong return 0. If your plug-in should only work with certain devices you can examine the pCamera structure and return 0 if you plug-in is not designed for that device.

Otherwise DevWare will add your plug-in to the “Plug-Ins” menu, using the title bar text from your window for its menu item. The API supports only one window per DLL. (But that window could be a tabbed dialog with any number of tabs, or could have child windows. Also, DevWare can load up to 24 DLLs simultaneously.)

GUI
CloseDialog

CloseDialog()
__declspec(dllexport) void CALLBACK
CloseDialog(void);

Called when DevWare is switching to another camera, or exiting. Destroy your window and free all allocated memory. If OpenDialog() returned 0, CloseDialog() will not be called.

GUI
ImageData

__declspec(dllexport) void CALLBACK
ImageData(unsigned char * pImage,
mi_image_types imageType,
int nWidth,
int nHeight,
int nStride);

DevWare will pass all image data to your plug-in through this function. It will be called at least twice for every frame displayed by DevWare. Once with the data in sensor-dependent format, and again with the final RGB image that DevWare is going to display in its window. You do not need to export this function if your plug-in does not use the image data.

Parameters:

  • pImage: Pointer to upper left pixel of image.
  • imageType: See midlib.h. Tells you the image type, for example, MI_BAYER_S12, MI_YCBCR, MI_RGB32, etc.
  • nWidth: Width in pixels.
  • nHeight: Height in pixels.
  • nStride: Distance in bytes between rows in the image. To get the y?th row use pImage + y * nStride. Never depend on the nWidth parameter for this. DevWare may put pad bytes between rows.

This function can be used for analysis, image processing, or data capture. You can write to the image buffer and DevWare will use the new data. For example, you can write to the MI_RGB32 buffer to create indicator graphics in the image. You could also filter image data, etc.

This function is called every frame regardless of whether your window is visible or not. If you want your processing to stop when your window is hidden then you must explicitly check for that case and return immediately from the function.

You must be careful of what you do in this function because it is called from a different thread than the UI thread. You must not directly access your window controls from this function. If the UI needs to be updated use PostMessage() to send a message to your window or use some other communication mechanism such as common variables and critical sections.

You should not call DevWare callback functions, except that it is permissible to read and write sensor registers.

DevWare converts all Bayer data to MI_BAYER_S12 for processing. MI_BAYER_S12 uses a 16-bit signed 2s-complement integer for each pixel. The value 0 represents the Black Level, and the value 4095 represents the maximum brightness. Values outside this range are possible as a result of noise or image processing. The final image is always MI_RGB32, which is 32-bits per pixel, B-G-R-x byte order.

The ImageData() function is optional. If you do not need image data then you do not need to have this function. OpenDialog() and CloseDialog() are required.

Display
GrabFrame

__declspec(dllexport) void CALLBACK
GrabFrame(unsigned char * pBuffer, int nDataLength);

DevWare will call this function every time it gets a new frame from the camera. The parameters are a pointer to the data and the data length. The data is just as it came from the camera. You do not need to export this function if your plug-in does not need this notification.

If you need to poll registers or update registers frequently, this function is the best place to do it. Register access here will have the least interference with the frame rate.

Parameters:

  • pBuffer: Pointer to the data from the camera.
  • nDataLength: Number of bytes of data received.

This function can be used for analysis, image processing, or data capture. You can write to the image buffer and DevWare will use the new data.

This function is called on every received frame regardless of whether your window is visible or not. If you want your processing to stop when your window is hidden then you must explicitly check for that case and return immediately from the function.

You must be careful of what you do in this function because it is called from a different thread than the UI thread. You must not directly access your window controls from this function. If the UI needs to be updated use PostMessage() to send a message to your window or use some other communication mechanism such as common variables and critical sections.

You should not call DevWare callback functions, except that it is permissible to read and write sensor registers.

The GrabFrame() function is optional. If you do not need the notifications then you do not need to have this function.

Camera
SaveImage

__declspec(dllexport) void CALLBACK
SaveImage(const char * szPath);

DevWare will call this function when it saves a captured image. The plug-in may save addition data if desired.

Parameters:

  • szPath: A C style string that is the saved file path and name without an extension.

This function is called whenever the application saves a capture image, regardless of whether your window is visible or not.

This function is typically called from the main thread.

The SaveImage() function is optional. If you do not need the notifications then you do not need to have this function.

Display?

 

DevWare Callback Functions

DevWare passes function pointers to your OpenDialog() function in the DEVW_Callbacks structure.

Function NameDetails
ReadRegister()

int Callbacks.ReadRegister(const char *regname, const char *fieldname, int cached);

Read a sensor register or field of a sensor register. If you want to read the whole register, pass NULL for the field name. You can only access registers and fields defined in the sensor data file.

For performance, DevWare caches the last value written to a register. For most registers it is sufficient to only get the cached value. In that case pass 1 for cached. If a register can be changed by the hardware or if it can return a different value each time when read then pass 0 for cached to always read the hardware (cached = 0 for volatile registers).

WriteRegister()

void Callbacks.WriteRegister(const char *regname, const char *fieldname, unsigned int value);

Write a sensor register or field of a sensor register. If you want to write the whole register, pass NULL for the fieldname. You can only access registers and fields defined in the sensor data file.

Important: call Begin/EndAccessRegs(), SyncChanges() or Stop() if needed around WriteRegister().

ReadRegisterAddr()

int Callbacks.ReadRegisterAddr(unsigned int nAddr, unsigned int nBitmask, unsigned int nAddrSpace, mi_addr_type nAddrType, int cached);

Read a sensor register or field of a sensor register by register number and address space. If you want to read the whole register, pass 0 for nBitmask. You can only access registers defined in the sensor data file.

WriteRegisterAddr()

void Callbacks.WriteRegisterAddr(unsigned int nAddr, unsigned int nBitmask, unsigned int nAddrSpace, mi_addr_type nAddrType, unsigned int value);

Write a sensor register or field of a sensor register by register number and address space. If you want to write the whole register, pass 0 for nBitmask. You can only access registers defined in the sensor data file.

Important: call Begin/EndAccessRegs(), SyncChanges() or Stop() if needed around WriteRegisterAddr().

PeekRegister()

int Callbacks.PeekRegister(unsigned int nBaseAddr, unsigned int nAddr, int nAddrSize, int nDataSize);

Read a register by Serial I/O. Can be a sensor register or a register on another chip on the Serial bus. nAddrSize and nDataSize are the width in bits of the register address and register value parameters. Valid values of nAddrSize and nDataSize are 8 or 16.

Important: call Begin/EndAccessRegs(), SyncChanges() or Stop() if needed around PeekRegister().

PokeRegister()

void Callbacks.PokeRegister(unsigned int nBaseAddr, unsigned int nAddr, unsigned int value, int nAddrSize, int nDataSize);

Write a register by Serial I/O. Can be a sensor register or a register on another chip on the Serial bus. nAddrSize and nDataSize are the width in bits of the register address and register value parameters. Valid values of nAddrSize and nDataSize are 8 or 16. This is a “dangerous” register write. It goes straight to the hardware without any snooping or special handling by DevWare.

Important: call Begin/EndAccessRegs(), SyncChanges() or Stop() if needed around PokeRegister().

PeekRegisters()

void Callbacks.PeekRegisters(unsigned int nBaseAddr, unsigned int nAddr, int count, void *pValues, int nAddrSize, int nDataSize);

Read a sequence of successive registers by Serial I/O in one function call. Can be sensor registers or registers on another chip on the Serial bus. nAddrSize and nDataSize are the width in bits of the register address and register value parameters. Valid values of nAddrSize and nDataSize are 8 or 16. The pValues parameter is interpreted as either an unsigned char * or unsigned short * depending on the value of nDataSize.

Important: call Begin/EndAccessRegs(), SyncChanges() or Stop() if needed around PeekRegisters().

PokeRegisters()

void Callbacks.PokeRegisters(unsigned int nBaseAddr, unsigned int nAddr, int count, void *pValues, int nAddrSize, int nDataSize);

Write a sequence of successive registers by Serial I/O in one function call. Can be sensor registers or registers on another chip on the Serial bus. nAddrSize and nDataSize are the width in bits of the register address and register value parameters. Valid values of nAddrSize and nDataSize are 8 or 16. The pValues parameter is interpreted as either an unsigned char * or unsigned short * depending on the value of nDataSize. This is a “dangerous” register write. It goes straight to the hardware without any snooping or special handling by DevWare.

Important: call Begin/EndAccessRegs(), SyncChanges() or Stop() if needed around PokeRegisters().

BeginAccessRegs() EndAccessRegs()

void Callbacks.BeginAccessRegs();
void Callbacks.EndAccessRegs();

This function pauses the capture thread in DevWare if the device or device driver does not support simultaneous register access and image capture. Call BeginAccessRegs() before reading or writing registers and EndAccessRegs() afterward. When writing several registers, call this function once at the beginning and once again when done:
Callbacks.BeginAccessRegs();
Callbacks.WriteRegister(…);

Callbacks.WriteRegister(…);
Callbacks.EndAccessRegs();
This is important for performance and reliability on the Demo board. Use Stop() instead if the register writes will change the image size or pixel format.

 

SyncChanges()

void Callbacks.SyncChanges(int sync);
Same as Begin/EndAccessRegs(), but also sets the SYNC or GROUPED_PARAMETER_HOLD bit on the sensor. The SYNC bit guarantees that all the register changes take effect at the same time. Call SyncChanges(TRUE) before writing registers and SyncChanges(FALSE) afterward. When writing several registers, call this function once at the beginning and once again when done:
Callbacks.SyncChanges(TRUE);
Callbacks.WriteRegister(…);

Callbacks.WriteRegister(…);
Callbacks.SyncChanges(FALSE);
This is important for performance and reliability on the Demo board. Use Stop() instead if the register writes will change the image size or pixel format.

Stop()

void Callbacks.Stop(int stop);

This function stops the image capture and image processing threads. Call Stop(TRUE) before writing registers that will change the image size or image pixel format. Call Stop(FALSE) afterward to restart image capturing:
Callbacks.Stop(TRUE);
Callbacks.WriteRegister(…);

Callbacks.WriteRegister(…);
Callbacks.Stop(FALSE);
This is important for performance and reliability.

Pause()

void Callbacks.Pause(int pause);

This function pauses the capture thread in DevWare. The image processing thread continues to run with the last captured image.

MonitorRegister()

void Callbacks.MonitorRegister(const char *regname, int id, HWND hwnd);

This provides a way for your plug-in to be notified if a register is written in another part of DevWare. If you have controls based on the register you can update your controls.

  • regname: Name of the register in the sensor data file.
  • id: An arbitrary integer value of your choosing. This value will be passed back to your window when this register changes so you can identify which register changed if you are monitoring more than one register.
  • hwnd: The Windows window handle of your window.

When a register you are monitoring changes, DevWare will send a message to the window handle you provided as follows:
Message = WM_MONITOR
wParam = id
lParam = new value of register

The WM_MONITOR messages will be sent even when your window is hidden. Normally, hwnd would be the handle of your dialog window, but it could be another if convenient. For example, if you have a tabbed dialog, you could have the messages sent to the appropriate page.

GetState()

int Callbacks.GetState(const char *state);
Retrieves the DevWare software control variable value for numeric-valued variables. These are mostly software color pipeline variables; for example, software auto exposure, software color processing, etc. The parameter is a string containing the name of the state. To see the state names, save a new preset using the Presets dialog in DevWare, open the sensor .ini file and look for lines beginning with “STATE=”.
Example:

int ae = Callbacks.GetState("Auto Exposure");
SetState()

void Callbacks.SetState(const char *state, int nVal);
Sets a state to a new value for numeric-valued state variables. See GetState(), above.
Example:

Callbacks.SetState("Auto Exposure", 0); // turn off software AE
GetStateStr()

char * Callbacks.GetStateStr(const char *state);
Retrieves the DevWare software control variable value for string-valued variables.

SetStateStr()

void Callbacks.SetStateStr(const char *state, const char *szVal);
Sets a state to a new value for string-valued state variables.

GetOption()

int Callbacks.GetOption(const char *option, int nDefault);
Retrieves the Option variable value for numeric-valued variables. There are variables that are used by DevWare to control various features of the application. See the DevWare COM document for more details. You can also create your own variables, just use any name. The Option values persist between invocations of DevWare.
The first parameter is a string containing the name of the variable. The second parameter is the default value to use if the variable hasn?t been defined yet.
Example:

int mode = Callbacks.GetOption("Myplugin Mode", 1);
SetOption()

void Callbacks.SetOption(const char *option, int nVal);
Sets an Option variable to a new value for numeric-valued state variables. See GetOption(), above.
Example:

Callbacks.SetOption("AnalysisDlg Show", 1); // make Analysis Graph visible
GetOptionStr()

void Callbacks.GetOptionStr(const char *option, char *szValue, int nBufSize, const char *szDefault);
Retrieves the Option variable value for string-valued variables. You must allocate a buffer to receive the string, and pass in the size of the buffer.

SetOptionStr()

void Callbacks.SetOptionStr(const char *option, const char *szValue);
Sets a new value for string-valued Option variables.

LoadPreset()

void Callbacks.LoadPreset(const char *szFilename, const char *szPreset);
Load an ini file preset. The szFilename parameter may be NULL or the empty string, in which case the currently loaded default ini file is used.
Example:

Callbacks.LoadPreset(NULL, "Demo Initialization");
RunPython()

int Callbacks.RunPython(const char *szStatements);
Pass a sequence of Python statements to the Python interpreter. There can be any number of statements separated by „\n? characters. This is the same as executing a Python preset.
Example:

CString stmt;
stmt.Format("image_size(%d, %d)", width, height);
Callbacks.RunPython(stmt);
GetMouseSelection()

void Callbacks.GetMouseSelection(int* pnSelectType, int* pnStartX, int* pnStartY, int* pnEndX, int* pnEndY);
Get the current Mouse Selection. The select type values are:
0 – Off
1 – Row; nStartY is the row
2 – Column; nStartX is the column
3 – Rectangle
4 – Point; nStartX, nStartY is the point

SetMouseSelection()

void Callbacks.SetMouseSelection(int nSelectType, int nStartX, int nStartY, int nEndX, int nEndY);
Sets the Mouse Selection.
Example:

Callbacks.SetMouseSelection(1, 0, height / 2, 0, height / 2);
GetIniFileName()

const char * Callbacks.GetIniFileName(int nSeq);
Gets the names of the currently loaded ini files. Pass 0, 1, 2, etc. to this function to enumerate the filenames. Returns NULL when the parameter meets or exceeds the number of open ini files.
Example:

CString sIniFile = Callbacks.GetIniFileName(0);

 

Window Messages


In addition to the function calls, some communication between DevWare and your window happens by window messages. The WM_MONITOR message was discussed above. Other messages are as follows.
Your window will get a WM_SHOWWINDOW message when DevWare shows or hides it. You should catch these events to know when your window is showing. Specifically, when your window is shown, you should update all of your controls according to the current register settings.

If the user clicks the Close button on your window (WM_CLOSE message), you should not destroy your window, instead just hide it. Also send a WM_PLUGIN_HIDE message to DevWare so that it can update its own UI (uncheck the Plug-in menu item).

Plug-Ins Directory

The DLL file must be in the plug-ins directory so DevWare can find it and load it. The plug-ins directory is determined in the DevWare.ini file. You will need to edit the DevWare.ini file to set it to where your plug-ins are located. By default it is the Plugins directory where your Aptina Imaging software is installed. Example:
[DevWare]

Plugin Directory=C:\Aptina Imaging\Plugins

Sample Code

There is a sample plug-in dialog called DialogDll, located in the samples directory Where your Aptina Imaging software is installed. The sample code is in C++ and includes Microsoft Visual Studio .NET 2005 project files.
The sample code demonstrates:

  •  Proper declarations of exported DLL functions.
  •  Sensor type and camera type information.
  •  Setting a register by a dialog control (slider).
  •  Automatically updating a control when the underlying register changes (WM_MONITOR).
  •  Handling hide and show of the window.
  •  Handling the Close button.
  •  Receiving image data and doing a simple analysis.
  •  Putting a graphic indicator in the RGB image.
  •  Updating dialog controls with image analysis results using PostMessage() and a custom window message to communicate from the worker thread to the main UI thread.
  • No labels