代码画图
网上查资料的过程中,发现一些比较好的用代码画图的例子。这里记录下来,供欣赏。如果对开发过程中有所帮助就更好了。
开始画图
画彩虹条
#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
内容有误?联系作者: