96 lines
2.4 KiB
Zig
96 lines
2.4 KiB
Zig
const std = @import("std");
|
|
|
|
pub const Rgb = struct {
|
|
r: u8,
|
|
g: u8,
|
|
b: u8,
|
|
};
|
|
|
|
pub const PixelOutOfBounds = error{PixelOutOfBounds};
|
|
|
|
pub const Bitmap = struct {
|
|
width: usize,
|
|
height: usize,
|
|
pixels: []Rgb,
|
|
|
|
// The ! next to the return type communicates that the function may return an error
|
|
pub fn new(allocator: std.mem.Allocator, width: usize, height: usize) !Bitmap {
|
|
// In Zig libraries that allocate receive an allocator
|
|
// instead of choosing one themselves
|
|
var pixels = try allocator.alloc(Rgb, width * height);
|
|
|
|
for (0..width*height) | i | {
|
|
pixels[i] = Rgb { .r = 0, .g = 0, .b = 0 };
|
|
}
|
|
|
|
return Bitmap {
|
|
.width = width,
|
|
.height = height,
|
|
.pixels = pixels,
|
|
};
|
|
}
|
|
|
|
pub fn free(self: Bitmap, allocator: std.mem.Allocator) void {
|
|
allocator.free(self.pixels);
|
|
}
|
|
|
|
pub fn fill(self: *Bitmap, color: Rgb) void {
|
|
for (0..self.width*self.height) | i | {
|
|
self.pixels[i] = color;
|
|
}
|
|
}
|
|
|
|
pub fn get_pixel_unchecked(self: Bitmap, x: usize, y: usize) Rgb {
|
|
return self.pixels[self.height * y + x];
|
|
}
|
|
|
|
pub fn get_pixel(self: Bitmap, x: usize, y: usize) !Rgb {
|
|
if (self.width <= x or self.height <= y) {
|
|
return error.PixelOutOfBounds;
|
|
}
|
|
|
|
return self.get_pixel_unchecked(x, y);
|
|
}
|
|
|
|
pub fn set_pixel_unchecked(self: *Bitmap, x: usize, y: usize, color: Rgb) void {
|
|
self.pixels[self.height * y + x] = color;
|
|
}
|
|
|
|
pub fn set_pixel(self: *Bitmap, x: usize, y: usize, color: Rgb) !void {
|
|
if (self.width <= x or self.height <= y) {
|
|
return error.PixelOutOfBounds;
|
|
}
|
|
|
|
return self.set_pixel_unchecked(x, y, color);
|
|
}
|
|
};
|
|
|
|
test "putting a pixel gets the pixel" {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
const allocator = gpa.allocator();
|
|
|
|
var bm = try Bitmap.new(allocator, 10, 10);
|
|
defer bm.free(allocator);
|
|
|
|
try bm.set_pixel(4, 4, Rgb {.r=255, .g=0, .b=0});
|
|
|
|
const pixel = try bm.get_pixel(4, 4);
|
|
|
|
try std.testing.expectEqual(255, pixel.r);
|
|
}
|
|
|
|
test "filling a pixel gets all the pixels" {
|
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
const allocator = gpa.allocator();
|
|
|
|
var bm = try Bitmap.new(allocator, 10, 10);
|
|
defer bm.free(allocator);
|
|
|
|
bm.fill(Rgb {.r=255, .g=0, .b=0});
|
|
|
|
for (0..10) | x | {
|
|
for (0..10) | y | {
|
|
try std.testing.expectEqual(255, bm.get_pixel_unchecked(x, y).r);
|
|
}
|
|
}
|
|
}
|