ImageGear Professional v18.2 > User Guide > Using ImageGear > Annotating Images > 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.
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. |
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().
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.
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().
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.
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.
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.
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.
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.
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.
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.
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.
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)"
|
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().