RosettaCodeData/Task/Bitmap/Zig/bitmap.zig
2026-04-30 12:34:36 -04:00

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);
}
}
}