1. New Features


1.1 Two new FM specifications have been added (Organization and URL).

1.1.1 The format of the Organization specification is:

Organization:"<name of your organization>"

Use this specification to supply the name of your organization for

use in the plug-in's VS_VERSION_INFO resource and elsewhere. The

string containing the Organization specification is available in

the new FM built-in variable filterOrganizationText, or as format

specifier '!O' within an FM-formatted string.

1.1.2 The format of the URL specification is:

URL:"<http://www.example.com>"

Use this specification to supply the URL of your website for use

in the plug-in's VS_VERSION_INFO resource and elsewhere. The

string containing the URL specification is available in the new

FM built-in variable filterURLText, or as format specifier '!U'

within an FM-formatted string.

1.2 FM now sets the following fields in the VS_VERSION_INFO resource in

a standalone filter. (These fields can be viewed by selecting the

plug-in in Windows Explorer and choosing File/Properties/Version

from the menu bar.)

File version: Set from the FM Version: specification.

Description: Set from the FM Description: specification.

Copyright: Set from the FM Copyright: specification.

Author: Set from the FM Author: specification.

Comments: Set to "Generated by FilterMeister®".

Company Name: Set from the FM Organization: specification.

Internal Name: Set to "AfhFM04".

Language: Set to "English (United States)".

Legal Trademarks: Set to "FilterMeister is a trademark of AFH Systems Group".

Original Filename: Set to the base file name to which the plug-in was saved.

Product Name: Set from the FM Title: specification.

Product Version: Set from the FM Version: specification.

URL: Set from the FM URL: specification if present.

1.3 A new built-in function, chooseColor(), invokes the host application's

default color picker dialog to allow the user to select an RGB color.

The form of a call to chooseColor() is:

rgb = chooseColor(initialColor, "Prompt string" [, args]...);

where:

initialColor specifies the initial or default color for the

color picker, as an RGB triple.

"Prompt string" specifies the prompt string for the color picker.

This string may contain printf-style format

descriptors, which will be expanded using the

succeeding arguments.

args are optional arguments to be expanded into the prompt

string.

rgb receives the chosen color, as an RGB triple, or -1

if the user cancels the color picker.

1.4 The host application's current foreground and background colors are now

available as RGB triples in the built-in variables fgColor and bgColor,

respectively.

1.5 The individual components of an RGB triple or an RGBA quadruple may now

be conveniently accessed with new built-in functions Rval, Gval, Bval, and

Aval, which select the Red, Green, Blue, or Alpha components, respectively.

The format for calling these functions is:

r = Rval(rgbTriple);

g = Gval(rgbTriple);

b = Bval(rgbTriple);

a = Aval(rgbaQuad);

1.6 Three new built-in functions allow your filter to play sound (.wav)

files upon demand.

The specified wave file name is first searched for in the filter's

embedded resources. If not found among the resources, the wave file

name is searched for in the local file system, using the customary

search paths (see 2.9 below).

Each function returns true if successful or false otherwise. Any

waveform sounds that are played asynchronously will be automatically

stopped when the filter exits.

1.6.1 To play a wave file asynchronously (i.e., the wave file starts

playing and the function returns immediately, without waiting for

the waveform sound to finish playing):

success = playSoundWave("wavefilename.wav");

To stop any currently playing waveform sound, call this function

with a NULL argument:

success = playSoundWave(NULL);

1.6.2 To play a wave file synchronously (i.e., the function waits for

the waveform sound to finish playing before returning):

success = playSoundWaveSync("wavefilename.wav");

1.6.3 To start playing a wave file repeatedly:

success = playSoundWaveLoop("wavefilename.wav");

To stop a looping waveform sound:

success = playSoundWave(NULL);

1.7 A new built-in string variable, filterInstallDir, will contain the

full path name of the directory from which your filter was loaded

(which is presumably the directory in which it was installed).

This is useful for locating files (such as HTML help files) which

were installed as separate resources in your filter's installation

directory. (Note that at filter design time, filterInstallDir

will contain the name of the directory from which FilterMeister

itself was loaded, not the directory from which your target

filter will ultimately be loaded at run-time.)

1.8 A new built-in function, shellExec(), lets your filter execute a

Windows shell command. The calling format is:

retcode = shellExec("Verb", "Filename", "Params", "DefDir");

where retcode will be -1 if successful, or an error code otherwise.

"Verb" is the shell operation to be performed (e.g., "open", "print",

or "explore"). "Filename" is the name of the file to be operated

