The TGX library's main class is the tgx::Image class which, as its name suggests, encapsulate an image, that is a rectangular array of pixels of a given color type. The library provides an extensive set of 2D and 3D drawing procedures to operates on image objects.
All methods/classes are defined inside the tgx
namespace. To use the library, just include tgx.h
:
Colors types
The library defines several color classes
- tgx::RGB565 : 16 bits colors: 5 bits red, 6 bits green, 5 bits blue. Aligned as and convertible to
uint16_t
. Preferred type when working with embedded platforms/MCUs.
- tgx::RGB24 : 24 bits color: 8 bits red, 8 bits: green, 8 bits blue. No alignement.
- tgx::RGB32 : 32 bits color: 8 bits red, 8 bits: green, 8 bits blue. 8 bits (pre-multipled) Alpha channel. Aligned as and convertible to
uint32_t
. Useful for blending.
- tgx::RGBf : 96 bits floating point color: 32 bits red (float), 32 bits green (float), 32 bits blue (float). Aligned as
float
, no alpha channel. Used in the 3D API.
- tgx::RGB64 : 64 bits color: 16 bits red, 16 bits: green, 16 bits blue. 16 bits (pre-multiplied) Alpha channel. Aligned as and convertible to
uint64_t
.
- tgx::HSV : 96 bits colors: 16 bits Hue, 16 bits Saturation, 16 bits Values. Partial support only. Slow, use only to convert between color space, not for drawing operations.
Color types are handled just like usual basic type int
, char
... Any color type can be converted into any other color type.
Examples:
uint16_t c2 = (uint16_t)color3;
color5.setOpacity(0.5f);
Color in R8/G8/B8/A8 format.
Definition: Color.h:1176
Color in R5/G6/B5 format.
Definition: Color.h:216
uint16_t G
Green channel (6 bits)
Definition: Color.h:232
uint16_t R
Red channel (5 bits)
Definition: Color.h:233
uint16_t B
Blue channel (5 bits)
Definition: Color.h:231
Predefined colors: Black, White, Blue, Green, Purple, Orange, Cyan, Lime, Salmon, Maroon, Yellow, Magenta, Olive, Teal, Gray, Silver, Navy, Transparent.
Example:
tgx::RGB32_Yellow;
tgx::RGB565_Green;
For additional details on color manipulations, look directly into the color classes definitions in color.h.
Blending and opacity parameter.
Color types tgx::RGB32 and tgx::RGB64 have an alpha channel which is used for alpha-blending during drawing operations.
- Note
- Colors with an alpha channel are always assumed to have pre-multiplied alpha.
Other color type do not have an alpha channel but the library still support simple blending operations through the (optional) opacity
parameter added to all drawing primitives. This parameter ranges in [0.0f, 1.0f]
with
opacity = 1.0f
: fully opaque drawing. This is the default value when the parameter is omited.
opacity = 0.0f
: fully transparent drawing (so this draws nothing).
Example:
const RGB565 RGB565_Red
Color red in RGB565 format.
Image class, memory layout and sub-images
An image object is a lightweight structure (only 16 bytes in memory) similar to a Numpy view in Python. The object records:
- the dimension of the image (
lx
, ly
).
- a pointer to the memory buffer
buffer[]
of pixel colors of type color_t
(the template color type of the image).
- a
stride
value that is the number of pixels per image row (which may be larger than ly
when working with sub-images).
In particular, the image object does not contain the pixels buffer itself but only a pointer to its memory location. As a general rule, the TGX library never perform any dynamic memory allocation.
Several images can reference the same memory buffer (or a part of it). Creating images/sub-images that share the same pixels buffer is useful to restrict drawing operations to a given rectangular region.
The position of a pixel inside an image is given in row major order:
Pixel(i, j) = buffer[i + stride*j]
for 0 ≤ i
< lx
and 0 ≤ j
< ly
.
Example:
Image class [MAIN CLASS FOR THE 2D API].
Definition: Image.h:143
TGX_INLINE int stride() const
Return the image stride.
Definition: Image.h:386
void set(T *buffer, int lx, int ly, int stride=DEFAULT_STRIDE)
Set/update the image parameters.
TGX_INLINE const color_t * data() const
Return a pointer to the pixel buffer.
Definition: Image.h:412
TGX_INLINE int lx() const
Return the image width.
Definition: Image.h:362
TGX_INLINE int ly() const
Return the image height.
Definition: Image.h:378
See also: Image::set(), Image::crop(), Image::getCrop(), Image::operator(), Image::isValid(), Image::setInvalid(), Image::imageBox().
- Note
- Creating image/sub-image is very fast and "cost free" so one should not refrain from creating Image/sub-images whenever needed ! It is the most efficient solution to clip/restrict any drawing operation to a given (rectangular) region of an image.
Vectors and Boxes
The tgx library defines classes for 2D vectors and boxes:
- tgx::iVec2 : integer-valued 2D vector. Use for pixel location in images
- tgx::fVec2 : floating point-valued 2D vector. Used for pixel location in images when using sub-pixel precision
- tgx::iBox2 : integer-valued 2D box. Used to represent a rectangular region inside an image
- tgx::fBox2 : floating point-valued 2D box. represent a rectangular region inside an image when using sub-pixel precision
- Note
- 3D variants for vectros and boxes are also available: tgx::iVec3, tgx::fVec3, tgx::iBox3, tgx::fBox3 c.f. the 3D API tutorials for details.
- Warning
- Pixel adressing varies slightly when using integer valued coordinates vs floating point valued coordinates.
- Integer valued cordinates:
iVec2(i,j)
represents the location of the pixel (i,j)
in the image. The whole image corresponds to the (integer valued) box iBox2(0, lx - 1, 0, ly - 1)
.
- Floating point valued coordinates:
fVec2(i,j)
represents the center of pixel (i,j)
in the image. The pixel itself is a unit lenght square box centered around this location i.e. represented by fBox2( i-0.5f, i+0.5f, j-0.5f, j+0.5f)
. The whole image corresponds to the (floating point valued) box fBox2( -0.5f, lx - 0.5f, -0.5f, ly - 0.5f)
.
Vectors and boxes support all the usual operations: arithmetics (addition, dot product..), copy, type conversion...
Most drawing methods take vectors and boxes as input parameters instead of scalars. It is recommended to use initializer lists makes the code more readable. For exapple, just write {10, 20}
instead of tgx::iVec2(10, 20)
.
Example:
float x = 2.0f;
(v2 + v3) * 3.0f;
im.drawCircle(v1, 12, tgx::RGB32_Red);
im.fillRect(B, tgx::RGB32_Black);
const RGB32 RGB32_Black
Color black in RGB32 format.
const RGB32 RGB32_Red
Color red in RGB32 format.
Generic 2D Box [specializations iBox2 , fBox2, dBox2].
Definition: Box2.h:151
Generic 2D vector [specializations iVec2, fVec2, dVec2].
Definition: Vec2.h:64
T x
'x' coordinate (first dimension)
Definition: Vec2.h:72
Storing images in .cpp files
The memory buffer an image points to may reside in flash/ROM and it if possible to define 'const' images directly in .cpp
files for easy inclusion in a project.
For example, the 10x10 image
Can be stored as:
#define C(val) tgx::RGB565((uint16_t)val)
C(0xffff), C(0xffff), C(0xf714), C(0xe609), C(0xdd40), C(0xdd40), C(0xe609), C(0xf714), C(0xffff), C(0xffff),
C(0xffff), C(0xee8f), C(0xddc6), C(0xeef1), C(0xfffb), C(0xfffb), C(0xeef1), C(0xddc6), C(0xee8f), C(0xffff),
C(0xeef4), C(0xdda5), C(0xf775), C(0xffd8), C(0xffd8), C(0xffd8), C(0xffd8), C(0xf775), C(0xdda5), C(0xeef4),
C(0xd5a9), C(0xee8d), C(0xff94), C(0x9b20), C(0xff94), C(0xff94), C(0x9b20), C(0xff94), C(0xee8d), C(0xd5a9),
C(0xc4a0), C(0xff50), C(0xff50), C(0xff50), C(0xff50), C(0xff50), C(0xff50), C(0xff50), C(0xff50), C(0xc4a0),
C(0xbc60), C(0xff0b), C(0xff0b), C(0xff0b), C(0xff0b), C(0xff0b), C(0xff0b), C(0xff0b), C(0xff0b), C(0xbc60),
C(0xc4e8), C(0xe5c4), C(0xfea6), C(0xaba0), C(0xfea6), C(0xfea6), C(0xaba0), C(0xfea6), C(0xe5c4), C(0xc4e8),
C(0xd612), C(0xc481), C(0xf622), C(0xdd40), C(0x9b20), C(0x9b20), C(0xdd40), C(0xf622), C(0xc481), C(0xd612),
C(0xf79e), C(0xc54d), C(0xbc60), C(0xdd60), C(0xfe40), C(0xfe40), C(0xdd60), C(0xbc60), C(0xc54d), C(0xf79e),
C(0xffff), C(0xef7d), C(0xcdd2), C(0xb4a8), C(0xaba0), C(0xaba0), C(0xb4a8), C(0xcdd2), C(0xef7d), C(0xffff) };
The /tools/
subdirectory of the library contains the Python script image_converter.py
which converts an image from a classical format (jpeg/png/bmp...) into a .cpp file.
- Note
- The TGX library also makes it easy to directly load PNG, JPEG and GIF images (which may be stored in RAM/FLASH or on another media such as a SD card) by using bindings with external libraries. See section TGX extensions via external librairies for more details.
Copying/converting images to different color types.
Recall that a tgx::Image object is just a view into a buffer of pixels of a given color type. Thus, copies of image object are shallow (they share the same image buffer / same color type).
The library provides methods the create "deep" copies and convert images to different color types:
Image< color_dst > convert()
Convert this image to another type.
void copyFrom(const Image< src_color_t > &src_im, float opacity=TGX_DEFAULT_NO_BLENDING)
Copy (or blend) the src image onto the destination image with resizing and color conversion.
Color in R8/G8/B8 format.
Definition: Color.h:681
- Note
- See also the methods for blitting sprites which may be used for copy and color type conversion.
Drawing things on an images...
Here comes the good part ! Now that can can create and manipulate images, we obviously want to draw thing on them !
TGX defines many primitives to draw shapes (such as lines, rectangle, circles, bezier curves), to blit sprites or write text... As well as a simple (but full-featured!) 3D engine.