324 lines
12 KiB
C
324 lines
12 KiB
C
#ifndef LIBIMG_H
|
|
#define LIBIMG_H
|
|
|
|
#include <gint/display.h>
|
|
#include <stdint.h>
|
|
|
|
/* This is substituted by CMake at compile-time */
|
|
#define IMG_VERSION "@libimg_VERSION@"
|
|
|
|
#ifdef FX9860G
|
|
/* On fx-9860G, the format is 8-bit per color. Although there are much less
|
|
than 256 colors (you could find 9 at best including partially-transparent
|
|
ones), it makes it possible to share code with the fx-CG 50, which is the
|
|
main target for this library. */
|
|
typedef uint8_t img_pixel_t;
|
|
|
|
#define IMG_ALPHA C_NONE
|
|
#endif /* FX9860G */
|
|
|
|
#ifdef FXCG50
|
|
/* On fx-CG 50, the format is 16-bit R5G6B5A. A value is reserved for
|
|
transparency; currently this is 0x0001. */
|
|
typedef uint16_t img_pixel_t;
|
|
|
|
#define IMG_ALPHA 0x0001
|
|
#endif /* FXCG50 */
|
|
|
|
/* The type of images; this is usually passed by value. The structure itself
|
|
only references the memory. Because it is passed by value, const qualifiers
|
|
are useless here (since the pixel pointer does not inherit them). */
|
|
typedef struct {
|
|
/* Image dimensions */
|
|
uint16_t width;
|
|
uint16_t height;
|
|
/* Number of pixels on each storage line */
|
|
uint16_t stride;
|
|
/* Flags (some internal) */
|
|
uint8_t flags;
|
|
/* Reserved for future use */
|
|
uint8_t _;
|
|
/* Pointer to pixels */
|
|
img_pixel_t *pixels;
|
|
} img_t;
|
|
|
|
|
|
//---
|
|
// Surface creation and destruction
|
|
//---
|
|
|
|
/* img_create(): Create a new, uninitialized image
|
|
|
|
This function creates a new surface and returns it. This surface must be
|
|
destroyed with img_destroy() when it is no longer needed. Sub-surfaces can
|
|
be created from it, but will no longer be usable when it is destroyed.
|
|
|
|
If the allocation fails, or the requested size is larger than 65535x65535,
|
|
this function returns a surface with zero dimensions and a NULL pixel
|
|
pointer. img_null() will return 1 on this error-image.
|
|
|
|
After creation, the image contains random pixels, which might not even be
|
|
valid colors on fx-9860G. It is advised to fill it with img_fill() unless
|
|
you know it will be filled by another mechanism such as a transform.
|
|
|
|
@w @h Dimensions of the new image */
|
|
img_t img_create(int w, int h);
|
|
|
|
/* img_copy(): Create a new image by copying an existing one
|
|
|
|
This function creates a new surface from a copy of the argument. Much like
|
|
with img_create(), the new surface must be destroyed with img_destroy(). */
|
|
img_t img_copy(img_t img);
|
|
|
|
/* img_null(): Check if an image is null (ie. failed to allocate)
|
|
|
|
A null image does not contain any data. It is correct to pass a null image
|
|
to any function of the library, but either nothing will happen or another
|
|
null image will be returned. */
|
|
int img_null(img_t img);
|
|
|
|
/* img_sub(): Get a reference to a section of an image
|
|
|
|
This function returns a surface that references a rectangle inside the
|
|
provided image [img]. This is *not* a new image; it is a view on a rectangle
|
|
inside [img]; just the same pixels viewed differently. It needs not be
|
|
destroyed, and it becomes invalid when [img] is destroyed. If you need an
|
|
actual copy, do img_copy(img_sub(img,x,y,w,h)).
|
|
|
|
The specified rectangle is clipped to fit into [img] before the reference is
|
|
created. If w or h is set to -1, then the full width or height of the image
|
|
is used.
|
|
|
|
@img Source image
|
|
@x @y Location of the top-left corner of the rectangle to reference
|
|
@w @h Size of the referenced rectangle */
|
|
img_t img_sub(img_t img, int x, int y, int w, int h);
|
|
|
|
/* img_at(): Get a reference to a section defined by its top-left corner
|
|
|
|
This function returns a sub-image of its first argument. The sub-image
|
|
starts at position (x,y) of the source image and ends in the bottom-right
|
|
corner.
|
|
|
|
This function is useful when transforming. This is because the result of a
|
|
transform is always drawn at position (0,0) on the destination image. To
|
|
change the position, one can get a reference using img_at().
|
|
|
|
For instance, the following call flips src horizontally and draws the result
|
|
onto dst at position (0,0):
|
|
img_hflip(src, dst);
|
|
To draw the flipped src at position (20,10), the call can be modified to:
|
|
img_hflip(src, img_at(dst, 20, 10));
|
|
If there is not enough space at position (20,10) of dst to draw the entirety
|
|
of the transformed src, the transform will fail and do nothing.
|
|
|
|
Calling img_at() is strictly equivalent to calling img_sub() with w=h=-1.
|
|
|
|
@img Source image
|
|
@x @y Location of the top-left corner to reference */
|
|
img_t img_at(img_t img, int x, int y);
|
|
|
|
#ifdef FXCG50
|
|
/* img_vram(): Obtain a reference to the current VRAM as an image
|
|
|
|
This function returns a reference to gint's VRAM wrapped into a surface
|
|
object. This is very useful to render to VRAM with all of the transforming
|
|
power of libimg surfaces. This surface needs not be destroyed.
|
|
|
|
This function is not available on fx-9860G because the format of the VRAM is
|
|
not compatible with that of surfaces. However, it is still possible to
|
|
render surfaces to VRAM using img_render_vram().
|
|
|
|
On fx-CG 50, the VRAM address changes at every frame when triple buffering
|
|
is active. It is recommended to call img_vram() at every frame to obtain the
|
|
correct address every time. (This function always executes instantly.) */
|
|
img_t img_vram(void);
|
|
#endif /* FXCG50 */
|
|
|
|
/* img_destroy(): Destroy an image
|
|
|
|
This function destroys an image. If the image did not own its memory,
|
|
nothing happens. Otherwise, the surface memory is released and all
|
|
references into it become invalid. */
|
|
void img_destroy(img_t img);
|
|
|
|
|
|
//---
|
|
// Basic rendering
|
|
//---
|
|
|
|
/* img_fill(): Fill an image with a single color */
|
|
void img_fill(img_t img, img_pixel_t color);
|
|
|
|
/* img_clear(): Fill an image with transparent pixels
|
|
Strictly equivalent to img_fill(img, IMG_ALPHA). Just a shortcut. */
|
|
void img_clear(img_t img);
|
|
|
|
/* img_render(): Render an image onto another one
|
|
|
|
Copies the source image [src] at position (0,0) of target [dst].
|
|
-> To copy at position (x,y), replace dst with img_at(dst,x,y).
|
|
-> To copy only a section of src, replace src with img_sub(src,x,y,w,h).
|
|
|
|
Unlike transforms, this function clips the copied rectangle onto the
|
|
destination, so the call will work even if src overflows from dst.
|
|
|
|
Transparent pixels in the source are not copied. If it is necessary to have
|
|
transparent pixels of the source become transparent on the destination as
|
|
well, first fill the destination with IMG_ALPHA (or use img_clear()).
|
|
|
|
Note that on fx-CG 50 the VRAM does not support transparency and transparent
|
|
pixels will appear as basically black. */
|
|
void img_render(img_t src, img_t dst);
|
|
|
|
/* img_render_vram(): Render an image to the VRAM
|
|
|
|
This function works like img_render() but renders to VRAM on fx-9860G. This
|
|
compensates the lack of img_vram() function on this platform. Rendering to
|
|
VRAM supports both monochrome and gray pixels. This function clips the
|
|
rendered image onto the VRAM.
|
|
|
|
This function only renders to black-and-white VRAM. Dark gray and light gray
|
|
pixels are replaced by black and while, respectively. To render imges under
|
|
the gray engine, use img_render_vram_gray().
|
|
|
|
On fx-CG 50, this function is exactly equivalent to:
|
|
img_render(src, img_at(img_vram(), x, y)).
|
|
|
|
@src Source image
|
|
@x @y Render destination on VRAM */
|
|
void img_render_vram(img_t src, int x, int y);
|
|
|
|
#ifdef FX9860G
|
|
/* img_render_vram_gray(): Render a gray image to the VRAM
|
|
|
|
On fx-9860G, mono and gray rendering code must be separated. This function
|
|
is the direct equivalent of img_render_vram(), but it renders to the gray
|
|
VRAM and is suitable for gray images.
|
|
|
|
@src Source image
|
|
@x @y Render destination on gray VRAM */
|
|
void img_render_vram_gray(img_t src, int x, int y);
|
|
#endif
|
|
|
|
|
|
//---
|
|
// Geometric transforms
|
|
//
|
|
// All geometric transforms render to position (0,0) of the target image and
|
|
// fail if the target image is not large enough to hold the transformed result
|
|
// (unlike the rendering functions which render only the visible portion).
|
|
//
|
|
// To render at position (x,y) of the target image, use img_at(). For instance:
|
|
// img_hflip(src, img_at(dst, x, y));
|
|
//
|
|
// Each transform function has a [_create] variant which does the same
|
|
// transform but allocates the target image on the fly and returns it. Remember
|
|
// that allocation can fail, so you need to check whether the returned image is
|
|
// null.
|
|
//
|
|
// (You can still pass a null image to libimg functions when chaining
|
|
// transforms. The null image will be ignored or returned unchanged, so you
|
|
// can check for it at the end of any large chain.)
|
|
//
|
|
// Some functions support in-place transforms. This means they can be called
|
|
// with the source as destination, and will transform the image without needing
|
|
// new memory. For instance, img_hflip(src, src) flips in-place and replaces
|
|
// src with a flipped version of itself.
|
|
//
|
|
// (However, it is not possible to transform in-place if the source and
|
|
// destination intersect in non-trivial ways. The result will be incorrect.)
|
|
//
|
|
// When transforming to a new image, transparent pixels are ignored, so if the
|
|
// destination already has some data, it will not be erased automatically. Use
|
|
// img_clear() beforehand to achieve that effect. This allows alpha blending
|
|
// while transforming, which is especially useful on the VRAM.
|
|
//---
|
|
|
|
/* img_hflip(): Flip horizontally (supports in-place)
|
|
The destination image must have the same size as the source. */
|
|
void img_hflip(img_t src, img_t dst);
|
|
img_t img_hflip_create(img_t src);
|
|
|
|
/* img_vflip(): Flip vertically (supports in-place)
|
|
The destination image must have the same size as the source. */
|
|
void img_vflip(img_t src, img_t dst);
|
|
img_t img_vflip_create(img_t src);
|
|
|
|
/* img_rotate(): Rotate by 90, 180 or 270 degrees (supports in-place)
|
|
|
|
This function applies a rotation of the specified angle (90, 180 or 270) in
|
|
degrees from the source image to the destination image. The rotation can be
|
|
performed in-place under the following conditions:
|
|
|
|
* For 180 degrees: no condition
|
|
* For 90 and 270 degrees: width and height of source image are equal
|
|
|
|
Even if the rotation is not in-place, the target image must have exactly the
|
|
size of the rotated source. You can use img_sub() to rotate into part of a
|
|
larger destination image. */
|
|
void img_rotate(img_t src, img_t dst, int angle);
|
|
img_t img_rotate_create(img_t src, int angle);
|
|
|
|
/* img_upscale(): Upscale by an integer ratio (does not support in-place) */
|
|
void img_upscale(img_t src, img_t dst, int scale);
|
|
img_t img_upscale_create(img_t src, int scale);
|
|
|
|
|
|
//---
|
|
// Color transforms
|
|
//
|
|
// All color transforms operate on a per-pixel basis. They never change the
|
|
// size of the image and can always (trivially) operate in-place. They still
|
|
// require the size of the output to be at least the size of the input.
|
|
//
|
|
// As for geometric transforms, all functions have a [_create] variant that
|
|
// copies the image before applying the transform.
|
|
//---
|
|
|
|
/* img_dye(): Replace all non-transparent pixels with a single color
|
|
|
|
This function repaints all non-transparent pixels of [src] with a fixed
|
|
color. This transform is commonly used in games to animate interactions
|
|
through various colors (red, white, etc). */
|
|
void img_dye(img_t src, img_t dst, img_pixel_t color);
|
|
img_t img_dye_create(img_t src, img_pixel_t color);
|
|
|
|
#ifdef FXCG50
|
|
|
|
/* img_lighten(): Roughly lighten an image
|
|
|
|
This function produces a lighter version of the specified image by doubling
|
|
the value of each color component (while capping to a maximum to prevent
|
|
overflow - this is called saturation arithmetic). Because RGB565 is used,
|
|
after 6 iterations, the resulting image will always be white.
|
|
|
|
This function does not work very well on pixel art but produces convincing
|
|
results on artworks and photos. */
|
|
void img_lighten(img_t src, img_t dst);
|
|
img_t img_lighten_create(img_t src);
|
|
|
|
/* img_whiten(): Fade an image to white
|
|
|
|
This function fades the provided image to white by halving the distance of
|
|
each color component to its maximum value. The result after 6 iterations
|
|
will always be white. */
|
|
void img_whiten(img_t src, img_t dst);
|
|
img_t img_whiten_create(img_t src);
|
|
|
|
/* img_darken(): Roughly darken an image (same as fading to black)
|
|
|
|
This function makes an image darken by halving the value of each color
|
|
component. After 6 iterations, the resulting image will always be black.
|
|
|
|
Note that both img_lighten() and img_darken() destroy some of the
|
|
information present in the image. They do not cancel each other. If the
|
|
original image is needed at some point, a copy must be made before
|
|
lightening or darkening it. */
|
|
void img_darken(img_t src, img_t dst);
|
|
img_t img_darken_create(img_t src);
|
|
|
|
#endif /* FXCG50 */
|
|
|
|
#endif /* LIBIMG_H */
|