upon; it may be an executable file, a document file, or a URL.

"Params" specifies any parameters to be passed to the application.

"DefDir" specifies the default directory for the execution of the

command. Any unneeded parameter may be set to NULL. If NULL is

specified for "Verb", the function opens the file or URL specified

by "Filename".

For example, the following call will open file help.html from

the filter's installation directory using the default web browser:

shellExec("open", "help.html", NULL, filterInstallDir);

1.9 Four new built-in functions allow you to set and retrieve pixel values

based on radial (polar) coordinates instead of rectangular (Cartesian)

coordinates:

pgetr(d, m, z) - returns the destination (output buffer) pixel value

at angle d, distance m, from channel z (analogous to

the pget(x,y,z) rectangular function)

psetr(d, m, z, v) - sets the pixel value at angle d, distance m, in

channel z of the destination (output) buffer to

the clamped value of v, and returns this clamped

value (analogous to the rectangular function

pset(x,y,z,v))

tgetr(d, m, z) - returns the pixel value at angle d, distance m, from

channel z of the first tile buffer (analogous to the

tget(x,y,z) rectangular function)

tsetr(d, m, z, v) - sets the pixel value at angle d, distance m, in

channel z of the first tile buffer to the clamped

value of v, and returns this clamped value

(analogous to the rectangular function tset(x,y,z,v))

t2getr(d, m, z) - returns the pixel value at angle d, distance m, from

channel z of the second tile buffer (analogous to the

t2get(x,y,z) rectangular function)

t2setr(d, m, z, v) - sets the pixel value at angle d, distance m, in

channel z of the second tile buffer to the clamped

value of v, and returns this clamped value

(analogous to the rectangular function t2set(x,y,z,v))

Note that care must be exercised when using the *setr() functions, since

there is no guarantee that they can be used to densely populate the plane;

i.e., due to integer rounding of coordinates, etc., there may be points in

the target buffer which cannot be addressed via integer polar coordinates

(d,m). Thus, you may want to set the destination plane to all black (for

example) before using the *setr() routines to cover any "holes" in the

mapping.

1.10 Two new built-in functions allow you to efficiently apply gamma correction

to an image:

setGamma(g) - precomputes a gamma correction table for gamma value g, where

g is a float or double value. (The gamma table is initially

set to gamma = 1.0.) Returns true if successful, else false.

gamma(i) - returns the gamma-corrected value of i, where 0 <= i <= 255. The

result is undefined if i is out of range.

Example: To copy the input buffer to the output buffer, applying a gamma

correction of 1.8:

setGamma(1.8);

for (x = x_start; x < x_end; x++)

for (y = y_start; y < y_end; y++)

for (z = 0; z < 3; z++)

pset(x, y, z, gamma(src(x, y, z)));

1.11 Three new event handlers have been added.

1.11.1 The OnFilterStart handler is invoked at the start of each filter run,

just before the ForEveryTile, ForEveryPixel, and R/G/B/A handlers are

called. The OnFilterStart handler is a good place to perform one-time

calculations at the start of a filter run, check for valid control

inputs, valid image mode, etc. The OnFilterStart handler should return

false if filter processing is to continue with the ForEveryTile handler,

or true to abort further filter processing (though this latter option

is currently ignored in FM 0.4.14).

1.11.2 The OnFilterEnd handler is invoked at the end of each filter run, after

all calls to the ForEveryTile, ForEveryPixel, and R/G/B/A handlers.

The OnFilterEnd handler is a good place to perform any necessary

cleanup at the end of a filter run, such as resetting the progress bar

indicator. The OnFilterEnd handler should return false if the default

OnFilterEnd handler code is to be invoked, or true to prevent the default

handler from being invoked (though this latter option is currently

ignored in FM 0.4.14). The default OnFilterEnd handler calls

playSoundWave(NULL) to terminate any wave file that may still be

playing.

1.11.3 The OnCtl(n) handler is invoked whenever the user clicks on or changes

the value of a control. Within the OnCtl(n) handler, built-in variable

n will be set to the index of the control which was activated, and

built-in variable e will be set to one of the following symbolic constants

to indicate the specific event that occurred:

Symbolic Constant FM Event



FME_UNKNOWN Unknown or unspecified event.

FME_CLICKED Control was clicked (push buttons, etc.).

FME_DBLCLK Control was double-clicked.

FME_PAGEUP(*) Control was incremented by a large step

(scrollbars, trackbars).

