read pixel

This commit is contained in:
Matthieu Baumann
2022-05-11 17:24:37 +02:00
parent 885b894682
commit bc2cfd359c
7 changed files with 77 additions and 55 deletions

View File

@@ -4,7 +4,7 @@ use wasm_bindgen::JsValue;
use crate::webgl_ctx::WebGlContext;
pub trait Pixel:
AsRef<[Self::Item]> + Default + std::cmp::PartialEq + std::fmt::Debug + std::clone::Clone
AsRef<[Self::Item]> + Default + std::cmp::PartialEq + std::fmt::Debug + std::clone::Clone + serde::ser::Serialize
{
type Item: std::cmp::PartialOrd + Clone + Copy + std::fmt::Debug + cgmath::Zero;
type Container: ArrayBuffer<Item = Self::Item>;
@@ -213,6 +213,15 @@ impl Pixel for [i32; 1] {
}
}
/*impl From<T> for JsValue
where
T: Pixel
{
fn from(p: T) -> Self {
JsValue::from_serde(&p).unwrap()
}
}*/
/*
pub enum PixelType {
RU8([u8; 1]),
RI16([i16; 1]),
@@ -233,4 +242,4 @@ impl From<PixelType> for JsValue {
PixelType::RGBAU8(v) => JsValue::from_serde(&v).unwrap(),
}
}
}
}*/

View File

