Cross-platform C SDK logo

Cross-platform C SDK

Images

❮ Back
Next ❯
This page has been automatically translated using the Google Translate API services. We are working on improving texts. Thank you for your understanding and patience.

Functions

Image*image_from_pixels (...)
Image*image_from_pixbuf (...)
Image*image_from_file (...)
Image*image_from_data (...)
const Image*image_from_resource (...)
Image*image_copy (...)
Image*image_trim (...)
Image*image_rotate (...)
Image*image_scale (...)
Image*image_read (...)
bool_timage_to_file (...)
voidimage_write (...)
voidimage_destroy (...)
pixformat_timage_format (...)
uint32_timage_width (...)
uint32_timage_height (...)
Pixbuf*image_pixels (...)
boolimage_codec (...)
codec_timage_get_codec (...)
uint32_timage_num_frames (...)
real32_timage_frame_length (...)
voidimage_data (...)
type*image_get_data (...)
void*image_native (...)

There is a close relationship between pixel buffers and images. Although the firsts contain "raw" color information, the latter are objects directly linked to the graphical API of each system, which allows them to be drawn in 2d contexts or viewed in a window (Figure 1).

Graph of Image object implementation as Gdiplus::Bitmap, NSBitmapImageRep or GdkPixbuf.
Figure 1: Image objects have a direct link to graphics APIs, while Pixbuf do not.

The structure of a digital image, also called bitmap or raster graphics, is the same as that of a buffer pixel. We have a discrete grid of color dots characterized by its resolution (width, height) and depth, which is the amount of bits needed to encode each pixel (Figure 2). bitmap images work best for taking snapshots of the real world, where it is practically impossible to describe the scene using geometric primitives, as we saw in Drawing primitives. On the other hand, as it is composed of discrete points, it does not behave well in the face of changes in size where it will suffer a loss of quality.

The same image in two different resolutions.
Figure 2: On the left an image of 64x64 pixels and 16 colors. Right 256x256 pixels and 16 million colors.

1. Load and view images

In most cases, the only thing we will need to know about images will be how to read them from disk or other data source and then display them on the screen as part of the user interface (Listing 1) (Figure 3). We consider that the images are stored in one of the standard formats: JPG, PNG, BMP or GIF.

Listing 1: Loading and viewing images.
1
2
3
4
5
Image *img = image_from_file("lenna.jpg", NULL);
Image *icon = image_from_resource(pack, ekCANCEL);
...
imageview_image(view, img);
button_image(button, icon);
Reading an image from disk and viewing.
Figure 3: Integration of images in the user interface.

Once the image object is loaded in memory, we have several ways to view it:


2. Generate images

As we saw in 2D Contexts, if necessary we can create our own images from drawing commands to later display them in the interface (Figure 4) or save them to disk.

  • Use dctx_image to create an image from a 2d context.
  • Image generated from drawing commands.
    Figure 4: Image generated by drawing commands.

3. Pixel access

Images are immutable objects optimized for recurring on-screen drawing, so certain licenses are allowed, both in the internal organization of color information and in the management of possible copies. For this reason it is not possible to directly manipulate the pixels, but we must access them using a Pixel Buffer.

Apple technical documentation: "Treat NSImage and its image representations as immutable objects. The goal of NSImage is to provide an efficient way to display images on the target canvas. Avoid manipulating the data of an image representation directly, especially if there are alternatives to manipulating the data, such as compositing the image and some other content into a new image object."

The pixel buffers allow us to optimally manipulate the content of the image. To view the result or store it in any of the supported formats, we must create a new image (Figure 5).

Process from a pixel buffer to an image.
Figure 5: Image editing process.

4. Save images: Codecs

One of the biggest problems of digital images is the large amount of memory they need. An image of only 1024x768 pixels and 32 bits of color needs 3 megabytes of memory. It may not seem like much, but at the end of the 80s this was a great handicap since memory was very expensive and transmissions were very slow. This is why several coding (compression) systems were devised that reduced the amount of memory needed and that were consolidated with the rise of the Internet (Figure 6).