FME_PAGEDOWN(*) Control was decremented by a large step

(scrollbars, trackbars).

FME_LINEUP(*) Control was incremented by a small step

(scrollbars, trackbars).

FME_LINEDOWN(*) Control was decremented by a small step

(scrollbars, trackbars).

FME_MOUSEOVER Mouse cursor entered the control window.

FME_MOUSEOUT Mouse cursor exited the control window.

(*) - These events are currently not processed by FM 0.4.14.

The following FM event codes are also defined, but cannot occur as

the value of e in the OnCtl(n) handler:

FME_ZERODIVIDE An attempt was made to divide an integer by 0.

FME_DIVIDEOVERFLOW Overflow occurred while trying to divide two

integers.

1.12 A new built-in function doAction(a) performs one of several predefined

control actions specified by its integer argument a, where a may have

one of the following predefined symbolic constant values:

Symbolic Constant Control Action



CA_PREVIEW Updates the proxy preview window.

CA_APPLY Applies the filter to the original source

image and exits the plug-in.

CA_CANCEL Exits the plug-in filter without modifying

the original source image.

CA_EDIT Enters or exits source code editing mode

(ignored in standalone filters).

CA_ABOUT Displays the ABOUT dialog box.

CA_RESET Resets all controls to their initial values

(not yet implemented in FM 0.4.14).

CA_NONE Performs no action.

1.13 The following additional built-in (read-only) variables have been added

to expose information provided by the host application. (Note that these

values are guaranteed to be valid only when Adobe Photoshop is the host;

other so-called Photoshop-compatible hosts may or may not provide useful

information in these variables.)

Variable Name Type Value




hostSerialNumber int The host application's serial number.

Your plug-in filter can use this value

as part of a copy-protection scheme.

(Note: The Mac version of Photoshop

apparently sets this field to a valid

serial number, but on the Windows

platforms Photoshop always sets this

field to 0. Use the hostSerialString

variable instead, which will be

implemented in a later version of FM.)

imageWidth int The source image’s width in pixels. If the

selection is floating, this variable instead

holds the width of the floating selection.

imageHeight int The source image’s height in pixels. If the

selection is floating, this variable instead

holds the height of the floating selection.

wholeWidth int The width in pixels of the entire source

image, regardless of any floating selection.

wholeHeight int The height in pixels of the entire source

image, regardless of any floating selection.

planes int For Photoshop 4+, this variable contains

the total number of active planes in the

image, including alpha channels. The

image mode should be determined by looking

at the imageMode variable. For earlier

versions of Photoshop, this variable will

be equal to 3 if filtering the RGB channel

of an RGB color image, or 4 if filtering

the CMYK channel of a CMYK color image.

Otherwise it will be equal to 1.

maxSpace int The maximum number of bytes of information

the plug-in can expect to be able to access

at once (input area size + output area size

+ mask area size + bufferSpace).

isFloating bool This variable is true if and only if the

selection is floating.

haveMask bool This variable is true if and only if a non-

rectangular area has been selected.

bgColor int The current background color as a packed

triple or quadruple in the color space

native to the source image. Use the Rval,

Gval, Bval, and Aval functions described

in section 1.5 above to access the individual

components of bgColor.

fgColor int The current foreground color as a packed

triple or quadruple in the color space

native to the source image. Use the Rval,

Gval, Bval, and Aval functions described

in section 1.5 above to access the individual

components of fgColor.

hostSig int The host application provides its signature

in this variable. Adobe Photoshop’s

signature is '8BIM'. In theory, you can

check for Photoshop as the host application

with the following code; however, some other

ill-behaved hosts also set hostSig to '8BIM'.

if (hostSig == '8BIM')

{ // Host is Adobe Photoshop...

}

imageMode int The mode of the image being filtered, where

Bitmap = 0, Gray Scale = 1, Indexed Color = 2,

RGB Color = 3, CMYK Color = 4, HSL Color = 5,

HSB Color = 6, Multichannel = 7, Duotone = 8,

Lab Color = 9, 16-bit Gray Scale = 10, and

48-bit RGB Color = 11.

filterCase int The type of data being filtered: Flat with no

selection (1), Flat with a selection (2), Floating

(3), Layer with editable transparency and no

selection (4), Layer with editable transparency

and a selection (5), Layer with preserved

transparency and no selection (6), or Layer

with preserved transparency and a selection (7).

A zero indicates that the host did not set this

variable, and the plug-in should look at the

