The Liquid Rescale library Manual

Carlo Baldassi


Table of Contents

1. Introduction
Copyright
About this document
Seam carving in brief
About enlarging
Overview of the library
Basic methods
2. LqR library API user manual
Signal handling
Generating the multi-size image
Carver object creation
Carver activation
Choosing the image type
Liquid rescaling
The resizing method
Flattening
Cancelling an action
Reading the multi-size image
Pixel by pixel
One line at a time
Resetting
Automatic feature detection
Foreword
Builtin energy functions
Custom energy functions
Reading out the energy
Adding a bias
Foreword
Adding a bias pixel by pixel
Using an array of floating-point values
Using another image
Operating on a specific area
Adding a rigidity mask
Foreword
Adding an individual rigidity coefficient to a pixel
Using an array of floating-point values
Using another image
Operating on a specific area
Tuning
Setting the enlargement step
Choosing the resize order
Choosing the side switch frequency
Using the cache
Dealing with the visibility maps (the seams)
Dumping the visibility map
Storing the visibility maps
Accessing the internally attached visibility maps
The visibility map objects
Importing a visibility map in a carver
Saving and loading visibility maps to/from files
Attaching extra images
Attaching a carver
Accessing attached carvers
Progress indicators
Creating and attaching a progress report object
Setting up progress hooks
Initial and ending progress messages
Progress update step
Releasing the memory
3. LqR library API reference
Types defined by the library
Carver objects
Visibiliy maps
Energy
Bias
Rigidity masks
Progress reports
4. References
A. API changes in new versions of the library
New symbols in version 0.4
New symbols in version 0.3
New symbols in version 0.2
Deprecated symbols

List of Tables

2.1. Image types assigned by default
2.2. Default progress messages
3.1. Image types assigned by default

List of Examples

2.1. A simple readout example
2.2. A simple readout example - extended version
2.3. Line-by-line readout example
2.4. Line-by-line readout example - extended version
2.5. Custom energy declaration
2.6. Custom energy definition and setup
2.7. Accessing visibility maps #1
2.8. Accessing visibility maps #2
2.9. Reading visibility maps data
2.10. Accessing attached carvers #1
2.11. Accessing attached carvers #2
2.12. Setting progress hooks
2.13. Progress hooks declaration

Chapter 1. Introduction

Copyright

Liquid Rescale Library Manual. Copyright (C) 2007-2009 Carlo Baldassi

This manual is released under the terms of the GNU General Public License as published by the Free Software Foundation; version 3 dated June, 2007.

You should have received a copy of the GNU General Public License along with the library; if not, see http://www.gnu.org/licenses

About this document

This manual describes in detail the Liquid Rescale library API, starting from a brief overview on seam carving, the internal image representation, a minimal list of basic methods and the full explanation of all the library public methods.

In the `examples' directory, you will find a minimal example program, which only uses basic methods, and a full-featured demo program, which uses almost all of the methods described in this document. Both programs are fully commented, see also the README file in the `examples' directory.

Refer to the README file for information about installing and compiling.

The latest version of the Liquid Rescale library and of this manual can be found at http://liblqr.wikidot.com.

Seam carving in brief

Basically, the rescaling algorithm tries to find out which parts of the image are important, and which are not, based on the contrast between adjacent pixels; then, the image is resized through the elimination or insertion of continuous paths, called `seams'. The seams connect the top of the image with the bottom when rescaling horizontally, or they connect the left side with the right side when rescaling vertically. In the seam carving process, seams are removed in sequence, therefore shrinking the image by one pixel at a time. The seam insertion process mirrors the seam carving process, introducing interpolated seams in regions where they would have been carved.

Once it has been computed, the carving information can be efficiently stored in a so called multi-sized image, which can be used to reproduce the carving operation on the fly at any later moment.

It often happens that the automatic feature detection fails to identify as significant some image regions; in these cases a preservation mask can be specified, which marks those regions. In fact, the feature recognition process can be manually driven quite easily to its full extent, by using custom masks.

See also the References section for more information about the algorithm.

About enlarging

As mentioneed above, the enlargment process mirrors the carving process. More precisely, in order to enlarge the image by a given amount of pixels, say N, the library first computes which would be the first N seams to be removed; then, it inserts N new seams nearby those.

This means that it is clearly not possible to go beyond twice the original size in a single step. It also means that doubling the image size in this way is just equivalent to standard scaling, since the result is that each seam is just duplicated. For these reasons, the library rescaling engine automatically divides enlarging sessions in steps, and allows to set the step size.

This same issue also affects in a tricky way the preservation of image areas when enlarging: suppose your image is 1000 pixels wide, and you have protected an area which is 800 pixels wide. It is then clear that you cannot shrink the image to less than 800 pixels without affecting the preserved area, but the same is true when enlarging, so you should not go beyond 1200 pixels in a single step (= 1000 + (1000 - 800)), i.e. you should use a value lower than 1.2 for the enlargement step size.

In general, however, the optimal enlargement step size depends on the image, since large step sizes have the disadvantages discussed above, while small step sizes will tend to inflate the same areas of the image over and over at each step.

Overview of the library

The Liquid Rescale library is written in C, but can be used into C++ programs without any modification. It has an object-oriented design, so that the terminology in this manual is borrowed from C++. The central class of the library is called LqrCarver. Carver objects can generate and store multi-size images, or load them, and read them out at the desired size.

Internally, multi-size images are stored simply as plain images with the addition of a visibility map. Each pixel in the image has its own visibility level. Whether to display a pixel or not simply depends on the comparison of each pixel's visibility with a given global visibility level. In this way, images of different sizes can be read out, simply by setting a global visibility level.

Therefore, once the visibility map has been computed, it allows effortless, real-time scaling. However, visibility maps also necessarily have an orientation, either horizontal or vertical. If we want to resize on the other direction, the visibility map has to be computed afresh, and the previous visibility map becomes useless, because the two maps are not consistent one with the other.

This also implies that the resizing order affects the final result: rescaling horizontally first, then vertically, does not yield the same result as following the reverse order. Moreover, one could choose an intermediate way, e.g. by rescaling by one pixel in one direction, one in the other, then iterating as needed to reach the final size.

The default behaviour of the library is to rescale horizontally first, then vertically, but this order can be reversed.

Visibility maps can be stored in objects of type LqrVMap. When an LqrCarver object is created from an input image, the visibility of each pixel is uninitialised. At this point, one could either import a previously computed LqrVMap, or activate the LqrCarver so that it creates one afresh when asked to.

In either case, there's a single method to call, specifiying the new desired size; all the rest will automatically be computed as necessary. By default, the visibility maps are only computed up to the extent to which they are needed for resizing.

Basic methods

Following is a list of the basic public methods associated with the LqrCarver objects:

  • constructors and destructor

    LqrCarver * lqr_carver_new (guchar *buffer, gint width, gint height, gint channels);
    LqrCarver * lqr_carver_new_ext (void *buffer, gint width, gint height, gint channels, LqrColDepth colour_depth);
    void lqr_carver_destroy (LqrCarver *carver);
                                

  • initialization

    LqrRetVal lqr_carver_init (LqrCarver *carver, gint delta_x, gfloat rigidity);
                                

  • image manipulations

    LqrRetVal lqr_carver_resize (LqrCarver *carver, gint new_width, gint new_width);
    LqrRetVal lqr_carver_flatten (LqrCarver *carver);
                                

  • readout

    gboolean lqr_carver_scan (LqrCarver *carver, gint *x, gint *y, guchar **rgb);
    gboolean lqr_carver_scan_ext (LqrCarver *carver, gint *x, gint *y, void **rgb);
    gboolean lqr_carver_scan_by_row (LqrCarver *carver);
    gboolean lqr_carver_scan_line (LqrCarver *carver, gint *n, guchar **rgb);
    gboolean lqr_carver_scan_line_ext (LqrCarver *carver, gint *n, void **rgb);
                                

  • get values

    gint lqr_carver_get_width (LqrCarver *carver);
    gint lqr_carver_get_height (LqrCarver *carver);
    gint lqr_carver_get_channels (LqrCarver *carver);
    LqrColDepth lqr_carver_get_col_depth (LqrCarver *carver);
                                

The fastest way to see how they work is having a look at the code of examples/liquidrescale-basic.cpp, which is a very simple and fully commented demostrative program.

The return value of many functions is of type LqrRetVal. This is just an enum type which can be used for signal handling, see the Signal handling section.

The other classes are optional: the class LqrVMap is used to hold the carving information (and the class LqrVMapList is used to retrieve it from the LqrCarver ojects); the class LqrProgress is used to customize progress report from the resizing engine (by default it is turned off).

A complete list of the library public methods can be found in the reference at the end of this document.

Chapter 2. LqR library API user manual

Signal handling

Many library functions return a value of type LqrRetVal. This is an enum type which can hold the values:

LQR_OK

everyting OK

LQR_ERROR

generic fatal error

LQR_NOMEM

not enough memory

LQR_USRCANCEL

action cancelled by the user

At top level, it is important that the user handle these values explicitly, because the library functions don't do anything else than stopping and returning an error signal in case of errors. An easy way is setting up some macros and wrap each function call with those, as shown in the example files.

Below top level, the library provides some convenient macros which can be used to wrap function calls, in order to propagate these signals:

LQR_CATCH (expr)

if expr is equal to LQR_OK it does nothing, otherwise it returns expr (or the result of the execution of expr if it happens to be a function)

LQR_CATCH_F (expr)

returns LQR_ERROR if expr is FALSE

LQR_CATCH_MEM (expr)

returns LQR_NOMEM if expr is NULL

Note

The names of these macros have changed since version 0.4; the previous names CATCH, CATCH_F and CATCH_MEM are still available, but they can be disabled at configure time if they cause conflicts (configure --help for details).

Generating the multi-size image

Carver object creation

The LqrCarver objects are initialised from a plain buffer representing an image. The default constructor assumes a colour depth of 8 bits per channel:

LqrCarver * lqr_carver_new( guchar *  buffer,
  gint  width,
  gint  height,
  gint  channels);

Here, buffer is the array representing an image of size width by height with channels colour channels per pixels. Thus, the overall buffer size has to be of widht * height * channels unsigned characters, and ordered such that the k-th colour of the pixel at row y and column x is found at:

buffer[(y * width + x) * channels + k]

(this assumes that x, y and k all start from 0 and reach the maximum values widht-1, height-1 and channels-1, respectively)

The function returns a pointer to the newly allocated LqrCarver upon success, or NULL in case of insufficient memory.

In order to create LqrCarver objects with more than 8 bits per channel, an extended version of the constructor must be used:

LqrCarver * lqr_carver_new_ext( void *  buffer,
  gint  width,
  gint  height,
  gint  channels,
  LqrColDepth  colour_depth);

The differnece with the default version is that the input buffer must be passed as void, and its type must be specified through the additional parameter colour_depth, which can take one of the following values:

LQR_COLDEPTH_8I

8 bit unsigned integers (guchar)

LQR_COLDEPTH_16I

16 bit unsigned integers (guint16)

LQR_COLDEPTH_32F

32 bit floating point (gfloat)

LQR_COLDEPTH_64F

64 bit floating point (gdouble)

Floating point type values must range between 0 and 1.

The library has some support for different image types and color models. When a LqrCarver object is created, the image type is automatically set from the number of channels (basically, assuming that the image is either grayscale or RGB with possibly an alpha channel), but it is important to set it manually using the function lqr_carver_set_image_type if your program has to deal with different color models. See the section Choosing the image type for more details.

By default, the buffer is assumed to be a copy of the original image, and therefore it is owned by the LqrCarver object and must not be accessed directly any more (and of course it must not be freed, the LqrCarver destructor does it). If, instead, you want the Liquid Rescale library to keep the buffer intact, you must flag the LqrCarver after creation (or after activation), using this function:

void lqr_carver_set_preserve_input_image( LqrCarver *  carver);

This function must be used before any other operation takes place.

Carver activation

The newly created LqrCarver consists only of the image buffer plus an uninitialised visibility map. If one had a previously computed visibility map, it could be imported into the LqrCarver and that would be enough (see the Importing a visibility map in a carver section).

If the visibility map has to be computed, the LqrCarver needs to be initialised through this function:

LqrRetVal lqr_carver_init( LqrCarver *  carver,
  gint  delta_x,
  gfloat  rigidity);

Here, delta_x is the maximum allowed transversal step of the seams (0 means straight seams, the typical value is 1), while the rigidity parameter can be used to introduce a global bias for non-straight seams (the typical value is 0; a nonzero value can be modulated locally for specific areas using the functions described in section Adding a rigidity mask).

Important

It is currently an error to initalise a carver object if a visibility map has been imported already.

Choosing the image type

The library supports a small number of different image types/color models in order to correctly compute quantities such as the brightness of a pixel, which are important for automatic feature detection.

The image type can be set manually using the function:

LqrRetVal lqr_carver_set_image_type( LqrCarver *  carver,
  LqrImageType  image_type);

The type LqrImageType is an enum which can take these values:

  • LQR_GREY_IMAGE
  • LQR_GREYA_IMAGE
  • LQR_RGB_IMAGE
  • LQR_RGBA_IMAGE
  • LQR_CMY_IMAGE
  • LQR_CMYK_IMAGE
  • LQR_CMYKA_IMAGE
  • LQR_CUSTOM_IMAGE

When creating a LqrCarver object, the image type is inferred from the number of channels according to this table:

Table 2.1. Image types assigned by default

channelstype
1LQR_GREY_IMAGE
2LQR_GREYA_IMAGE
3LQR_RGB_IMAGE
4LQR_RGBA_IMAGE
5LQR_CMYKA_IMAGE
>5LQR_CUSTOM_IMAGE


When setting a carver to LQR_CUSTOM_IMAGE, it is assumed that there are no alpha or black channels, but if there are, their index can be specified with the functions:

LqrRetVal lqr_carver_set_alpha_channel( LqrCarver *  carver,
  gint  channel_index);

LqrRetVal lqr_carver_set_black_channel( LqrCarver *  carver,
  gint  channel_index);

Use the value -1 in the indices arguments to unset those channels. Note that using LQR_CUSTOM_IMAGE in a carver normally requires special care in the choice and definitions of the energy functions (see the Automatic feature detection section).

Note

Setting manually the alpha or black channel with the above functions automatically sets the carver image type to LQR_CUSTOM_IMAGE.

Note

The support for CMY (and derived) color models is very naïve, since no color profiles are yet managed by the library.

Liquid rescaling

The resizing method

Once initialised, or if a visibility map has been loaded, the image can be resized through this function:

LqrRetVal lqr_carver_resize( LqrCarver *  carver,
  gint  new_width,
  gint  new_height);

This function decides automatically whether it can use the already computed visibility map, it has to update it or waste it completely and start afresh. This last event occurs when the map was computed for horizontal resizing and a vertical resize has been requested, or vice versa, and also when the required enlargment is bigger than the enlargement step value (see Setting the enlargement step). Note that only initialised carvers can update or change the visibility map; if this is not the case, an error is returned.

The function also takes advantage of the fact that the enlargment process mirrors the shrink process. For example, if the original size of the image is (w0, h0) and lqr_carver_resize is invoked with (w0 - 100, h0) as an argument, then subsequent calls to the function will allow on-the-fly resizing in the whole range from (w0 - 100, h0) to (w0 + 100, h0). (But note that this may be overcome if w0 + 100 is bigger than the enlargement step.)

Flattening

In order to resize in more than one step, the image can be flattened in its current state, thrugh this function:

gboolean lqr_carver_flatten( LqrCarver *  carver);

The return value is FALSE in case of insufficient memory, TRUE otherwise.

This function destroys the current visibility map and reinitialises the multi-size image from its current state.

Note

Every time that the image is flattened (including when changing the resize direction) the original image and all information about it is lost.

Cancelling an action

The resizing and flattening operations can be aborted using this function:

LqrRetVal lqr_carver_cancel( LqrCarver *  carver);

This function can be invoked asynchronously, from a different thread with respect to the one in which the resizing or flattening methods were called. If successful, this function will return LQR_OK, and any ongoing resizing or flattening functions will immidiately abort and return the special value LQR_USRCANCEL; however, this function will have no effect if no operation was in progress when calling it.

This function can be called multiple times.

Important

Whenever a function returns LQR_USRCANCEL, it means that the LqrCarver object is in an inconsistent state, and there is currently no way to recover from this situation. Therefore, any further operation on it must be avoided, and it must be destroyed.

Important

The functions lqr_carver_resize and lqr_carver_flatten are not the only ones which can return LQR_USRCANCEL; instead, any function in the library whose return type is LqrRetVal and which operates on LqrCarver objects can return such value: for example, any function will do so if called over a LqrCarver object for which an operation was actually cancelled (but this is not the only possibility).

Reading the multi-size image

Pixel by pixel

Once you have rescaled the image, you can read out the result through the functions:

gboolean lqr_carver_scan( LqrCarver *  carver,
  gint*  x,
  gint*  y,
  guchar**  rgb);

or

gboolean lqr_carver_scan_ext( LqrCarver *  carver,
  gint*  x,
  gint*  y,
  void**  rgb);

Here, x and y are pointers to the varaibles which will hold the pixel coordinate, while rgb is a pointer to an array which will contain the pixel colour information. If the carver was created using the standard 8-bit constructor lqr_carver_new, the first form can be used, otherwise you must use the extended form lqr_carver_scan_ext. In this last case, the output pointer rgb must be passed as a pointer to void*, but the outcome should actually be cast to a pointer to an array of the appropriate type, depending on the LqrCarver colour depth.

The return value is FALSE when the end of the image is reached, or the buffer has the wrong number of bits, TRUE otherwise.

Each time these functions are invoked, they will store the coordinates and rgb information in the output pointers and move to the next pixel. If they reach the end, they reset the reader and return FALSE.

Here is a sample code usage:

Example 2.1. A simple readout example

gint x, y;
guchar *rgb;

while (lqr_carver_scan (carver, &x, &y, &rgb) {
    my_plot (x, y, rgb[0], rgb[1], rgb[2]);
}
                        


In this example, it is assumed that the image has three 8-bit colour channels, and that there exist some function my_plot which writes out the pixels somewhere.

The same readout example with different colour depth would read like this:

Example 2.2. A simple readout example - extended version

gint x, y;
void *rgb;
gdouble *rgb_out;

while (lqr_carver_scan (carver, &x, &y, &rgb) {
    rgb_out = (gdouble*) rgb;
    my_plot (x, y, rgb_out[0], rgb_out[1], rgb_out[2]);
}
                        


In this example it is assumed that the carver was loaded with the LQR_COLDEPTH_64F as the colour_depth argument in the constructor lqr_carver_new_ext, and that it has 3 colour channels (see the constructor section for details); therefore, the output is cast to type gdouble before using it.

Important

The rgb array is owned by to the carver object, so it doesn't need initialization, as in the example. Indeed, it must be used for read-only purposes, and the content should always be copyed after each call to a scan function.

One line at a time

The image can also be read one line at a time, but it is not possible to freely decide if it is to be read by row or by column. Instead, this has to be queried by calling this function:

gboolean lqr_carver_scan_by_row(LqrCarver*  carver);

The function returns TRUE if the image is read by row, and FALSE if it is read by column.

Then, the image can be read through these functions:

gboolean lqr_carver_scan_line(LqrCarver*  carver,
 gint*  n,
 guchar**  rgb);

or

gboolean lqr_carver_scan_line_ext(LqrCarver*  carver,
 gint*  n,
 void**  rgb);

These functions work exactly the same way as lqr_carver_scan and lqr_carver_scan_ext, but only one coordinate is stored (either the row or the column number), and the rgb array will contain a whole line.

Here is a sample code usage for the standard 8-bit case:

Example 2.3. Line-by-line readout example

gint n;
guchar *rgb;
gboolean by_row;

by_row = lqr_carver_scan_by_row (carver);

while (lqr_carver_scan_line (carver, &n, &rgb) {
    by_row ? my_plot_row (n, rgb) : my_plot_col (n, rgb);
}
                        


where, as before, it is assumed that the my_plot_row and my_plot_col functions have been previously defined and "know what to do".

The extended version for images with more colour depth is very similar, it only requires an additional cast:

Example 2.4. Line-by-line readout example - extended version

gint n;
void *rgb;
guchar *rgb_out;
gboolean by_row;

by_row = lqr_carver_scan_by_row (carver);

while (lqr_carver_scan_line_ext (carver, &n, &rgb) {
    rgb_out = (gboolean*) rgb;
    by_row ? my_plot_row (n, rgb_out) : my_plot_col (n, rgb_out);
}
                        


Resetting

Normally, it is not needed to reset the image scan. However, if the scan has been stopped at same intermediate step for some reason, the following function can be used to restart from the beginning:

void lqr_carver_scan_reset(LqrCarver*  carver);

Automatic feature detection

Foreword

The automatic feature detection relies on the evaluation of the relevance of each pixel; this quantity is called `energy': the higher the energy of a pixel, the less likely it will be that such pixel will be directly involved in the rescaling. The energy function which the library uses can be customised; normally, edge detector filters are the best choices for this purpose.

