rstiff 0.2.0

A Rust library for high-precision, type-preserving GeoTiff I/O powered by GDAL.
///! 窗口化读取示例
///!
///! 展示如何只读取栅格文件的一部分,避免加载整个大文件到内存。
///!
///! 运行方式:
///! ```bash
///! cargo run --example window_read
///! ```
use rstiff::{GeoTiff, RasterInfo};
use std::error::Error;
use std::path::Path;

fn main() -> Result<(), Box<dyn Error>> {
    let input = Path::new("./data/Hawaiin_part.tif");
    if !input.exists() {
        println!("请先准备 ./data/Hawaiin_part.tif 文件");
        return Ok(());
    }

    // ============================================================
    // 1. 使用 RasterInfo 快速获取文件元数据(不加载像素数据)
    // ============================================================
    println!("=== 1. 读取元数据 ===");
    let info = RasterInfo::from_file(input)?;

    println!("文件尺寸: {} x {} 像素", info.width, info.height);
    println!("波段数量: {}", info.bands);
    println!("数据类型: {:?}", info.original_type);
    println!("NoData 值: {:?}", info.nodata);

    // 获取地理范围
    let (min_x, min_y, max_x, max_y) = info.bounds();
    println!(
        "地理范围: X[{:.6} ~ {:.6}], Y[{:.6} ~ {:.6}]",
        min_x, max_x, min_y, max_y
    );

    // 获取分辨率
    let (res_x, res_y) = info.res();
    println!("像素分辨率: {:.6} x {:.6}", res_x, res_y);

    // ============================================================
    // 2. 坐标转换示例
    // ============================================================
    println!("\n=== 2. 坐标转换 ===");

    // 像素坐标 -> 地理坐标
    let (geo_x, geo_y) = info.pixel_to_geo(100, 200);
    println!("像素 (100, 200) -> 地理坐标 ({:.6}, {:.6})", geo_x, geo_y);

    // 地理坐标 -> 像素坐标
    let (col, row) = info.geo_to_pixel(geo_x, geo_y);
    println!(
        "地理坐标 ({:.6}, {:.6}) -> 像素 ({}, {})",
        geo_x, geo_y, col, row
    );

    // ============================================================
    // 3. 像素坐标窗口读取
    // ============================================================
    println!("\n=== 3. 像素窗口读取 ===");

    // 只读取左上角 256x256 的区域
    let x_off = 0;
    let y_off = 0;
    let width = 256;
    let height = 256;

    println!(
        "读取窗口: x={}, y={}, w={}, h={}",
        x_off, y_off, width, height
    );
    let tile = GeoTiff::read_window(input, x_off, y_off, width, height)?;

    println!("读取成功!数据尺寸: {:?}", tile.data.dim());
    println!(
        "窗口左上角坐标: ({:.6}, {:.6})",
        tile.geo_transform[0], tile.geo_transform[3]
    );

    // 保存切片
    let output_tile = Path::new("./data/window_tile.tif");
    tile.write(output_tile)?;
    println!("已保存到: {:?}", output_tile);

    // ============================================================
    // 4. 地理坐标范围读取
    // ============================================================
    println!("\n=== 4. 地理坐标范围读取 ===");

    // 计算中心区域的范围(取中间 1/4 区域)
    let center_x = (min_x + max_x) / 2.0;
    let center_y = (min_y + max_y) / 2.0;
    let quarter_w = (max_x - min_x) / 4.0;
    let quarter_h = (max_y - min_y) / 4.0;

    let bounds = (
        center_x - quarter_w, // min_x
        center_y - quarter_h, // min_y
        center_x + quarter_w, // max_x
        center_y + quarter_h, // max_y
    );

    println!(
        "读取范围: ({:.4}, {:.4}, {:.4}, {:.4})",
        bounds.0, bounds.1, bounds.2, bounds.3
    );

    let center_roi = GeoTiff::read_bounds(input, bounds)?;
    println!("读取成功!数据尺寸: {:?}", center_roi.data.dim());

    let output_center = Path::new("./data/window_center.tif");
    center_roi.write(output_center)?;
    println!("已保存到: {:?}", output_center);

    // ============================================================
    // 5. 对比内存使用
    // ============================================================
    println!("\n=== 5. 内存对比 ===");

    let full_pixels = info.width * info.height * info.bands;
    let tile_pixels = 256 * 256 * info.bands;

    println!(
        "完整读取需要: {} 像素 ({:.2} MB @ f64)",
        full_pixels,
        (full_pixels * 8) as f64 / 1024.0 / 1024.0
    );
    println!(
        "窗口读取只需: {} 像素 ({:.2} MB @ f64)",
        tile_pixels,
        (tile_pixels * 8) as f64 / 1024.0 / 1024.0
    );
    println!(
        "内存节省: {:.1}%",
        (1.0 - tile_pixels as f64 / full_pixels as f64) * 100.0
    );

    println!("\n完成!");
    Ok(())
}