haveMask and isFloating variables to determine

the filter case.

samplingSupport int Indicates whether the host supports non-1:1

sampling for the proxy preview. 0 means no

sampling support, 1 means integral sampling

support, and 2 means fractional sampling

support. Photoshop 3.0.1+ supports integral

sampling steps; future versions may support

non-integral sampling steps.

1.14 A new integer built-in variable, zoomFactor, has been added. This will contain

a value between 1 and 16 to indicate the current zoom factor of the proxy

preview window, or 0 if the proxy zoom factor has not yet been set. (In the

current implementation, the zoomFactor variable is essentially the same as the

built-in scaleFactor variable.)

1.15 Two new built-in functions, getCtlColor(c) and getCtlVal(c), have been added.

getCtlColor(c) returns the current color of control c, as an RGB triple.

getCtlVal(c) returns the current integer value of control c, and is simply

a synonym for the ctl(c) function.

1.16 Two new built-in integer functions, HDBUsToPixels(n) and VDBUsToPixels(n),

have been added. HDBUsToPixels converts horizontal DBUs (Dialog Box Units)

to pixels; VDBUsToPixels converts vertical DBUs to pixels. The conversion

factor depends on the current system font, and can be different in the

horizontal and vertical directions.

2. Changes


2.1 The number of anonymous put/get cells has been increased from 256

to 1024.

2.2 The maximum number of local variables that the user can declare in a handler

has been doubled from 200 to 400 (float and double variables count as two

variables each).

2.3 The size of the compiler's semantic descriptor stack has been doubled,

allowing the compilation of very complex expressions. Various code buffer

sizes have also been increased to allow for the compilation of very long

code sequences. If a code buffer nevertheless overflows, the name of the

code buffer will now be identified in the overflow error message. Please

report this buffer name when submitting a bug/performance report against

FM.

2.4 Control values are now properly cached before the OnFilterStart handler

is invoked.

2.5 Two alternatives to the built-in mix() function have been added, to handle

rounding errors in different ways: mix1() and mix2(). The original mix()

function retains its previous behavior for compatibility with Filter

Factory.

mix(a,b,n,d) is computed as a*n/d + b*(d-n)/d, per Filter Factory.

mix1(a,b,n,d) is computed as (a*n + b*(d-n))/d, per Werner Streidt, to

avoid some of the rounding errors inherent in the FF formula.

mix2(a,b,n,d) is computed using a more complex formula to avoid

other rounding errors that are introduced when (b - a)*n < 0.

The bottom line: Experiment with mix, mix1, and mix2 to find out

which version works best in your filter. When in doubt, mix1 is

probably the best choice.

2.6 The size of the static text label associated with a standard scrollbar

control is now dynamically adjusted to exactly fit the displayed text

rather than using a fixed-size field. This should help eliminate some

problems with truncation or overlap of label fields. Also, tooltips

have been re-enabled for the static text label.

2.7 Setting the border style for a standard scrollbar control now sets the

border style of the associated static text label.

2.8 The NOTIFY attribute has been implemented for button class controls.

Setting this attribute allows the control to generate FME_DBLCLK events,

which may then be processed by the OnCtl(n) handler. Note that an

FME_DBLCLK event will always be preceded by an FME_CLICKED event for

the same control.

2.9 FM now searches for a file in the following order when looking for

a resource file such as a bitmap, icon, metafile, or sound wave file:

1. The current working directory is searched;

2. All directories listed in the PATH environment variable are

searched;

3. All directories listed in the FM_PATH environment variable (if

defined) are searched;

4. If the filename specifies an absolute pathname, that pathname

is searched.

2.10 An error message is now issued when a case label (FM-E-ILLCASELAB)

or a default label (FM-E-ILLDEFLAB) is found outside of any

switch statement.

2.11 A warning is now issued (FM-I-IGNLAB) when a statement label is

encountered, to warn that the label will be ignored.

2.12 Fatal "X86 Emit Error" message boxes during compilation now correctly

abort the compilation when acknowledged, instead of trying to continue.

2.13 The CANCEL button in an "X86 Emit Warning" message box now correctly

aborts the compilation.

2.14 FM now recognizes 'UP20' as the host signature for Megalux Ultimate

Paint 2.0.

2.15 The host signature 'PSAd' is now reported as "Adobe Photoshop Adapter"

instead of "ImageReady", since this signature is used by several Adobe

products, not just ImageReady.

2.16 The body color of a scrollbar (STANDARD or SCROLLBAR) control can now

