Audio and video introduction-06-code drawing time

Time:2020-5-27

Audio and video introduction article directory

Code drawing

In the process of searching information on the Internet, we found some good examples of drawing with code. It’s recorded here for appreciation. It would be better if it could help in the development process.

Start drawing

Draw rainbow bar

Audio and video introduction-06-code drawing time

#include <stdio.h>
#include <stdlib.h>
#include "bmp/bmp.h"

//Seven colors of rainbow
u_int32_t rainbowColors[] = {
        0xxff0000, // red
        0xffa500, // orange
        0xfff00, // yellow
        0x00ff00, // Green
        0x007fff, // Green
        0x0000ff, // blue
        0x8b00ff // Purple
};

void writeRGBToBmp(char *filename, int width, int height) {
    char bmp[BMP_SIZE(width, height)];
    bmp_init(bmp, width, height);

    for (int i = 0; i < width; ++i) {
        //Current color
        u_int32_t currentColor = rainbowColors[0];
        if(i < 100) {
            currentColor = rainbowColors[0];
        } else if(i < 200) {
            currentColor = rainbowColors[1];
        } else if(i < 300) {
            currentColor = rainbowColors[2];
        } else if(i < 400) {
            currentColor = rainbowColors[3];
        } else if(i < 500) {
            currentColor = rainbowColors[4];
        } else if(i < 600) {
            currentColor = rainbowColors[5];
        } else if(i < 700) {
            currentColor = rainbowColors[6];
        }
        for (int j = 0; j < height; ++j) {
            bmp_set(bmp, j, i, currentColor);
        }
    }

    FILE *f = fopen(filename, "wb");
    fwrite(bmp, sizeof(bmp), 1, f);
    fclose(f);
}

int main() {
    writeRGBToBmp("/Users/staff/Desktop/draw-rainbow.bmp", 700, 700);
    return 0;
}

Draw chessboard

Audio and video introduction-06-code drawing time

#include <stdio.h>
#include "bmp/bmp.h"

void writeRGBToBmp(char *filename, int width, int height) {
    char bmp[BMP_SIZE(width, height)];
    bmp_init(bmp, width, height);

    // Draw a checkerboard pattern:
    for (size_t y = 0; y < width; y++){
        for (size_t x = 0; x < height; x++) {
            if ((y % 128 < 64 && x % 128 < 64) ||
                (y % 128 >= 64 && x % 128 >= 64)) {
                bmp_set(bmp, x, y, bmp_encode(255, 255, 255));
            } else {
                bmp_set(bmp, x, y, bmp_encode(0, 0, 0));
            }
        }
    }

    FILE *f = fopen(filename, "wb");
    fwrite(bmp, sizeof(bmp), 1, f);
    fclose(f);
}

int main() {
    writeRGBToBmp("/Users/staff/Desktop/draw-checkerboard.bmp", 512, 512);
    return 0;
}

Draw gradients

Audio and video introduction-06-code drawing time

#include <stdio.h>
#include <stdlib.h>
#include "bmp/bmp.h"

void writeRGBToBmp(char *filename, int width, int height) {
    char bmp[BMP_SIZE(width, height)];
    bmp_init(bmp, width, height);

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            float r = y / (float)height;
            float g = x / (float)width;
            float b = 1.0f;
            bmp_set(bmp, x, y, bmp_encode(r, g, b));
        }
    }

    FILE *f = fopen(filename, "wb");
    fwrite(bmp, sizeof(bmp), 1, f);
    fclose(f);
}

int main() {
    writeRGBToBmp("/Users/staff/Desktop/draw-gradient.bmp", 512, 512);
    return 0;
}

Mandelbrot set fractal

Audio and video introduction-06-code drawing time

#include <stdio.h>
#include <math.h>
#include "common.h"
#include "bmp/bmp.h"

