ImageGear for C and C++ on Linux v19.10 - Updated
Working with ART Marks
User Guide > How to Work with... > Annotations > Annotation API: ART > Working with ART Marks

Once you attach ART component you can annotate any image that you load into ImageGear. ART internally tracks the marks that are associated with an image. The end-user can save the image with the marks in a separate file with the .ART filename extension. Anytime the image is reloaded, a simple import call is used to "re-apply" the annotations.

You can also "burn in" the marks so they become part of the image and are not stored separately.

If the image is saved as a TIFF file, the annotations are automatically embedded in the TIFF file.

This option can be disabled - see "Saving Marks to File", below.

If a TIFF file with embedded annotations is loaded, the annotations are automatically "re-applied."

ART annotations saved to a separate file (.ART) can be read only by software that supports .ART files, such as ImageGear and the Imaging for Windows 95 and Imaging for Windows NT Wang products.

The XML schema used for ART 3.0 annotations is defined in ARTXMLStorage.xsd
This section provides information about the following:

Components of a Mark

All mark objects contain the following components:

The Mark Attributes structure is a set of attributes associated with a mark object. Attributes that do not apply are ignored.

The index block contains an unique number that is used for the mark object identification. When new mark object is created its index is generated (by incrementing 1 to the number just assigned) and stored in the global index block.

This unique number (32-bit unsigned integer) is used to refer to the mark in many of ART's operations. It cannot be modified.

The group block contains a NULL-terminated string that acts as the name of the block. It is initialized to the value contained in the global group block. If you have not set the global group block, a default value of "(Untitled)" is used. See the section ART Component Important Structures and Types or i_ART.h for more information about these structures.

ART refers to all data blocks associated with marks as "named blocks." Each data block has a unique 8-byte name for identification. All names that are less than 8 bytes are padded with NULLs. The ART component uses two kinds of named blocks:

Mark blocks contain data for individual marks. Global blocks contain data that is used to define the next mark created, as well as to store data that is not associated with an individual mark.

This diagram above shows the components of a mark. Central to any mark is the Mark Attributes structure. In addition, each mark contains a pointer to a list that includes the index and group blocks and other mandatory blocks, that vary depending on the type of mark, and an unlimited number of user-defined blocks. User-defined blocks contain data that might be useful to the developer.

You can define as many user-defined blocks as you want. Information that might be stored in a user-defined block includes:

Note that the block shown in the list can occur in any order.

When a mark is created using ART_mark_create(), which is a lower-level method of creation, the group and index blocks are created automatically; any other mandatory blocks pertaining to the type of mark created need to be added one at a time using the ART_mark_block_create() function.

The following named blocks are defined by ART in the i_ART.h file:

