.{Color, Surface, new_surface} := @use("../lib.hb"); .{log} := @use("../../../stn/src/lib.hb") /* source: https://github.com/phoboslab/qoi/blob/master/qoi.h */ $QOI_SRGB := 0 $QOI_LINEAR := 1 $QOI_OP_INDEX := 0x0 $QOI_OP_DIFF := 0x40 $QOI_OP_LUMA := 0x80 $QOI_OP_RUN := 0xC0 $QOI_OP_RGB := 0xFE $QOI_OP_RGBA := 0xFF $QOI_MASK_2 := 0xC0 $QOI_COLOR_HASH := fn(c: Color): u8 { return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64 } $QOI_MAGIC := 0x716F6966 $QOI_PIXELS_MAX := 400000000 QuiteOkayHeader := packed struct { magic: u32, width: u32, height: u32, channels: u8, colorspace: u8, } be_to_le := fn(big: u32): u32 { return big >> 24 | big >> 8 & 0xFF00 | big << 8 & 0xFF0000 | big << 24 } from := fn(qoi: ^u8): ?Surface { header := @as(^QuiteOkayHeader, @bitcast(qoi)) qoi += @sizeof(QuiteOkayHeader) width := be_to_le(header.width) height := be_to_le(header.height) if be_to_le(header.magic) != QOI_MAGIC | width == 0 | height == 0 | header.channels < 3 | header.channels > 4 { log.error("Invalid QOI image.\0") return null } surface := new_surface(width, height) index := @as([Color; 64], idk) run := 0 px := Color.(0, 0, 0, 255) px_pos := 0 total_pixels := width * height loop if px_pos >= total_pixels break else { if run > 0 { run -= 1 } else { b1 := *qoi qoi += 1 if b1 == QOI_OP_RGB { px.r = *qoi px.g = *(qoi + 1) px.b = *(qoi + 2) qoi += 3 } else if b1 == QOI_OP_RGBA { px.r = *qoi px.g = *(qoi + 1) px.b = *(qoi + 2) px.a = *(qoi + 3) qoi += 4 } else if (b1 & QOI_MASK_2) == QOI_OP_INDEX { px = index[b1 & 0x3F] } else if (b1 & QOI_MASK_2) == QOI_OP_DIFF { px.r = px.r + (b1 >> 4 & 0x3) - 2 & 0xFF px.g = px.g + (b1 >> 2 & 0x3) - 2 & 0xFF px.b = px.b + (b1 & 0x3) - 2 & 0xFF } else if (b1 & QOI_MASK_2) == QOI_OP_LUMA { b2 := *qoi vg := (b1 & 0x3F) - 32 px.r = px.r + vg - 8 + (b2 >> 4 & 0xF) & 0xFF px.g = px.g + vg & 0xFF px.b = px.b + vg - 8 + (b2 & 0xF) & 0xFF qoi += 1 } else if (b1 & QOI_MASK_2) == QOI_OP_RUN { run = b1 & 0x3F } index[QOI_COLOR_HASH(px)] = px }; *(surface.buf + px_pos) = px px_pos += 1 } return surface }