be set with the color= property or the setCtlColor() function.

2.17 In Advanced editing mode, the following additional fields are now

displayed in the Filter Parameter Block window if the Property Suite

is available:

propertyProcsVersion, numPropertyProcs, getPropertyProc, setPropertyProc

If the getPropertyProc (or older getProperty) procedure is available,

it is used to obtain and display the following additional information:

propNumberOfChannels - Number of channels in the document.

propCopyright - Whether the current image is considered

copyrighted (1) or not (0).

propInterpolationMethod - Current interpolation method: 1=point sample,

2=bilinear, 3=bicubic.

propTitle - The title of the current image (usually its

file name, or "Untitled-n" if not yet saved).

propURL - The URL for the current image.

propSerialString - Serial number of the plug-in host as a string.

2.18 The syntax for <color> can now include any integer expression; e.g.,

Dialog:color=100*256 will set the dialog background color to a dark

green, and ctl[0]:fontcolor=fgColor will set the font color of control

0 to the currently selected foreground color.

2.19 The temporary tile buffers (tbuf and t2buf) are now set to the size of

the input tile instead of the size of the output tile.

2.20 Several additional format descriptors are now recognized by the formatString()

function and all other functions which implicitly call formatString:

!h, !m, !O, !U, !w, and !z.

The complete list of descriptors recognized by formatString is now:

descriptor is replaced by



!! "!" (i.e., a verbatim exclamation point)

!A text specified by the Author key (filterAuthorText)

!a text specified by the About key (filterAboutText)

!C text specified by the Category key (filterCategoryText)

!c text specified by the Copyright key (filterCopyrightText)

!D text specified by the Description key (filterDescriptionText)

!F text specified by the Filename key (filterFilenameText)

!f the current Filter Case as a text string (filterCaseText)

e.g., "Flat image, no selection"

!H the name of the Host application (filterHostText)

e.g., "Adobe Photoshop"

!h the source image height as a decimal integer (imageHeight)

!M the current Image Mode as a text string (filterImageModeText)

e.g., "RGB Color"

!m the current Image Mode as a decimal integer (imageMode)

!O text specified by the Organization key (filterOrganizationText)

!T text specified by the Title key (filterTitleText)

!t text specified by the Title key, with any trailing ellipsis removed

!U text specified by the URL key (filterURLText)

!V text specified by the Version key (filterVersionText)

!w the source image width as a decimal integer (imageWidth)

!z the proxy zoom factor as a decimal integer (zoomFactor)

3. Bug Fixes


3.1 The built-in (val)?() function now works correctly when the control

range is other than the default [0, 255].

3.2 A setCtlText() redraw problem has been fixed for check box and

radio button controls.

3.3 A bug which occurred when a switch statement had no default case

has been fixed.

3.4 A problem which caused spurious error messages for 'short' and 'long'

type specifiers has been fixed.

3.5 A bug which could cause a General Protection fault when the proxy

preview was zoomed larger than the size of the preview window has

been fixed.

3.6 A bug which caused incorrect code to be generated for Duff's device

(and other cases in which a case label was nested within a loop

statement enclosed by the corresponding switch statement) has been

fixed.

3.7 A bug in the deletion of control fonts which could cause a crash on

Windows NT has been fixed.

3.8 A problem which caused an incorrect syntax error message while looking

for a specific character during compilation has been fixed.

3.9 A retry bug when tile buffer allocation failed has been fixed.

3.10 A workaround has been added for hosts such as PiCo (which uses

imhost32.dll) and several others which expect the propertyLength

field in the PiPL resource to always be a multiple of 4.

3.11 Several redundant stores to the Premiere-compatible variables i0,

i1, u0, u1, v0, and v1 have been eliminated.

4. Known Problems


4.1 The 'MaxBox' subkey in a Dialog specification is currently ignored.

This fixes a problem in which the dialog box could be inadvertently

maximized but not restored.

4.2 HDBUsToPixels() or VDBUsToPixels() can cause a divide error in USER.EXE if

the result would be greater than approximately 32K pixels. This appears

to be a limitation of the MapDialogRect Win32 API function.

4.3 Returning a value of true from the OnFilterStart handler does not abort

the filter run as it should.

4.4 Returning a value of true from the OnFilterEnd handler does not cause

the default OnFilterEnd processing to be skipped as it should.

4.5 The OnCtl(n) handler does not get invoked when a scrollbar or trackbar

control is activated.