Skip to content

How to create linear gradient?

VBrazhnik edited this page Aug 23, 2018 · 3 revisions

Here we will consider how to find the color between any two color points through linear interpolation.

First of all we need to find current point position between two points with known colors. Position value must be expressed in percentages.

The following function will help you find this value:

double percent(int start, int end, int current)
{
    double placement;
    double distance;

    placement = current - start;
    distance = end - start;
    return ((distance == 0) ? 1.0 : (placement / distance));
}

You can calculate this value depending on which delta value is bigger. Delta between x values of known points or delta between y values.

Part of code:

// ...
    double percentage;

    if (delta.x > delta.y)
        percentage = percent(start.x, end.x, current.x);
    else
        percentage = percent(start.y, end.y, current.y);
// ...

Then for creating each light (Red, Green, Blue) we need to get light from start and end point and use linear interpolation. At the end we need to get new color by union red, green and blue light.

Part of code:

// ...
    int red;
    int green;
    int blue;

    // Get percentage

    red = get_light((start.color >> 16) & 0xFF, (end.color >> 16) & 0xFF, percentage);
    green = get_light((start.color >> 8) & 0xFF, (end.color >> 8) & 0xFF, percentage);
    blue = get_light(start.color & 0xFF, end.color & 0xFF, percentage);
    return ((red << 16) | (green << 8) | blue);
int get_light(int start, int end, double percentage)
{
    return ((int)((1 - percentage) * start + percentage * end));
}

Complete code:

int get_light(int start, int end, double percentage)
{
    return ((int)((1 - percentage) * start + percentage * end));
}

int get_color(t_point current, t_point start, t_point end, t_point delta)
{
    int     red;
    int     green;
    int     blue;
    double  percentage;

    if (current.color == end.color)
        return (current.color);
    if (delta.x > delta.y)
        percentage = percent(start.x, end.x, current.x);
    else
        percentage = percent(start.y, end.y, current.y);
    red = get_light((start.color >> 16) & 0xFF, (end.color >> 16) & 0xFF, percentage);
    green = get_light((start.color >> 8) & 0xFF, (end.color >> 8) & 0xFF, percentage);
    blue = get_light(start.color & 0xFF, end.color & 0xFF, percentage);
    return ((red << 16) | (green << 8) | blue);
}

Basic information was found here.

Additional information

On macOS endian value is useless and bits_per_pixel value is constant. You can find the following lines in source files of minilibx:

/*
** endian : 0 = sever X is little endian, 1 = big endian
** endian : useless on macos, client and graphical framework have the same endian
*/
#define UNIQ_BPP 4
// assume here 32bpp little endian

char *mlx_get_data_addr(mlx_img_list_t *img_ptr, int *bits_per_pixel, int *size_line, int *endian)
{
    *bits_per_pixel = UNIQ_BPP * 8;
    *size_line = img_ptr->width * UNIQ_BPP;
    *endian = 0; // little endian for now on mac-intel
    return (img_ptr->buffer);
}

So order of lights in your code must be exactly RGB (If you decided to support only macOS).

Structure of color looks like:

0 R G B
8 bits 8 bits 8 bits 8 bits

You can find this information in mlx_pixel_put man file.

What is bits per pixel or bit-depth value?

The number of bits used to define a pixel's color shade is its bit-depth. True color is sometimes known as 24-bit color. Some new color display systems offer a 32-bit color mode. The extra byte, called the alpha channel, is used for control and special effects information.

Clone this wiki locally