@@ -26,7 +26,7 @@ pub struct Texture2D {
}
use crate::image::format::ImageFormat;
use super::pixel::Pixel;
use super::pixel::PixelType;
//use super::pixel::PixelType;
use std::path::Path;
impl Texture2D {
pub fn create_from_path<P: AsRef<Path>, F: ImageFormat>(
@@ -267,7 +267,7 @@ impl Texture2D {
Texture2DBoundMut { texture_2d: self }
}
pub fn read_pixel(&self, x: i32, y: i32) -> Result<PixelType, JsValue> {
pub fn read_pixel(&self, x: i32, y: i32) -> Result<JsValue, JsValue> {
// Create and bind the framebuffer
let reader = self.gl.create_framebuffer();
self.gl
@@ -306,28 +306,28 @@ impl Texture2D {
#[cfg(feature = "webgl2")]
let value = match (*format, *type_) {
(WebGlRenderingCtx::RED_INTEGER, WebGlRenderingCtx::UNSIGNED_BYTE) => {
let val = <[u8; 1]>::read_pixel(&self.gl, x, y)?;
Ok(PixelType::RU8(val))
let p = <[u8; 1]>::read_pixel(&self.gl, x, y)?;
Ok(JsValue::from_serde(&p).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
(WebGlRenderingCtx::RED_INTEGER, WebGlRenderingCtx::SHORT) => {
let val = <[i16; 1]>::read_pixel(&self.gl, x, y)?;
Ok(PixelType::RI16(val))
let p = <[i16; 1]>::read_pixel(&self.gl, x, y)?;
Ok(JsValue::from_serde(&p).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
(WebGlRenderingCtx::RED_INTEGER, WebGlRenderingCtx::INT) => {
let val = <[i32; 1]>::read_pixel(&self.gl, x, y)?;
Ok(PixelType::RI32(val))
let p = <[i32; 1]>::read_pixel(&self.gl, x, y)?;
Ok(JsValue::from_serde(&p).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
(WebGlRenderingCtx::RED, WebGlRenderingCtx::FLOAT) => {
let val = <[f32; 1]>::read_pixel(&self.gl, x, y)?;
Ok(PixelType::RF32(val))
let p = <[f32; 1]>::read_pixel(&self.gl, x, y)?;
Ok(JsValue::from_serde(&p).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
(WebGlRenderingCtx::RGB, WebGlRenderingCtx::UNSIGNED_BYTE) => {
let val = <[u8; 3]>::read_pixel(&self.gl, x, y)?;
Ok(PixelType::RGBU8(val))
let p = <[u8; 3]>::read_pixel(&self.gl, x, y)?;
Ok(JsValue::from_serde(&p).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
(WebGlRenderingCtx::RGBA, WebGlRenderingCtx::UNSIGNED_BYTE) => {
let val = <[u8; 4]>::read_pixel(&self.gl, x, y)?;
Ok(PixelType::RGBAU8(val))
let p = <[u8; 4]>::read_pixel(&self.gl, x, y)?;
Ok(JsValue::from_serde(&p).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
_ => Err(JsValue::from_str(
"Pixel retrieval not implemented for that texture format.",
@@ -336,21 +336,22 @@ impl Texture2D {
#[cfg(feature = "webgl1")]
let value = match (*format, *type_) {
(WebGlRenderingCtx::LUMINANCE_ALPHA, WebGlRenderingCtx::FLOAT) => {
let val = <[f32; 1]>::read_pixel(&self.gl, x, y)?;
Ok(PixelType::RF32(val))
let p = <[f32; 1]>::read_pixel(&self.gl, x, y)?;
Ok(JsValue::from_serde(&p).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
(WebGlRenderingCtx::RGB, WebGlRenderingCtx::UNSIGNED_BYTE) => {
let val = <[u8; 3]>::read_pixel(&self.gl, x, y)?;
Ok(PixelType::RGBU8(val))
let p = <[u8; 3]>::read_pixel(&self.gl, x, y)?;
Ok(JsValue::from_serde(&p).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
(WebGlRenderingCtx::RGBA, WebGlRenderingCtx::UNSIGNED_BYTE) => {
let val = <[u8; 4]>::read_pixel(&self.gl, x, y)?;
Ok(PixelType::RGBAU8(val))
let p = <[u8; 4]>::read_pixel(&self.gl, x, y)?;
Ok(JsValue::from_serde(&p).map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
_ => Err(JsValue::from_str(
"Pixel retrieval not implemented for that texture format.",
)),
};
// Unbind the framebuffer
self.gl
.bind_framebuffer(WebGlRenderingCtx::FRAMEBUFFER, None);

View File

@@ -11,7 +11,7 @@ use crate::{async_task::{TaskExecutor, BuildCatalogIndex, ParseTableTask, TaskRe
}, shader::ShaderManager, survey::ImageSurveys, tile_fetcher::TileFetcherQueue, time::DeltaTime, utils};
use al_core::{
resources::Resources,
pixel::PixelType, WebGlContext
WebGlContext
};
use al_api::{
@@ -381,7 +381,7 @@ pub trait AppTrait {
// Setter of the meta data of a layer
fn set_image_survey_color_cfg(&mut self, layer: String, meta: ImageSurveyMeta) -> Result<(), JsValue>;
fn read_pixel(&self, pos: &Vector2<f64>, base_url: &str) -> Result<PixelType, JsValue>;
fn read_pixel(&self, pos: &Vector2<f64>, base_url: &str) -> Result<JsValue, JsValue>;
fn set_projection<Q: Projection>(self) -> App<Q>;
//fn set_longitude_reversed(&mut self, longitude_reversed: bool);
@@ -543,7 +543,7 @@ where
}
} else {
let Allsky { image, time_req, .. } = allsky;
{
let mutex_locked = image.lock().unwrap();
let images = mutex_locked.as_ref();
@@ -614,12 +614,12 @@ where
self.set_center(&self.get_center());
}
fn read_pixel(&self, pos: &Vector2<f64>, layer_id: &str) -> Result<PixelType, JsValue> {
fn read_pixel(&self, pos: &Vector2<f64>, layer_id: &str) -> Result<JsValue, JsValue> {
if let Some(lonlat) = self.screen_to_world(pos) {
let survey = self.surveys.get_from_layer(layer_id)
.ok_or(JsValue::from_str(&format!("Did not found the survey {:?}", layer_id)))?;
survey.read_pixel(&lonlat)
survey.read_pixel(&lonlat, &self.camera)
} else {
Err(JsValue::from_str(&format!(
"{:?} is out of projection",

View File

@@ -45,4 +45,8 @@ pub fn grid_lonlat<S: BaseFloat>(cell: &HEALPixCell, n_segments_by_side: u16) ->
LonLatT::new(Angle(lon), Angle(lat))
})
.collect()
}
pub fn hash_with_dxdy(depth: u8, lonlat: &LonLatT<f64>) -> (u64, f64, f64) {
healpix::nested::hash_with_dxdy(depth, lonlat.lon().0, lonlat.lat().0)
}

View File

@@ -514,46 +514,43 @@ impl ImageSurveyTextures {
self.heap.update_entry(tex_cell_item);
}
// lonlat is given in the
pub fn get_pixel_position_in_texture(
&self,
lonlat: &LonLatT<f64>,
depth: u8,
) -> Result<Vector3<i32>, JsValue> {
let (pix, dx, dy) = healpix::nested::hash_with_dxdy(depth, lonlat.lon().0, lonlat.lat().0);
let (pix, dx, dy) = crate::healpix::utils::hash_with_dxdy(depth, lonlat);
let texture_cell = HEALPixCell(depth, pix);
let cell = HEALPixCell(depth, pix);
// Index of the texture in the total set of textures
if let Some(texture) = self.textures.get(&cell) {
if let Some(texture) = self.textures.get(&texture_cell) {
let cfg = &self.config;
// Index of the texture in the total set of textures
let texture_idx = texture.idx();
// Index of the slice of textures
let idx_slice = texture_idx / self.config.num_textures_by_slice();
let num_textures_by_slice = cfg.num_textures_by_slice();
let idx_slice = texture_idx / num_textures_by_slice;
// Index of the texture in its slice
let idx_in_slice = texture_idx % self.config.num_textures_by_slice();
let idx_in_slice = texture_idx % num_textures_by_slice;
// Index of the column of the texture in its slice
let idx_col_in_slice = idx_in_slice / self.config.num_textures_by_side_slice();
let num_textures_by_side_slice = cfg.num_textures_by_side_slice();
let idx_col_in_slice = idx_in_slice / num_textures_by_side_slice;
// Index of the row of the texture in its slice
let idx_row_in_slice = idx_in_slice % self.config.num_textures_by_side_slice();
// Row and column indexes of the tile in its texture
let (idx_col_in_tex, idx_row_in_tex) = cell.get_offset_in_texture_cell(&self.config);
let idx_row_in_slice = idx_in_slice % num_textures_by_side_slice;
// The size of the global texture containing the tiles
let texture_size = self.config.get_texture_size();
// The size of a tile in its texture
let tile_size = self.config.get_tile_size();
let texture_size = cfg.get_texture_size();
// Offset in the slice in pixels
let mut offset = Vector3::new(
(idx_row_in_slice as i32) * texture_size
+ (idx_row_in_tex as i32) * tile_size
+ ((dy * (tile_size as f64)) as i32),
(idx_col_in_slice as i32) * texture_size
+ (idx_col_in_tex as i32) * tile_size
+ ((dx * (tile_size as f64)) as i32),
(idx_row_in_slice as i32) * texture_size + ((dy * (texture_size as f64)) as i32),
(idx_col_in_slice as i32) * texture_size + ((dx * (texture_size as f64)) as i32),
idx_slice,
);
// Offset in the slice in pixels
if self.config.tex_storing_fits {
let mut uvy = offset.y as f32 / 4096.0;
uvy = self.config.size_tile_uv
@@ -567,7 +564,7 @@ impl ImageSurveyTextures {
} else {
Err(JsValue::from_str(&format!(
"{:?} not loaded in the GPU, please wait before trying again.",
cell
texture_cell
)))
}
}

View File

@@ -487,7 +487,6 @@ use crate::{
},
};
use al_core::pixel::PixelType;
use web_sys::{WebGl2RenderingContext, WheelEvent};
use wasm_bindgen::JsCast;
use al_core::{
@@ -496,6 +495,7 @@ use al_core::{
image::Image
};
use crate::math::lonlat::LonLat;
impl ImageSurvey {
fn new(
config: HiPSConfig,
@@ -652,11 +652,17 @@ impl ImageSurvey {
self.view.reset_frame();
}
pub fn read_pixel(&self, pos: &LonLatT<f64>) -> Result<PixelType, JsValue> {
// Position given is in the camera space
pub fn read_pixel(&self, pos: &LonLatT<f64>, camera: &CameraViewPort) -> Result<JsValue, JsValue> {
// 1. Convert it to the hips frame system
let camera_frame = camera.get_system();
let hips_frame = &self.get_config().get_frame();
let pos = crate::coosys::apply_coo_system(camera_frame, hips_frame, &pos.vector());
// Get the array of textures from that survey
let pos_tex = self
.textures
.get_pixel_position_in_texture(pos, self.view.get_depth())?;
let pos_tex = self.textures
.get_pixel_position_in_texture(&pos.lonlat(), self.view.get_depth())?;
let slice_idx = pos_tex.z as usize;
let texture_array = self.textures.get_texture_array();
@@ -1079,10 +1085,10 @@ impl ImageSurveys {
}
}
pub fn read_pixel(&self, pos: &LonLatT<f64>, url: &Url) -> Result<PixelType, JsValue> {
pub fn read_pixel(&self, pos: &LonLatT<f64>, url: &Url, camera: &CameraViewPort) -> Result<JsValue, JsValue> {
if let Some(survey) = self.surveys.get(url) {
// Read the pixel from the first survey of layer
survey.read_pixel(pos)
survey.read_pixel(pos, camera)
} else {
Err(JsValue::from_str("No survey found"))
}

View File

@@ -465,6 +465,11 @@ export let HpxImageSurvey = (function() {
return this.meta.opacity;
};
// @api
HpxImageSurvey.prototype.readPixel = function(x, y) {
return this.backend.aladin.webglAPI.readPixel(x, y, this.layer);
};
HpxImageSurvey.DEFAULT_SURVEY_ID = "P/DSS2/color";
HpxImageSurvey.SURVEYS_OBJECTS = {};