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

  • 2019 年 10 月 3 日
  • 笔记

* 音视频入门文章目录 *

代码画图

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

开始画图

画彩虹条

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

内容有误?联系作者:

联系作者