MappTrace
This example shows how to generate an AIL trace using the Zebra Profiler utility. To generate a trace, you must open Zebra Profiler (accessible from the Aurora Imaging Control Center) and select 'Generate New Trace' from the File menu.
Language: C#
Functions used: MappAlloc, MappControl, MappFree, MappInquire, MappTrace, MbufAlloc2d, MbufAllocColor, MbufFree, MdigAlloc, MdigFree, MdigGetHookInfo, MdigInquire, MdigProcess, MdispAlloc, MdispFree, MdispSelect, MimArith, MimBinarize, MimConvert, MimHistogramEqualize, MsysAlloc, MsysFree, MthrAlloc, MthrControl, MthrFree, MthrWait
Categories: Overview, General, Industries, Applications, Modules, Buffer, Display, Image Processing, What's New, Older
///////////////////////////////////////////////////////////////////////////////
// Aurora Imaging Library
// Filename: MappTrace.cs
//
// Description: This example shows how to explicitly control and generate a trace for
// functions and how to visualize it using the Aurora Imaging Profiler utility.
// To generate a trace, you must open Aurora Imaging Profiler (accessible from the
// Aurora Imaging Control Center) and select 'Generate New Trace' from the 'File' menu
// before to run your application.
//
// Note: By default, all applications are traceable without code modifications.
// You can try this using Aurora Imaging Profiler with any example (Ex: MappStart).
//
// (C) 1992-2026 Zebra Technologies Corp. and/or its affiliates
// All Rights Reserved
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Runtime.InteropServices;
using Zebra.AuroraImagingLibrary;
namespace MappTrace
{
class HookDataStruct
{
public AIL_ID AilImageDisp;
public AIL_ID AilImageTemp1;
public AIL_ID AilImageTemp2;
public AIL_INT ProcessedImageCount;
public AIL_ID DoneEvent;
}
class MappTrace
{
// Trace related constants
private const int TRACE_TAG_HOOK_START = 1;
private const int TRACE_TAG_PROCESSING = 2;
private const int TRACE_TAG_PREPROCESSING = 3;
// General constants.
private static readonly int COLOR_BROWN = AIL.M_RGB888(100, 65, 50);
private const int BUFFERING_SIZE_MAX = 3;
private const int NUMBER_OF_FRAMES_TO_PROCESS = 10;
static void Main(string[] args)
{
AIL_ID AilApplication = AIL.M_NULL;
AIL_ID AilSystem = AIL.M_NULL;
AIL_ID AilDisplay = AIL.M_NULL;
AIL_ID AilDigitizer = AIL.M_NULL;
AIL_ID[] AilGrabBuf = new AIL_ID[BUFFERING_SIZE_MAX];
AIL_ID AilDummyBuffer = AIL.M_NULL;
AIL_INT TracesActivated = AIL.M_NO;
AIL_INT NbGrabBuf = 0;
AIL_INT SizeX = 0, SizeY = 0;
HookDataStruct UserHookData = new HookDataStruct();
Console.WriteLine();
Console.WriteLine("PROGRAM TRACING AND PROFILING:");
Console.WriteLine("----------------------------------");
Console.WriteLine();
Console.WriteLine("This example shows how to generate a trace for the execution");
Console.WriteLine("of the functions, and to visualize it using");
Console.WriteLine("the Aurora Imaging Profiler utility.");
Console.WriteLine();
Console.WriteLine("ACTION REQUIRED:");
Console.WriteLine();
Console.WriteLine("Open 'Aurora Imaging Profiler' from the 'Aurora Imaging Control Center' and");
Console.WriteLine("select 'Generate New Trace' from the 'File' menu.");
Console.WriteLine();
Console.WriteLine("Press any key to continue.");
Console.WriteLine();
Console.ReadKey(true);
//************** Untraceable code section ***************
// The following code will not be visible in the trace.
// Application allocation.
// At Application allocation time, M_TRACE_LOG_DISABLE can be used to ensures that
// an application will not be traceable regardless of Aurora Imaging Profiler or Aurora Imaging Configurator requests
// unless traces are explicitly enabled in the program using an MappControl command.
//
AIL.MappAlloc("M_DEFAULT", AIL.M_TRACE_LOG_DISABLE, ref AilApplication);
// Dummy calls that will be invisible in the trace.
AIL.MsysAlloc(AIL.M_DEFAULT, AIL.M_SYSTEM_HOST, AIL.M_DEFAULT, AIL.M_DEFAULT, ref AilSystem);
AIL.MbufAllocColor(AilSystem, 3, 128, 128, 8 + AIL.M_UNSIGNED, AIL.M_IMAGE, ref AilDummyBuffer);
AIL.MbufClear(AilDummyBuffer, 0L);
AIL.MbufFree(AilDummyBuffer);
AIL.MsysFree(AilSystem);
//*******************************************************
// Explicitly allow trace logging after a certain point if Aurora Imaging Profiler has
// requested a trace. Note that M_TRACE = M_ENABLE can be used to force the log
// of a trace even if Profiler is not opened; M_TRACE = M_DISABLE can prevent
// logging of code section.
//
AIL.MappControl(AIL.M_DEFAULT, AIL.M_TRACE, AIL.M_DEFAULT);
// Inquire if the traces are active (i.e. Profiler is open and waiting for a trace).
AIL.MappInquire(AIL.M_DEFAULT, AIL.M_TRACE_ACTIVE, ref TracesActivated);
if (TracesActivated == AIL.M_YES)
{
// Create custom trace markers: setting custom names and colors.
// Initialize a custom Tag for the grab callback function with a unique color (blue).
AIL.MappTrace(AIL.M_DEFAULT,
AIL.M_TRACE_SET_TAG_INFORMATION,
TRACE_TAG_HOOK_START,
AIL.M_COLOR_BLUE, "Grab Callback Marker");
// Initialize the custom Tag for the processing section.
AIL.MappTrace(AIL.M_DEFAULT,
AIL.M_TRACE_SET_TAG_INFORMATION,
TRACE_TAG_PROCESSING,
AIL.M_DEFAULT, "Processing Section");
// Initialize the custom Tag for the preprocessing with a unique color (brown).
AIL.MappTrace(AIL.M_DEFAULT,
AIL.M_TRACE_SET_TAG_INFORMATION,
TRACE_TAG_PREPROCESSING,
COLOR_BROWN, "Preprocessing Marker");
}
// Allocate objects.
AIL.MsysAlloc(AIL.M_DEFAULT, AIL.M_SYSTEM_HOST, AIL.M_DEFAULT, AIL.M_DEFAULT, ref AilSystem);
AIL.MdigAlloc(AilSystem, AIL.M_DEFAULT, "M_DEFAULT", AIL.M_DEFAULT, ref AilDigitizer);
AIL.MdispAlloc(AilSystem, AIL.M_DEFAULT, "M_DEFAULT", AIL.M_DEFAULT, ref AilDisplay);
SizeX = AIL.MdigInquire(AilDigitizer, AIL.M_SIZE_X, AIL.M_NULL);
SizeY = AIL.MdigInquire(AilDigitizer, AIL.M_SIZE_Y, AIL.M_NULL);
AIL.MbufAllocColor(AilSystem, 3, SizeX, SizeY, 8 + AIL.M_UNSIGNED,
AIL.M_IMAGE + AIL.M_GRAB + AIL.M_PROC + AIL.M_DISP, ref UserHookData.AilImageDisp);
AIL.MdispSelect(AilDisplay, UserHookData.AilImageDisp);
// Allocate the processing temporary buffers.
AIL.MbufAlloc2d(AilSystem, SizeX, SizeY, 8 + AIL.M_UNSIGNED, AIL.M_PROC + AIL.M_IMAGE, ref UserHookData.AilImageTemp1);
AIL.MbufAlloc2d(AilSystem, SizeX, SizeY, 8 + AIL.M_UNSIGNED, AIL.M_PROC + AIL.M_IMAGE, ref UserHookData.AilImageTemp2);
// Allocate the grab buffers.
for (NbGrabBuf = 0; NbGrabBuf < BUFFERING_SIZE_MAX; NbGrabBuf++)
{
AIL.MbufAllocColor(AilSystem, 3, SizeX, SizeY, 8 + AIL.M_UNSIGNED,
AIL.M_IMAGE + AIL.M_GRAB + AIL.M_PROC, ref AilGrabBuf[NbGrabBuf]);
}
// Initialize the user's processing function data structure.
UserHookData.ProcessedImageCount = 0;
AIL.MthrAlloc(AilSystem, AIL.M_EVENT, AIL.M_NOT_SIGNALED + AIL.M_AUTO_RESET, AIL.M_NULL,
AIL.M_NULL, ref UserHookData.DoneEvent);
GCHandle UserHookDataPtr = GCHandle.Alloc(UserHookData);
AIL_DIG_HOOK_FUNCTION_PTR HookFunctionPtr = new AIL_DIG_HOOK_FUNCTION_PTR(HookFunction);
// Start the processing. The processing function is called with every frame grabbed.
AIL.MdigProcess(AilDigitizer, AilGrabBuf, BUFFERING_SIZE_MAX, AIL.M_START,
AIL.M_DEFAULT, HookFunctionPtr, GCHandle.ToIntPtr(UserHookDataPtr));
// Stop the processing when the event is triggered.
AIL.MthrWait(UserHookData.DoneEvent, AIL.M_EVENT_WAIT + AIL.M_EVENT_TIMEOUT(2000), AIL.M_NULL);
// Stop the processing.
AIL.MdigProcess(AilDigitizer, AilGrabBuf, BUFFERING_SIZE_MAX, AIL.M_STOP, AIL.M_DEFAULT,
HookFunctionPtr, GCHandle.ToIntPtr(UserHookDataPtr));
UserHookDataPtr.Free();
// Free the grab and temporary buffers.
for (NbGrabBuf = 0; NbGrabBuf < BUFFERING_SIZE_MAX; NbGrabBuf++)
AIL.MbufFree(AilGrabBuf[NbGrabBuf]);
AIL.MbufFree(UserHookData.AilImageTemp1);
AIL.MbufFree(UserHookData.AilImageTemp2);
// Free defaults.
AIL.MthrFree(UserHookData.DoneEvent);
AIL.MappFreeDefault(AilApplication,
AilSystem,
AilDisplay,
AilDigitizer,
UserHookData.AilImageDisp);
// If Aurora Imaging Profiler activated the traces, the trace file is now ready.
if (TracesActivated == AIL.M_YES)
{
Console.WriteLine("A PROCESSING SEQUENCE WAS EXECUTED AND LOGGED A NEW TRACE:");
Console.WriteLine();
Console.WriteLine("The trace can now be loaded in Aurora Imaging Profiler by selecting the");
Console.WriteLine("corresponding file listed in the 'Trace Generation' dialog.");
Console.WriteLine();
Console.WriteLine("Once loaded, Aurora Imaging Profiler's main window displays the 'Main'");
Console.WriteLine("and the 'MdigProcess' threads of the application.");
Console.WriteLine();
Console.WriteLine("- This main window can now be used to select a section");
Console.WriteLine(" of a thread and to zoom or pan in it.");
Console.WriteLine();
Console.WriteLine("- The right pane shows detailed statistics as well as a");
Console.WriteLine(" 'Quick Access' list displaying all function calls.");
Console.WriteLine();
Console.WriteLine("- The 'User Markers' tab lists the markers and sections logged");
Console.WriteLine(" during the execution. For example, selecting 'Tag:Processing'");
Console.WriteLine(" allows double-clicking to refocus the display on the related");
Console.WriteLine(" calls.");
Console.WriteLine();
Console.WriteLine("- By clicking a particular function call, either in the");
Console.WriteLine(" 'main view' or in the 'Quick Access', additional details");
Console.WriteLine(" are displayed, such as its parameters and execution time.");
Console.WriteLine();
}
else
{
Console.WriteLine("ERROR: No active tracing detected in Profiler!");
Console.WriteLine();
}
Console.WriteLine("Press any key to end.");
Console.ReadKey(true);
}
static AIL_INT HookFunction(AIL_INT HookType, AIL_ID HookId, IntPtr HookDataPtr)
{
AIL_ID CurrentImage = AIL.M_NULL;
if (HookDataPtr != IntPtr.Zero)
{
HookDataStruct UserDataPtr = GCHandle.FromIntPtr(HookDataPtr).Target as HookDataStruct;
// Add a marker to indicate the reception of a new grabbed image.
AIL.MappTrace(AIL.M_DEFAULT,
AIL.M_TRACE_MARKER,
TRACE_TAG_HOOK_START,
AIL.M_NULL,
"New Image grabbed");
// Retrieve the AIL_ID of the grabbed buffer.
AIL.MdigGetHookInfo(HookId, AIL.M_MODIFIED_BUFFER + AIL.M_BUFFER_ID, ref CurrentImage);
// Start a Section to highlight the processing calls on the image.
AIL.MappTrace(AIL.M_DEFAULT,
AIL.M_TRACE_SECTION_START,
TRACE_TAG_PROCESSING,
UserDataPtr.ProcessedImageCount,
"Processing Image");
// Add a Marker to indicate the start of the preprocessing section.
AIL.MappTrace(AIL.M_DEFAULT,
AIL.M_TRACE_MARKER,
TRACE_TAG_PREPROCESSING,
UserDataPtr.ProcessedImageCount,
"Start Preprocessing");
// Do the preprocessing.
AIL.MimConvert(CurrentImage, UserDataPtr.AilImageTemp1, AIL.M_RGB_TO_L);
AIL.MimHistogramEqualize(UserDataPtr.AilImageTemp1, UserDataPtr.AilImageTemp1, AIL.M_UNIFORM, AIL.M_NULL, 55, 200);
// Add a Marker to indicate the end of the preprocessing section.
AIL.MappTrace(AIL.M_DEFAULT,
AIL.M_TRACE_MARKER,
TRACE_TAG_PREPROCESSING,
UserDataPtr.ProcessedImageCount,
"End Preprocessing");
// Do the main processing.
AIL.MimBinarize(UserDataPtr.AilImageTemp1, UserDataPtr.AilImageTemp2, AIL.M_IN_RANGE, 120, 140);
AIL.MimBinarize(UserDataPtr.AilImageTemp1, UserDataPtr.AilImageTemp1, AIL.M_IN_RANGE, 220, 255);
AIL.MimArith(UserDataPtr.AilImageTemp1, UserDataPtr.AilImageTemp2, UserDataPtr.AilImageDisp, AIL.M_OR);
// End the Section that highlights the processing.
AIL.MappTrace(AIL.M_DEFAULT,
AIL.M_TRACE_SECTION_END,
TRACE_TAG_PROCESSING,
UserDataPtr.ProcessedImageCount,
"Processing Image End");
// Signal that we have done enough processing.
if (++(UserDataPtr.ProcessedImageCount) >= NUMBER_OF_FRAMES_TO_PROCESS)
AIL.MthrControl(UserDataPtr.DoneEvent, AIL.M_EVENT_SET, AIL.M_SIGNALED);
}
return 0;
}
}
}