void writeRGBToBmp(char *filename, int width, int height) {
    char bmp[BMP_SIZE(width, height)];
    bmp_init(bmp, width, height);

    double    cr,    ci;
    double nextr, nexti;
    double prevr, previ;

    const unsigned int max_iterations = 1000;

    for (unsigned int y = 0; y < height; ++y)
    {
        for (unsigned int x = 0; x < width; ++x)
        {
            cr = 1.5 * (2.0 * x / width - 1.0) - 0.5;
            ci =       (2.0 * y / height - 1.0);

            nextr = nexti = 0;
            prevr = previ = 0;

            for (unsigned int i = 0; i < max_iterations; ++i)
            {
                prevr = nextr;
                previ = nexti;

                nextr =     prevr * prevr - previ * previ + cr;
                nexti = 2 * prevr * previ + ci;

                if (((nextr * nextr) + (nexti * nexti)) > 4) {

                    const double z = sqrt(nextr * nextr + nexti * nexti);

                    //https://en.wikipedia.org/wiki/Mandelbrot_set#Continuous_.28smooth.29_coloring
                    const unsigned int index = (1000.0 * log2(1.75 + i - log2(log2(z))) / log2(max_iterations));
                    
                    rgb_t color = jet_colormap[index];
                    bmp_set(bmp, x, y, bmp_encode(color.red, color.green, color.blue));
                    break;
                }
            }
        }
    }

    FILE *f = fopen(filename, "wb");
    fwrite(bmp, sizeof(bmp), 1, f);
    fclose(f);
}

int main() {
    writeRGBToBmp("/Users/staff/Desktop/draw-mandelbrot-set.bmp", 600, 400);
    return 0;
}

Julia set fractal

Audio and video introduction-06-code drawing time

#include <stdio.h>
#include "bmp/bmp.h"
#include "common.h"

void writeRGBToBmp(char *filename, int width, int height) {
    char bmp[BMP_SIZE(width, height)];
    bmp_init(bmp, width, height);

    const unsigned int max_iterations = 300;

    const double cr = -0.70000;
    const double ci =  0.27015;

    double prevr, previ;

    for (unsigned int y = 0; y < height; ++y) {
        for (unsigned int x = 0; x < width; ++x) {
            double nextr = 1.5 * (2.0 * x / width - 1.0);
            double nexti =       (2.0 * y / height - 1.0);

            for (unsigned int i = 0; i < max_iterations; ++i) {
                prevr = nextr;
                previ = nexti;

                nextr =     prevr * prevr - previ * previ + cr;
                nexti = 2 * prevr * previ + ci;

                if (((nextr * nextr) + (nexti * nexti)) > 4) {
                    const unsigned int index = ((1000.0 * i) / max_iterations);
                    rgb_t color = hsv_colormap[index];
                    bmp_set(bmp, x, y, bmp_encode(color.red, color.green, color.blue));
                    break;
                }
            }
        }
    }

    FILE *f = fopen(filename, "wb");
    fwrite(bmp, sizeof(bmp), 1, f);
    fclose(f);
}

int main() {
    writeRGBToBmp("/Users/staff/Desktop/draw-julia-set.bmp", 600, 400);
    return 0;
}

Magnifier effect

Audio and video introduction-06-code drawing time

#include <math.h>
#include "common.h"
#include "bmp/bmp.h"
#include <string.h>
#include <stdio.h>

void writeRGBToBmp(char *baseFilename, char *filename, int width, int height) {

    char base[BMP_SIZE(width, height)];
    bmp_init(base, width, height);

    {
        // Draw a checkerboard pattern:
        for (size_t y = 0; y < width; y++){
            for (size_t x = 0; x < height; x++) {
                if ((y % 128 < 64 && x % 128 < 64) ||
                    (y % 128 >= 64 && x % 128 >= 64)) {
                    bmp_set(base, x, y, bmp_encode(255, 255, 255));
                } else {
                    bmp_set(base, x, y, bmp_encode(0, 0, 0));
                }
            }
        }
    }

    char lens_image[BMP_SIZE(width, height)];
    bmp_init(lens_image, width, height);

    memcpy(lens_image, base, sizeof(base));

    const double lens_center_x = width / 2.0;
    const double lens_center_y = height / 2.0;
    const double lens_radius   = fmin(width, height) / 4.0;
    const double lens_factor   = 0.7;

    for (unsigned int y = 0; y < height; ++y) {
        for (unsigned int x = 0; x < width; ++x) {
            const double dx = x - lens_center_x;
            const double dy = y - lens_center_y;

            const double distance = sqrt((dx * dx) + (dy * dy));

            if (distance <= lens_radius) {
                const double radius     = distance / lens_radius;
                const double angle      = atan2(dy, dx);
                const double distortion = pow(radius, lens_factor) * distance;

                int sx = (distortion * cos(angle) + lens_center_x);
                int sy = (distortion * sin(angle) + lens_center_y);

                if (
                        (sx >= 0)                 &&
                        (sy >= 0)                 &&
                        (sx < (int)width) &&
                        (sy < (int)height)
                        ) {

                    bmp_set(lens_image, x, y, bmp_get(base, sx, sy));
                }
            }
        }
    }

    FILE *baseFile = fopen(baseFilename, "wb");
    FILE *file = fopen(filename, "wb");
    fwrite(base, sizeof(base), 1, baseFile);
    fwrite(lens_image, sizeof(lens_image), 1, file);
    fclose(baseFile);
    fclose(file);

}