There is a unified framework in the Liquid Rescale library for energy fucntions: briefly, each energy function used by the library receives the current position and image size as parameters, and is provided access to a square of values from the image, centered around the current position. This access is provided through an object which is called a "reading window", and the image pixels are not read directly, but rather they are accessed according to a "reader type", which means that the energy function can get e.g. the brightness of a pixel without needing to care for the underlying image representation, i.e. the image type or the colour depth.

The library provides a small set of very simple (yet normally effective) gradient-based energy functions, and a customisation framework for defining more functions.

Builtin energy functions

The library has some builtin functions for energy evaluation; in order to set one of the builtin functions in a LqrCarver object this function is used:

LqrRetVal lqr_carver_set_energy_function_builtin(LqrCarver*  carver,
 LqrEnergyFunctionBuiltinType  ef_ind);

The currently available builtin functions which can be used as ef_ind are:

LQR_EF_GRAD_XABS

absolute value of the brightness gradient in the direction of the rescaling (this is the default)

LQR_EF_GRAD_SUMABS

sum of absolute values of the brightness gradients in both directions

LQR_EF_GRAD_NORM

norm of the brightness gradient

LQR_EF_LUMA_GRAD_XABS

absolute value of the luma gradient in the direction of the rescaling

LQR_EF_LUMA_GRAD_SUMABS

sum of absolute values of the luma gradients in both directions

LQR_EF_LUMA_GRAD_NORM

norm of the luma gradient

LQR_EF_NULL

null

All of the above gradient functions have a radius of 1 pixel.

Custom energy functions

Custom energy functions for a LqrCarver object are set using this function:

LqrRetVal lqr_carver_set_energy_function(LqrCarver*  carver,
 LqrEnergyFunc  ef_func,
 gint  radius,
 LqrEnergyReaderType  reader_type,
 gpointer  extra_data);

Here, ef_func is the function (the prototype will be explained below), radius is used to set the size of the square region around each pixel which is used to evaluate the energy for that pixel, reader_type is used to set which quantity is used for the energy computation (e.g. brightness, luma etc.) and extra_data is a (void) pointer which can be used to pass additional parameters to the energy function.

The LqrEnergyReaderType is an enum which can take these values (also noted is the number of channels of the corresponging output):

LQR_ER_BRIGHTNESS

brightness (1 channel)

LQR_ER_LUMA

luma (1 channel)

LQR_ER_RGBA

RGBA (4 channels)

LQR_ER_CUSTOM

read the normalised image channels as they are (as many channels as the image has)

These readouts always return values beetween 0 and 1.

Note

Note that these readouts may have special meanings depending on the image type:

  • for LQR_GREY_IMAGE, LQR_GREYA_IMAGE and LQR_CUSTOM_IMAGE images, the LQR_ER_LUMA readout will yield the same result as LQR_ER_BRIGHTNESS

  • for LQR_CUSTOM_IMAGE images, the LQR_ER_BRIGHTNESS readout will return the average pixel value (additive, i.e. if a black channel is present the channel values will be inverted and multiplied by the black channel inverse), multiplied by the alpha channel value.

  • for LQR_CUSTOM_IMAGE images, the LQR_ER_RGBA readout cannot be used: it will always return 0

The custom energy function must be declared like in the following sample declaration:

Example 2.5. Custom energy declaration

gfloat my_energy (gint x, gint y, gint width, gint height, LqrReadingWindow *rwindow, gpointer extra_data);
                        


This function should return the energy at pixel x, y, based on the knowledge of the current image size (obtained from width and height) and the content of the image in a square around that pixel, which is passed through the rwindow reading window: in order to access this content, this function must be used:

gdouble lqr_rwindow_read(LqrReadingWindow *  rwindow,
 gint  x,
 gint  y,
 channel  channel);

When reading out the content from a window, the x and y parameters are relative to the window centre (which instead is given by the x, y parameters passed to the custom energy function), and they both range between -radius and radius included (radius being the same one which is used in lqr_carver_set_energy_function). The parameter channel specifies which channel to read out; depending on the read_type passed to lqr_carver_set_energy_function the range and meaning of this parameter will change: for the cases LQR_ER_BRIGHTNESS and LQR_ER_LUMA it must be 0, because the readout consists of a single channel, for LQR_ER_RGBA it must be between 0 and 3 (and then the readout will contain the RGBA information), while for LQR_ER_CUSTOM it must be one of the original image channels.

The rwindow parameters can be read out from within a custom defined energy function using these functions:

LqrEnergyReaderType lqr_rwindow_get_read_t(LqrReadingWindow *  rwindow);
gint lqr_rwindow_get_radius(LqrReadingWindow *  rwindow);
gint lqr_rwindow_get_channels(LqrReadingWindow *  rwindow);

Following is an example of how a simple Sobel fliter can be defined and used within this framework:

Example 2.6. Custom energy definition and setup

/* definition */

gfloat sobel(gint x, gint y, gint width, gint height, LqrReadingWindow *rw, gpointer extra_data)
{
    gint i, j;
    gdouble ex = 0;
    gdouble ey = 0;
    gdouble k[3][3] = {{0.125, 0.25, 0.125}, {0, 0, 0}, {-0.125, -0.25, -0.125}};

    for (i = -1; i <=1; i++) {
        for (j = -1; j <=1; j++) {
            ex += k[i + 1][j + 1] * lqr_rwindow_read(rw, i, j, 0);
            ey += k[j + 1][i + 1] * lqr_rwindow_read(rw, i, j, 0);
        }
    }
    return (gfloat) sqrt(ex * ex + ey * ey);
}

/* usage */

lqr_carver_set_energy_function (carver, sobel, 1, LQR_ER_BRIGHTNESS, NULL);
                        


In the above sobel function it is assumed that the radius is 1 and that the readout will consist of a single channel. Furthermore, no boundary checking is performed, and therefore the parameters x, y, width and height are not used. Also, no extra parameters are passed to the function.

Note

The function lqr_rwindow_read returns 0 when the requested value is out of the image boundary or beyond the reading window radius.

Note

The energy functions are called over the transposed image in case of vertical scaling, therefore, if they are asymmetrical, the result will be different depending on the scaling orientation (this is the case for example for the LQR_EF_GRAD_XABS builtin function).

Note

The energy function output should be normalised in order to be comparable with the builtin functions, otherwise the scale of the bias would be different depending on the energy function used. This is the reason why in the Sobel filter written above the kernel k is scaled so that the sum of the absolute values of the matrix is equal to 1.

Note

In actual code, the call to lqr_carver_set_energy_function should be protected to test its return value.

