~turminal/raytracing

8b7388d47c8a8386fffd786dc7aaebeb2415680d — Bor Grošelj Simić 2 years ago 822e5c3
implement image reading
2 files changed, 76 insertions(+), 1 deletions(-)

M color.ha
M image.ha
M color.ha => color.ha +13 -1
@@ 24,6 24,19 @@ export fn torgb(c: color, scale: f64) rgb = rgb {
	b = (clamp(sqrtf64(c.b * scale), 0.0, 0.9999) * 256f64): int: u8,
};

export fn fromrgb(c: rgb) color = {
	let c = color {
		r = c.r: i32: f64 / 256f64,
		g = c.g: i32: f64 / 256f64,
		b = c.b: i32: f64 / 256f64,
	};
	return color {
		r = c.r * c.r,
		g = c.g * c.g,
		b = c.b * c.b,
	};
};

export fn lerp(c1: *const color, c2: *const color, t: f64) color = color {
	r = (1.0 - t) * c1.r + t * c2.r,
	g = (1.0 - t) * c1.g + t * c2.g,


@@ 38,4 51,3 @@ export fn sum_color(c1: *const color, c2: *const color) color = color {

export fn equal(c1: color, c2: color) bool =
	c1.r == c2.r && c1.g == c2.g && c1.b == c2.b;


M image.ha => image.ha +63 -0
@@ 1,11 1,18 @@
use bufio;
use fmt;
use io;
use strconv;
use strings;

def MAGIC: str = "P6";
def MAXVAL: u16 = 255;

export type image = [][]color;

export type invalid = !void;

export type error = !(invalid | io::error);

export fn image_create(width: size, height: size, init: color) image = {
	let img: image = alloc([[]...], height);
	for (let i = 0z; i < height; i += 1) {


@@ 35,6 42,62 @@ export fn write(h: io::handle, img: image, samples: u32) (size | io::error) = {
	return ln;
};

fn tonl(h: io::handle) ([]u8 | error) = match (bufio::scantok(h, '\n': u32: u8)?) {
case io::EOF =>
	yield invalid;
case let buf: []u8 =>
	yield buf;
};

export fn read(f: io::handle) (image | error) = {
	let magic = strings::fromutf8(tonl(f)?);
	if (magic != MAGIC) {
		return invalid;
	};
	let w = match (strconv::stoz(strings::fromutf8(tonl(f)?))) {
	case let sz: size =>
		yield sz;
	case =>
		return invalid;
	};
	let h = match (strconv::stoz(strings::fromutf8(tonl(f)?))) {
	case let sz: size=>
		yield sz;
	case =>
		return invalid;
	};
	match (strconv::stou(strings::fromutf8(tonl(f)?))) {
	case let u: uint =>
		if (u != MAXVAL) {
			return invalid;
		};
	case =>
		return invalid;
	};

	let img: image = alloc([[]...], h);
	for (let i = h - 1; i < h; i -= 1) {
		img[i] = alloc([color { ... }...], w);
		for (let j = 0z; j < w; j += 1) {
			let buf: [3]u8 = [0...];
			match (io::read(f, buf)?) {
			case let sz: size =>
				if (sz != 3) {
					return invalid;
				};
				img[i][j] = fromrgb(rgb {
					r = buf[0],
					g = buf[1],
					b = buf[2],
				});
			case io::EOF =>
				return invalid;
			};
		};
	};
	return img;
};

@test fn image_create() void = {
	let grey = C(0.5, 0.5, 0.5);
	let img = image_create(10, 20, grey);