int main() {
    writeRGBToBmp("/Users/staff/Desktop/draw-magnifying-glass-base.bmp", "/Users/staff/Desktop/draw-magnifying-glass.bmp", 600, 600);
    return 0;
}

Vortex effect

Audio and video introduction-06-code drawing time

#include <math.h>
#include "common.h"
#include "bmp/bmp.h"
#include <string.h>
#include <stdio.h>

void writeRGBToBmp(char *baseFilename, char *filename, int width, int height) {

    char base[BMP_SIZE(width, height)];
    bmp_init(base, width, height);

    {
        // Draw a checkerboard pattern:
        for (size_t y = 0; y < width; y++){
            for (size_t x = 0; x < height; x++) {
                if ((y % 128 < 64 && x % 128 < 64) ||
                    (y % 128 >= 64 && x % 128 >= 64)) {
                    bmp_set(base, x, y, bmp_encode(255, 255, 255));
                } else {
                    bmp_set(base, x, y, bmp_encode(0, 0, 0));
                }
            }
        }
    }

    char swirl_image[BMP_SIZE(width, height)];
    bmp_init(swirl_image, width, height);

    const double swirl_center_x = width / 2.0;
    const double swirl_center_y = height / 2.0;
    const double swirl_radius   = fmin(width, height) / 3.0;

    const double pi_ = 3.1415926535897932384626433832795028841971;
    const double swirl_angle = pi_ / 3.0;

    for (unsigned int y = 0; y < height; ++y)
    {
        for (unsigned int x = 0; x < width; ++x)
        {
            const double dx = x - swirl_center_x;
            const double dy = y - swirl_center_y;

            const double distance = sqrt((dx * dx) + (dy * dy));

            const double angle = swirl_angle * (distance / swirl_radius);

            const double cosa = cos(angle);
            const double sina = sin(angle);

            int sx = (dx * cosa - dy * sina + swirl_center_x);
            int sy = (dx * sina + dy * cosa + swirl_center_y);

            if (
                    (sx >= 0)                 &&
                    (sy >= 0)                 &&
                    (sx < (int)width) &&
                    (sy < (int)height)
                    ) {
                bmp_set(swirl_image, x, y, bmp_get(base, sx, sy));
            }
        }
    }

    FILE *baseFile = fopen(baseFilename, "wb");
    FILE *file = fopen(filename, "wb");
    fwrite(base, sizeof(base), 1, baseFile);
    fwrite(swirl_image, sizeof(swirl_image), 1, file);
    fclose(baseFile);
    fclose(file);

}

int main() {
    writeRGBToBmp("/Users/staff/Desktop/draw-swirl-effect-base.bmp", "/Users/staff/Desktop/draw-swirl-effect.bmp", 600, 600);
    return 0;
}

Ground glass effect

Audio and video introduction-06-code drawing time

#include <math.h>
#include "common.h"
#include "bmp/bmp.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void writeRGBToBmp(char *baseFilename, char *filename, int width, int height) {
    
    const int kernel_size =  10;
    char base[BMP_SIZE(width, height)];
    bmp_init(base, width, height);

    {
        // Draw a checkerboard pattern:
        for (size_t y = 0; y < width; y++){
            for (size_t x = 0; x < height; x++) {
                if ((y % 128 < 64 && x % 128 < 64) ||
                    (y % 128 >= 64 && x % 128 >= 64)) {
                    bmp_set(base, x, y, bmp_encode(255, 255, 255));
                } else {
                    bmp_set(base, x, y, bmp_encode(0, 0, 0));
                }
            }
        }
    }

    char glass_image[BMP_SIZE(width, height)];
    bmp_init(glass_image, width, height);

    memcpy(glass_image, base, sizeof(base));

    for (int y = 0; y < height; ++y)
    {
        for (int x = 0; x < width; ++x)
        {
            const unsigned int min_x = fmax(0, x - kernel_size);
            const unsigned int min_y = fmax(0, y - kernel_size);
            const unsigned int max_x = fmin(x + kernel_size, width  - 1);
            const unsigned int max_y = fmin(y + kernel_size, height - 1);
            const unsigned int dx    = (max_x - min_x);
            const unsigned int dy    = (max_y - min_y);
            const unsigned int N     = rand() % (dx * dy);
            const unsigned int cx    = (N % dx) + min_x;
            const unsigned int cy    = (N / dx) + min_y;

            bmp_set(glass_image, x, y, bmp_get(base, cx, cy));
        }
    }


    FILE *baseFile = fopen(baseFilename, "wb");
    FILE *file = fopen(filename, "wb");
    fwrite(base, sizeof(base), 1, baseFile);
    fwrite(glass_image, sizeof(glass_image), 1, file);
    fclose(baseFile);
    fclose(file);

}

