Note that there are important changes in the API since version 1.5, and that these break compatibility.
Add-ons are loaded and linked to Becasso at run time. Becasso knows four types of add-ons: Filters, Generators, Transformers, and Capture Add-ons. There is no structural difference between the first three types, and it is up to the add-on itself to identify itself as either of these types at initialization time. This will allow Becasso to place the add-on under the corresponding menu item, and take appropriate action when the user selects the add-on.
There are, of course, functional differences between these three types of add-ons. Filters are probably the most common type of add-ons, comprising conventional blurring filters, Gaussian blurring filters, contrast enhancing filters, spread filters, despeckle filters, etc. Generators are add-ons that fill a given selection of the canvas with a new image, not necessarily as a function of the previous contents of the canvas. Examples would be a color gradient generator, a fractal generator, a plasma generator, or a simple texture painting add-on. Transformers, finally, generate a new image by performing some kind of operation on the existing canvas, not necessarily in the local way in which a filter does. Examples include add-ons that zoom or shrink a given selection, rotate it, flip it, or warp it in some special way.
One special feature of the way Becasso interacts with its add-ons is that it opens the way to interactive operation of the add-ons. With most other image processing software, the user has to go through a process of setting parameters, waiting for the result to compute, decide whether it is as desired, and if not, adjusting the parameters and re-entering the cycle. Becasso tries to shorten this process by showing the effects of a change in parameters directly on the canvas, if only in a 'preview' version.
When a filter is opened by the user, for example, a small rectangle is shown on the canvas, the contents of which are continuously fed through the filter. If the filter comprises lengthy calculations that would hurt responsiveness, it can supply a 'preview' version of its algorithm and only use the 'real' one when the user is satisfied with the settings.
To give another example, the Gradient generator can generate color gradients continuously as the user drags the mouse over the canvas and can visually determine when the gradient is placed just right.
Especially for add-on developers, there are command line options for
Becasso which respectively disable add-on loading alltogether
(the -x
switch) or to enable "verbose" add-on loading
(the -v
switch). When launched from a terminal,
Becasso will print out the names of each add-on loaded, and
print out a report on the initialization of each.
Structure of a Becasso Add-On
A Becasso add-on needs to export the following five
functions:
status_t addon_init (uint32 index, becasso_addon_info *info); status_t addon_exit (void); status_t addon_make_config (BView **view, BRect rect); status_t process (Layer *inLayer, Selection *inSelection, Layer **outLayer, Selection **outSelection, int32 mode, BRect *frame, bool final, BPoint point, uint32 buttons);With version 2.0 of the API, the distinction between Capture add-ons and Editor add-ons has widened. A Capture add-on must export
BBitmap *bitmap (char *title);instead of the
process()
function, and also export
status_t addon_open (BWindow *client, const char *name);There are also several optional hook functions which an add-on may export:
void addon_color_changed (void); void addon_mode_changed (void); status_t addon_persist_settings (BMessage *settings); status_t addon_apply_settings (BMessage *settings);These are documented below. It is easiest to take one of the example add-ons and work from there as a framework. There is probably lots of code you can simply leave in place as some tasks are shared by all add-ons.
addon_init()
function is called by Becasso.
The index
parameter is a unique number for each add-on.
It is used in further 'correspondence' with Becasso. The
info
parameter is a special struct
that
needs to be filled in with all kinds of information about the add-on.
The becasso_addon_info
struct
is defined as
follows:
typedef struct { char name[80]; // The name as it appears in the menu uint32 index; // A unique index assigned at init time int type; // Filter, Transformer or Generator int version; // Version of the add-on int release; // Release of the add-on int becasso_version; // Required Becasso version (other won't load) int becasso_release; // Written for release (older will warn) char author[128]; // Author (company) of the add-on char copyright[128]; // Copyright notice char description[128]; // Explains what the add-on does uint8 does_preview; // bitmask for various preview notifications uint32 flags; // bitmask } becasso_addon_info;So the typical
addon_init()
function of an add-on looks
like this:
status_t addon_init (uint32 index, becasso_addon_info *info) { strcpy (info->name, "Blur"); strcpy (info->author, "Sander Stoks"); strcpy (info->copyright, "(c) 1997-2001 Sum Software"); strcpy (info->description, "Applies a 3x3 blur kernel convolution"); info->type = BECASSO_FILTER; info->index = index; info->version = 1; info->release = 0; info->becasso_version = 2; info->becasso_release = 0; info->does_preview = PREVIEW_FULLSCALE; info->flags = 0; return B_OK; }Most entires in the
addon_info
structure are
self-explanatory.type
is one of
BECASSO_FILTER
,
BECASSO_TRANSFORMER
, BECASSO_GENERATOR
, or
BECASSO_CAPTURE
.
The does_preview
can be set to
NULL
PREVIEW_FULLSCALE
PREVIEW_2x2
PREVIEW_MOUSE
LAYER_AND_SELECTION
The flags
bitmask can be used to signify certain aspects of
your add-on. For the v2.0 API, the only values are
LAYER_ONLY
and
SELECTION_ONLY
. These are mutually exclusive, and should be
set when your add-on only makes sense for either layers or selections,
respectively (an example would be the BumpMap add-on, which uses the selection to
modify the layer, but doesn't make sense when operated in Selection Mode).
The becasso_version
and becasso_release
can be used if your add-on uses functionality that was added in a specific
version of Becasso. If an older version of Becasso finds an add-on
designed for a newer version, it will skip loading that add-on because it might be
incompatible. It is therefore a good idea to set these values to the
lowest version of Becasso which will be able to use your add-ons.
Note to developers familiar with the v1.5 API: TheWhen you manage to complete your initialization successfully, you signal this to Becasso by returningaddon_init()
function used to be the place to initialize the window for the addon settings. You derived this window from the genericAddOnWindow
, and start the window thread at the end of theaddon_init()
function by callingRun()
on it. This has changed for the v2.0 API. The reason is that every add-on otherwise would have its own window (a leftover from the early days of Becasso, when multiple add-ons could be opened simultaneously; this feature was removed because it didn't make much sense), and thus had its own thread. When you had lots of add-ons, that meant there would be dozens of window threads being spawned.
B_OK
. If anything else
is returned, Becasso will print a warning message and leave
the add-on alone.
The next time the add-on hears from Becasso is when the user
selects it from the menu. In that case, Becasso will call
addon_make_config()
, so the add-on can provide Becasso
with its own configuration view which Becasso will then add to a window,
add some common buttons and a status bar, and show on screen. Typically,
an implementation of addon_make_config()
looks like this:
status_t addon_make_config (BView **view, BRect rect) { *view = new ConfigView (rect); return B_OK; }where it is assumed that you have defined your own
ConfigView
class (derived from BView
). If your add-on has no controls or
parameters, you may simply set view
to NULL
. The
rect
parameter is only passed as a convenience. It's width will
be set to the default add-on window width (don't rely on the height).
You are free to resize your view to however big or small you like.
Becasso will enlarge it to a minimum width if you
make it too small, though.
Note that since you have no access to the add-on
window's MessageReceived()
and are expected to override
the view's MessageReceived()
to take care of any
messages sent by your controls, the target of your
controls needs to be set to the view. You can't do this in the view
constructor, because obviously the view "doesn't exist yet" at that point.
Therefore, you would override AttachedToWindow()
to iterate
over your controls and call SetTarget(this)
on them.
If you have an intricate custom view with child views that have their own
MessageReceived()
hooks, you still need to do this. For most
common cases, you don't need to worry about the target of your controls.
Becasso, after attaching your view to the add-on window, will take care of
iterating over your entire view hierarchy, setting the target of
any BControl
s and BMenuField
s (i.e. popup menus)
to the view itself. (This should take care of all interface widgets - if
you need any other kind of views added here, please let us know.).
If your add-on uses things like temporary lookup-tables,
the best time to set them up would be in addon_make_config()
(because that is always called just before the add-on window is opened
and the add-on is ready to use).
Note to developers familiar with the v1.5 API:
the addon_open()
function is now only used for
Capture add-ons - see below.
See also: addon_refresh_config()
and the ADDON_RESIZED
message.
When the user is done with the add-on, Becasso will call
addon_close()
. If you had allocated lookup tables in
addon_make_config()
and you want to get rid of them before
going to sleep, this is the time to do it. Otherwise, simply return
B_OK
. (If you return a non-zero error code from this
function, Becasso will print it out if ran from a Terminal, for debugging
purposes.)
When Becasso exits, it calls the addon_exit()
function of each add-on. Most add-ons can simply return
B_OK
here, but this provision is for add-ons that hold on to
some kind of global resource (a Capture add-on would be very likely to do
so). You don't have to clear the becasso_addon_info
struct
.
Of course, the real action happens when the user actually
uses the add-on. There are various scenarios for that, but
they all have in common that Becasso calls the
process()
function. This function has quite an array of
parameters, which are detailed below:
Layer *inLayer |
The current layer of the canvas. |
Selection
*inSelection |
The current selection map, if a selection is made, and
NULL if there isn't. In that case, the default action of
an add-on is to operate on the entire canvas. |
Layer **outLayer |
This can point to a valid Layer , or
be
NULL . In the first case, the add-on must write its
results in the given layer. If it is NULL , the add-on
can choose whether to allocate a new Layer , point
outLayer to inLayer , or overwrite the data in
inLayer directly and leave outLayer
NULL . Becasso will handle each of these
cases. |
Selection
**outSelection |
Ditto as above. |
int32 mode |
The current drawing mode of Becasso. This is either
M_DRAW or M_SELECT , when BecassoBecasso is
in drawing or selection mode, respectively. An add-on should modify
the part of the layer that corresponds to the selection map only when
mode is M_DRAW , and modify the selection map
itself when mode is M_SELECT . |
BRect *frame |
This contains the minimal rectangle in which the current selection
fits, or the entire bounds of the canvas when there is no selection
made. Most add-ons can ignore frame as it is mainly
useful for speedups, since not the entire selection map needs to be
checked. Note that it is the responsability of the add-on that
frame contains the 'dirty' rectangle upon exit, as only
that part of the canvas will be refreshed. The add-on can also alter
frame when it has changed the minimal rectangle, for
instance when a transformer has enlarged part of the
canvas. Even in that case, it cannot exceed the bounds of the
canvas. |
bool final |
This variable controls whether the add-on should try to save time
by using a 'preview version' of its algorithm (a.k.a.
'quick-and-dirty'). For example, anti-aliasing of the result should
be switched off then final is false . A more
detailed description of what should be done when is given below. |
BPoint point |
In interactive operation of the add-on, this contains the current mouse position. |
uint32 buttons |
In interactive operation of the add-on, this contains the current state of the mouse buttons. |
process()
function of
an add-on is called with different parameter meanings. Most of the
information about the desired behavior can be extracted out of the
inSelection
, mode
, and buttons
parameters.
When inSelection
is NULL
, this means that
the user hasn't made a selection. The default operation of an add-on
is to apply to the entire canvas.
When final
is false
, the add-on is asked to
provide a quick-and-dirty 'preview' of its working.
When the add-on is operated interactively, it depends on the type of
add-on what happens. For filters, simply a small portion of the
current layer is passed to process()
, and the
final
flag is set to false
. This happens everytime the user
moves the preview rectangle by ALT-dragging the mouse across the
canvas, or whenever the contents of the preview rectangle are changed
(for instance when the user draws through it with a drawing tool).
For generators and transformers, the interactive
operation is more elaborate. The add-on then receives a continuous
stream of process()
calls with the current mouse position
in point
and the button mask in buttons
.
During this time, the final
flag is set to
false
. When the user releases the mouse button, a final
call to process()
is made with buttons
set
to zero but final
still false
. This allows
for a three-way granularity in image quality: when a generator or
transformer is very time-consuming, it might be better not to
start the calculation in final quality until the user clicks the
Apply button on its window. Of course, this only happens when you told
Becasso that you're interested in mouse events at all, by setting the
PREVIEW_MOUSE
flag in addon_init()
.
To preserve the orthogonality of the user interface of Becasso,
add-ons should be prepared to operate on either the current layer or
the current selection. Sometimes it is more intuitive to operate on
both (for instance when a transformer scales the selected part
of the canvas, it should also scale the selection itself). Of course,
it doesn't make sense for all add-ons to operate on the
selection –
the BumpMap add-on for instance uses the selection to modify the actual
layer contents, but would not make any sense when called upon the selection
itself.
Note that you should be prepared to handle either
case (by checking the mode and simply returning if it's not to your liking),
even if you told Becasso about your preference via LAYER_ONLY
or SELECTION_ONLY
in addon_init()
.
Since filter calculations can sometimes be quite complex and lengthy,
it is good practise to keep the user informed of what's going on.
Becasso will signal activity by means of the rotating crosshair
cursor, but this only signals that work is being done, not how much
longer the user needs to wait for the result.
Add-on windows contain a progress bar, which is a standard
BStatusBar
object. Furthermore, there is a
"Stop" button which the user can press if (s)he finds the
calculations to take too long, and the add-on should check
whether this button is pressed every now and then (for instance, at
the same time as the progress bar is updated). This button starts out
in disabled state (since there is nothing to stop!) so the add-on should
signal when it starts a complex and lengthy calculation by calling the
addon_start()
function which
Becasso exports.
The progress bar can be updated simply by calling the
addon_update_statusbar (float
delta)
function exported by Becasso, where
delta
is a float
that determines the amount
of work done since the last call.
If the user has clicked the "Stop" button in the meantime,
the addon_stop()
function will
return true
.
The best place for the update/checking is in the outermost loop of the
calculation. Don't update the bar for every pixel calculated, as this
would have far too much overhead. And also don't use the progress bar
if process()
is called with final
set to
false
, otherwise the bar would be flickering constantly
as the user moves the preview rectangle across the canvas.
Lastly, when the add-on is finished, the add-on should call addon_done()
to reset the
progres bar and disable the "Stop" button.
Note to developers familiar with the v1.5 API:
These new functions exported by Becasso replace the old way of doing
things with methods of the AddOnWindow
class.
The possible return values for the process()
function are
addon_stop()
),
or because you decided to abort processing yourself for some reason. Becasso will
discard the partly processed Layer
and/or Selection
.process()
function of a
filter addon would look something like this:
status_t process (Layer *inLayer, Selection *inSelection, Layer **outLayer, Selection **outSelection, int32 mode, BRect *frame, bool final, BPoint point, uint32 buttons) { int error = ADDON_OK; if (*outLayer == NULL && mode == M_DRAW) *outLayer = new Layer (*inLayer); if (*outSelection == NULL && mode == M_SELECT) *outSelection = new Selection (inLayer->Bounds()); if (*outLayer) (*outLayer)->Lock(); if (*outSelection) (*outSelection)->Lock(); int h = frame->Height(); int w = frame->Width(); float delta = 100.0/h; // For the progress bar if (final) addon_start(); switch (mode) { case M_DRAW: for (int y = 0; y < h; y++) { if (final) { addon_update_statusbar (delta); if (addon_stop()) { error = ADDON_ABORT; break; } } for (int x = 0; x < w; x++) do_the_calculation(); } break; case M_SELECT: // Likewise... break; default: fprintf (stderr, "MyAddOn: Invalid mode\n"); error = ADDON_UNKNOWN; break; } if (*outSelection) (*outSelection)->Unlock(); if (*outLayer) (*outLayer)->Unlock(); if (final) addon_done(); return (error); }For a generator or a transformer add-on, there would be code like
status_t process (...) { static BPoint firstpoint = BPoint (0, 0); static BPoint lastpoint = BPoint (0, 0); static bool entry = false; if (!entry && buttons && !final) // First entry of a realtime drag { firstpoint = point; entry = true; } if (!final && !buttons) // Exit a realtime drag (buttons released) { lastpoint = point; entry = false; } // Lots of code if (final) // Apply clicked slow_generator (firstpoint, lastpoint); else if (!buttons) // End of a realtime drag medium_generator (firstpoint, lastpoint); else // We're in a realtime drag here... fast_generator (firstpoint, point); // Some more code }As a final summary of the "program flow" between Becasso and an add-on, the following schema might clarify (by Michael Pfeiffer).
addon_make_config()
, and instead of process()
,
they export BBitmap *bitmap (char *title)
. Also, they do
export status_t addon_open (void)
. This function is called
when the user selects the add-on from a menu. You are relatively free in
what you do in this function - most likely, you will be instantiating and
opening your own window. However you capture, grab, or generate images is your
own business - whenever you're ready (when the user presses a "Grab" button
for instance) you send a BMessage (CAPTURE_READY)
to Becasso
with your index
added, and it will take care of the rest (involving
calling your bitmap()
function to collect the actual bitmap).
See the included CaptureTest.cpp
for an example.
_APP_
. Becasso exports a number of
classes and useful functions for use in your add-ons.
Note to developers familiar with the v1.5 API:
The AddOnWindow
class is obsolete.
void addon_color_changed
(void)
This hook function is called (if you provide it) when either the foreground or background color, or the current pattern has changed. Note that Becasso will also callprocess()
, so in most cases that should suffice even if you use either of these. This hook is only useful if you cache these colors somehow (or use them as the basis of a calculation you do outside ofprocess()
.
void addon_mode_changed
(void)
This hook function is called (if you provide it) when the current mode has changed. Note that Becasso will also callThe following two optional hook functions are for persistance of filter settings. Support for this was added in Becasso version 2.3process()
, so in most cases that should suffice. In some cases though, you might want to change certain aspects of your UI (in that case, you can calladdon_refresh_config()
. See alsocurrentmode()
.
status_t addon_persist_settings
(BMessage *settings)
This hook function is called when the add-on is about to be unloaded. You should add your add-on specific settings to theBMessage
. These should be simple name-value pairs; allowed are strings,int32
values, andfloat
values. For an example, see the OilPaint add-on sample code.
status_t addon_apply_settings
(BMessage *settings)
This hook function is used to re-apply persisted filter settings. For an example, see the OilPaint add-on sample code.
void addon_start (void)
Call this when you are about to start doing processor-intensive stuff
in process()
. It will reset the status bar and enable the
"Stop" button on the add-on window.
bool addon_stop (void)
Check the return value of this function periodically inside your mainprocess()
loop (for example, in the outer loop iterating over the rows of pixels - better not in the inner loop). A good place to do this is right next toaddon_update_statusbar()
. If this function returnstrue
, the user has clicked the "Stop" button, and you should end your operation withADDON_ABORT
.
void addon_done (void)
Call this function at the end of a normal run of your
process()
code. This will disable the "Stop" button again.
void addon_update_statusbar (float
delta, const char *text = NULL, const char *trailingText =
NULL)
Update the status bar by "delta" (note that the statusbar uses percentages, so you should have it update from 0 to 100). This function should only be used for a final, high-quality rendering of your add-on, and not in the real-time preview.
void addon_reset_statusbar (const
char *label = NULL, const char *trailingText = NULL)
Use this to set the status bar in the add-on window back to zero. Note
that addon_done()
does this for you.
void addon_preview (void)
Call this function to request a new preview. You generally do this after
your parameters have changed (you would probably see this function being called
in your ConfigView's MessageReceived()
method).
void addon_refresh_config
(void)
Call this function if you want to change your GUI in a more or less drastic way. For example, your add-on could have different parameters depending in whether it is being run in selection mode or in drawing mode, and you could call this function from theTheaddon_mode_changed()
hook to let Becasso know. It will then get rid of your old config view and calladdon_make_config()
for your new one. If you were able to take care of refreshing your view yourself but have resized it, you can inform Becasso with the message below.
ADDON_RESIZED
message
If your add-on has changed its config view for some reason (for instance, because you have a popup selecting a multitude of different options, or because you were informed of a mode change (throughaddon_mode_changed()
) and have changed your UI as a result), you can inform the add-on window by sending a simpleADDON_RESIZE
message. This can be as simple asResizeTo (newWidth, newHeight); Window()->PostMessage (ADDON_RESIZE);Note that you must make sure your view has the right risizing mask. If that containsB_FOLLOW_RIGHT
and/orB_FOLLOW_BOTTOM
, your view will resize twice, with undesirable results.
Layer
BBitmap
in the
B_RGB_32_BIT
color space, along with some additional
variables. There are more methods in the Layer
class
than are explained below, for instance for setting whether the layer
is hidden or visible, but these should not be called from within
an add-on.
Defined in:Layer.h
Layer (BRect bounds, const char *name) Layer (const Layer& layer)The first constructor takes a rectangle for size and a name as it will appear in the Layer Manager window of Becasso. The second version takes an existingLayer
and models the new one after it (i.e. copy the name, size, and all other settings). Note that there is no color space parameter; Becasso layers are always 32 bit BGRA bitmaps. For convenience,AddOnSupport.h
definesbgra_pixel
as the type for the pixels in aLayer
.
Note that the order in which the channels are stored is blue, green, red, alpha, i.e. not RGBA!void ClearTo (bgra_pixel p)Clears the entire layer to the value given byp
.
Selection
Selection
is a BBitmap
in
B_GREYSCALE_8_BIT
color space, although the values are not
meant to represent colors in the BeOS palette. It was
B_COLOR_8_BIT
in Becasso 1.3 due to a bug
introduced in BeOS R3, but this was restored to B_GREYSCALE_8_BIT since
R4.5 fixed this problem, and it reflects the nature of a selection more
truthfully. Being an 8bit bitmap means
that its width in pixels need not necessarily be the same as its
width in bytes, due to padding. Be sure to take this into account
when using the raw bitmap data! Becasso more or less treats
a Selection
map as a separate alpha channel. When a
given pixel is non-zero, the corresponding pixel in the current layer
is selected. Becasso does not use a simple binary selection
map, so every pixel can have 255 values of 'selectedness', which come
into play for instance when the selection is cut and pasted. An add-on
should also take this into account whenever appropriate, i.e. a value
of 0 stands for 'leave the corresponding pixel as it was', and 255 means
'maximum appliance of the filter'.
Defined in:Selection.h
Selection (BRect bounds) Selection (const Selection &selection)AddOnSupport.h
definesgrey_pixel
as a type for the pixels in a selection map.void ClearTo (grey_pixel p)Clears the entire selection map to the value given byp
.
Slider
Slider
class, which is
convenient for settings in an add-on window. Since R3, the BeOS also
has a slider class (and a TabView, see below) but these classes were
added to Becasso before that, and should still be used to keep
the same look and feel across add-ons.
Defined in:Slider.h
Slider (BRect frame, float sep, const char *name, float min, float max, float step, BMessage *msg, orientation posture = B_HORIZONTAL, int size = 0, const char *fmt = "%.0f")Slider
is derived fromBView
. Theframe
parameter is self-explanatory; thesep
parameter is the width in pixels that will be taken by the text labelname
. The minimum and maximum values are designated bymin
andmax
, andstep
is the minimum change of value. Whenever the value of the slider is changed by the user, either by dragging or by clicking next to the knob, the givenmsg
will be sent, with afloat
entry with the name "value
". Although the presence of aB_HORIZONTAL
default suggests the possibility of vertical sliders, this is presently unimplemented. The parametersize
designates the size of the slider knob. If zero (the default) it is adjusted to the maximum value. The final parameter is a format string, like in theprintf
argument, which designates how the value should be written in the knob.float Value ()This returns the current value of the slider.void SetValue (float v)With this method, you can set the value of the slider from within your code. The slider defaults to the minimum position. CallingSetValue
does not result in a message being sent.
TabView
TabView
is the set of "overlaying" views as
visible in, for instance, the Fill tool attribute window. You can use
these tabviews in your own add-on windows as well.
Defined in:TabView.h
TabView (BRect frame, const char *name, uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP)TabView
is derived fromBView
. The parameters are the same as with a normalBView
. To aid in the layout of your views, there is a valueTAB_HEIGHT
defined which is the extra height you should take into account, which is taken by the tabs themselves.void AddView (BView *view, const char *tab)This method adds theview
to theTabView
. Thetab
parameter designates the name to be drawn in the tab; it should not be more thanMAX_TAB
characters in length.void RaiseView (int n)By calling this method, you can "raise" one of the tabviews manually, but this is seldom needed. Once added to the tabview, everything is handled fully automatically. The tabs are numbered in the order in which they are added.
AddOnSupport.h
file and are
documented below.
bgra_pixel average4 (bgra_pixel a, bgra_pixel b, bgra_pixel c, bgra_pixel d) bgra_pixel average6 (bgra_pixel a, bgra_pixel b, bgra_pixel c, bgra_pixel d, bgra_pixel e, bgra_pixel f) bgra_pixel average9 (bgra_pixel a, bgra_pixel b, bgra_pixel c, bgra_pixel d, bgra_pixel e, bgra_pixel f, bgra_pixel g, bgra_pixel h, bgra_pixel i)
Since pixel data packed in a 32 bit integer cannot simply be manipulated with the normal operators, Becasso offers these functions for the often-used case of averaging entire pixel values. The Blur filter code uses these functions quite extensively. These functions are highly optimized. See the Tips and Tricks Department below.
bgra_pixel pixelblend (bgra_pixel d, bgra_pixel s)
This function returns anbgra_pixel
in which the two arguments are blended, taking the alpha channel ofs
into account. An alpha value of 0 means thats
is fully transparent, so the result will bed
. When the alpha value ofs
is 255, it is fully opaque, so there won't be anyd
shining through. Any intermediate value results in the corresponding mixing of the colors.
uint8 clip8 (int32 c)
Returns the value ofc
, clipped to the range0..255
.
rgb_color highcolor (void) rgb_color lowcolor (void)
Return the currently selected high and low colors (in the corresponding menu buttons of the Becasso main menu).
pattern currentpattern (void)
Returns the currently selected pattern from the rightmost menu button of the Becasso main window.
int32 currentmode (void)
Returns the currently selected mode of Becasso (eitherM_DRAW
orM_SELECT
). Note that this is passed to theprocess()
function as a parameter, but you might need this function if your add-on changes its UI depending on the mode. You are informed about mode changes while your add-on is open by providing anaddon_mode_changed()
hook (see Optional Hook Functions, above).
rgb_color *highpalette (void) rgb_color *lowpalette (void)
Return the current foreground and background palettes, respectively. Note
that you receive
a pointer to a copy of the palette, which means you are free to do
with it whatever
you please, as long as you delete []
it yourself.
int highpalettesize (void) int lowpalettesize (void)
Return the number of colors in the foreground and background palettes, respectively. This is currently always 256, but who knows what might happen in the future.
rgb_color closesthigh (rgb_color a) rgb_color closestlow (rgb_color a)
Return the color from the foreground or background palette, respectively,
which Becasso thinks is closest to the given color a
.
rgb_color contrastingcolor (rgb_color a, rgb_color b)
Returns a color that contrasts with botha
andb
. An illustration of its use is given in the Gradient generator example code, where a color is needed to contrast with both 'end points' of the gradient. The default color is red, unless one (or both) ofa
andb
is 'reddish', in which case either black or white is returned, depending on the average 'brightness' ofa
andb
.
bgra_pixel weighted_average (bgra_pixel a, uint8 wa, bgra_pixel b, uint8 wb) bgra_pixel weighted_average_rgb (rgb_color a, uint8 wa, rgb_color b, uint8 wb)
These functions return a color that is the weighted average ofa
andb
, via the formularesult = (a*wa + b*wb)/(wa + wb),naturally taking the separate color channels into account.
int Scale (BBitmap *src, BBitmap *srcmap, BBitmap *dest, BBitmap *destmap)
This function performes an anti-aliased scaling (using MMX if available).src
anddest
areBBitmap
s inB_RGB_32_BIT
color space, andsrcmap
anddestmap
areBBitmap
s inB_COLOR_8_BIT
color space. Eithersrc
anddest
, orsrcmap
anddestmap
can beNULL
, in which case only the other bitmap is scaled. If all arguments are non-NULL
, a 32 bit bitmap and an 8 bit bitmap (for instance a Layer and its corresponding Selection) can be scaled with one call.This function can handle arbitrary scaling factors, both enlarging or shrinking, and with different horizontal and vertical factors. See the Scale add-on sample code for an example. Note that the Be-supplied
DrawBitmap
call offers similar functionality, but that this one does not anti-alias, which has considerable impact on the result. Anti-aliasing does slow the process down considerably, so for realtime preview it is recommended you use the method withDrawBitmap
.
void AddWithAlpha (BBitmap *src, BBitmap *dest, long x, long y)
Bothsrc
anddest
must be 32 bitBBitmap
s. Thedest
bitmap is alpha blended on thesrc
bitmap, at the coordinates (x
,y
) in the coordinate space ofsrc
. The bitmaps need not be of the same size anddest
need not be contained withinsrc
, i.e. the necessary clipping is performed.This function is actually used by Becasso to paste a selection.
void CutOrCopy (BBitmap *src, BBitmap *dest, BBitmap *selection, long offx, long offy, bool cut)
This function expectssrc
anddest
to be 32 butBBitmap
s, andselection
to be an 8 bit selection map. It copiessrc
selectively intodest
via the selection map, i.e. the resulting alpha channel is taken from the selection map. The copying starts at offset (offx
,offy
) and fills the entiredest
bitmap. Ifcut
istrue
, the selection is also 'cut' (i.e. deleted) fromsrc
.This function is actually used by Becasso to cut/copy a selection. If
selection == NULL
, Becasso assumes a full selection.
rgb_color hsv2rgb (hsv_color c) rgb_color bgra2rgb (bgra_pixel c) rgb_color cmyk2rgb (cmyk_pixel c) hsv_color rgb2hsv (rgb_color c) hsv_color bgra2hsv (bgra_pixel c) hsv_color cmyk2hsv (cmyk_pixel c) bgra_pixel cmyk2bgra (cmyk_pixel c) bgra_pixel rgb2bgra (rgb_color c) bgra_pixel hsv2bgra (hsv_color c) cmyk_pixel bgra2cmyk (bgra_pixel c) cmyk_pixel rgb2cmyk (rgb_color c) cmyk_pixel hsv2cmyk (hsv_color c)
These functions convert pixels between various color spaces. The typesbgra_pixel
andcmyk_pixel
are actuallyuint32
's, with the color components in there as indicated by the name.
float diff (rgb_color a, rgb_color b)
Returns the luminance distance between the two given colors, as used for example to determine the closest match in the palette.
uchar clipchar (float x) float clipone (float x) float clipdegr (float x)
These functions return the value passed in, clipped to the given range. I.e. 0 <=Becasso further exports a number ofclipchar (x)
<= 255, 0 <=clipone (x)
<= 1, and 0 <=clipdegr(x)
< 360.
rgb_color
definitions, so that after including Colors.h
, you can
use Red
, Green
, Blue
,
Black
, White
, and several others.
bgra_pixel
bgra_pixel
pointer to a
char
pointer and extract the channel data this way,
because this would result in four consecutive byte memory reads. On
most modern processors, extracting a single longword on a 4-byte
aligned memory address is much faster. Unfortunately, the shifting
and masking required to extract the color channels from a single
32-bit longword is CPU-specific. Becasso offers a set of
macros that take care of this.
You can then get at the respective color channels like so:
bgra_pixel pixel = *pixelpointer; uint8 red = RED (pixel); uint8 green = GREEN (pixel); uint8 blue = BLUE (pixel); uint8 alpha = ALPHA (pixel);These are actually macros, defined in
BecassoAddOn.h
,
which take care of the Endianness issue when creating code that should
compile on both Intel Architecture and PowerPC machines. Take a look
in that header file for a lot more helpful macros.
bgra_pixel *src = (bgra_pixel *) inLayer->Bits(); bgra_pixel *dest = (bgra_pixel *) outLayer->Bits(); for (uint32 i = 0; i < layer->BitsLength()/4; i++) { *dest++ = do_something_with_pixel (*src++); }to
bgra_pixel *src = (bgra_pixel *) inLayer->Bits() - 1; // Note the -1 ! bgra_pixel *dest = (bgra_pixel *) outLayer->Bits() - 1; for (uint32 i = 0; i < layer->BitsLength()/4; i++) { *(++dest) = do_something_with_pixel (*(++src)); }