120 lines
2.8 KiB
Odin
120 lines
2.8 KiB
Odin
package main
|
|
|
|
import "core:c"
|
|
import "core:fmt"
|
|
import "core:os"
|
|
import "core:os/os2"
|
|
import "core:strconv"
|
|
import "core:strings"
|
|
|
|
PPM_MAGIC_NUMBER :: enum {
|
|
P6,
|
|
P3,
|
|
}
|
|
|
|
Ppm_Pixel :: struct {
|
|
red: u8,
|
|
green: u8,
|
|
blue: u8,
|
|
}
|
|
|
|
Ppm_file :: struct {
|
|
file: os2.File, //TODO: use this instead perhaps?
|
|
data: []byte,
|
|
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) -> (success: bool) {
|
|
if !strings.has_suffix(filename, ".ppm") {
|
|
fmt.eprintfln("ERROR: File %s does not have a valid ppm extention (.ppm)", filename)
|
|
return false
|
|
}
|
|
|
|
succ: bool
|
|
ppm_file.data, succ = os.read_entire_file_from_filename(filename, context.temp_allocator)
|
|
if !succ {
|
|
fmt.eprintfln("ERROR: Failed to load file: %s ", filename)
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
//TODO: handle errors and err return type (success: bool?, err: ErrorType?)
|
|
ppm_parse :: proc(ppm_file: ^Ppm_file) {
|
|
magic_num_found := false
|
|
w_h_found := false
|
|
max_col_val_found := false
|
|
sb := strings.builder_make(allocator = context.temp_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, " ")
|
|
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,
|
|
context.temp_allocator,
|
|
)
|
|
w_h_found = true
|
|
continue
|
|
}
|
|
|
|
max_val_part := strings.split(line, " ")
|
|
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, " ") {
|
|
strings.write_string(&sb, value)
|
|
strings.write_string(&sb, " ")
|
|
}
|
|
}
|
|
}
|
|
|
|
all_values := strings.to_string(sb)
|
|
|
|
index := 0
|
|
pixel_values := strings.split(all_values, " ")
|
|
|
|
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
|
|
}
|
|
}
|
|
}
|