int main() {
    writeRGBToBmp("/Users/staff/Desktop/draw-frosted-glass-effect-base.bmp", "/Users/staff/Desktop/draw-frosted-glass-effect.bmp", 600, 600);
    return 0;
}

maze

Audio and video introduction-06-code drawing time

#include <cstdlib>
#include "bitmap/bitmap_image.hpp"

enum compass { N = 1, E = 2, S = 4, W = 8 };

const int untouched = (N | E | S | W);

struct move_t { int x, y, inverse; };

const move_t move[5] =
        {
                { 0, 0, 0 },
                // North        East         South         West
                { 0, -1, S }, { 1, 0, W }, { 0, 1, N },  { -1, 0, E }
        };

const int movemap[] = {0, 1, 2, 0, 3, 0, 0, 0, 4};

const compass permutations[] =
        {
                N,S,E,W, S,N,E,W, E,N,S,W, N,E,S,W, S,E,N,W, E,S,N,W, E,S,W,N, S,E,W,N,
                W,E,S,N, E,W,S,N, S,W,E,N, W,S,E,N, W,N,E,S, N,W,E,S, E,W,N,S, W,E,N,S,
                N,E,W,S, E,N,W,S, S,N,W,E, N,S,W,E, W,S,N,E, S,W,N,E, N,W,S,E, W,N,S,E
        };

void generate_maze(int cx, int cy, response_image<int>& maze)
{
    const unsigned int perm_index = 4 * ((rand() % 24));

    std::vector<compass>
            directions(&permutations[perm_index], &permutations[perm_index + 4]);

    for (std::size_t i = 0; i < directions.size(); ++i)
    {
        const move_t m = move[movemap[directions[i]]];

        const int x = cx + m.x;
        const int y = cy + m.y;

        if (
                (x < 0) || (y < 0)        ||
                (x >= (int)maze.width ()) ||
                (y >= (int)maze.height()) ||
                (untouched != maze(x,y))
                )
            continue;

        // Eliminate the wall corresponding to the selected direction.
        maze(cx,cy) = maze(cx,cy) & ~directions[i];
        maze( x, y) = maze( x, y) & ~m.inverse;

        generate_maze(x,y, maze);
    }
}

int main() {
    const std::size_t maze_width  = 80;
    const std::size_t maze_height = 70;

    response_image<int> maze(maze_width, maze_height);

    maze.set_all(untouched);

    generate_maze(rand() % maze_width, rand() % maze_height, maze);

    const std::size_t wall_size_x = 10; // 10 pixels
    const std::size_t wall_size_y =  8; //  8 pixels
    const std::size_t pen_size    =  2; //  2 pixels

    bitmap_image image(
            (maze_width ) * wall_size_x + (pen_size - 1),
            (maze_height) * wall_size_y + (pen_size - 1)
    );

    image.clear();

    {
        // Render background using Plasma effect
        const double c1 = 0.9;
        const double c2 = 0.5;
        const double c3 = 0.3;
        const double c4 = 0.7;

        ::srand(0xA5AA5AA5);

        plasma(image, 0, 0, image.width(), image.height(), c1, c2, c3, c4, 3.0, jet_colormap);
    }

    image_drawer draw(image);

    draw.pen_width(2);
    draw.pen_color(0, 0, 0);

    draw.rectangle(0, 0, image.width() - pen_size, image.height() - pen_size);

    // Draw the maze
    for (std::size_t y = 0; y < maze.height(); ++y)
    {
        for (std::size_t x = 0; x < maze.width(); ++x)
        {
            // Cell(x,y) coordinates
            const int x0 = x * wall_size_x;
            const int y0 = y * wall_size_y;
            const int x1 = x * wall_size_x + wall_size_x;
            const int y1 = y * wall_size_y + wall_size_y;

            const int cell = maze(x,y);

            // Is north wall present?
            if ((cell & N))
                draw.line_segment(x0, y0, x1, y0);

            // Is south wall present?
            if ((cell & S))
                draw.line_segment(x0, y1, x1, y1);

            // Is east wall present?
            if ((cell & E))
                draw.line_segment(x1, y0, x1, y1);

            // Is west wall present?
            if ((cell & W))
                draw.line_segment(x0, y0, x0, y1);
        }
    }
    image.save_image("/Users/staff/Desktop/draw-maze.bmp");
    return 0;
}

