use crate::{ArcGISClient, ArcGISGeometry, Result};
use tracing::instrument;
use super::types::{
ExportImageParameters, ExportImageResult, HistogramParameters, HistogramResult,
IdentifyParameters, ImageIdentifyResult, RasterInfo, SampleParameters, SampleResult,
};
#[derive(Clone)]
pub struct ImageServiceClient<'a> {
url: String,
client: &'a ArcGISClient,
}
impl<'a> ImageServiceClient<'a> {
pub fn new(url: impl Into<String>, client: &'a ArcGISClient) -> Self {
ImageServiceClient {
url: url.into(),
client,
}
}
#[instrument(skip(self, params))]
pub async fn export_image(&self, params: ExportImageParameters) -> Result<ExportImageResult> {
tracing::debug!("Exporting image");
let export_url = format!("{}/exportImage", self.url);
let response = self
.client
.http()
.get(&export_url)
.query(¶ms)
.query(&[("f", "json")])
.send()
.await?;
let result: ExportImageResult = response.json().await?;
tracing::debug!(url = %result.href(), "Image exported");
Ok(result)
}
#[instrument(skip(self))]
pub async fn identify(&self, geometry: &ArcGISGeometry) -> Result<ImageIdentifyResult> {
tracing::debug!("Identifying pixel value");
let identify_url = format!("{}/identify", self.url);
let geometry_json = serde_json::to_string(geometry)?;
let geometry_type = match geometry {
ArcGISGeometry::Point(_) => "esriGeometryPoint",
ArcGISGeometry::Polygon(_) => "esriGeometryPolygon",
_ => "esriGeometryPoint",
};
let response = self
.client
.http()
.get(&identify_url)
.query(&[
("f", "json"),
("geometry", &geometry_json),
("geometryType", geometry_type),
])
.send()
.await?;
let result: ImageIdentifyResult = response.json().await?;
tracing::debug!("Identification complete");
Ok(result)
}
#[instrument(skip(self, params), fields(geometry_type))]
pub async fn identify_with_params(
&self,
params: IdentifyParameters,
) -> Result<ImageIdentifyResult> {
tracing::debug!("Identifying with custom parameters");
let identify_url = format!("{}/identify", self.url);
let mut query_params = vec![
("f", "json".to_string()),
("geometry", params.geometry().to_string()),
("geometryType", params.geometry_type().to_string()),
];
if let Some(sr) = params.geometry_sr() {
query_params.push(("geometrySR", sr.to_string()));
}
if let Some(return_geom) = params.return_geometry() {
query_params.push(("returnGeometry", return_geom.to_string()));
}
if let Some(return_catalog) = params.return_catalog_items() {
query_params.push(("returnCatalogItems", return_catalog.to_string()));
}
if let Some(mosaic_rule) = params.mosaic_rule() {
let mosaic_json = serde_json::to_string(mosaic_rule)?;
query_params.push(("mosaicRule", mosaic_json));
}
if let Some(rendering_rule) = params.rendering_rule() {
let rendering_json = serde_json::to_string(rendering_rule)?;
query_params.push(("renderingRule", rendering_json));
}
let response = self
.client
.http()
.get(&identify_url)
.query(&query_params)
.send()
.await?;
let result: ImageIdentifyResult = response.json().await?;
tracing::debug!("Identification complete");
Ok(result)
}
#[instrument(skip(self, params))]
pub async fn get_samples(&self, params: SampleParameters) -> Result<SampleResult> {
tracing::debug!("Getting samples");
let samples_url = format!("{}/getSamples", self.url);
let response = self
.client
.http()
.get(&samples_url)
.query(¶ms)
.query(&[("f", "json")])
.send()
.await?;
let result: SampleResult = response.json().await?;
tracing::debug!(count = result.samples().len(), "Samples retrieved");
Ok(result)
}
#[instrument(skip(self, params))]
pub async fn compute_histograms(&self, params: HistogramParameters) -> Result<HistogramResult> {
tracing::debug!("Computing histograms");
let histogram_url = format!("{}/computeHistograms", self.url);
let response = self
.client
.http()
.get(&histogram_url)
.query(¶ms)
.query(&[("f", "json")])
.send()
.await?;
let result: HistogramResult = response.json().await?;
tracing::debug!(bands = result.histograms().len(), "Histograms computed");
Ok(result)
}
#[instrument(skip(self))]
pub async fn get_raster_info(&self) -> Result<RasterInfo> {
tracing::debug!("Getting raster info");
let response = self
.client
.http()
.get(&self.url)
.query(&[("f", "json")])
.send()
.await?;
let info: RasterInfo = response.json().await?;
tracing::debug!("Raster info retrieved");
Ok(info)
}
}