Draw2D does not natively support other formats than those mentioned. If necessary, you will have to find a way to create a Pixbuf from the specific data of your format, in order to integrate these images into the user interface.
  • JPEG: Joint Photographic Experts Group is a format with a very good compression rate based on the Fourier Transform. Ideal for capturing real-world snapshots, although it will detract some quality from the original capture (lossy compression).
  • PNG: Portable Network Graphics emerged in response to legal problems with the GIF format. Supports lossless LZ77/Deflate compression and indexed pixel formats. Ideal for computer generated diagrams, graphics or images.
  • GIF: Graphics Interchange Format uses the proprietary compression algorithm LZW, although the patent expired in 2003. It has survived PNG because it can include animations in a single file, something that neither of the two previous formats supports.
  • BMP: BitMaP. Windows native format widely surpassed by the other three. Although it supports a special type of compression called Run-Length encoding, the truth is that most files are saved uncompressed. BMP files take up much more space, for this reason very little is used on the Internet and almost nothing on non-Windows machines. It is supported by almost all programs and systems because it is very simple an fast to interpret.

To be able to display on the screen, the image must be decompressed (de-encoded), a process that is performed automatically when reading the image. When saving it to disk or sending it over the network, the opposite process is performed, compressed or encoded using the algorithm associated with it (Table 1), but it can be changed.

Table 1: Default image codecs.
Constructor Codec
image_from_file The original codec.
image_from_data The original codec.
image_from_resource The original codec.
image_from_pixels Transparencies? Yes:ekPNG No:ekJPG.
dctx_image ekPNG.
Generally, GDI+, NSImage or GdkPixbuf support for codec settings is quite limited. For example, it is not possible to generate indexed PNG files, which is very useful when reducing the size of images for the web. If the application requires more control over the export, we will have no choice but to use libpng, libjpeg or any other third-party solution.

image_from_pixels ()

Create an image from an array of pixels.

Image*
image_from_pixels(const uint32_t width,
                  const uint32_t height,
                  const pixformat_t format,
                  const byte_t *data,
                  const color_t *palette,
                  const uint32_t palsize);
width

The image width (in pixels).

height

The image height (in pixels).

format

Pixel format.

data

Buffer that contains the color value of each pixel. It will depend on the resolution and format.

palette

Color palette required to render indexed images. If it is NULL a Predefined palette will be used if necessary.

palsize

Number of colors in the palette.

Return

The image.

Remarks

See Pixel access.


image_from_pixbuf ()

Create an image from a buffer pixel.

Image*
image_from_pixbuf(const Pixbuf *pixbuf,
                  const Palette *palette);
pixbuf

The buffer.

palette

The palette.

Return

The image.

Remarks

Equal to image_from_pixels avoiding indicating parameters separately.


image_from_file ()

Create an image from a file on disk.

Image*
image_from_file(const char_t *pathname,
                ferror_t *error);
pathname

The file path. Filename and pathname.

error

Error code if the function fails. Can be NULL.

Return

The image.

Remarks

Only formats jpg, png, bmp and gif are accepted.


image_from_data ()

Create an image from a buffer containing the encoded data.

Image*
image_from_data(const byte_t *data,
                const uint32_t size);
data

The buffer with the image data.

size

The buffer size in bytes.

Return

The image.

Remarks

The buffer represents data encoded in jpg, png, bmp or gif. To create the image directly from pixels use image_from_pixels.


image_from_resource ()

Get an image of a resource package.

const Image*
image_from_resource(const ResPack *pack,
                    const ResId id);
pack

The resource package.

id

The resource identifier.

Return

The image.

Remarks

The image should not be destroyed with image_destroy as it is part of the package itself (it is constant). Make a copy with image_copy in case it needs to be kept after destroying the resources. See Resources.


image_copy ()

Create a copy of the image.

Image*
image_copy(const Image *image);
image

The source image.

Return

The image copy.

Remarks

Images are immutable objects. Copying really means increasing an internal counter without cloning the object. However, the application must destroy the copy with image_destroy just like those created with any other constructor. When all copies are destroyed, it will actually be removed from memory.


image_trim ()

Create an image by cropping another image.

Image*
image_trim(const uint32_t x,
           const uint32_t y,
           const uint32_t width,
           const uint32_t height);
x

X coordinate of the origin of the sub-image.

y

Y coordinate of the origin of the sub-image.

width

Width in pixels of the sub-image.

height

Height in pixels of the sub-image.

Return

The new image.


image_rotate ()

Create a new image by rotating an existing one.

Image*
image_rotate(const Image *image,
             const real32_t angle,
             const bool_t nsize,
             const color_t background,
             T2Df *t2d);
image

The original image.

angle

Angle in radians.

nsize

TRUE the resulting image will be resized to fit the entire original. FALSE the resulting image will have the same dimensions as the original, cutting part of the content (clipping).

background

Background color. The new image will have "blank" areas due to rotation.

t2d

Saves the transformation applied to the image. They can be NULL if we don't need this value.