Fireballs along the Lisa curve

Audio and video introduction-06-code drawing time

#include <cmath>
#include <iterator>
#include <vector>
#include "bitmap/bitmap_image.hpp"

struct lissajous_curve
{
    lissajous_curve(const double xs, const double ys)
            : scale_x(xs),
              scale_y(ys)
    {}

    inline double x(const double t) const { return scale_x * std::sin(4 * t); }
    inline double y(const double t) const { return scale_y * std::cos(3 * t); }

    double scale_x;
    double scale_y;
};

int main()
{
    bitmap_image image(700,500);

    image.clear();

    lissajous_curve curve(image.width () / 2.0 - 25, image.height() / 2.0 - 25);

    const double pi_   = 3.1415926535897932384626433832795028841971;
    const double delta = (2.0 * pi_) / 100000.0;

    const std::size_t max_fire_balls   = 30;
    const std::size_t number_of_frames = 3000;

    const double cooling_factor = 0.940; // [0,1]

    // Arc-length of curve: x(t) = a0 * sin(4t), y(t) = a1 * cos(3t)
    const double curve_length = 6151.0;

    double segment_length  = curve_length / max_fire_balls;
    double curr_seg_length = 0;

    double prev_x = curve.x(0);
    double prev_y = curve.y(0);

    std::vector<double> fire_ball;

    // Set the initial location for each fireball
    for (double t = delta;  fire_ball.size() < max_fire_balls; t += delta)
    {
        const double center_x = curve.x(t);
        const double center_y = curve.y(t);

        const double dx = (prev_x - center_x);
        const double dy = (prev_y - center_y);

        curr_seg_length += std::sqrt((dx * dx) + (dy * dy));

        prev_x = center_x;
        prev_y = center_y;

        if (curr_seg_length >= segment_length)
        {
            curr_seg_length = 0.0;
            fire_ball.push_back(t);
        }
    }

    response_image<double> resp_image(image.width(),image.height(), -1.0);
    response_image<double> fb_misses (image.width(),image.height(), -1.0);

    resp_image.set_all(-999.0);
    fb_misses .set_all(   0.0);

    std::vector<rgb_t> fire_palette;

    // Baseline colours used in fire palette
    rgb_t black  = make_colour(  0,   0,   0);
    rgb_t red    = make_colour(255,   0,   0);
    rgb_t yellow = make_colour(255, 255,   0);
    rgb_t white  = make_colour(255, 255, 255);

    // Setup the fire palette:
    // Black (Coolest - 0) --> Red --> Yellow --> White (Hottest - 999)
    generate_colours(334,  black,    red, std::back_inserter(fire_palette));
    generate_colours(333,    red, yellow, std::back_inserter(fire_palette));
    generate_colours(333, yellow,  white, std::back_inserter(fire_palette));

    for (std::size_t k = 0; k < number_of_frames; ++k)
    {
        fb_misses.inc_all(1);

        // Render fireballs on response image
        for (std::size_t i = 0; i < fire_ball.size(); ++i)
        {
            const double fb_x = curve.x(fire_ball[i]) + image.width () / 2.0;
            const double fb_y = curve.y(fire_ball[i]) + image.height() / 2.0;

            // Draw circles with radii in the range [1,10]
            for (double t = 0;  t < (2 * pi_); t += (((2.0 * pi_) / 360)))
            {
                for (double r = 1; r <= 10; ++r)
                {
                    std::size_t rx = static_cast<std::size_t>(r * std::sin(t) + fb_x);
                    std::size_t ry = static_cast<std::size_t>(r * std::cos(t) + fb_y);

                    // Per-frame in the range [0,100]
                    double heat_distortion = 50.0 * std::cos(delta * i) + 50;

                    resp_image(rx,ry) = fire_palette.size() * 0.8 +
                                        heat_distortion +
                                        (::rand() % 100);

                    fb_misses (rx,ry) = 0;
                }
            }

            // Move fireball to its next location
            fire_ball[i] += delta;
        }

        // Apply cooling process to the entire plane
        for (std::size_t y = 1; y < resp_image.height() - 1; ++y)
        {
            for (std::size_t x = 1; x < resp_image.width() - 1; ++x)
            {
                double avg = (
                                     resp_image(x - 1, y - 1) + resp_image(x    , y - 1) +
                                     resp_image(x + 1, y - 1) + resp_image(x - 1, y    ) +
                                     resp_image(x + 1, y    ) + resp_image(x    , y + 1) +
                                     resp_image(x - 1, y + 1) + resp_image(x + 1, y + 1)
                             ) / (7.0 + cooling_factor);

                // Only allow cooler averages to be applied
                if (avg > resp_image(x, y))
                    continue;

                // More rapidly cool points that haven't seen fireballs in the last N-frames
                if (fb_misses(x,y) > 2000)
                    avg *= 0.90 + ((::rand() % 10) / 100.0);

                // Clamp average in the range [0,999]
                resp_image(x,y) = ((avg < 0.0) ? 0.0 : ((avg > 999.0) ? 999.0 : avg));
            }
        }
    }

    convert_rsp_to_image(resp_image, fire_palette, image);

    image.save_image("/Users/staff/Desktop/draw-fireballs.bmp");

    return 0;
}