Reading out the energy

The energy can be read out with three similar functions, all of which fill a buffer provided by the user, but in different ways: two of them are suitable for plotting, while the third one can be used to retreive the true values of the energy, as used internally.

The first function can be used to get a buffer of normalised values, and it has a simple syntax:

LqrRetVal lqr_carver_get_energy(LqrCarver *  carver,
 gfloat *  buffer,
 gint  orientation);

This function writes the the energy values at the time of calling to the given buffer, ordered by row and then by column. All values range between 0 and 1. The buffer must be allocated by the user before calling it.

The orientation parameter determines which orientation will be used when computing the energy: 0 means horizontal, 1 means vertical.

The carver need not be initialised; if a bias was added to it (see the Adding a bias section), its effect is included in the output.

The above function does not return the true energy which is used internally, because that would not be suitable for plotting, since the energy range is arbitrary (only the energy differences are meaningful, and there is no upper nor lower bound to the values). In order to get the true energy values used internally, this function must be used instead (with the same syntax):

LqrRetVal lqr_carver_get_true_energy(LqrCarver *  carver,
 gfloat *  buffer,
 gint  orientation);

The last function can be used to fill directly an image buffer:

LqrRetVal lqr_carver_get_energy_image(LqrCarver *  carver,
 void *  buffer,
 gint  orientation,
 LqrColDepth  col_depth,
 LqrImageType  image_type);

In this case, the buffer must be passed as void*, while the col_depth and image_type are used to specify the colour depth and the image type, in the same way as is done when creating an LqrCarver object (see Carver objcet creation and the Choosing the image type sections). The only restriction is that it is not possible to ask for LQR_CUSTOM_IMAGE image types.

For any choice of the parameters, the buffer will hold a greyscale image, ranging from black (lowest energy) to white (highest energy). The opacity (alpha) will be set to 1, if present. All the information will be stored in the black channel in LQR_CMYK_IMAGE and LQR_CMYKA_IMAGE image types.

Note

Calling the function lqr_carver_get_energy_image with LQR_COLDEPTH_32F and LQR_GREY_IMAGE arguments will yield the same result as calling the function lqr_carver_get_image, but the latter is slightly more efficient.

Adding a bias

Foreword

The automatic feature detection can be driven manually by adding a bias to the pixels of the image.

For example, it is possible to protect regions of the image by adding a positive bias to the corresponding pixels. This will make the seams more unlikely to cross those regions, thus avoiding distortion (but increasing distortion of the other regions).

It is also possible to make the seams more likely to cross some regions by adding a negative bias to them. In this case, reducing the size of the image will tend to erase those regions, while (possibly) keeping the rest of the image in a consistent state.

Important

The bias has to be added before the resizing takes place (but it can be added before initialisation since version 0.4).

Note

In all of the bias-related functions, the bias is added on top of the existing one, so that all of the functions can be called multiple times.

Adding a bias pixel by pixel

The function to use in order to add a bias to a given pixel is:

LqrRetVal lqr_carver_bias_add_xy(LqrCarver*  carver,
 gdouble  bias,
 gint  x,
 gint  y);

Typical values for the bias parameter would be between 100 and 10000 in module.

Using an array of floating-point values

It is possible to use a whole array of floating points at once through this function:

LqrRetVal lqr_carver_bias_add(LqrCarver*  carver,
 gdouble*  buffer,
 gint  bias_factor);

Here, buffer is an array contining the bias values, and it is assumed to have the same size as the image loaded in carver, while bias_factor is an overall bias factor, which can be used to affect the global bias level: if the elements of buffer are of order 1, a standard choice for the bias_factor would be between 100 and 10000 (in module).

Note

This function, and all the following, will not swallow the buffer (to the contrary of what happens e.g. when creating a new LqrCarver object and allowing the default behaviour), therefore the buffer must be freed by the user afterwards.

Using another image

The bias can also be read from an 8-bit rgb buffer. This buffer has to be in the same format as the one used in the 8-bit LqrCarver constructor (but may have a different number of colours per channel). The function is:

LqrRetVal lqr_carver_bias_add_rgb(LqrCarver*  carver,
 guchar*  buffer,
 gint  bias_factor,
 gint  channels);

As in the previous case, buffer is assumed to hold and image of the same size as the one in the carver.

The buffer contents will be transformed into floating-points by averaging the colour components and multiplying the result by the alpha channel (transparency) value.

Important

The existence of an alpha channel is inferred from the channels value: if this is 1 or 3, no alpha channel is assumed, if it is 2 or 4 or greater, it is assumed that the last channel holds the alpha value. If this is not what you want, you should resort to one of the previous methods.

Operating on a specific area

The two previously described functions operate on the whole LqrCarver image. It is also possible to access specific image regions in a similar way; for the floating point case use:

LqrRetVal lqr_carver_bias_add_area(LqrCarver*  carver,
 gdouble*  buffer,
 gint  bias_factor,
 gint  width,
 gint  height,
 gint  x_off,
 gint  y_off);

while for the rgb image case use:

LqrRetVal lqr_carver_bias_add_rgb_area(LqrCarver*  carver,
 guchar*  buffer,
 gint  bias_factor,
 gint  channels,
 gint  width,
 gint  height,
 gint  x_off,
 gint  y_off);

In both functions, width and height are used to specify the size of the area of interest, while x_off and y_off specify its offset. For the rest, both functions work in the same way as their global couterpart.

The provided buffers have to be of size width * height (or width * height * channels for the rgb case) but the specified areas need not to be strictly included inside the LqrCarver image area : only the parts which overlap with it will be used. For example, the offsets can also be negative.

Adding a rigidity mask

Foreword

The rigidity parameter which is set at carver activation time (see section Carver activation) normally affects the whole image. It is possible, however, to specify which areas of the image should be affected by using a rigidity mask.

When a rigidity mask is used, each pixel of the image acquires an individual rigidity coefficient, which has to be multiplied with the overall rigidity parameter to get the actual pixel's rigidity. This is useful in some situations to reduce distorsions in specific areas of the image while keeping the seams optimal in other areas.

The library interface to deal with rigidity masks follows very closely the scheme for bias masks as described in the bias section, the main difference being that no equivalent to the bias factor has to be provided (since it is already given in the lqr_carver_init function).

Important

The rigidity mask has to be added always after the LqrCarver initialization and before resizing takes place. (Note that this is different from the bias, which instead can also be added to non-initialised carver objects.)

Important

Whenever a rigidity mask is set, all pixels for which the value is not explicitly defined will have coefficient 0, i.e. the rigidity setting will will be disabled.

Note

All of the functions can be called multiple times, but their effect is not summed up, to the contrary of what happens for the bias functions; instead, new values will substitute old ones when the affected regions overlap.

Adding an individual rigidity coefficient to a pixel

The function to use in order to set the rigidity mask at a given pixel is:

LqrRetVal lqr_carver_rigmask_add_xy(LqrCarver*  carver,
 gdouble  rigidity,
 gint  x,
 gint  y);

Using an array of floating-point values

It is possible to use a whole array of floating points at once through this function:

LqrRetVal lqr_carver_rigmask_add(LqrCarver*  carver,
 gdouble*  buffer);

Here, buffer is an array contining the rigidity coefficients values, and it is assumed to have the same size as the image loaded in carver.

Note

This function, and all the following, will not swallow the buffer (to the contrary of what happens e.g. when creating a new LqrCarver object and allowing the default behaviour), therefore the buffer must be freed by the user afterwards.

Using another image

The rigidity mask can also be read from an 8-bit rgb buffer. This buffer has to be in the same format as the one used in the 8-bit LqrCarver constructor (but may have a different number of colours per channel). The function is:

LqrRetVal lqr_carver_rigmask_add_rgb(LqrCarver*  carver,
 guchar*  buffer,
 gint  channels);

As in the previous case, buffer is assumed to hold and image of the same size as the one in the carver.

The buffer contents will be transformed into floating-points by averaging the colour components and multiplying the result by the alpha channel (transparency) value.

Important

The existence of an alpha channel is inferred from the channels value: if this is 1 or 3, no alpha channel is assumed, if it is 2 or 4, it is assumed that the last channel is holds the alpha value. If this is not what you want, you should resort to one of the previous methods.

Operating on a specific area

The two previously described functions operate on the whole LqrCarver image. It is also possible to access specific image regions in a similar way; for the floating point use:

LqrRetVal lqr_carver_rigmask_add_area(LqrCarver*  carver,
 gdouble*  buffer,
 gint  width,
 gint  height,
 gint  x_off,
 gint  y_off);

while for the rgb image use:

LqrRetVal lqr_carver_rigmask_add_rgb_area(LqrCarver*  carver,
 guchar*  buffer,
 gint  channels,
 gint  width,
 gint  height,
 gint  x_off,
 gint  y_off);

In both functions, width and height are used to specify the size of the area of interest, while x_off and y_off specify its offset. For the rest, both functions work in the same way as their global couterpart.

The provided buffers have to be of size width * height (or width * height * channels for the rgb case) but the specified areas need not to be strictly included inside the LqrCarver image area : only the parts which overlap with it will be used. For example, the offsets can also be negative.

Tuning

The behaviour can be tuned through some additional functions.

Setting the enlargement step

As mentioned in About enlarging, if the requested final size is too big, the rescaling is automatically divided in steps.

For example, let us suppose that we have created an LqrCarver object from a 100 by 100 pixels image, and that we call lqr_carver_resize with 600 and 100 as width and height arguments. With the default settings, the rescaling of the width will be performed in 3 steps: first, from 100 to 199, then from 199 to 397, and finally from 397 to 600.

The rule here is that the maximum size which can be reached in a single step is equal to twice the original size minus one, and that at each step the original size is reset to the current size (through an internal call to lqr_carver_flatten).

In most situations, however, the steps should be smaller in order to obtain good results. This can be set with this function:

LqrRetVal lqr_carver_set_enl_step( LqrCarver *  carver,
  gfloat  enl_step);

The value of enl_step must be strictly grater then 1.0 and less then (or equal to) 2.0. The default value is 2.0 (for back-compatibility reasons); any other value will result in the function returning an error. The new maximum size for a step will then be obtained by multiplying the original size by the enlargement step and subtracting 1.

The current value of the enlargement step can be retrieved with this function:

gfloat lqr_carver_get_enl_step( LqrCarver *  carver);

Choosing the resize order

When the function lqr_carver_resize is asked to resize along both directions in a single step, it has to choose which direction to resize first. The resize order can be changed through this function:

void lqr_carver_set_resize_order(LqrCarver*  carver,
 LqrResizeOrder  resize_order);

The possible values for resize_order are:

LQR_RES_ORDER_HOR

resize horizonally first (this is the default)

LQR_RES_ORDER_VERT

resize vertically first

Choosing the side switch frequency

When the function lqr_carver_resize is invoked, it chooses at each step the optimal seam to carve based on the relvance value for each pixel. However, in the case two seams are equivalent (which may happen when large portions of the image have the same colour, for example), the algorithm always chooses the seams from one side, which might be a problem (e.g. an object centered in the original image might not be centered any more in the resulting image).

In order to overcome this effect, an option is given to automatically switch the favoured side during rescaling, at the cost of a slightly worse performance. The number of times such a switching event occurs for each rescale operation can be set using the function:

void lqr_carver_set_side_switch_frequency(LqrCarver*  carver,
 guint  switch_frequency);

The default value for newly created LqrCarver objects is 0, which is equivalent to disabling this feature. Giving a value greater than the number of pixels by which to rescale produces a switch for each pixel, therefore you could set switch_freqency to a ridicolously high value in order to be sure to get this effect.

As for the final result, a very small value (e.g. 1 to 4) will normally suffice to balance the left and right side of the image (or the top and the bottom sides for vertical rescalings), without noticeable computational costs. However, in order to obtain a smoother behaviour for the visibiliy map, i.e. for the intermediate steps, higher values may be required.

Using the cache

By default, the library tries to cache some quantities in order to save computational time. The cache may be disabled in order to save memory instead, using this function:

void lqr_carver_set_use_cache(LqrCarver*  carver,
 gboolean  use_cache);

To disable the cache, set use_cache to FALSE. To re-enable it back, set it to TRUE.

Dealing with the visibility maps (the seams)

Dumping the visibility map

The visibility map can be saved at any moment by calling the function:

LqrVMap* lqr_vmap_dump(LqrCarver*  carver);

This function will return a pointer to a newly allocated LqrVMap object, or NULL in case of failure. See also the section "The visibility map objects".

Storing the visibility maps

By default, the computed visibility maps are wasted. Instead of saving them individually, it is possible to automatically dump them at the end of the carving process, attaching them to their associated LqrCarver. In order to activate this feature, the following function has to be called:

void lqr_carver_set_dump_vmaps(LqrCarver*  carver);

This will have the effect of dumping the visibility map each time lqr_carver_resize is invoked, and storing it internally. When resizing along both directions, two maps will be dumped, one for each direction.

In order to revert the effect of lqr_carver_set_dump_vmaps, thus stopping the automatic dumping, use the function

void lqr_carver_set_no_dump_vmaps(LqrCarver*  carver);

Alternatively, the internal storage mechanism can be called over the current visibility map at any given moment by calling this function:

LqrRetVal lqr_vmap_internal_dump(LqrCarver*  carver);

The dumped maps are stored inside LqrVMap objects, and these are attached to their corresponing LqrCarver object through a linked list, whose type is LqrVMapList

Accessing the internally attached visibility maps

To access the maps attached to a carver one has first to obtain the pointer to the list, with the function:

LqrVMapList* lqr_vmap_list_start(LqrCarver*  carver);

Then, one can iterate through the attached maps by using these two functions:

LqrVMap* lqr_vmap_list_current(LqrVMapList*  list);

LqrVMapList* lqr_vmap_list_next(LqrVMapList*  list);

Here is a sample code usage:

