tx2-iff 0.1.0

PPF-IFF (Involuted Fractal Format) - Image codec using Physics-Prime Factorization, 360-prime quantization, and symplectic warping
Documentation
// Inverse CDF 5/3 wavelet transform shader
// Reconstructs image from wavelet coefficients using integer lifting scheme

struct Metadata {
    width: u32,
    height: u32,
    levels: u32,
    _padding: u32,
}

@group(0) @binding(0) var<storage, read> wavelet_data: array<i32>;
@group(0) @binding(1) var<uniform> metadata: Metadata;
@group(0) @binding(2) var<storage, read_write> output: array<u32>;

// Fixed-point helpers (16.16 format)
fn fixed_from_int(x: i32) -> i32 {
    return x << 16;
}

fn fixed_to_int(x: i32) -> i32 {
    return x >> 16;
}

// CDF 5/3 inverse lifting steps
// Undo update: s[i] -= floor((d[i-1] + d[i] + 2) / 4)
// Undo predict: d[i] += floor((s[2i] + s[2i+2]) / 2)

fn inverse_lifting_horizontal(data: ptr<function, array<i32, 256>>, size: u32) {
    // Undo update step
    for (var i = 1u; i < size - 1u; i += 2u) {
        let correction = (data[i - 1u] + data[i + 1u] + 2) / 4;
        data[i] += correction;
    }

    // Undo predict step
    for (var i = 0u; i < size; i += 2u) {
        if (i > 0u && i < size - 1u) {
            let correction = (data[i - 1u] + data[i + 1u]) / 2;
            data[i] -= correction;
        }
    }
}

fn inverse_lifting_vertical(data: ptr<function, array<i32, 256>>, size: u32) {
    // Same as horizontal
    inverse_lifting_horizontal(data, size);
}

@compute @workgroup_size(8, 8, 1)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let x = global_id.x;
    let y = global_id.y;

    if (x >= metadata.width || y >= metadata.height) {
        return;
    }

    let idx = y * metadata.width + x;

    // For now, implement a simple passthrough that converts from wavelet to RGB
    // A full implementation would reconstruct per-level using the lifting scheme
    // This is a simplified version that reads low-frequency approximation

    // Read wavelet coefficient (assumed to be centered at 0)
    let coeff_idx = idx * 3u;

    let r_val = wavelet_data[coeff_idx] + 128;
    let g_val = wavelet_data[coeff_idx + 1u] + 128;
    let b_val = wavelet_data[coeff_idx + 2u] + 128;

    // Clamp to [0, 255]
    let r = clamp(r_val, 0, 255);
    let g = clamp(g_val, 0, 255);
    let b = clamp(b_val, 0, 255);

    // Pack as RGBA8 (alpha = 255)
    output[idx] = u32(r) | (u32(g) << 8u) | (u32(b) << 16u) | (255u << 24u);
}