Scherbinsky’s triangle Monte Carlo method

Audio and video introduction-06-code drawing time

#include <cmath>
#include <cstdlib>
#include "bitmap/bitmap_image.hpp"

struct point_t { double x,y; };

int main()
{
    const int canvas_width  = 600;
    const int canvas_height = 400;

    cartesian_canvas canvas(canvas_width,canvas_height);

    {
        // Render background using Plasma effect
        const double c1 = 0.9;
        const double c2 = 0.3;
        const double c3 = 0.5;
        const double c4 = 0.7;

        ::srand(0xA5AA5AA5);

        plasma(canvas.image(), c1, c2, c3, c4, 3.5, jet_colormap);
    }

    point_t triangle[3];

    triangle[0].x = 0;
    triangle[0].y = +canvas_height / 2.0;
    triangle[1].x = -canvas_width  / 2.0;
    triangle[1].y = -canvas_height / 2.0;
    triangle[2].x = +canvas_width  / 2.0;
    triangle[2].y = -canvas_height / 2.0;

    point_t pnt = triangle[0];

    const std::size_t max_iterations = 1000000;

    for (std::size_t i = 0; i < max_iterations; ++i)
    {
        const point_t target_point = triangle[rand() % 3];

        pnt.x += (target_point.x - pnt.x) / 2.0;
        pnt.y += (target_point.y - pnt.y) / 2.0;

        canvas.plot_pen_pixel(pnt.x,pnt.y);
    }

    canvas.image().save_image("/Users/staff/Desktop/draw-sierpinski-triangle.bmp");

    return 0;
}

Circular and equilateral triangles

Audio and video introduction-06-code drawing time

#include <cmath>
#include <cstdlib>
#include "bitmap/bitmap_image.hpp"

struct point_t { double x,y; };

