• 音视频入门-06-代码画图时间


    * 音视频入门文章目录 *

    代码画图

    网上查资料的过程中,发现一些比较好的用代码画图的例子。这里记录下来,供欣赏。如果对开发过程中有所帮助就更好了。

    开始画图

    画彩虹条

    rainbow.jpg

    #include <stdio.h>
    #include <stdlib.h>
    #include "bmp/bmp.h"
    
    // 彩虹的七种颜色
    u_int32_t rainbowColors[] = {
            0XFF0000, // 红
            0XFFA500, // 橙
            0XFFFF00, // 黄
            0X00FF00, // 绿
            0X007FFF, // 青
            0X0000FF, // 蓝
            0X8B00FF  // 紫
    };
    
    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) {
            // 当前颜色
            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;
    }
    

    画棋盘格

    checkerboard.jpg

    #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;
    }
    

    画渐变图

    gradient.jpg

    #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 分形图

    mandelbrot-set.jpg

    #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 分形图

    julia-set.jpg

    #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;
    }
    

    放大镜效果

    magnifying-glass.jpg

    #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;
    }
    

    旋涡效果

    swirl-effect.jpg

    #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;
    }
    

    毛玻璃效果

    frosted-glass-effect.jpg

    #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.jpg

    #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.jpg

    #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;
    }
    

    谢尔宾斯基三角形-蒙特卡罗方法

    sierpinski-triangle.jpg

    #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;
    }
    

    圆型和等边三角形

    circles_and_triangles.jpg

    #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;
    }
    

    阿基米德螺旋

    archimedean-spirals.jpg

    #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;
    }
    

    图片拼图

    image-shuffled.jpg

    #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;
    }
    

    叶序螺旋

    phyllotaxis-spiral.jpg

    #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;
    }
    

    点状效果

    pointissist-effect.jpg

    #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;
    }
    

    代码:

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

    参考资料:

    Simple Bitmap Library Usage Examples

    内容有误?联系作者:

    联系作者


  • 相关阅读:
    王者齐聚!Unite 2017 Shanghai 日程讲师全揭晓
    微软在.NET官网上线.NET 架构指南频道
    期待微软平台即服务技术Service Fabric 开源
    Visual Studio 20周年软件趋势随想
    .NET 十五岁,谈谈我眼中的.NET
    API网关Ocelot 使用Polly 处理部分失败问题
    互联网背景下知识半衰期这么短,如何学习?
    CentOS 7 上面安装PowerShell
    搭建consul 集群
    Entity Framework Core 实现MySQL 的TimeStamp/RowVersion 并发控制
  • 原文地址:https://www.cnblogs.com/binglingziyu/p/audio-video-basic-06-code-drawing.html
Copyright © 2020-2023  润新知