ART_BLOCK_ANODAT Used by many mark types to hold points and rotation information.
ART_BLOCK_FILNAM Name of file used for Image Reference, Text from File, and Audio.
ART_BLOCK_DIB Embedded DIB image.
ART_BLOCK_GROUP Name of group to which the mark belongs.
ART_BLOCK_INDEX Unique index number for mark.
ART_BLOCK_ANTEXT For text mark types. Orientation and length of text, in bytes.

 
Copy Code
ART_MARK_ATTRIBUTES ma; /* Mark Attributes Structure */
. . .
switch (dwButtonID)
{
case ART_BUTTON_HOT_SPOT:
ma.dwType = ART_MARK_HOT_SPOT;
ma.rgbColor1.rgbRed   = 0xFF;
ma.bVisible = TRUE;
ART_GUI_tool_set(hIGear, &ma);
ART_GUI_interaction_process(hIGear, IG_GRP_DEFAULT, hWnd, msg, 
nUserMode, &pt);
break;

Creating a Mark Using Low-Level Calls

If you need to create a mark without the end user, call ART_mark_create(). You supply this function a structure of type ART_MARK_ATTRIBUTES, and it returns a unique index to the mark.

ART_mark_create() automatically creates the index and group blocks for your object. You have to add other required named blocks (their types depend on the mark object) one at a time using ART_mark_block_create_ex(). To see what blocks are required by each mark type look at the section Mark Objects: Descriptions, Types and Attributes.To display the mark call ART_GUI_mark_paint().

Modifying Marks

Most often, marks are modified interactively by the end user. Whether a mark can be modified depends on its access setting. A mark has write-access or is read-only. Access can be applied to a group of marks. See the "Working With Mark Groups" section below for a discussion about group operations.

To check the access of a mark, call ART_mark_is_access_granted(). To set the access of a mark, call ART_mark_block_create(). To set the access for a group of marks, call ART_group_access().

There are differences in the way you handle modifying marks, depending on who modifies the mark - you or the end user. See the "Modifying Marks By the End User" section next.

Modifying Marks By the End User

The end user modifies a mark by clicking the mouse over it. ART automatically updates the mark's attributes structure and appropriate blocks when the user is modifying the mark.

Call ART_mark_modify() to make the changes permanently to the mark attributes structure. Call ART_mark_block_create() to overwrite the old data with the new. To redraw the mark with the new attributes, call ART_GUI_mark_paint().

Modifying Marks Programmatically

To modify marks programmatically, you set the attributes for block data, and call ART_mark_modify() or ART_mark_block_create_ex()to update that information. Call ART_GUI_mark_paint() to see the changes.

Deleting Marks

To delete a mark, call ART_mark_delete() with the index number you supply. To delete a group of marks, call ART_group_delete(). When a mark is deleted, the unique index identifiers of the remaining marks are not changed.

The callback function LPFNIG_ART_DELETENOTIFYFUNC is used to create a function that is called each time the user tries to delete a mark. If you return TRUE from a callback of this type, the mark is deleted.

Clipboard Operations

ART marks can be cut from and copied to the clipboard as well as pasted into an image individually or in groups.

The names of all functions that handle clipboard operations begin with ART_edit_. This group includes functions that undo changes made to marks. See the next section for a discussion about performing undos.

ART_edit_copy() Copies an array of marks to the clipboard
ART_edit_cut() Cuts an array of marks to the clipboard
ART_edit_paste() Pastes any available marks from the clipboard into the current HIGEAR image
ART_edit_paste_count() Queries the clipboard for the number marks available for pasting

To see the results of cutting or pasting the marks associated with an image, call ART_GUI_mark_paint() function.

Undoing Edits

As with Clipboard operations, undo begins with ART_edit_. The scope is determined by what is recorded. ART component supplies the following functions for "undoing edits":

ART_edit_undo_enable() Enable or disable undo operations.
ART_edit_undo() Reverses any changes made to any mark
ART_edit_undo_clear() Clears all pending undos from memory
ART_edit_undo_count() Returns (in lpUndoCount) the number of times that ART_edit_undo() can be called (you can limit your undo loop)
ART_edit_undo_record() Enables or disables the recording of every action

The example below shows ART_edit_undo_record() being set "on" before each mark in the image is deleted. Once the deletion loop has been completed, recording is shut "off" by calling ART_edit_undo_record() a second time with the last argument set to FALSE.

 
Copy Code
/* Record all the deletes so that when an ART_edit_undo()  */
/* is called, the deleted marks will be restored at once,  */
/* instead of being restored individually. */
ART_edit_undo_record(hIGear, TRUE);
ART_mark_selected_first(hIGear, &hMarkIndex);
while (hMarkIndex != ART_INVALID_ID)
{
hMarkDelete = hMarkIndex;
ART_mark_selected_next(hIGear, &hMarkIndex);
ART_mark_delete(hIGear, hMarkDelete);
}
/* Turn off undo recording */
ART_edit_undo_record(hIGear, FALSE);
ART_GUI_mark_paint(hIGear, 
IG_GRP_DEFAULT, ART_INVALID_ID, hWnd, TRUE);

A call to ART_edit_undo() restores all marks that were modified while recording was on. This means that all deleted marks are restored at once. If ART_edit_undo_record() was not used, then ART_edit_undo() would have to be called many times to restore all of the deleted marks.

Iterating Through Marks

ART component provides two functions that iterate through all of the marks associated with the current HIGEAR image. ART_mark_first() returns the index of the first mark. ART_mark_next() returns the index of the next mark. To iterate through all marks, call ART_mark_first(), then call ART_mark_next() within a loop, with a line such as:

 
Copy Code
ART_mark_first(hIGear, &hMarkIndex);
while (hMarkIndex != ART_INVALID_ID)
{
...
   ART_mark_next(hIGear, &hMarkIndex);
}

ART returns ART_INVALID_ID when there are no more marks to iterate through.

As you iterate through the marks, you can pass the returned index of each mark to any of the mark modification functions.

Iterating Through Blocks

ART supplies functions that let you iterate through both global blocks and mark blocks. To iterate through global blocks, use ART_global_block_first() and ART_global_block_next(). To iterate through the blocks that belong to an individual mark, use ART_mark_block_first() and ART_mark_block_next().

All of these block iteration functions set the block name to NULL when there are no more blocks to iterate through.

ART Textflow Functionality

The ART textflow functionality allows you to process several separated text marks as single text document. It includes the possibilities of checking of the text overflowing, calculating of the preferable mark bounds to draw the mark text in and automatic moving of the overflowed text from one text mark to another one.

Currently ART textflow functionality can be applied only for Typed Text, Attach-a-Note and Text from File mark types.

Working With Mark Groups

Each mark received a group name when it is created. If you do not assign it a name, ART assigns it the default group name "(Untitled)". Group names provide a convenient way to associate groups of marks so that you can modify, delete, send to the front or back of the stacking order, change access, perform clipboard operation, and select attributes.

The group name for the next mark created comes from the Global Group Block. To set it to a new name, you need to overwrite the block in the following manner:

 
Copy Code
LPSTR lpszGroup = "New Group";
ART_global_block_create(hIGear, ART_BLOCK_GROUP, lpszGroup, lstrlen(lpszGroup) + 1);

All named block names that are less than 8 bytes must be padded with NULLs. See ART Component Important Structures and Types for the composition of a Global Group Block structure.

All names of functions that operate on groups begin with ART_group_. Here are the names of the functions that operate on groups:

ART_group_access() Sets access of a group to allow for edit or read only access.
ART_group_bring_to_front() Moves group to the front of the stacking order.
ART_group_delete() Deletes a group.
ART_group_edit_copy() Copies a group to the clipboard.
ART_group_edit_cut() Cuts a group to the clipboard.
ART_group_select() Selects all marks in a group.
ART_group_send_to_back() Sends a group to the back of the stacking order.
ART_group_visible() Makes marks visible or invisible.

Use ART_edit_paste() and ART_edit_paste_count() to perform paste operations on groups of marks.

Saving Marks to File

When the set of marks belonging to a HIGEAR image are saved, they can be saved separately into a file with filename extension ".ART", burned permanently into the image, or embedded into an image file. You can embed marks into TIFF files only.

If you are saving a TIFF file, the annotations are automatically saved as an embedded file. Use ART_control_option_set() with the appropriate setting if you do not want the annotations to be embedded into the file:

 
Copy Code
nErrcount=ART_control_option_set(hIGear, ART_CONTROL_SAVE_ENABLE, FALSE)"

Importing Marks to an Image

An .ART file can be imported into any loaded HIGEAR image as long as the ART component is attached. If the .ART file to import has multiple pages, you can specify the number of the page to load. To import an .ART file for association with the current HIGEAR file call ART_file_import().