int main()
{
    const int canvas_width  = 700;
    const int canvas_height = 460;

    cartesian_canvas canvas(canvas_width,canvas_height);

    canvas.image().clear(255);

    canvas.pen_width(1);

    ::srand(0xA5A5A5A5);

    for (std::size_t i = 0; i < 100; ++i)
    {
        double cx = ((rand() % canvas_width ) - canvas_width  / 2.0);
        double cy = ((rand() % canvas_height) - canvas_height / 2.0);
        double r  = (rand() % 70) + 10;

        const double pi_   = 3.1415926535897932384626433832795028841971;
        const double _120d = (2.0 * pi_/ 3.0);

        double rndang = ((2.0 * pi_) / 360.0) * ((rand() % 360) + 1.0);

        point_t p0, p1, p2;
        point_t p3, p4, p5;

        p0.x = r * std::sin(1.0 * _120d + rndang) + cx;
        p0.y = r * std::cos(1.0 * _120d + rndang) + cy;
        p1.x = r * std::sin(2.0 * _120d + rndang) + cx;
        p1.y = r * std::cos(2.0 * _120d + rndang) + cy;
        p2.x = r * std::sin(3.0 * _120d + rndang) + cx;
        p2.y = r * std::cos(3.0 * _120d + rndang) + cy;

#define rnd_colour (copper_colormap[rand() % 1000])

        // Draw and fill the circle
        canvas.pen_color(rnd_colour);
        canvas.fill_circle(cx, cy, r);
        canvas.pen_color(rnd_colour);
        canvas.circle(cx, cy, r);

        // Draw and fill the main equilateral triangles
        canvas.pen_color(rnd_colour);
        canvas.fill_triangle(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y);
        canvas.pen_color(rnd_colour);
        canvas.triangle(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y);

        // Draw the inner-equilateral triangles
        for (unsigned int j = 0; j < 4; ++j)
        {
            p3.x = (p0.x + p1.x) / 2.0;
            p3.y = (p0.y + p1.y) / 2.0;
            p4.x = (p1.x + p2.x) / 2.0;
            p4.y = (p1.y + p2.y) / 2.0;
            p5.x = (p2.x + p0.x) / 2.0;
            p5.y = (p2.y + p0.y) / 2.0;

            p0 = p3; p1 = p4; p2 = p5;

            canvas.pen_color(rnd_colour);
            canvas.fill_triangle(p3.x, p3.y, p4.x, p4.y, p5.x, p5.y);
            canvas.pen_color(rnd_colour);
            canvas.triangle(p3.x, p3.y, p4.x, p4.y, p5.x, p5.y);
        }
    }

    canvas.image().save_image("/Users/staff/Desktop/draw-circles_and_triangles.bmp");

    return 0;
}

Archimedes spiral

Audio and video introduction-06-code drawing time

#include <cmath>
#include <cstdlib>
#include "bitmap/bitmap_image.hpp"

struct point_t
{
    point_t(double _x = 0.0, double _y = 0.0) : x(_x), y(_y) {}
    double x,y;
};

int main()
{
    const double pi_ = 3.1415926535897932384626433832795028841971;
    const double a   = 20.0;
    const double b   = 20.0;
    const double dr  = (2.0 * pi_) / 1000.0;

    const std::size_t N = 5;
    const double delta_angle = (2.0 * pi_) / N;

    std::vector<point_t> spiral;

    for (std::size_t i = 0; i < N; ++i)
    {
        spiral.push_back(
                point_t(a * std::cos((delta_angle * i)),
                        a * std::sin((delta_angle * i))));
    }

    const int canvas_width  = 600;
    const int canvas_height = 600;

    cartesian_canvas canvas(canvas_width,canvas_height);

    canvas.image().clear(0);

    {
        // Render background using Plasma effect
        const double c1 = 0.9;
        const double c2 = 0.5;
        const double c3 = 0.3;
        const double c4 = 0.7;

        bitmap_image& image = canvas.image();

        ::srand(0xA5AA5AA5);

        plasma(image, 0, 0, image.width(), image.height(), c1, c2, c3, c4, 3.0, gray_colormap);
    }

    for (double angle = dr; (a + b * angle) < canvas.image().width() / 2.0; angle += dr)
    {
        for (std::size_t i = 0; i < spiral.size(); ++i)
        {
            const double theta = angle + delta_angle * i;
            const double d     = (a + b * angle);
            const point_t curr(d * std::cos(theta), d * std::sin(theta));

            const double centre_ratio =
                    (sqrt(curr.x * curr.x + curr.y * curr.y) / (canvas.image().width() / 2.0));

            if (centre_ratio <= 0.25) canvas.pen_width(1);
            else if (centre_ratio <= 0.50) canvas.pen_width(2);
            else if (centre_ratio <= 0.75) canvas.pen_width(3);
            else if (centre_ratio <= 1.00) canvas.pen_width(4);

            unsigned int index = (unsigned int)(1000.0 * centre_ratio);

            canvas.pen_color(hsv_colormap[index]);

            canvas.line_segment(spiral[i].x, spiral[i].y, curr.x, curr.y);

            spiral[i] = curr;
        }
    }

    canvas.image().save_image("/Users/staff/Desktop/draw-archimedean-spirals.bmp");

    return 0;
}

Picture mosaic

Audio and video introduction-06-code drawing time

#include <cmath>
#include <cstdlib>
#include <vector>
#include "bitmap/bitmap_image.hpp"

