Add M7: REST API server (ri-agent) with headless mode
Axum-based REST API that mirrors Tauri IPC commands, sharing the same ImageStore via Arc. Endpoints for image open/list/close/save, stats/histogram/ pixel inspection, operations (invert, blur, threshold, edge detection, FFT, projections, etc.), undo, and PNG tile rendering. Auto-starts on port 8787 alongside Tauri GUI. Standalone headless binary via `cargo run --bin ri-headless`. CORS enabled for browser-based clients. 75 tests passing. Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
14ba65851a
commit
432554a258
@@ -0,0 +1,53 @@
|
||||
use axum::extract::{self, State};
|
||||
use axum::http::{header, StatusCode};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
|
||||
use ri_lut::Lut;
|
||||
use ri_render::CompositeChannel;
|
||||
use ri_types::ImageId;
|
||||
|
||||
use crate::error::ApiError;
|
||||
use crate::state::AppState;
|
||||
|
||||
/// GET /images/:id/tile/:c/:z/:t/:x/:y/:w/:h -> image/png
|
||||
pub async fn get_tile(
|
||||
State(state): State<AppState>,
|
||||
extract::Path((id, _c, z, t, x, y, w, h)): extract::Path<(String, u32, u32, u32, u32, u32, u32, u32)>,
|
||||
) -> Result<Response, ApiError> {
|
||||
let image_id: ImageId = id.parse().map_err(|e: uuid::Error| ApiError::bad_request(e.to_string()))?;
|
||||
let store = state.store.clone();
|
||||
|
||||
let png_bytes = tokio::task::spawn_blocking(move || {
|
||||
store.with_entry(&image_id, |entry| {
|
||||
let hs = &entry.hyperstack;
|
||||
let img_w = hs.width();
|
||||
let img_h = hs.height();
|
||||
|
||||
let visible: Vec<_> = entry
|
||||
.channel_states
|
||||
.iter()
|
||||
.filter(|cs| cs.visible)
|
||||
.filter_map(|cs| {
|
||||
let plane = hs.get_plane(cs.channel_index, z, t)?;
|
||||
Some(CompositeChannel {
|
||||
plane,
|
||||
lut: Lut::from_channel_color(&cs.color),
|
||||
display_range: &cs.display_range,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
ri_render::render_composite_tile_png(&visible, img_w, img_h, x, y, w, h)
|
||||
})
|
||||
.map_err(|e| ApiError::not_found(e.to_string()))?
|
||||
.map_err(|e| ApiError::internal(e.to_string()))
|
||||
})
|
||||
.await??;
|
||||
|
||||
Ok((
|
||||
StatusCode::OK,
|
||||
[(header::CONTENT_TYPE, "image/png")],
|
||||
png_bytes,
|
||||
)
|
||||
.into_response())
|
||||
}
|
||||
Reference in New Issue
Block a user