2026-06-02 22:25:24 +01:00

122 lines
2.8 KiB
Odin

#+vet explicit-allocators
package main
import "core:os"
import "core:strconv"
import "core:strings"
PPM_MAGIC_NUMBER :: enum {
P6,
P3,
}
Ppm_Pixel :: struct {
red: u8,
green: u8,
blue: u8,
}
Ppm_file :: struct {
data: []u8,
magic_num: PPM_MAGIC_NUMBER,
width: int,
height: int,
max_col_val: int,
pixels: []Ppm_Pixel,
}
load_ppm :: proc(
ppm_file: ^Ppm_file,
filename: string,
allocator := context.allocator,
) -> (
bool,
os.Error,
) {
if ppm_file == nil || len(filename) == 0 {
return false, .Not_Exist
}
if !strings.has_suffix(filename, ".ppm") {
return false, .Invalid_File
}
//if file is valid, opemn but check error too!
err: os.Error
ppm_file.data, err = os.read_entire_file_from_path(filename, allocator)
if err != nil {
return false, err
}
return true, err
}
//TODO: handle errors and err return type (success: bool?, err: ErrorType?)
ppm_parse :: proc(ppm_file: ^Ppm_file, allocator := context.allocator) {
magic_num_found := false
w_h_found := false
max_col_val_found := false
sb := strings.builder_make(allocator)
defer strings.builder_destroy(&sb)
it := string(ppm_file.data)
for line in strings.split_lines_iterator(&it) {
if strings.starts_with(line, "#") {continue} //ignore comments
if !magic_num_found && strings.starts_with(line, "P") {
num, _ := strconv.parse_int(strings.trim(line, "P"))
if num == 3 {
ppm_file.magic_num = .P3
} else if num == 6 {
ppm_file.magic_num = .P6
}
magic_num_found = true
continue
}
w_h_parts := strings.split(line, " ", allocator)
if !w_h_found && len(w_h_parts) == 2 {
ppm_file.width, _ = strconv.parse_int(w_h_parts[0])
ppm_file.height, _ = strconv.parse_int(w_h_parts[1])
ppm_file.pixels = make([]Ppm_Pixel, ppm_file.width * ppm_file.height, allocator)
w_h_found = true
continue
}
max_val_part := strings.split(line, " ", allocator)
if !max_col_val_found && len(max_val_part) == 1 {
ppm_file.max_col_val, _ = strconv.parse_int(max_val_part[0])
max_col_val_found = true
continue
}
if magic_num_found && w_h_found && max_col_val_found {
for value in strings.split(line, " ", allocator) {
strings.write_string(&sb, value)
strings.write_string(&sb, " ")
}
}
}
all_values := strings.to_string(sb)
index := 0
pixel_values := strings.split(all_values, " ", allocator)
for i := 0; i < len(pixel_values); i += 3 {
if index < len(ppm_file.pixels) {
if i + 2 < len(pixel_values) {
red_val, _ := strconv.parse_int(pixel_values[i])
green_val, _ := strconv.parse_int(pixel_values[i + 1])
blue_val, _ := strconv.parse_int(pixel_values[i + 2])
ppm_file.pixels[index].red = u8(red_val)
ppm_file.pixels[index].green = u8(green_val)
ppm_file.pixels[index].blue = u8(blue_val)
index += 1
}
} else {
break
}
}
}