mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2026-01-27 15:25:53 -08:00
read pixel
This commit is contained in:
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"))
|
||||
}
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
Reference in New Issue
Block a user