138 lines
3.8 KiB
C++
138 lines
3.8 KiB
C++
#include <iostream>
|
|
#include <fstream>
|
|
#include <vector>
|
|
|
|
// Define a structure for a pixel
|
|
struct Pixel {
|
|
unsigned char r, g, b;
|
|
};
|
|
|
|
|
|
|
|
// Define a structure for an image
|
|
struct Image {
|
|
int width, height;
|
|
std::vector<Pixel> pixels;
|
|
|
|
Image(int w, int h) : width(w), height(h) {
|
|
pixels.resize(width * height);
|
|
}
|
|
|
|
// Set the color of a specific pixel
|
|
void setPixel(int x, int y, const Pixel& color) {
|
|
if (x >= 0 && x < width && y >= 0 && y < height) {
|
|
pixels[y * width + x] = color;
|
|
}
|
|
}
|
|
|
|
// Save the image in PPM format
|
|
void savePPM(const std::string& filename) {
|
|
std::ofstream file(filename);
|
|
if (!file.is_open()) {
|
|
std::cerr << "Failed to open file for writing." << std::endl;
|
|
return;
|
|
}
|
|
|
|
// Write the header for P3 format
|
|
file << "P3\n" << width << " " << height << "\n255\n";
|
|
|
|
// Write pixel data in ASCII format
|
|
for (const auto& pixel : pixels) {
|
|
file << static_cast<int>(pixel.r) << " "
|
|
<< static_cast<int>(pixel.g) << " "
|
|
<< static_cast<int>(pixel.b) << "\n";
|
|
}
|
|
|
|
file.close();
|
|
}
|
|
|
|
// void savePPM(const std::string& filename) {
|
|
// std::ofstream file(filename, std::ios::binary);
|
|
// file << "P6\n" << width << " " << height << "\n255\n";
|
|
// for (const auto& pixel : pixels) {
|
|
// file << pixel.r << pixel.g << pixel.b;
|
|
// }
|
|
// file.close();
|
|
// }
|
|
};
|
|
|
|
struct Point {
|
|
int x, y;
|
|
};
|
|
|
|
// Function to check if a point is inside a triangle using barycentric coordinates
|
|
bool isInsideTriangle(int x, int y, const Point& v1, const Point& v2, const Point& v3) {
|
|
int a = (v1.x - x) * (v2.y - v1.y) - (v2.x - v1.x) * (v1.y - y);
|
|
int b = (v2.x - x) * (v3.y - v2.y) - (v3.x - v2.x) * (v2.y - y);
|
|
int c = (v3.x - x) * (v1.y - v3.y) - (v1.x - v3.x) * (v3.y - y);
|
|
|
|
// A point is inside the triangle if all barycentric coordinates are positive or all are negative
|
|
return (a <= 0 && b <= 0 && c <= 0) || (a > 0 && b > 0 && c > 0);
|
|
}
|
|
|
|
// Function to draw a triangle
|
|
void drawTriangle(Image& img, const Point& v1, const Point& v2, const Point& v3, const Pixel& color) {
|
|
// Find the bounding box of the triangle
|
|
|
|
int minX = std::min(std::min(v1.x, v2.x), v3.x);
|
|
int maxX = std::max(std::max(v1.x, v2.x), v3.x);
|
|
int minY = std::min(std::min(v1.y, v2.y), v3.y);
|
|
int maxY = std::max(std::max(v1.y, v2.y), v3.y);
|
|
|
|
|
|
// Iterate over the bounding box and color the pixels inside the triangle
|
|
for (int y = minY; y <= maxY; ++y) {
|
|
for (int x = minX; x <= maxX; ++x) {
|
|
if (isInsideTriangle(x, y, v1, v2, v3)) {
|
|
img.setPixel(x, y, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool insideCircle(int x, int y, const Point& c, const int r){
|
|
return ((x - c.x)*(x - c.x) + (y - c.y)*(y - c.y)) < r*r;
|
|
}
|
|
|
|
void drawCircle(Image& img, const Point& c, const int r, const Pixel& color){
|
|
int minX = c.x - r;
|
|
int maxX = c.x + r;
|
|
int minY = c.y - r;
|
|
int maxY = c.y + r;
|
|
|
|
for(int y= minY; y <= maxY; y++){
|
|
for(int x = minX; x <= maxX; x++){
|
|
if(insideCircle(x,y,c,r)){
|
|
img.setPixel(x,y,color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
// Create an image of 100x100
|
|
Image img(200, 200);
|
|
|
|
// Set some pixels to create a pattern
|
|
for (int y = 0; y < img.height; ++y) {
|
|
for (int x = 0; x < img.width; ++x) {
|
|
if ((x + y) % 20 < 10) {
|
|
img.setPixel(x, y, {255, 0, 0}); // Red color
|
|
} else {
|
|
img.setPixel(x, y, {0, 0, 255}); // Blue color
|
|
}
|
|
}
|
|
}
|
|
|
|
drawTriangle(img, {20,80}, {80,80}, {80, 120}, {100,100,100});
|
|
|
|
drawCircle(img, {100,100}, 30, {0,200,0});
|
|
|
|
// Save the image
|
|
img.savePPM("output.ppm");
|
|
|
|
std::cout << "Image saved as output.ppm" << std::endl;
|
|
|
|
return 0;
|
|
}
|