Example 2.7. Accessing visibility maps #1

LqrVMap *vmap;
LqrVMapList *list;

list = lqr_vmap_list_start (carver);
while (list) {
    vmap = lqr_vmap_list_current (list);
    /* ... do something on vmap ... */
    list = lqr_vmap_list_next (list);
}
                        


The maps will always be accessed in the order in which they were dumped.

Alternatively, one can apply a function to all the elements of the list, through this function:

LqrRetVal lqr_vmap_list_foreach(LqrVMapList*  list,
 LqrVMapFunc  func,
 gpointer  data);

To use this second method, you'll need to define a function first, as in this sample code:

Example 2.8. Accessing visibility maps #2

LqrRetVal my_func (LqrVMap vmap, gpointer data)
{
    /* ... do something on vmap ... */
    return LQR_OK;
}

LqrVMapList *list;

list = lqr_vmap_list_start (carver);
lqr_vmap_list_foreach (list, my_func, NULL);
                        


In the above example, no data is actually passed on to the function.

Note

In actual code the call to lqr_vmap_list_foreach should be protected to test its return value, which is LQR_OK if all my_func calls have been successful, or it will hold the first non-successful return value from my_func.

The visibility map objects

The LqrVMap objects contain an int buffer with the actual map data (plain array, ordered by row), plus all the information needed to be able to recover it from scratch.

The information can be extracted with these functions:

gint* lqr_vmap_get_data (LqrVMap* vmap);
gint lqr_vmap_get_width (LqrVMap* vmap);
gint lqr_vmap_get_height (LqrVMap* vmap);
gint lqr_vmap_get_orientation (LqrVMap* vmap);
gint lqr_vmap_get_depth (LqrVMap* vmap);
                    

The first one returns a pointer to the data buffer.

The orientation of the map is 0 if the map is to be used for horizontal rescaling, 1 otherwise.

The depth of the map is the maximum amount of rescaling possible with that map, either shrinking or enlarging.

Example 2.9. Reading visibility maps data

If we have a LqrVMap pointer called vmap, we could access the value at (x,y) by:

gint *buffer;
gint width;
gint vis;

buffer = lqr_vmap_get_data (vmap);
width = lqr_vmap_get_width (vmap);
vis =  buffer[y * width + x];
                        

Uninitialised points will yield vis = 0. For initialised points, vis will store a positive value between 1 (least visible points, the first to be carved away or to be duplicated) and (depth + 1) (most visible points, the last to be carved away or to be duplicated).

If the orientation is 0, the map allows resizing in the whole range form (width - depth) to (width + depth). If the orientation is 1, the analogue formula holds with height in place of width.


Importing a visibility map in a carver

Having an LqrVMap object, one can load it in an LqrCarver simply by calling this function:

LqrRetVal lqr_vmap_load(LqrCarver*  carver,
 LqrVMap*  vmap);

The carver must not to be initialised, neither before nor after invoking this function.

Note

This implies that the map cannot be updated, and that it will only be possible to resize the carver by an amount depth along the orientation given by lqr_vmap_orientation. The enlargment step is also set to its maximum, 2.0. Invoking lqr_carver_resize with an out-of-bounds argument results in a fatal error (i.e. it returns LQR_ERROR).

Note

Do not attach other carvers after you have loaded a visibility map (see also the Attaching extra images section).

Saving and loading visibility maps to/from files

The library does not include methods to load/save visibility maps to/from files. However, a way to do so is shown in the demo program `liquidrescale' in the `examples' directory.

Attaching extra images

Attaching a carver

Given an LqrCarver object, it is possible to attach an arbitrary number of extra carvers to it: these will passively undergo the same carving process as the root carver. In order for this to be possible, the carvers must be all of the same size.

The function to use is simply:

LqrRetVal lqr_carver_attach(LqrCarver*  carver,
 LqrCarver*  aux);

This attaches aux to carver.

It is not necessary that the parent LqrCarver is activated. In fact, a carver can be attached to a carver which is itself attached to another one.

Needless to say, no resizing operation should be done directly on an LqrCarver once it has been attached to another LqrCarver, and neither should the cancel method be invoked directly on them.

Important

The carvers always have to be attached before loading visibility maps.

Accessing attached carvers

Attached carvers can be read-out in the same way as their parents. There are however also methods to span all them, in a way very similar to that in which internally dumped LqrVMap's are accessed, but LqrVMapList objects are substitued in this case by LqrCarverList objects.

First, the starting point of the list has to be retreived through:

LqrCarverList* lqr_carver_list_start(LqrCarver*  carver);

Then, one can iterate through the attached carvers by using these two functions:

LqrCarver* lqr_carver_list_current(LqrCarverList*  list);

LqrCarverList* lqr_carver_list_next(LqrCarverList*  list);

Here is a sample code usage:

Example 2.10. Accessing attached carvers #1

LqrCarver *aux;
LqrCarverList *list;

list = lqr_carver_list_start (carver);
while (list) {
    aux = lqr_carver_list_current (list);
    /* ... do something on aux ... */
    list = lqr_carver_list_next (list);
}
                        


The carvers will always be accessed in the order in which they were attached.

Alternatively, one can apply a function to all the elements of the list (and recursively to all the elements of their attached lists, if there are any), through this function:

LqrRetVal lqr_carver_list_foreach_recursive(LqrCarverList*  list,
 LqrCarverFunc  func,
 LqrDataTok  data);

To use this second method, you'll need to define a function first, as in the following sample code:

Example 2.11. Accessing attached carvers #2

LqrRetVal my_func (LqrCarver *aux, LqrDataTok data)
{
    /* ... do something on aux ... */
    return LQR_OK;
}

LqrCarverList *list;
LqrDataTok data_tok;

list = lqr_carver_list_start (carver);
data_tok->data = NULL;
lqr_carver_list_foreach_recursive (list, my_func, data_tok);
                        


The data to be passed on to the LqrCarverFunc is of type LqrDataTok. This is defined as a union, with the following fields:

  • LqrCarver* carver

  • gint integer

  • gpointer data

In the above example, no data is actually passed on to the function.

Note

In actual code, the call to lqr_carver_list_foreach_recursive should be protected to test its return value, which is LQR_OK if all my_func calls have been successful (or if the list is empty), or it will hold the first non-successful return value from my_func.

Progress indicators

By default, the resizing performed silently. However, it is possible to define progress report functions, to receive feedback while the resizing is in progress. This is done through the LqrProgress objects.

Creating and attaching a progress report object

A LqrProgress object is created through the function:

LqrProgress* lqr_progress_new(void); 

and can be associated to an LqrCarver object through this function:

void lqr_carver_set_progress(LqrCarver*  carver,
 LqrProgress*  p);

Setting up progress hooks

Newly created progress objects are inactive, and need to be set up.

First, hook functions have to be set, which specify the action to take as the rescaling process starts, progresses, and ends, by using the functions:

LqrRetVal lqr_progress_set_init (LqrProgress * p, LqrProgressFuncInit init_func)
LqrRetVal lqr_progress_set_update (LqrProgress * p, LqrProgressFuncUpdate update_func)
LqrRetVal lqr_progress_set_end (LqrProgress * p, LqrProgressFuncEnd end_func)
                    

as in this sample piece of code:

Example 2.12. Setting progress hooks

LqrProgress *p;

p = lqr_progress_new();
lqr_progress_set_init (p, my_init);
lqr_progress_set_update (p, my_update);
lqr_progress_set_end (p, my_end);
                        


The above example requires that the hook functions my_init, my_update and my_end are defined as in the following sample declarations:

Example 2.13. Progress hooks declaration

LqrRetVal my_init (const gchar *init_message);
LqrRetVal my_update (gdouble percentage);
LqrRetVal my_end (const gchar *end_message);
                        


Initial and ending progress messages

The init and end hooks will be called at the beginning and at the end of each rescaling operation by function lqr_carver_resize. The messages that will be passed to these hooks will change, depending if the resizing is occurring in the horizontal or in the vertical direction. The defaults for newly created LqrProgress objects are:

Table 2.2. Default progress messages

 initend
horizontal"Resizing width...""done"
vertical"Resizing height...""done"


These can be changed using these functions:

LqrRetVal lqr_progress_set_init_width_message (LqrProgress *p, const gchar * message)
LqrRetVal lqr_progress_set_init_height_message (LqrProgress *p, const gchar * message)
LqrRetVal lqr_progress_set_end_width_message (LqrProgress *p, const gchar * message)
LqrRetVal lqr_progress_set_end_height_message (LqrProgress *p, const gchar * message)
                    

Progress update step

The update hook will be called at regular intervals, and it will be passed the completion percentage as the argument.

The update step can be specified through:

LqrRetVal lqr_progress_set_update_step(LqrProgress*  p,
 gfloat  update_step);

The default step is 0.02 (i.e. 2%).

Releasing the memory

LqrCarver objects can be destroyed using this function:

void lqr_carver_destroy(LqrCarver*  carver);

This function also destroys any attached object, thus it should never be called on attached carvers.

LqrVMap objects can be destroyed using this function:

void lqr_vmap_destroy(LqrVMap*  vmap);

Chapter 3. LqR library API reference

Types defined by the library

LqrRetVal — the return value of many Liquid Rescale library functions
LqrColDepth — carver objects colour depth specification
LqrImageType — carver objects image type (colour model) specification

Name

LqrRetVal — the return value of many Liquid Rescale library functions

Description

The return type of many functions in the Liquid Rescale library is LqrRetVal, which is an enum type that can take these values:

LQR_OK

everyting OK

LQR_ERROR

generic fatal error

LQR_NOMEM

not enough memory

LQR_USRCANCEL

action cancelled by the user

The user should handle the error values explicitly at each function call returning this type.


Name

LqrColDepth — carver objects colour depth specification

Description

The default LqrCarver object constructor lqr_carver_new uses a colour depth of 8 bits per channel, and therefore its input must be an array of unsigned chars. However, the LqrCarver objects can handle images of grater colour depth, if they are created with the lqr_carver_new_ext constructor. The possible colour depths are specified through variables of type LqrColDepth, which is an enum type; its possible values, and the type of the input buffer associated with them, are:

LQR_COLDEPTH_8I

use type guchar (8 bit unsigned integers) - the default

LQR_COLDEPTH_16I

use type guint16 (16 bit unsigned integers)

LQR_COLDEPTH_32F

use type gfloat (32 bit floating point)

LQR_COLDEPTH_64F

use type gdouble (64 bit floating point)

These values are also relevant when reading out a LqrCarver object with the functions lqr_carver_scan_ext or lqr_carver_scan_line_ext, since the readout buffer must be cast to the appropriate type to be actually read.

The colour depth of an LqrCarver object can be obtained with the function lqr_carver_get_col_depth.


Name

LqrImageType — carver objects image type (colour model) specification

Description

The LqrCarver objects use knowledge about the image type they're working on in order to compute correctly some quantities (e.g. the brightness) for the automatic feature detection. Image types are set automatically by the constructors, but they can also be specified manually using quantities of the type LqrImageType, which is an enum which can take these values:

  • LQR_GREY_IMAGE
  • LQR_GREYA_IMAGE
  • LQR_RGB_IMAGE
  • LQR_RGBA_IMAGE
  • LQR_CMY_IMAGE
  • LQR_CMYK_IMAGE
  • LQR_CMYKA_IMAGE
  • LQR_CUSTOM_IMAGE

Use the function lqr_carver_set_image_type(3) to set the image type of a carver, and the function lqr_carver_get_image_type(3) to read it out.

Carver objects

lqr_carver_new — the LqrCarver object constructors
lqr_carver_destroy — the LqrCarver object destructor
lqr_carver_init — activates an LqrCarver object
lqr_carver_set_image_type — sets the image type of an LqrCarver object
lqr_carver_set_alpha_channel — sets the alpha channel index in a LqrCarver object
lqr_carver_set_black_channel — sets the black channel index in a LqrCarver object
lqr_carver_resize — liquid rescale a LqrCarver object
lqr_carver_flatten — flatten a LqrCarver object
lqr_carver_cancel — cancel ongoing operations on a LqrCarver object
lqr_carver_scan_reset — reset the readout cursor of a multi-size image
lqr_carver_scan — read out a multi-size image one pixel at a time
lqr_carver_scan_by_row — tells if the image in LqrCarver will be scanned by row or by column
lqr_carver_scan_line — read out a multi-size image one line at a time
lqr_carver_get_width — get the current width of a LqrCarver object
lqr_carver_get_height — get the current height of a LqrCarver object
lqr_carver_get_ref_width — get the reference width of a LqrCarver object
lqr_carver_get_ref_height — get the reference height of a LqrCarver object
lqr_carver_get_channels — get the number of channels in a LqrCarver object
lqr_carver_get_col_depth — get the colour depth of a LqrCarver object
lqr_carver_get_image_type — get the image type of a LqrCarver object
lqr_carver_get_enl_step — get the enlargement step of a LqrCarver object
lqr_carver_get_orientation — get the orientation of a LqrCarver object
lqr_carver_get_depth — get the depth of a LqrCarver object
lqr_carver_set_enl_step — set the enlargement step of a LqrCarver object
lqr_carver_set_resize_order — set LqrCarver object resize order
lqr_carver_set_dump_vmaps — set the visibility maps autodump for an LqrCarver object
lqr_carver_set_side_switch_frequency — set LqrCarver object side switch frequency
lqr_carver_set_progress — set the progress report function for an LqrCarver object
lqr_carver_set_preserve_input_image — set a flag to preserve the buffer passed to a LqrCarver object upon creation
lqr_carver_set_use_cache — enable/disable LqrCarver object cache
lqr_carver_attach — attach an LqrCarver to another LqrCarver
lqr_carver_list_start — get the staritng point of the attachement list in an LqrCarver object
lqr_carver_list_current — get current LqrCarver object in a LqrCarverList object
lqr_carver_list_next — advance the LqrCarverList object
lqr_carver_list_foreach — perform operations on all LqrCarver objects in an LqrCarverList object

Name

lqr_carver_new, lqr_carver_new_ext — the LqrCarver object constructors

Synopsis

#include <lqr.h>
LqrCarver* lqr_carver_new(guchar*  buffer,
 gint  width,
 gint  height,
 gint  channels);
LqrCarver* lqr_carver_new_ext(void*  buffer,
 gint  width,
 gint  height,
 gint  channels,
 LqrColDepth  colour_depth);

Description

The functions lqr_carver_new and lqr_carver_new_ext create a new LqrCarver object from an image of size width * height with channels colour channels.

The image must be stored in buffer as a plain array of unsigned chars (for lqr_carver_new) or the appropriate type cast to void (for lqr_carver_new_ext), ordered by row, then by column, then by colour channel.

In the extended constructor lqr_carver_new_ext, the additional parameter colour_depth is required to specify the colour depth of the buffer (see LqrColDepth(3) for more information).

After calling the function, the buffer will be owned by the LqrCarver object and must not be accessed any more, unless you subsequently call the lqr_carver_set_preserve_input_image(3) function.

The image type is et automatically from the value of channels according to this table:

Table 3.1. Image types assigned by default

channelstype
1LQR_GREY_IMAGE
2LQR_GREYA_IMAGE
3LQR_RGB_IMAGE
4LQR_RGBA_IMAGE
5LQR_CMYKA_IMAGE
>5LQR_CUSTOM_IMAGE


Return value

The return value is the address of the newly created LqrCarver object, or NULL in case of failure (insufficient memory).


Name

lqr_carver_destroy — the LqrCarver object destructor

Synopsis

#include <lqr.h>
void lqr_carver_destroy(LqrCarver*  carver);

Description

The function lqr_carver_destroy destroys the LqrCarver object pointed to by carver, and all of its attched components (visibility maps and attached carvers). It must never be invoked over a carver which is attached to another one.

This function will not release the memory buffer passed to lqr_carver_new(3) if it was protected by calling lqr_carver_set_preserve_input_image(3).


Name

lqr_carver_init — activates an LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_init(LqrCarver*  carver,
 gint  delta_x,
 gfloat  rigidity);

Description

The function lqr_carver_init initialises the LqrCarver pointed to by carver, so that it can compute the visibility maps as needed upon calls of lqr_carver_resize.

The parameter delta_x controls the maximum transversal step a seam can make. A value of 0 means straight seams. Normally, it is set to 1.

The parameter rigidity can be used to add a negative bias to non-straight seams, and it is normally set to 0.

Visibility maps must not be loaded with the function lqr_vmap_load when using this function, neither before nor after invoking it.

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_carver_set_image_type — sets the image type of an LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_set_image_type(LqrCarver*  carver,
 LqrImageType  image_type);

Description

The function lqr_carver_set_image_type sets the image type of the LqrCarver pointed to by carver to image_type.

If image_type is equal to LQR_CUSTOM_IMAGE, it is assumed that there are no alpha or black channels. You can set those independently using lqr_carver_set_alpha_channel(3) and lqr_carver_set_black_channel(3).

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_carver_set_alpha_channel — sets the alpha channel index in a LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_set_alpha_channel( LqrCarver *  carver,
  gint  channel_index);

Description

The function lqr_carver_set_alpha_channel sets the alpha channel index of the image stored in the LqrCarver pointed to by carver to channel_index (between 0 and channels - 1, where channels is the number of colour channels of the carver).

Use a negative value for cahnnel_index to specify that no alpha channel is present.

If the specified channel coincides with the current value of the black channel, the black channel is unset.

Calling this function sets the image time of the carver to LQR_CUSTOM_IMAGE.

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_carver_set_black_channel — sets the black channel index in a LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_set_black_channel( LqrCarver *  carver,
  gint  channel_index);

Description

The function lqr_carver_set_black_channel sets the black channel index of the image stored in the LqrCarver pointed to by carver to channel_index (between 0 and channels - 1, where channels is the number of colour channels of the carver).

Use a negative value for cahnnel_index to specify that no black channel is present.

If the specified channel coincides with the current value of the alpha channel, the alpha channel is unset.

Calling this function sets the image time of the carver to LQR_CUSTOM_IMAGE. Furthermore, the image color model will be assumed to be subtractive by the function lqr_rwindow_read(3) when it computes the brightness or the luma.

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_carver_resize — liquid rescale a LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_resize(LqrCarver*  carver,
 gint  new_width,
 gint  new_height);

Description

The function lqr_carver_resize performs the liquid rescaling over the LqrCarver object pointed to by carver. If a visibility map was loaded through the function lqr_vmap_load, and the carver was not initialised, the resizing operations must be limited to the direction and the sizes included in the loaded map. If the carver was initialised through the function lqr_carver_init, there are no limitations to the final size.

The resizing function can be called multiple times, and it will decide automatically whether the computation of the visibility map is necessary or not. In case it isn't, the function returns almost immediately, otherwise operations will proceed following the order given through the function lqr_carver_set_resize_order. Currently, on-the-fly rescaling without computation is only possible for a single direction at a time.

If the new size (in one direction or in both) is greater than or equal to the original size multiplied by the enlargement step of the carver object (as obtained through lqr_carver_get_enl_step(3)), the rescaling will be performed in multiple steps. At each step, the original size stored internally is reset to the new value; therefore, each step in the process can be bigger then the previous one.

Whenever the resizing dirction changes (this may happen in a single call of the rescaling function or through multiple calls), or if performing a multiple steps enlargement as per the previous paragraph, the visibility map computed during the first direction rescale is dropped to make place for the one for the second (and the original size of the image is reset to the current value). These visibility maps can be saved by using the lqr_carver_set_vmap_dump function, for inspection or future use.

Return value

The return value follows the Liquid Rescale library signalling system. It returns an error if trying to exceed the limitations of a loaded visibility map, or if passed a negative or null size.


Name

lqr_carver_flatten — flatten a LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_flatten(LqrCarver*  carver);

Description

The function lqr_carver_flatten can be used to discard the visibility map information and flatten the multi-size image contained in the LqrCarver object pointed to by carver to its current state.

It will also reset the internally stored original width and height, as if the image was just loaded in the LqrCarver object.

This function must only be invoked over initialised LqrCarver objects.

This function is called internally each time the rescaling direction changes, or at each new step in a multiple-step enlargement, but, when calling it manually, the discarded visibility map will not be dumped automatically by it; use the functions lqr_vmap_dump(3) or lqr_vmap_internal_dump(3) in order to save it before invoking this function.

Return value

The return value follows the Liquid Rescale library signalling system. Errors can occur for non-initialised LqrCarver objects or in case of insufficient memory.


Name

lqr_carver_cancel — cancel ongoing operations on a LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_cancel(LqrCarver*  carver);

Description

The function lqr_carver_cancel can be used to cancel an ongoing operation which is currently being performed on the the LqrCarver object pointed to by carver. It must be used asynchronouly, from within an independent thread.

If an operation is in fact cancelled by this function, the function which was performing the operation will return the value LQR_USRCANCEL, and so will do any other operation successively called on the same LqrCarver object whose return type is LqrRetVal; otherwise it will have no effect.

Whenever a function returns LQR_USRCANCEL, it means that the LqrCarver object is in an inconsistent state, and, since there is currently no way to recover from this situation, any further operation on that object must be avoided, and it must be destroyed.

This function will fail if invoked over attached LqrCarver objects.

Return value

The return value follows the Liquid Rescale library signalling system. However, it can be called multiple times, so it will never return LQR_USRCANCEL itself.


Name

lqr_carver_scan_reset — reset the readout cursor of a multi-size image

Synopsis

#include <lqr.h>
void lqr_carver_scan_reset(LqrCarver*  carver);

Description

