音视频入门-06-代码画图时间
- 2019 年 10 月 3 日
- 笔记
代码画图
网上查资料的过程中,发现一些比较好的用代码画图的例子。这里记录下来,供欣赏。如果对开发过程中有所帮助就更好了。
开始画图
画彩虹条
#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; }
画棋盘格
#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; }
画渐变图
#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 分形图
#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 分形图
#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; }
放大镜效果
#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; }
旋涡效果
#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; }
毛玻璃效果
#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; }
迷宫图
#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; }
沿着利萨曲线的火球
#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; }
谢尔宾斯基三角形-蒙特卡罗方法
#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; }
圆型和等边三角形
#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; }
阿基米德螺旋
#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; }
图片拼图
#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; }
叶序螺旋
#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; }
点状效果
#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
内容有误?联系作者: