use std::io::Cursor;
use actix_http::StatusCode;
use actix_web::web::Data;
use image::{ImageBuffer, Rgb};
use crate::{
config::data::AppDataInner,
error::ServiceError,
model::{
dto::{HeatMapQueryParams, RelationSearchParameters, RelationsDto},
entity::plant_layer,
},
};
pub async fn heatmap(
map_id: i32,
query_params: HeatMapQueryParams,
app_data: &Data<AppDataInner>,
) -> Result<Vec<u8>, ServiceError> {
let mut conn = app_data.pool.get().await?;
let result = plant_layer::heatmap(
map_id,
query_params.layer_id,
query_params.plant_id,
&mut conn,
)
.await?;
let buffer = matrix_to_image(&result)?;
Ok(buffer)
}
#[allow(
clippy::cast_possible_truncation, clippy::indexing_slicing, clippy::cast_sign_loss )]
fn matrix_to_image(matrix: &[Vec<f32>]) -> Result<Vec<u8>, ServiceError> {
let (width, height) = (matrix[0].len(), matrix.len());
let mut imgbuf = ImageBuffer::new(width as u32, height as u32);
for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
let data = matrix[y as usize][x as usize];
let red = data.mul_add(-128.0, 128.0);
let green = data.mul_add(255.0 - 128.0, 128.0);
let blue = data.mul_add(-128.0, 128.0);
*pixel = Rgb([red as u8, green as u8, blue as u8]);
}
let mut buffer: Vec<u8> = Vec::new();
imgbuf
.write_to(&mut Cursor::new(&mut buffer), image::ImageOutputFormat::Png)
.map_err(|err| ServiceError::new(StatusCode::INTERNAL_SERVER_ERROR, &err.to_string()))?;
Ok(buffer)
}
pub async fn find_relations(
search_query: RelationSearchParameters,
app_data: &Data<AppDataInner>,
) -> Result<RelationsDto, ServiceError> {
let mut conn = app_data.pool.get().await?;
let result = plant_layer::find_relations(search_query, &mut conn).await?;
Ok(result)
}