The function lqr_carver_scan_reset resets the readout pointer associated with the LqrCarver object pointed to by carver to the start of the image. (Normally, calling this function isn't needed, as the pointer is reset automatically whenever an operation is performed or once a readout has completed.)


Name

lqr_carver_scan, lqr_carver_scan_ext — read out a multi-size image one pixel at a time

Synopsis

#include <lqr.h>
gboolean lqr_carver_scan(LqrCarver*  carver,
 gint*  x,
 gint*  y,
 guchar**  rgb);
gboolean lqr_carver_scan_ext(LqrCarver*  carver,
 gint*  x,
 gint*  y,
 void**  rgb);

Description

The functions lqr_carver_scan and lqr_carver_scan_ext are used to read out the multi-size image contained in the LqrCarver object pointed to by carver one pixel at a time. They store the pixel coordinates in the variables pointed to by x and y, and the pixel content in the array pointed to by rgb; then they move the readout pointer to the next pixel, or they reset it if the end of the image is reached.

The first one must only be used on the LqrCarver objects created with lqr_carver_new, i.e. with 8-bit images, while the second one is general (see LqrColDepth(3)), but the rgb pointer must be cast to the appropriate type to be used (i.e pass the address of a pointer to void to the function lqr_carver_scan_ext, then cast it to a pointer of the appropriate type and use this last one for reading the output).

The rgb variable will point to an array which is internal to the LqrCarver object, so there is no need to allocate memory for it. However, it should only be accessed right after a call to the scan functions, and writing to it must be avoided.

Return value

These functions return TRUE in case the readout is successful and the end of the image was not reached, FALSE otherwise. If lqr_carver_scan is called over a non-8-bit LqrCarver object, it will return FALSE.


Name

lqr_carver_scan_by_row — tells if the image in LqrCarver will be scanned by row or by column

Synopsis

#include <lqr.h>
gboolean lqr_carver_scan_by_row(LqrCarver*  carver);

Description

The function lqr_carver_scan_by_row must be used before calling the functions lqr_carver_scan_line and lqr_carver_scan_line_ext, in order to ascertain if those functions will scan the multi-size image contained in the LqrCarver object pointed to by carver by row or by column, which depends on which was last rescaling direction and cannot be controlled directly by the user.

Return value

This function returns TRUE in case the image is going to be scanned by row, FALSE in case it is going to be scanned by column;


Name

lqr_carver_scan_line, lqr_carver_scan_line_ext — read out a multi-size image one line at a time

Synopsis

#include <lqr.h>
gboolean lqr_carver_scan_line(LqrCarver*  carver,
 gint*  n,
 guchar**  rgb);
gboolean lqr_carver_scan_line_ext(LqrCarver*  carver,
 gint*  n,
 void**  rgb);

Description

The functions lqr_carver_scan_line and lqr_carver_scan_line_ext are used to read out the multi-size image contained in the LqrCarver object pointed to by carver one line at a time. They store the line number (row or column) in the variable pointed to by n and the colour values in the array pointed to by rgb; then they move the readout pointer to the next line, or they reset it if the end of the image is reached.

The first one must only be used on the LqrCarver objects created with lqr_carver_new, i.e. with 8-bit images, while the second one is general, but the rgb pointer must be cast to the appropriate type to be used (i.e pass the address of a pointer to void to the function lqr_carver_scan_line_ext, then cast it to a pointer of the appropriate type and use this last one for reading the output).

Use the function lqr_carver_scan_by_row(3) before calling these to know whether your image will be scanned by row or by column.

Return value

These functions return TRUE in case the readout is successful and the end of the image was not reached, FALSE otherwise. If lqr_carver_scan_line is called over a non-8-bit LqrCarver object, it will return FALSE.


Name

lqr_carver_get_width — get the current width of a LqrCarver object

Synopsis

#include <lqr.h>
gint lqr_carver_get_width(LqrCarver*  carver);

Description

The function lqr_carver_get_width returns the current width of the image contained in the LqrCarver object pointed to by carver, in pixel units.


Name

lqr_carver_get_height — get the current height of a LqrCarver object

Synopsis

#include <lqr.h>
gint lqr_carver_get_height(LqrCarver*  carver);

Description

The function lqr_carver_get_height returns the current height of the image contained in the LqrCarver object pointed to by carver, in pixel units.


Name

lqr_carver_get_ref_width — get the reference width of a LqrCarver object

Synopsis

#include <lqr.h>
gint lqr_carver_get_ref_width(LqrCarver*  carver);

Description

The function lqr_carver_get_ref_width returns the internal reference width of the image contained in the LqrCarver object pointed to by carver, in pixel units.

The reference width is set as the original height at carver initialization, and reset any time the carver gets subsequently flattened, either explicitly through lqr_carver_flatten(3) or implicitly when the rescale direction changes or an enlargment beyond the maximum enlargement step is performed.


Name

lqr_carver_get_ref_height — get the reference height of a LqrCarver object

Synopsis

#include <lqr.h>
gint lqr_carver_get_ref_height(LqrCarver*  carver);

Description

The function lqr_carver_get_ref_height returns the internal reference height of the image contained in the LqrCarver object pointed to by carver, in pixel units.

The reference height is set as the original height at carver initialization, and reset any time the carver gets subsequently flattened, either explicitly through lqr_carver_flatten(3) or implicitly when the rescale direction changes or an enlargment beyond the maximum enlargement step is performed.


Name

lqr_carver_get_channels, lqr_carver_get_bpp — get the number of channels in a LqrCarver object

Synopsis

#include <lqr.h>
gint lqr_carver_get_channels(LqrCarver*  carver);
gint lqr_carver_get_bpp(LqrCarver*  carver);

Description

The functions lqr_carver_get_channels returns the number of colour channels of the image contained in the LqrCarver object pointed to by carver.

The function lqr_carver_get_bpp is an alias for lqr_carver_get_channels, it is deprecated and it is maintained for backward compatibility purposes only.


Name

lqr_carver_get_col_depth — get the colour depth of a LqrCarver object

Synopsis

#include <lqr.h>
LqrColDepth lqr_carver_get_col_depth(LqrCarver*  carver);

Description

The function lqr_carver_get_col_depth returns the colour depth of the image contained in the LqrCarver object pointed to by carver.


Name

lqr_carver_get_image_type — get the image type of a LqrCarver object

Synopsis

#include <lqr.h>
LqrImageType lqr_carver_get_image_type(LqrCarver*  carver);

Description

The function lqr_carver_get_image_type returns the image type (i.e. colour model) of the image contained in the LqrCarver object pointed to by carver.


Name

lqr_carver_get_enl_step — get the enlargement step of a LqrCarver object

Synopsis

#include <lqr.h>
gfloat lqr_carver_get_enl_step(LqrCarver*  carver);

Description

The function lqr_carver_get_enl_step returns the enlargement step of the LqrCarver object pointed to by carver, i.e. the maximum enlargement allowed in a single step for that carver, expressed as the ratio with respect to its reference width (for horizontal rescalings) or height (for vertical rescalings). The returned value is strictly greater than 1 and less than 2.


Name

lqr_carver_get_orientation — get the orientation of a LqrCarver object

Synopsis

#include <lqr.h>
gint lqr_carver_get_orientation(LqrCarver*  carver);

Description

The function lqr_carver_get_orientation returns the current orientation of the visibility map internal to the LqrCarver object pointed to by carver, which is 0 if the last rescale operation has been in the horizontal direction, 1 if it has been in the vertical direction.


Name

lqr_carver_get_depth — get the depth of a LqrCarver object

Synopsis

#include <lqr.h>
gint lqr_carver_get_depth(LqrCarver*  carver);

Description

The function lqr_carver_get_depth returns the current depth of the visibility map internal to the LqrCarver object pointed to by vmap, i.e. the maximum amount of scaling which can be performed with respect to the internal reference sizes in the current orientation without updating the internal map.


Name

lqr_carver_set_enl_step — set the enlargement step of a LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_set_enl_step(LqrCarver*  carver,
 gfloat  enl_step);

Description

The function lqr_carver_set_enl_step sets the enlargement step of the LqrCarver object pointed to by carver to the value specified in enl_step, which must be strictly greater than 1 and less than 2.

The enlargement step is the maximum enlargement ratio (with respect to either the original width or original height of carver) which the function lqr_carver_resize applies in a single step; if that function is asked a greater enlargement, it divides the process in multiple steps (and updates the original sizes accordingly at each new step - these can be readout at any time with lqr_carver_get_ref_width(3) and lqr_carver_get_ref_height(3)).

The default value for new LqrCarver objects is 2.0.

Return value

The return value follows the Liquid Rescale library signalling system. LQR_ERROR is returned if the enl_step parameter is out of bounds.


Name

lqr_carver_set_resize_order — set LqrCarver object resize order

Synopsis

#include <lqr.h>
void lqr_carver_set_resize_order(LqrCarver*  carver,
 LqrResizeOrder  resize_order);

Description

When the function lqr_carver_resize(3) is invoked and both the horizontal and vertical sizes are different from the current ones, the rescaling occurs first in one direction and then in the other.

The function lqr_carver_set_resize_order can be used to set which direction to rescale first for the LqrCarver object pointed to by carver. The parameter resize_order can take either the value LQR_RES_ORDER_HOR (horizontal rescale first) or LQR_RES_ORDER_VERT (vertical rescale first). By default, when an LqrCarver object is created, the value is set to LQR_RES_ORDER_HOR


Name

lqr_carver_set_dump_vmaps, lqr_carver_set_no_dump_vmaps — set the visibility maps autodump for an LqrCarver object

Synopsis

#include <lqr.h>
void lqr_carver_set_dump_vmaps(LqrCarver*  carver);
void lqr_carver_set_no_dump_vmaps(LqrCarver*  carver);

Description

Invoking function lqr_carver_set_dump_vmaps over the LqrCarver object pointed to by carver has the effect of activating the automatic dumping of visibility maps at each rescale operation (which by default is turned off).

Rescale operations involving both directions will dump two maps.

The dumped maps will be attached to the LqrCarver object and can be accessed at any later time using the functions lqr_vmap_list_foreach(3) or a combination of lqr_vmap_list_start(3), lqr_vmap_list_current(3) and lqr_vmap_list_next(3).

Using this setting is pointless if the LqrCarver object is not initialised.

The function lqr_carver_set_no_dump_vmaps reverts the effect of the previous one (but the maps dumped so far will be kept).

Note that it is also possible to dump the visibility maps manually; however, using the automatic dump is the only way to get intermidiate maps when the function lqr_carver_resize(3) performs the rescaling in both directions, or in more than one step.


Name

lqr_carver_set_side_switch_frequency — set LqrCarver object side switch frequency

Synopsis

#include <lqr.h>
void lqr_carver_set_side_switch_frequency(LqrCarver*  carver,
 guint  switch_frequency);

Description

When the function lqr_carver_resize(3) is invoked, it computes a relevance value for each pixel in the image, then chooses the optimal seam to carve based on such relvance values. However, in the case two seams are equivalent (which may happen when large portions of the image have the same colour, for example), the algorithm always chooses the seams from one side.

In order to overcome this effect, an option is given to automatically switch the favoured side during rescaling, at the cost of a slightly worse performance.

The function lqr_carver_set_side_switch_frequency sets the side switch frequency to switch_frequency for the LqrCarver object pointed to by carver. This will have the effect that, for each rescale operation, the favoured side will be switched switch_frequency times (or as much times as the number of pixels to rescale).

The default value for newly created LqrCarver objects is 0.

As for the final result, a very small value (e.g. 1 to 4) will normally suffice to balance the left and right side of the image (or the top and the boddom sides for vertical rescalings), without noticeable computational costs. However, in order to obtain a smoother behaviour for the visibiliy map, i.e. for the intermediate steps, higher values may be required.


Name

lqr_carver_set_progress — set the progress report function for an LqrCarver object

Synopsis

#include <lqr.h>
void lqr_carver_set_progress(LqrCarver*  carver,
 LqrProgress*  p);

Description

The function lqr_carver_set_progress associates the progress indicator pointed to by progress to the LqrCarver object pointed to by carver. Progress indicators objects are created with the function lqr_progress_new(3).

By default, no progress indicator is used.


Name

lqr_carver_set_preserve_input_image — set a flag to preserve the buffer passed to a LqrCarver object upon creation

Synopsis

#include <lqr.h>
void lqr_carver_set_preserve_input_image(LqrCarver*  carver);

Description

The function lqr_carver_set_preserve_input_image flags the LqrCarver object pointed to by carver so that it does not alter in any way the buffer which is passed to it by the constructor. It must be used before any resizing-related operation takes place, either after the carver construction or after the calls to lqr_carver_init(3) or lqr_vmap_load(3).


Name

lqr_carver_set_use_cache — enable/disable LqrCarver object cache

Synopsis

#include <lqr.h>
void lqr_carver_set_use_cache(LqrCarver*  carver,
 gboolean  use_cache);

Description

The function lqr_carver_set_use_cache can be used to disable or enable the cache for the LqrCarver object pointed to by carver.

By default, the caching is on.


Name

lqr_carver_attach — attach an LqrCarver to another LqrCarver

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_attach(LqrCarver*  carver,
 LqrCarver*  aux);

Description

The function lqr_carver_attach is used to attach an LqrCarver object (pointed to by aux) to another one (pointed to by carver). This will have the effect that each operation performed over the carver object will be reflected on aux (they will share the same visibility map).

This function must not be used after a visibility map was loaded into the base object (the one pointed to by carver).

The object pointed to by aux must have the same original size as the base object. Note that the original size information is reset whenever a flattening operation occurs, or the rescaling direction changes, so that this function should be called befor rescaling occurs.

There is no limitation on the number of LqrCarver objects which is possible to attach. Nesting is also possible. It is irrelevant if the aux carver is initialised or not; from the moment of attachment, it will passively undergo all transformations performed over carver.

Return value

The return value follows the Liquid Rescale library signalling system. LQR_ERROR is returned if the sizes of carver and aux don't match.


Name

lqr_carver_list_start — get the staritng point of the attachement list in an LqrCarver object

Synopsis

#include <lqr.h>
LqrCarverList* lqr_carver_list_start(LqrCarver*  carver);

Description

The function lqr_carver_list_start returns the stating point of the LqrCarverList object associated with the LqrCarver object pointed to by carver, which is used to keep track of the LqrCarver objects attached to it.

The returned value is NULL if there are no attached carvers.

Use the functions lqr_carver_list_current(3) and lqr_carver_list_next(3) to access the list element individually, or the function lqr_carver_list_foreach(3) to operate on whole lists.


Name

lqr_carver_list_current — get current LqrCarver object in a LqrCarverList object

Synopsis

#include <lqr.h>
LqrCarver* lqr_carver_list_current(LqrCarverList*  list);

Description

The function lqr_carver_list_current returns a pointer to the LqrCarver object corresponding to the current value of the list parameter, or NULL in case of errors.


Name

lqr_carver_list_next — advance the LqrCarverList object

Synopsis

#include <lqr.h>
LqrCarverList* lqr_carver_list_next(LqrCarverList*  list);

Description

The function lqr_carver_list_next returns a pointer to the next attached LqrCarver object in list, or NULL if the list has reached the end.


Name

lqr_carver_list_foreach — perform operations on all LqrCarver objects in an LqrCarverList object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_list_foreach(LqrCarverList*  list,
 LqrCarverFunc  func,
 LqrDataTok  data);
LqrRetVal lqr_carver_list_foreach_recursive(LqrCarverList*  list,
 LqrCarverFunc  func,
 LqrDataTok  data);

Description

The function lqr_carver_list_foreach can be used to apply the function func to all the LqrCarver objects listed in list. The parameter data is used to pass arguments to the function.

The list value should be obtained through the function lqr_carver_list_start(3). The order in the list will then follow the one in which carver objects were attached.

The function func is of type LqrCarverFunc, whose prototype is defined by:

typedef LqrRetVal (*LqrCarverFunc) (LqrCarver *carver, LqrDataTok data);
                        

The data argument is of type LqrDataTok, which is defined as a union with the following fields:

  • LqrCarver* carver

  • gint integer

  • gpointer data

The function lqr_carver_list_foreach_recursive is equivelant to lqr_carver_list_foreach, but it works recursively if the LqrCarver objects in list have themselves other attached LqrCarver objects attached. In this case, the function func will be applied to each element of the list and to each element of the attached list recursively, before moving on to the next element.

Visibiliy maps

lqr_vmap_new — the LqrVMap object constructor
lqr_vmap_destroy — the LqrVMap object destructor
lqr_vmap_get_data — get varous LqrVMap object quantities
lqr_vmap_get_depth — get the depth of an LqrVMap object
lqr_vmap_get_width — get the width of an LqrVMap object
lqr_vmap_get_height — get the height of an LqrVMap object
lqr_vmap_get_orientation — get the orientation of an LqrVMap object
lqr_vmap_dump — dump an LqrVMap object
lqr_vmap_internal_dump — dump an LqrVMap objects into an LqrCarver object
lqr_vmap_load — load an LqrVMap object into an LqrCarver object
lqr_vmap_list_start — get the LqrVMapList list attached to an LqrCarver
lqr_vmap_list_current — get current LqrVMap object in a LqrVMapList object
lqr_vmap_list_next — advance the LqrVMapList object
lqr_vmap_list_foreach — perform operations on all LqrVMap objects in an LqrVMapList object

Name

lqr_vmap_new — the LqrVMap object constructor

Synopsis

#include <lqr.h>
LqrVMap* lqr_vmap_new(gint*  buffer,
 gint  width,
 gint  height,
 gint  depth,
 gint  orientation);

Description

The function lqr_vmap_new is the constructor for LqrVMap objects. It can be used to convert saved data in a format which can be loaded in an LqrCarver object.

The parameter buffer must point to an an array of width * height ints holding the visibility information.

The parameter depth represents the maximum possible amount of rescaling with the given map.

The parameter orientation must be 0 if the map is to be used for horizontal rescaling, 1 if it is to be used for vertical rescaling.

Visibility maps format

The buffer must be an array of integers of size width * height. For an horizontally oriented visibility map, the format is as such: each row must contain all values between 1 and depth (included) exactly once, with low values indicating the pixels which will be operated on first during rescaling. All other pixels must be 0, which means that they won't be affected by rescaling. Such a map allows for horizontal rescaling in the range from width - depth to width + depth. The same applies to vertically oriented visibility maps, with columns in place of rows and height in place of width.

Return value

The function returns the newly created LqrVMap if successful, or NULL in case of insufficient memory.


Name

lqr_vmap_destroy — the LqrVMap object destructor

Synopsis

#include <lqr.h>
void lqr_vmap_destroy(LqrVMap*  vmap);

Description

The function lqr_vmap_destroy destroys the LqrVMap object. It is not necessary to invoke it over visibility maps which were loaded in LqrCarver objects, as this is done already by the carver object destructor.


Name

lqr_vmap_get_data — get varous LqrVMap object quantities

Synopsis

#include <lqr.h>
gint* lqr_vmap_get_data(LqrVMap*  vmap);

Description

The function lqr_vmap_get_data returns an array with the data stored into the LqrVMap object pointed to by vmap, ordered first by row, then by column.

Reading the data requires retrieval of the other quantities, through the functions lqr_vmap_get_depth(3), lqr_vmap_get_width(3), lqr_vmap_get_height(3) and lqr_vmap_get_orientation(3).

See the LqrVMap objects format description in the page for lqr_vmap_new(3).


Name

lqr_vmap_get_depth — get the depth of an LqrVMap object

Synopsis

#include <lqr.h>
gint lqr_vmap_get_depth(LqrVMap*  vmap);

Description

The function lqr_vmap_get_depth returns the depth of the LqrVMap object pointed to by vmap, i.e. the maximum scaling allowed by it.

See the LqrVMap objects format description in the page for LqrVMap constructor and destructor.


Name

lqr_vmap_get_width — get the width of an LqrVMap object

Synopsis

#include <lqr.h>
gint lqr_vmap_get_width(LqrVMap*  vmap);

Description

The function lqr_vmap_get_width returns the width of the LqrVMap object pointed to by vmap.

See the LqrVMap objects format description in the page for LqrVMap constructor and destructor.


Name

lqr_vmap_get_height — get the height of an LqrVMap object

Synopsis

#include <lqr.h>
gint lqr_vmap_get_height(LqrVMap*  vmap);

Description

The function lqr_vmap_get_height returns the height of the LqrVMap object pointed to by vmap.

See the LqrVMap objects format description in the page for LqrVMap constructor and destructor.


Name

lqr_vmap_get_orientation — get the orientation of an LqrVMap object

Synopsis

#include <lqr.h>
gint lqr_vmap_get_orientation(LqrVMap*  vmap);

Description

The function lqr_vmap_get_orientation returns the orientation of the LqrVMap object pointed to by vmap, which is 0 for horizontally oriented maps, 1 for vertically oriented ones.

See the LqrVMap objects format description in the page for LqrVMap constructor and destructor.


Name

lqr_vmap_dump — dump an LqrVMap object

Synopsis

#include <lqr.h>
LqrVMap* lqr_vmap_dump(LqrCarver*  carver);

Description

The function lqr_vmap_dump returns the current visibility map of the LqrCarver object pointed to by carver, or NULL in case of errors.


Name

lqr_vmap_internal_dump — dump an LqrVMap objects into an LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_vmap_internal_dump(LqrCarver*  carver);

Description

The function lqr_vmap_internal_dump dumps the current visibility map of the LqrCarver object pointed to by carver internally to it, attaching it to the same LqrVMapList object list as the one used for automatic dumping (as activated by lqr_carver_set_dump_vmaps(3).


Name

lqr_vmap_load — load an LqrVMap object into an LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_vmap_load(LqrCarver*  carver,
 LqrVMap*  vmap);

Description

The function lqr_vmap_load loads the visibility map contained in the LqrVMap object pointed to by vmap in the LqrCarver object pointed to by carver.

It can only be called over uninitialised carver objects, therefore care must be taken not to exceed the loaded map depth when resizing (see the LqrVMap objects format description in the page for lqr_vmap_new(3)).

The return value follows the Liquid Rescale library signalling system.


Name

lqr_vmap_list_start — get the LqrVMapList list attached to an LqrCarver

Synopsis

#include <lqr.h>
LqrVMapList* lqr_vmap_list_start(LqrCarver*  carver);

Description

The function lqr_vmap_list_start returns the stating point of the LqrVMapList object associated with the LqrCarver object pointed to by carver, which is used to keep track of the LqrVMap objects internally dumped by it.

The returned value is NULL if there are no dumped visibility maps.

The function lqr_vmap_list_current returns the LqrVMap object corresponding to the current value of the list parameter, or NULL in case of errors.

Use the functions lqr_vmap_list_current(3) and lqr_vmap_list_next(3) to access the list element individually, or the function lqr_vmap_list_foreach(3) to operate on whole lists.


Name

lqr_vmap_list_current — get current LqrVMap object in a LqrVMapList object

Synopsis

#include <lqr.h>
LqrVMap lqr_vmap_list_current(LqrVMapList*  list);

Description

The function lqr_vmap_list_current returns the LqrVMap object corresponding to the current value of the list parameter, or NULL in case of errors.


Name

lqr_vmap_list_next — advance the LqrVMapList object

Synopsis

#include <lqr.h>
LqrVMapList lqr_vmap_list_next(LqrVMapList*  list);

Description

The function lqr_vmap_list_next returns a pointer the next dumped LqrVMap object in list, or NULL if the list has reached the end.


Name

lqr_vmap_list_foreach — perform operations on all LqrVMap objects in an LqrVMapList object

Synopsis

#include <lqr.h>
LqrRetVal lqr_vmap_list_foreach(LqrVMapList*  list,
 LqrVMapFunc  func,
 gpointer  data);

Description

The function lqr_vmap_list_foreach can be used to apply the function func to all the LqrVMap objects listed in list. The parameter data is used to pass arguments to the function.

The list value should be obtained through the function lqr_vmap_list_start(3).

The function func is of type LqrVMapFunc, whose prototype is defined by:

typedef LqrRetVal (*LqrVMapFunc) (LqrVMap *vmap, gpointer data);
                        

The data argument is of type gpointer, which is just a pointer to void.

Energy

lqr_carver_set_energy_function_builtin — set a builtin energy function for a LqrCarver object
lqr_carver_set_energy_function — set a custom energy function for a LqrCarver object
lqr_carver_get_energy — get the energy map for a LqrCarver object
lqr_rwindow_read — read the content of a LqrReadingWindow object
lqr_rwindow_get_read_t — get the reader type of a LqrReadingWindow object
lqr_rwindow_get_radius — get the size of the region accessible from a LqrReadingWindow object
lqr_rwindow_get_channels — get the number of channels of a LqrReadingWindow object
lqr_carver_set_gradient_function — set the gradient function for an LqrCarver object

Name

lqr_carver_bias_set_energy_function_builtin — set a builtin energy function for a LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_set_energy_function_builtin(LqrCarver*  carver,
 LqrEnergyFuncBuiltinType  ef_ind);

Description

The function lqr_carver_set_energy_function_builtin allows to pick a builtin energy function for the LqrCarver object pointed to by carver.

The possible values for ef_ind are:

LQR_EF_GRAD_XABS

absolute value of the brightness gradient in the direction of the rescaling (this is the default)

LQR_EF_GRAD_SUMABS

sum of absolute values of the brightness gradients in both directions

LQR_EF_GRAD_NORM

norm of the brightness gradient

LQR_EF_LUMA_GRAD_XABS

absolute value of the luma gradient in the direction of the rescaling

LQR_EF_LUMA_GRAD_SUMABS

sum of absolute values of the luma gradients in both directions

LQR_EF_LUMA_GRAD_NORM

norm of the luma gradient

LQR_EF_NULL

null

All of the above gradient functions have a radius of 1 pixel.

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_carver_bias_set_energy_function — set a custom energy function for a LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_set_energy_function(LqrCarver*  carver,
 LqrEnergyFunc  en_func,
 gint  radius,
 LqrEnergyReaderType  reader_type,
 gpointer  extra_data);

Description

The function lqr_carver_set_energy_function assigns the energy function en_func to the LqrCarver object pointed to by carver (see below for more details on custom functions definitions).

The parameter radius determines the size of the square region which affects the computation around each pixel (the side of the square will be 2 * radius + 1 pixels long).

The parameter reader_type sets the reader type used when reading the image, and therefore it determines what quantity will be passed on to the function en_func (see below for more details on reader types).

The parameter extra_data is a (void) pointer which can be used to pass on additional values to the function ef_func.

Custom functions definition

The function en_func must be of type LqrEnergyFunc, whose prototype is defined by:

typedef gfloat (*LqrEnergyFunc) (gint x, gint y, gint img_width, gint img_height, LqrReadingWindow * rwindow, gpointer extra_data);
                        

Such a function is expected to compute the energy at pixel x, y based on the knowledge of the current image size (obtained from width and height) and the content of the image in a square around that pixel, which is passed through the rwindow reading window.

In most cases, the parameters x, y, width and height would only be used to determine whether the region under consideration is at the image boundary or not.

The rwindow content must be read using the function lqr_rwindow_read(3).

Reader types

The LqrEnergyReaderType is an enum which can take these values (also noted is the number of channels of the corresponging reading window):

LQR_ER_BRIGHTNESS

brightness (1 channel)

LQR_ER_BRIGHTNESS

luma (1 channel)

LQR_ER_RGBA

RGBA (4 channels)

LQR_ER_CUSTOM

read the normalised image channels as they are (as many channels as the image has)

These readouts always return values beetween 0 and 1.

Note that these readouts may have special meanings depending on the image type:

  • for LQR_GREY_IMAGE, LQR_GREYA_IMAGE and LQR_CUSTOM_IMAGE images, the LQR_ER_LUMA readout will yield the same result as LQR_ER_BRIGHTNESS

  • for LQR_CUSTOM_IMAGE images, the LQR_ER_BRIGHTNESS readout will return the average pixel value (additive, i.e. if a black channel is present the channel values will be inverted and multiplied by the black channel inverse), multiplied by the alpha channel value.

  • for LQR_CUSTOM_IMAGE images, the LQR_ER_RGBA readout cannot be used: it will always return 0

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_carver_get_energy, lqr_carver_get_true_energy, lqr_carver_get_energy_image — get the energy map for a LqrCarver object

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_get_energy(LqrCarver*  carver,
 gfloat *  buffer,
 gint  orientation);

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_get_true_energy(LqrCarver*  carver,
 gfloat *  buffer,
 gint  orientation);

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_get_energy(LqrCarver*  carver,
 void *  buffer,
 gint  orientation,
 LqrColDepth  col_depth,
 LqrImageType  image_type);

Description

The function lqr_carver_get_energy writes the energy map of the LqrCarver object pointed to by carver to the given buffer, in a format suitable for plotting: all values are in the range between 0 and 1, and the true values are mapped nonlinearly and stretched on this whole range, so that the differences between the middle values are enhanced with respect to very high or very low values.

The orientation parameter must be either 0 to get the energy map used for horizontal scalings, or 1 to get the map for vertical scalings.

The buffer must be allocated by the user before calling this function, and its size must be at least width * height, where width and height are the current width and height of the carver. The energy values are ordered by row first, then by column.

The outcome will include the effect of the bias added to the carver, if any.

This function can be called over non-initialised LqrCarver objects, e.g. to provide previews on the effect of different energy functions, but it can also be invoked at any later time. Note, however, that in this latter case the carver could be flattened if necessary, therefore the function invocation is potentially destructive of the internal visibiliy map.

The function lqr_carvet_get_true_energy is identical to the previous one, but the resulting buffer will contain the true energy, not scaled nor shifted.

The function lqr_carver_get_energy_image is very similar to the function lqr_carveR_get_energy, but it can be used to fill directly an image buffer of the format specified through the additional parameters col_depth and image_type (see LqrColDepth(3) and LqrImageType(3)). The buffer must be passed as void*, but it must point to a memory area with sufficient allocated space for the chosen image type and colour depth. The image type cannot be LQR_CUSTOM_IMAGE.

For any choice of the parameters describing the image, the resulting buffer will hold a greyscale image, ranging from black (lowest energy) to white (highest energy). The opacity (alpha) will be set to 1, if present. All the information will be stored in the black channel in LQR_CMYK_IMAGE and LQR_CMYKA_IMAGE image types.

Return values

The return values follow the Liquid Rescale library signalling system. The function lqr_carver_get_energy_image will return an error if image_type is LQR_CUSTOM_IMAGE.


Name

lqr_rwindow_read — read the content of a LqrReadingWindow object

Synopsis

#include <lqr.h>
gfloat lqr_rwindow_read(LqrReadingWindow*  rwindow,
 gint  x,
 gint  y,
 gint  channel);

Description

The function lqr_rwindow_read returns the content of the reading window rwindow at point x, y and at channel channel.

The coordinates x and y are relative to the rwindow centre, and they both can range from -radius to radius (extremes included), where radius can be obtained with the function lqr_rwindow_get_radius(3).

The function returns 0 when the coordinates are out of range, either because they are beyond the rwindow radius or because they are outside the image boundary.

The channel parameter specifies which channel to read out; depending on the rwindow reader type, the range and meaning of this parameter changes: for the cases LQR_ER_BRIGHTNESS and LQR_ER_LUMA it must be 0, because the readout consists of a single channel, for LQR_ER_RGBA it must be between 0 and 3 (and then the readout will contain the RGBA information), while for LQR_ER_CUSTOM it must be one of the original image channels.


Name

lqr_rwindow_get_read_t — get the reader type of a LqrReadingWindow object

Synopsis

#include <lqr.h>
LqrEnergyReaderType lqr_rwindow_get_read_t(LqrReadingWindow*  rwindow);

Description

The function lqr_rwindow_get_read_t returns the reader type associated with the reading window rwindow.

The reader types are described in the page for lqr_carver_set_energy_function(3).


Name

lqr_rwindow_get_radius — get the size of the region accessible from a LqrReadingWindow object

Synopsis

#include <lqr.h>
gint lqr_rwindow_get_radius(LqrReadingWindow*  rwindow);

Description

The function lqr_rwindow_get_radius returns the radius of the region accessible through the reading window rwindow.

The region is a square of size 2 * radius - 1 pixels.


Name

lqr_rwindow_get_channels — get the number of channels of a LqrReadingWindow object

Synopsis

#include <lqr.h>
gint lqr_rwindow_get_channels(LqrReadingWindow*  rwindow);

Description

The function lqr_rwindow_get_channels returns the number of channels of reading window rwindow.

This function is actually only necessary when the rwindow reader type is LQR_ER_CUSTOM.

The reader types are described in the page for lqr_carver_set_energy_function(3).


Name

lqr_carver_set_gradient_function — set the gradient function for an LqrCarver object

Synopsis

#include <lqr.h>
void lqr_carver_set_gradient_function(LqrCarver*  carver,
 LqrGradFuncType  gf_ind);

Description

The function lqr_carver_set_gradient_function is deprecated and should not be used in newly written code. The function lqr_carver_set_energy_function_builtin(3) should be used instead.

The function lqr_carver_set_gradient_function is still maintained for backwards compatibility reasons; its result is equivalent to calling lqr_carver_set_energy_function_builtin, with the following mapping between the argument gs_ind of the former and the argument ef_ind of the latter:

LqrGradFuncTypeLqrEnergyFuncBuiltinType
LQR_GF_XABSLQR_EF_GRAD_XABS
LQR_GF_SUMABSLQR_EF_GRAD_SUMABS
LQR_GF_NORMLQR_EF_GRAD_NORM
LQR_GF_NULLLQR_EF_NULL

Bias

lqr_carver_bias_add — update an LqrCarver bias
lqr_carver_bias_clear — clear an LqrCarver bias

Name

lqr_carver_bias_add_xy, lqr_carver_bias_add_area, lqr_carver_bias_add, lqr_carver_bias_add_rgb_area, lqr_carver_bias_add_rgb — update an LqrCarver bias

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_bias_add_xy(LqrCarver*  carver,
 gdouble  bias,
 gint  x,
 gint  y);
LqrRetVal lqr_carver_bias_add_area(LqrCarver*  carver,
 gdouble*  buffer,
 gint  bias_factor,
 gint  width,
 gint  height,
 gint  x_off,
 gint  y_off);
LqrRetVal lqr_carver_bias_add(LqrCarver*  carver,
 gdouble*  buffer,
 gint  bias_factor);
LqrRetVal lqr_carver_bias_add_rgb_area(LqrCarver*  carver,
 gdouble*  buffer,
 gint  bias_factor,
 gint  channels,
 gint  width,
 gint  height,
 gint  x_off,
 gint  y_off);
LqrRetVal lqr_carver_bias_add_rgb(LqrCarver*  carver,
 gdouble*  buffer,
 gint  bias_factor,
 gint  channels);

Foreword

All the functions described in this page are used to add a bias to LqrCarver objects. A positive biased pixel will be more likely to be avoided by seams, and thus be preserved during rescaling, while a negative bias has the opposite effect.

All of these functions must be called before lqr_carver_resize(3). If called multiple times, the biases added at each call will sum up.

Adding a bias pixel by pixel

The function lqr_carver_bias_add_xy adds a bias to the x, y pixel of the image loaded into the LqrCarver object pointed to by carver

A typical value for bias_factor would be 1000 (in absolute value).

Adding a bias from a buffer

The function lqr_carver_bias_add_area adds a bias to an area of the image loaded into the LqrCarver object pointed to by carver.

The parameter buffer must point to an array of doubles of size width * height, ordered first by rows, then by columns.

The offset of the area relative to the image can be specified through x_off and y_off. The bias area can exceed the boundary of the image, and the offsets can be negative.

The parameter bias_factor is an overall bias scale. A typical value when the buffer contents are of the order of 1 would be 1000 (in absolute value).

The function lqr_carver_bias_add can be used when the area to add is of the same size of the image loaded in the LqrCarver object and the offsets are 0.

Adding a bias from an image

The functions lqr_carver_bias_add_rgb_area and lqr_carver_bias_add_rgb are very similar to lqr_carver_bias_add_area and lqr_carver_bias_add, except that they use 8-bit multi-channel images as inputs.

The number of channels in the image is passed via the parameter channels. The last channel is assumed to be the alpha (opacity) channel if channels is equal to 2 or greater than 3 (if this is not the case, use the previous functions).

The bias is computed from the average of the colour channels, multiplied by the value of the alpha channel if present. For example, in RGBA images a white, nontransparent pixel is equivalent to a value of 1.0 when using a buffer in lqr_carver_bias_add_area.

Return values

The return values follow the Liquid Rescale library signalling system.


Name

lqr_carver_bias_clear — clear an LqrCarver bias

Synopsis

#include <lqr.h>
void lqr_carver_bias_clear(LqrCarver*  carver);

Description

The function lqr_carver_bias_clear clears the bias from the LqrCarver object pointed to by carver

Rigidity masks

lqr_carver_rigmask_add — update an LqrCarver rigidity mask
lqr_carver_rigmask_clear — clear an LqrCarver rigidity mask

Name

lqr_carver_rigmask_add_xy, lqr_carver_rigmask_add_area, lqr_carver_rigmask_add, lqr_carver_rigmask_add_rgb_area, lqr_carver_rigmask_add_rgb — update an LqrCarver rigidity mask

Synopsis

#include <lqr.h>
LqrRetVal lqr_carver_rigmask_add_xy(LqrCarver*  carver,
 gdouble  rigidity,
 gint  x,
 gint  y);
LqrRetVal lqr_carver_rigmask_add_area(LqrCarver*  carver,
 gdouble*  buffer,
 gint  width,
 gint  height,
 gint  x_off,
 gint  y_off);
LqrRetVal lqr_carver_rigmask_add(LqrCarver*  carver,
 gdouble*  buffer);
LqrRetVal lqr_carver_rigmask_add_area(LqrCarver*  carver,
 gdouble*  buffer,
 gint  channels,
 gint  width,
 gint  height,
 gint  x_off,
 gint  y_off);
LqrRetVal lqr_carver_rigmask_add_rgb(LqrCarver*  carver,
 gdouble*  buffer,
 gint  channels);

Foreword

All the functions described in this page are used to add a rigidity mask to LqrCarver objects. Whenever one of these functions is called, a rigidity mask is activated for the whole image; the mask contains coefficients which modulate the value of the rigidity (which is set with lqr_carver_init(3)) in different areas of the image.

It is very important to note that using no rigidity masks at all is equivalent to use a rigidity mask over the whole image with all the values set to 1.0, but, when first adding a rigidity mask to a LqrCarver object, all the pixels outside the affected area will have their rigidity set to zero; therefore, the functions lqr_carver_rigmask_add_xy, lqr_carver_rigmask_add_area and lqr_carver_rigmask_add_rgb_area actually affect the whole image, despite their name.

All the functions must be called after lqr_carver_init and before lqr_carver_resize. If called multiple times over the same area, new values will replace the old ones.

Setting the rigidity mask pixel by pixel

The function lqr_carver_rigmask_add_xy sets the rigidity mask value of the x, y pixel of the image loaded into the LqrCarver object pointed to by carver

Setting the rigidity mask from a buffer

The function lqr_carver_rigmask_add_area adds a rigidity mask to an area of the image loaded in the LqrCarver object pointed to by carver.

The parameter buffer must point to an array of doubles of size width * height, ordered first by rows, then by columns.

The offset of the area relative to the image are specified through x_off and y_off. The rigidity mask area can exceed the boundary of the image, and the offsets can be negative.

The values in the given buffer are scaled by the overall rigidity value set when calling the function lqr_carver_init.

The function lqr_carver_rigmask_add can be used when the area to add is of the same size of the image loaded in the LqrCarver object and the offsets are 0.

Setting the rigidity mask from an image

The functions lqr_carver_rigmask_add_rgb_area and lqr_carver_rigmask_add_rgb are very similar to lqr_carver_rigmask_add_area and lqr_carver_rigmask_add, but use 8-bit multi-channel images as inputs.

The number of channels in the image is passed via the parameter channels. The last channel is assumed to be the alpha (opacity) channel if channels is equal to 2 or greater than 3 (if this is not the case, use the previous functions).

The rigidity value is computed from the average of the colour channels, multiplied by the value of the alpha channel if present. For example, in RGBA images a white, nontransparent pixel is equivalent to a value of 1.0 when using a buffer in lqr_carver_rigmask_add_area.

Return value

The return values follow the Liquid Rescale library signalling system.


Name

lqr_carver_rigmask_clear — clear an LqrCarver rigidity mask

Synopsis

#include <lqr.h>
void lqr_carver_rigmask_clear(LqrCarver*  carver);

Description

The function lqr_carver_rigmask_clear clears the rigidity mask from the LqrCarver object pointed to by carver

Progress reports

lqr_progress_new — the LqrProgress object constructor
lqr_progress_set_init — execude custom code before each rescaling operation
lqr_progress_set_update — execude custom code at regular steps during each rescaling operation
lqr_progress_set_end — execude custom code after each rescaling operation
lqr_progress_set_update_step — setup update step for LqrProgress objects
lqr_progress_set_init_width_message — setup width message for init hooks in LqrProgress objects
lqr_progress_set_init_height_message — setup height message for init hooks in LqrProgress objects
lqr_progress_set_end_width_message — setup width message for end hooks in LqrProgress objects
lqr_progress_set_end_height_message — setup height message for end hooks in LqrProgress objects

Name

lqr_progress_new — the LqrProgress object constructor

Synopsis

#include <lqr.h>
LqrProgress* lqr_progress_new(void); 

Description

The function lqr_progress_new is the constructor for LqrProgress objects. It can be used to setup a progress report indicator for rescale operations performed through lqr_carver_resize(3).

Newly created LqrProgress objects are inactive, and need to be set up using the functions lqr_progress_set_init(3), lqr_progress_set_update(3) and lqr_progress_set_end(3).

LqrProgress objects are associated to LqrCarver objects using the function lqr_carver_set_progress(3)

Return value

The function returns the newly created LqrProgress if successful, or NULL in case of insufficient memory.


Name

lqr_progress_set_init — execude custom code before each rescaling operation

Synopsis

#include <lqr.h>
LqrRetVal lqr_progress_set_init(LqrProgress*  p,
 LqrProgressFuncInit  init_func);

Description

The function lqr_progress_set_init sets the hook init_func to the LqrProgress object pointed to by p.

The function init_func is of type LqrProgressFuncInit, whose prototype is defined by:

typedef LqrRetVal (*LqrProgressFuncInit) (const gchar* init_message);
                        

Each time that the function lqr_carver_resize(3) performs a rescale operation (recall that it can perform more than one rescale operation at each call) this function will be called first, with a string argument passed through the parameter init_message, which is different for horizontal and vertical rescalings.

The message arguments can be set with the functions lqr_progress_set_init_width_message(3) and lqr_progress_set_init_height_message(3).

The default values for newly created LqrProgress objects are:

Horizontal:

"Resizing width..."

Vertical:

"Resizing height..."

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_progress_set_update — execude custom code at regular steps during each rescaling operation

Synopsis

#include <lqr.h>
LqrRetVal lqr_progress_set_update(LqrProgress*  p,
 LqrProgressFuncUpdate  update_func);

Description

The function lqr_progress_set_update sets the hook update_func to the LqrProgress object pointed to by p.

The function update_func is of type LqrProgressFuncUpdate, whose prototype is defined by:

typedef LqrRetVal (*LqrProgressFuncUpdate) (gdouble completion_percentage);
                        

Each time that the function lqr_carver_resize(3) performs a rescale operation (recall that it can perform more than one rescale operation at each call) this function will be called at regular intervale, with the current completion percentage completion_percentage as an argument.

The update step can be set with the function lqr_progress_set_update_step(3).

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_progress_set_end — execude custom code after each rescaling operation

Synopsis

#include <lqr.h>
LqrRetVal lqr_progress_set_end(LqrProgress*  p,
 LqrProgressFuncEnd  end_func);

Description

The function lqr_progress_set_end sets the hook end_func to the LqrProgress object pointed to by p.

The function end_func is of type LqrProgressFuncEnd, whose prototype is defined by:

typedef LqrRetVal (*LqrProgressFuncEnd) (const gchar* end_message);
                        

Each time that the function lqr_carver_resize(3) performs a rescale operation (recall that it can perform more than one rescale operation at each call) this function will be called at the end, with a string argument passed through the parameter end_message, which is different for horizontal and vertical rescalings.

The message arguments can be set with the functions lqr_progress_set_end_width_message(3) and lqr_progress_set_end_height_message(3).

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_progress_set_update_step — setup update step for LqrProgress objects

Synopsis

#include <lqr.h>
LqrRetVal lqr_progress_set_update_step(LqrProgress*  p,
 gfloat  update_step);

Description

The function lqr_progress_set_update_step sets the update step of the LqrProgress pointed to by p to the value update_step.

The update step must be between 0 and 1.

The default value is 0.02 (i.e. 2%).

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_progress_set_init_width_message — setup width message for init hooks in LqrProgress objects

Synopsis

#include <lqr.h>
LqrRetVal lqr_progress_set_init_width_message(LqrProgress*  p,
 const guchar*  message);

Description

The function lqr_progress_set_init_width_message sets the string message in the LqrProgress object pointed to by p as the argument when rescaling the width for init hooks set with lqr_progress_set_init(3)

The default value for newly created LqrProgress objects is: "Resizing width..."

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_progress_set_init_height_message — setup height message for init hooks in LqrProgress objects

Synopsis

#include <lqr.h>
LqrRetVal lqr_progress_set_init_height_message(LqrProgress*  p,
 const guchar*  message);

Description

The function lqr_progress_set_init_height_message sets the string message in the LqrProgress object pointed to by p as the argument when rescaling the height for init hooks set with lqr_progress_set_init(3)

The default value for newly created LqrProgress objects is: "Resizing height..."

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_progress_set_end_width_message — setup width message for end hooks in LqrProgress objects

Synopsis

#include <lqr.h>
LqrRetVal lqr_progress_set_end_width_message(LqrProgress*  p,
 const guchar*  message);

Description

The function lqr_progress_set_end_width_message sets the string message in the LqrProgress object pointed to by p as the argument when rescaling the width for end hooks set with lqr_progress_set_end(3)

The default value for newly created LqrProgress objects is: "done".

Return value

The return value follows the Liquid Rescale library signalling system.


Name

lqr_progress_set_end_height_message — setup height message for end hooks in LqrProgress objects

Synopsis

#include <lqr.h>
LqrRetVal lqr_progress_set_end_height_message(LqrProgress*  p,
 const guchar*  message);

Description

The function lqr_progress_set_end_height_message sets the string message in the LqrProgress object pointed to by p as the argument when rescaling the height for end hooks set with lqr_progress_set_end(3)

The default value for newly created LqrProgress objects is: "done".

Return value

The return value follows the Liquid Rescale library signalling system.

Chapter 4. References

The library implements the algorithm described in the paper "Seam Carving for Content-Aware Image Resizing" by Shai Avidan and Ariel Shamir, which can be found at http://www.faculty.idc.ac.il/arik/imret.pdf

Appendix A. API changes in new versions of the library