void shuffle(unsigned int n, std::vector<unsigned int>& v)
{
    ::srand(0x13A1515A);
    for (unsigned int i = 0; i < n; ++i) v.push_back(i);
    for (unsigned int i = v.size() - 1; i > 0; --i)
    { std::swap(v[i], v[rand() % (i + 1)]); }
}

int main()
{
    bitmap_image image("/Users/staff/Documents/Cpp/image-demo-rgb-pixel/06-drawing-time-cpp/tiger.bmp");

    const unsigned int divisions    = 3;
    const unsigned int block_width  = image.width () / divisions;
    const unsigned int block_height = image.height() / divisions;

    std::vector<unsigned int> cell;

    shuffle(divisions * divisions, cell);

    bitmap_image shuffled(image.width(), image.height());
    bitmap_image region;

    shuffled.clear();

    for (std::size_t i = 0; i < cell.size(); ++i)
    {
        unsigned int x_offset = block_width  * (i % divisions);
        unsigned int y_offset = block_height * (i / divisions);

        // Copy region from original image
        image.region(x_offset, y_offset,
                     block_width, block_height, region);

        x_offset = block_width  * (cell[i] % divisions);
        y_offset = block_height * (cell[i] / divisions);

        // Paste region to new location in shuffled image
        shuffled.copy_from(region, x_offset, y_offset);
    }

    shuffled.save_image("/Users/staff/Desktop/draw-image-shuffled.bmp");

    return 0;
}

Helix of phyllodes

Audio and video introduction-06-code drawing time

#include <cmath>
#include <cstdlib>
#include "bitmap/bitmap_image.hpp"

int main()
{
    const int canvas_width  = 600;
    const int canvas_height = 600;

    const double pi       = 3.1415926535897932384626433832795028841971;
    const double phi      = pi * (3.0 - std::sqrt(5.0));
    const double radius   = (std::min(canvas_width, canvas_height) / 2.0) - 5.0;
    const double N        = 1200.0;
    const double spread   = radius / std::sqrt(N);
    const double p_radius = std::floor(spread / 2.0);

    cartesian_canvas canvas(canvas_width,canvas_height);

    {
        // Render background using Plasma effect
        const double c1 = 0.9;
        const double c2 = 0.5;
        const double c3 = 0.3;
        const double c4 = 0.7;

        bitmap_image& image = canvas.image();

        ::srand(0xA5AA5AA5);

        plasma(image, 0, 0, image.width(), image.height(), c1, c2, c3, c4, 3.0, copper_colormap);
    }

    for (double i = 0.0; i < N; ++i)
    {
        const double theta = phi * i;
        const double d     = spread * std::sqrt(i);
        const double x     = d * std::cos(theta);
        const double y     = d * std::sin(theta);

        canvas.pen_color(hsv_colormap[static_cast<std::size_t>(1000.0 * (i  / N))]);
        canvas.fill_circle(x, y, p_radius);
    }

    canvas.image().save_image("/Users/staff/Desktop/draw-phyllotaxis-spiral.bmp");

    return 0;
}

Punctate effect

Audio and video introduction-06-code drawing time

#include <cstdlib>
#include "bitmap/bitmap_image.hpp"

int main()
{
    bitmap_image base("/Users/staff/Documents/Cpp/image-demo-rgb-pixel/06-drawing-time-cpp/sunflower.bmp");

    cartesian_canvas canvas(base.width(),base.height());
    canvas.image() = base;

    const int pixel_count  = base.width() * base.height();
    const int N            = static_cast<int>(pixel_count * 0.03); // 3% of pixels
    const double rnd_ratio = pixel_count / (1.0 + RAND_MAX);

    ::srand(0xA57A57A5);

    for (int i = 0; i < N; ++i)
    {
        const int    r  = static_cast<int>(rand() * rnd_ratio);
        const int    x  = (r % base.width());
        const int    y  = (r / base.width());
        const double cx = x - (base.width() / 2.0);
        const double cy = (base.height() / 2.0) - y;
        const double radius = 1.0 + (r % 7);

        canvas.pen_color(base.get_pixel(x, y));
        canvas.fill_circle(cx, cy, radius);
    }

    canvas.image().save_image("/Users/staff/Desktop/draw-pointillist-effect.bmp");

    return 0;
}

code:

06-drawing-time & 06-drawing-time-cpp

reference material:

Simple Bitmap Library Usage Examples

Wrong content? Contact author:

Audio and video introduction-06-code drawing time