Return

The newly created image.


image_scale ()

Create a copy of the image, with a new size.

Image*
image_scale(const Image *image,
            const uint32_t nwidth,
            const uint32_t nheight);
image

The source image.

nwidth

The width of the new image. Pass UINT32_MAX so that the aspect ratio with respect to nheight.

nheight

The height of the new image. Pass UINT32_MAX so that the aspect ratio with respect to nwidth.

Return

The image.

Remarks

If both values nwidth, nheight are UINT32_MAX or the new dimensions are identical to the current ones, the internal reference counter will increase, as is the case in image_copy.


image_read ()

Create an image from the data read from a Streams.

Image*
image_read(Stream *stm);
stm

Input stream. Data encoded in jpg, png, bmp or gif are expected. The function detects the format automatically.

Return

The image.


image_to_file ()

Save an image to disk, using the codec associated with it.

bool_t
image_to_file(const Image *image,
              const char_t *pathname,
              ferror_t *error);
image

The image.

pathname

The path of the destination file. Filename and pathname.

error

Error code if the function fails. Can be NULL.

Return

TRUE if it was saved correctly or FALSE and an error has occurred.

Remarks

Use image_codec to change the default codec.


image_write ()

Write an image in an output stream, using the codec associated with it.

void
image_write(Stream *stm,
            const Image *image);
stm

Writing stream. Data encoded in jpg, png, bmp or gif will be written.

image

The image.

Remarks

Use image_codec to change the default codec.


image_destroy ()

Destroy the image.

void
image_destroy(Image **image);
image

The image. Will be set to NULL after destruction.


image_format ()

Get the pixel format of the image.

pixformat_t
image_format(const Image *image);
image

The image.

Return

Pixel format.


image_width ()

Get the width of the image in pixels.

uint32_t
image_width(const Image *image);
image

The image.

Return

Number of pixels wide.


image_height ()

Get the height of the image in pixels.

uint32_t
image_height(const Image *image);
image

The image.

Return

Number of pixels in height.


image_pixels ()

Get a buffer with the pixels that make up the decoded image.

Pixbuf*
image_pixels(const Image *image,
             const pixformat_t format);
image

The image.

format

The required pixel format.

Return

Pixel buffer with image content.

Remarks

If in pixformat we indicate ekFIMAGE it will return the buffer with the original format of the image. We can indicate ekRGB24, ekRGBA32 or ekGRAY8 if we need a specific format. Cannot use indexed formats.


image_codec ()

Change the default codec associated with the image.

bool
image_codec(const Image *image,
            const codec_t codec);
1
2
3
4
Image *img = image_from_file("lenna.jpg", NULL);
Stream *stm = stm_socket(ip, port, NULL, NULL);
image_codec(img, ekPNG);
image_write(socket, img);
image

The image.

codec

The new codec.

Return

TRUE if the graphical API supports the selected codec. FALSE otherwise.

Remarks

The change will take effect the next time we save or write the image. By default, the image retains the codec with which it was read. When we create it with image_from_pixels ekJPG codec is assigned as default. For images from 2d contexts dctx_image, the default codec is ekPNG. All codecs are supported by all graphical APIs, except ekGIF in some versions of Linux. Check the return value if it is imperative that your application export images in GIF.


image_get_codec ()

Get the codec associated with the image.

codec_t
image_get_codec(const Image *image);
image

The image.

Return

El codec.

Remarks

See image_codec.


image_num_frames ()

Get the number of sequences in animated images.

uint32_t
image_num_frames(const Image *image);
image

The image.

Return

The number of sequences or frames.

Remarks

Only the gif format supports animations. For the rest 1 will always be returned.


image_frame_length ()

Get the time of an animation sequence.

real32_t
image_frame_length(const Image *image,
                   const uint32_t findex);
image

The image.

findex

The frame index.

Return

Sequence time in seconds.

Remarks

Only gif format supports animations.


image_data ()

Link user data with the image.

void
image_data(Image *image,
           type *data,
           FPtr_destroy func_destroy_data,
           type );
image

The image.

data

The user data.

func_destroy_data

Destructor of user data.

User data type.


image_get_data ()

Gets the user data of the image.

type*
image_get_data(const Image *image,
               type );
image

The image.

User data type.

Return

The user data.


image_native ()

Gets the image in the native format of each platform.

void*
image_native(const Image *image);
image

The image.

Return

The native image. Gdiplus::Bitmap in Windows, GdkPixbuf in Linux and NSImage in macOS.

❮ Back
Next ❯