mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2026-01-20 08:41:54 -08:00
keep the true data of the cubic tiles. This will be needed to get the spectra at a specific sky location
This commit is contained in:
committed by
Matthieu Baumann
parent
1dca5b1845
commit
0462a451b3
@@ -9,6 +9,7 @@ use fitsrs::WCS;
|
||||
use fitsrs::{Fits, HDU};
|
||||
use std::fmt::Debug;
|
||||
use std::io::Cursor;
|
||||
use std::ops::Range;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -31,6 +32,8 @@ pub struct FitsImage<'a> {
|
||||
pub blank: Option<f32>,
|
||||
// optional wcs
|
||||
pub wcs: Option<WCS>,
|
||||
// bytes offset where the data bytes are located inside the fits
|
||||
pub data_byte_offset: Range<usize>,
|
||||
// raw bytes of the data image (in Big-Endian)
|
||||
pub raw_bytes: &'a [u8],
|
||||
}
|
||||
@@ -76,7 +79,8 @@ impl<'a> FitsImage<'a> {
|
||||
let off = hdu.get_data_unit_byte_offset() as usize;
|
||||
let len = hdu.get_data_unit_byte_size() as usize;
|
||||
|
||||
let raw_bytes = &bytes[off..(off + len)];
|
||||
let data_byte_offset = off..(off + len);
|
||||
let raw_bytes = &bytes[data_byte_offset.clone()];
|
||||
|
||||
let wcs = hdu.wcs().ok();
|
||||
|
||||
@@ -92,6 +96,7 @@ impl<'a> FitsImage<'a> {
|
||||
wcs,
|
||||
bzero,
|
||||
blank,
|
||||
data_byte_offset,
|
||||
raw_bytes,
|
||||
});
|
||||
}
|
||||
@@ -117,10 +122,6 @@ impl Image for FitsImage<'_> {
|
||||
// An offset to write the image in the texture array
|
||||
offset: &Vector3<i32>,
|
||||
) -> Result<(), JsValue> {
|
||||
crate::log(&format!(
|
||||
"{0}, {1}, {2}",
|
||||
self.width, self.height, self.depth
|
||||
));
|
||||
let view = unsafe { R8U::view(self.raw_bytes) };
|
||||
textures.tex_sub_image_3d_with_opt_array_buffer_view(
|
||||
offset.x + self.trim1 as i32,
|
||||
@@ -136,6 +137,7 @@ impl Image for FitsImage<'_> {
|
||||
}
|
||||
|
||||
fn get_size(&self) -> (u32, u32, u32) {
|
||||
// The true image size is given by ONAXISi keywords
|
||||
(self.width, self.height, self.depth)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,10 +311,10 @@ impl Image for ImageType {
|
||||
ImageType::Canvas { canvas } => canvas.insert_into_3d_texture(textures, offset)?,
|
||||
ImageType::ImageRgba8u { image } => image.insert_into_3d_texture(textures, offset)?,
|
||||
ImageType::ImageRgb8u { image } => image.insert_into_3d_texture(textures, offset)?,
|
||||
ImageType::HTMLImageRgba8u { image } => {
|
||||
ImageType::HTMLImageRgba8u { image, .. } => {
|
||||
image.insert_into_3d_texture(textures, offset)?
|
||||
}
|
||||
ImageType::HTMLImageRgb8u { image } => {
|
||||
ImageType::HTMLImageRgb8u { image, .. } => {
|
||||
image.insert_into_3d_texture(textures, offset)?
|
||||
}
|
||||
ImageType::RawRgb8u { image } => image.insert_into_3d_texture(textures, offset)?,
|
||||
|
||||
@@ -8,8 +8,8 @@ pub struct ImageBuffer<T>
|
||||
where
|
||||
T: TextureFormat,
|
||||
{
|
||||
pub data: Vec<<<T as TextureFormat>::P as Pixel>::Item>,
|
||||
pub size: Vector2<i32>,
|
||||
pub data: Box<[<<T as TextureFormat>::P as Pixel>::Item]>,
|
||||
pub size: (u32, u32, u32),
|
||||
}
|
||||
|
||||
use crate::texture::format::Bytes;
|
||||
@@ -26,21 +26,22 @@ where
|
||||
T: TextureFormat,
|
||||
{
|
||||
pub fn new(
|
||||
data: Vec<<<T as TextureFormat>::P as Pixel>::Item>,
|
||||
width: i32,
|
||||
height: i32,
|
||||
data: Box<[<<T as TextureFormat>::P as Pixel>::Item]>,
|
||||
width: u32,
|
||||
height: u32,
|
||||
depth: u32,
|
||||
) -> Self {
|
||||
let size_buf = width * height * (T::NUM_CHANNELS as i32);
|
||||
debug_assert!(size_buf == data.len() as i32);
|
||||
let size_buf = width * height * depth * (T::NUM_CHANNELS as u32);
|
||||
debug_assert!(size_buf == data.len() as u32);
|
||||
//let buf = <<T as ImageFormat>::P as Pixel>::Container::new(buf);
|
||||
let size = Vector2::new(width, height);
|
||||
let size = (width, height, depth);
|
||||
Self { data, size }
|
||||
}
|
||||
|
||||
pub fn from_encoded_raw_bytes(
|
||||
raw_bytes: &[u8],
|
||||
width: i32,
|
||||
height: i32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<Self, JsValue> {
|
||||
let mut decoded_bytes = match T::decode(raw_bytes).map_err(JsValue::from_str)? {
|
||||
Bytes::Borrowed(bytes) => bytes.to_vec(),
|
||||
@@ -55,29 +56,33 @@ where
|
||||
std::mem::transmute::<Vec<u8>, Vec<<<T as TextureFormat>::P as Pixel>::Item>>(
|
||||
decoded_bytes,
|
||||
)
|
||||
.into_boxed_slice()
|
||||
};
|
||||
|
||||
Ok(Self::new(decoded_pixels, width, height))
|
||||
Ok(Self::new(decoded_pixels, width, height, 1))
|
||||
}
|
||||
|
||||
pub fn from_raw_bytes(mut raw_bytes: Vec<u8>, width: i32, height: i32) -> Self {
|
||||
let size_buf = width * height * (std::mem::size_of::<T::P>() as i32);
|
||||
debug_assert!(size_buf == raw_bytes.len() as i32);
|
||||
pub fn from_raw_bytes(mut raw_bytes: Vec<u8>, width: u32, height: u32) -> Self {
|
||||
let size_buf = width * height * (std::mem::size_of::<T::P>() as u32);
|
||||
debug_assert!(size_buf == raw_bytes.len() as u32);
|
||||
|
||||
let decoded_pixels = unsafe {
|
||||
raw_bytes.set_len(raw_bytes.len() / std::mem::size_of::<<T::P as Pixel>::Item>());
|
||||
std::mem::transmute::<Vec<u8>, Vec<<T::P as Pixel>::Item>>(raw_bytes)
|
||||
std::mem::transmute::<Vec<u8>, Vec<<T::P as Pixel>::Item>>(raw_bytes).into_boxed_slice()
|
||||
};
|
||||
|
||||
Self::new(decoded_pixels, width, height)
|
||||
Self::new(decoded_pixels, width, height, 1)
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
let size = Vector2::new(0, 0);
|
||||
Self { data: vec![], size }
|
||||
let size = (0, 0, 0);
|
||||
Self {
|
||||
data: Box::new([]),
|
||||
size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn allocate(pixel_fill: &T::P, width: i32, height: i32) -> ImageBuffer<T> {
|
||||
pub fn allocate(pixel_fill: &T::P, width: u32, height: u32) -> ImageBuffer<T> {
|
||||
let size_buf = ((width * height) as usize) * (T::NUM_CHANNELS);
|
||||
|
||||
let data = pixel_fill
|
||||
@@ -86,9 +91,10 @@ where
|
||||
.cloned()
|
||||
.cycle()
|
||||
.take(size_buf)
|
||||
.collect::<Vec<_>>();
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice();
|
||||
|
||||
ImageBuffer::<T>::new(data, width, height)
|
||||
ImageBuffer::<T>::new(data, width, height, 1)
|
||||
}
|
||||
|
||||
pub fn tex_sub(&mut self, src: &Self, s: &ImageBufferView, d: &ImageBufferView) {
|
||||
@@ -97,8 +103,8 @@ where
|
||||
|
||||
for ix in s.x..(s.x + s.w) {
|
||||
for iy in s.y..(s.y + s.h) {
|
||||
let s_idx = (iy * src.width() + ix) as usize;
|
||||
let d_idx = (di * self.width() + dj) as usize;
|
||||
let s_idx = ((iy * src.width() as i32) + ix) as usize;
|
||||
let d_idx = ((di * self.width() as i32) + dj) as usize;
|
||||
|
||||
for i in 0..T::NUM_CHANNELS {
|
||||
let si = s_idx * T::NUM_CHANNELS + i;
|
||||
@@ -124,12 +130,12 @@ where
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn width(&self) -> i32 {
|
||||
self.size.x
|
||||
pub fn width(&self) -> u32 {
|
||||
self.size.0
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
self.size.y
|
||||
pub fn height(&self) -> u32 {
|
||||
self.size.1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +150,7 @@ pub enum ImageBufferType {
|
||||
}
|
||||
|
||||
use crate::image::{ArrayBuffer, Image};
|
||||
use cgmath::{Vector2, Vector3};
|
||||
use cgmath::Vector3;
|
||||
impl<I> Image for ImageBuffer<I>
|
||||
where
|
||||
I: TextureFormat,
|
||||
@@ -161,9 +167,9 @@ where
|
||||
offset.x,
|
||||
offset.y,
|
||||
offset.z,
|
||||
self.width(),
|
||||
self.height(),
|
||||
1,
|
||||
self.width() as i32,
|
||||
self.height() as i32,
|
||||
self.size.2 as i32,
|
||||
Some(js_array.as_ref()),
|
||||
);
|
||||
|
||||
@@ -172,6 +178,6 @@ where
|
||||
|
||||
// The size of the image
|
||||
fn get_size(&self) -> (u32, u32, u32) {
|
||||
(self.size.x as u32, self.size.y as u32, 1)
|
||||
self.size.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -563,7 +563,7 @@ impl App {
|
||||
|
||||
let rscs_received = self.downloader.borrow_mut().get_received_resources();
|
||||
|
||||
//let mut tile_copied = false;
|
||||
let mut tile_copied = false;
|
||||
|
||||
for rsc in rscs_received {
|
||||
match rsc {
|
||||
@@ -608,15 +608,6 @@ impl App {
|
||||
|
||||
// 2. Add the tile to its HiPS
|
||||
if let Some(img) = &*image.borrow() {
|
||||
/*if tile_copied {
|
||||
self.downloader
|
||||
.borrow_mut()
|
||||
.delay(Resource::Tile(tile));
|
||||
continue;
|
||||
}
|
||||
tile_copied = true;
|
||||
*/
|
||||
|
||||
// For PNG/JPEG cubic tiles, all the slices are in the lonely image
|
||||
match (&tile.cell, hips) {
|
||||
(CellDesc::HiPS2D { cell, tile_size }, HiPS::D2(hips)) => {
|
||||
@@ -654,6 +645,17 @@ impl App {
|
||||
},
|
||||
HiPS::D3(hips),
|
||||
) => {
|
||||
// As the decoding and copying to the GPU of cubic tile is more costly
|
||||
// (not that much but there is more because they are smaller)
|
||||
// then we delay their treatment through the frames
|
||||
if tile_copied {
|
||||
self.downloader
|
||||
.borrow_mut()
|
||||
.delay(RequestType::Tile(tile));
|
||||
continue;
|
||||
}
|
||||
tile_copied = true;
|
||||
|
||||
// TODO PNG/JPG case to handle here
|
||||
match img {
|
||||
ImageType::HTMLImageRgba8u {
|
||||
@@ -671,6 +673,11 @@ impl App {
|
||||
.ceil()
|
||||
as u32;
|
||||
|
||||
let tile_size = *tile_size;
|
||||
let mut decoded_bytes = Vec::with_capacity(
|
||||
(tile_size * tile_size * *tile_depth)
|
||||
as usize,
|
||||
);
|
||||
for x in 0..num_rows {
|
||||
for y in 0..num_cols {
|
||||
let document = web_sys::window()
|
||||
@@ -680,45 +687,52 @@ impl App {
|
||||
let canvas = document
|
||||
.create_element("canvas")?
|
||||
.dyn_into::<web_sys::HtmlCanvasElement>()?;
|
||||
canvas.set_width(*tile_size);
|
||||
canvas.set_height(*tile_size);
|
||||
canvas.set_width(tile_size);
|
||||
canvas.set_height(tile_size);
|
||||
let context = canvas
|
||||
.get_context("2d")?
|
||||
.unwrap_abort()
|
||||
.dyn_into::<web_sys::CanvasRenderingContext2d>()?;
|
||||
|
||||
let sx = (y * *tile_size) as f64;
|
||||
let sy = (x * *tile_size) as f64;
|
||||
let sw = *tile_size as f64;
|
||||
let sh = *tile_size as f64;
|
||||
let sx = (y * tile_size) as f64;
|
||||
let sy = (x * tile_size) as f64;
|
||||
let sw = tile_size as f64;
|
||||
let sh = tile_size as f64;
|
||||
let dx = 0.0;
|
||||
let dy = 0.0;
|
||||
let dw = *tile_size as f64;
|
||||
let dh = *tile_size as f64;
|
||||
let dw = tile_size as f64;
|
||||
let dh = tile_size as f64;
|
||||
|
||||
context.draw_image_with_html_image_element_and_sw_and_sh_and_dx_and_dy_and_dw_and_dh(image, sx, sy, sw, sh, dx, dy, dw, dh)?;
|
||||
|
||||
let slice_img = ImageType::Canvas {
|
||||
canvas: Canvas::<RGBA8U>::new(
|
||||
canvas,
|
||||
),
|
||||
};
|
||||
let slice_idx = y + x * num_cols;
|
||||
let slice_bytes = context
|
||||
.get_image_data(dx, dy, dw, dh)?
|
||||
.data();
|
||||
|
||||
hips.push_tile_slice(
|
||||
cell,
|
||||
slice_img,
|
||||
tile.request.time_request,
|
||||
slice_idx as u16,
|
||||
)?
|
||||
decoded_bytes.extend(
|
||||
slice_bytes
|
||||
.0
|
||||
.chunks(4)
|
||||
.map(|p| p[0]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
hips.push_tile_from_jpeg(
|
||||
cell,
|
||||
decoded_bytes.into_boxed_slice(),
|
||||
(tile_size, tile_size, *tile_depth),
|
||||
tile.request.time_request,
|
||||
)?;
|
||||
}
|
||||
_ => hips.push_tile(
|
||||
cell,
|
||||
img,
|
||||
tile.request.time_request,
|
||||
)?,
|
||||
ImageType::FitsRawBytes { raw_bytes, size } => hips
|
||||
.push_tile_from_fits(
|
||||
cell,
|
||||
raw_bytes.clone(),
|
||||
*size,
|
||||
tile.request.time_request,
|
||||
)?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
||||
@@ -95,18 +95,12 @@ impl Downloader {
|
||||
self.queried_list.contains(id)
|
||||
}
|
||||
|
||||
/*pub fn delay(&mut self, r: RequestType) {
|
||||
pub fn delay(&mut self, r: RequestType) {
|
||||
match r {
|
||||
Resource::Tile(tile) => {
|
||||
let k = format!(
|
||||
"{:?}{:?}/{:?}",
|
||||
tile.get_hips_cdid(),
|
||||
tile.cell.depth(),
|
||||
tile.cell.idx()
|
||||
);
|
||||
self.cache.insert(k, Resource::Tile(tile));
|
||||
RequestType::Tile(tile) => {
|
||||
self.cache.insert(tile.id.clone(), RequestType::Tile(tile));
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ async fn query_allsky(
|
||||
|
||||
let raw_bytes = image_data.data();
|
||||
|
||||
Ok(ImageBuffer::from_raw_bytes(raw_bytes.0, w as i32, h as i32))
|
||||
Ok(ImageBuffer::from_raw_bytes(raw_bytes.0, w, h))
|
||||
}
|
||||
|
||||
impl From<query::Allsky> for AllskyRequest {
|
||||
@@ -95,12 +95,18 @@ impl From<query::Allsky> for AllskyRequest {
|
||||
.map(|image| {
|
||||
let ImageBuffer { data, size } = image;
|
||||
let data = data
|
||||
.into_iter()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(i, _)| i % 4 != 3)
|
||||
.map(|(_, v)| v)
|
||||
.collect();
|
||||
let image = ImageBuffer::new(data, size.x, size.y);
|
||||
.map(|(_, v)| *v)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let image = ImageBuffer::new(
|
||||
data.into_boxed_slice(),
|
||||
size.0,
|
||||
size.1,
|
||||
size.2,
|
||||
);
|
||||
|
||||
ImageType::RawRgb8u { image }
|
||||
})
|
||||
@@ -226,8 +232,11 @@ fn handle_allsky_file<F: TextureFormat>(
|
||||
|
||||
let mut src_idx = 0;
|
||||
let tiles = (0..12).map(move |_| {
|
||||
let mut base_tile =
|
||||
ImageBuffer::<F>::allocate(&F::P::BLACK, allsky_tile_size, allsky_tile_size);
|
||||
let mut base_tile = ImageBuffer::<F>::allocate(
|
||||
&F::P::BLACK,
|
||||
allsky_tile_size as u32,
|
||||
allsky_tile_size as u32,
|
||||
);
|
||||
for idx_tile in 0..64 {
|
||||
let (x, y) = crate::utils::unmortonize(idx_tile as u64);
|
||||
let dx = x * (d3_tile_allsky_size as u32);
|
||||
@@ -274,8 +283,14 @@ fn handle_allsky_fits<F: TextureFormat>(
|
||||
.rev()
|
||||
.flatten()
|
||||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
let image = ImageBuffer::<F>::new(reversed_rows_data, width_allsky_px, height_allsky_px);
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice();
|
||||
let image = ImageBuffer::<F>::new(
|
||||
reversed_rows_data,
|
||||
width_allsky_px as u32,
|
||||
height_allsky_px as u32,
|
||||
1,
|
||||
);
|
||||
|
||||
let allsky_tiles_iter =
|
||||
handle_allsky_file::<F>(image, allsky_tile_size, tile_size)?.map(move |image| {
|
||||
@@ -292,7 +307,12 @@ fn handle_allsky_fits<F: TextureFormat>(
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
ImageBuffer::<F>::new(new_image_data, allsky_tile_size, allsky_tile_size)
|
||||
ImageBuffer::<F>::new(
|
||||
new_image_data,
|
||||
allsky_tile_size as u32,
|
||||
allsky_tile_size as u32,
|
||||
1,
|
||||
)
|
||||
});
|
||||
|
||||
Ok(allsky_tiles_iter)
|
||||
|
||||
@@ -10,11 +10,13 @@ pub struct CellVertices {
|
||||
|
||||
const BIT_MASK_ALL_ONE_EXCEPT_FIRST: u32 = !0x1;
|
||||
|
||||
use cgmath::BaseFloat;
|
||||
use healpix::compass_point::Cardinal;
|
||||
use healpix::compass_point::MainWind;
|
||||
use healpix::compass_point::Ordinal;
|
||||
use healpix::compass_point::OrdinalMap;
|
||||
|
||||
use crate::math::lonlat::LonLatT;
|
||||
use crate::utils;
|
||||
|
||||
impl HEALPixCell {
|
||||
@@ -495,6 +497,22 @@ use crate::math::spectra::Freq;
|
||||
use crate::math::spectra::SpectralUnit;
|
||||
|
||||
impl HEALPixFreqCell {
|
||||
pub fn from_lonlat(lonlat: LonLatT<f64>, freq: Freq, s_depth: u8, f_depth: u8) -> Self {
|
||||
let hpx = HEALPixCell::new(
|
||||
s_depth,
|
||||
lonlat.lon().to_radians(),
|
||||
lonlat.lat().to_radians(),
|
||||
);
|
||||
|
||||
let f_hash = freq.hash(f_depth);
|
||||
|
||||
Self {
|
||||
hpx,
|
||||
f_hash,
|
||||
f_depth,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(hpx: HEALPixCell, f_hash: u64, f_depth: u8) -> Self {
|
||||
Self {
|
||||
hpx,
|
||||
|
||||
@@ -101,16 +101,17 @@ impl HiPS3DBuffer {
|
||||
let texture = self.textures.get_mut(cell).unwrap_abort();
|
||||
|
||||
// And copy the image in that cubic tile
|
||||
texture.append_tile_slice(image, slice_idx, &self.config, &self.gl)?;
|
||||
texture.append_tile_slice(image, slice_idx)?;
|
||||
self.available_tiles_during_frame = true;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn push_tile<I: Image>(
|
||||
pub fn push_tile_from_fits(
|
||||
&mut self,
|
||||
cell: &HEALPixFreqCell,
|
||||
image: I,
|
||||
raw_bytes: js_sys::Uint8Array,
|
||||
size: (u32, u32, u32),
|
||||
time_request: Time,
|
||||
) -> Result<(), JsValue> {
|
||||
self.push_cell(cell, time_request)?;
|
||||
@@ -118,7 +119,25 @@ impl HiPS3DBuffer {
|
||||
let texture = self.textures.get_mut(cell).unwrap_abort();
|
||||
|
||||
// And copy the image in that cubic tile
|
||||
texture.append_tile(image, &self.config, &self.gl)?;
|
||||
texture.set_data_from_fits(raw_bytes, size)?;
|
||||
self.available_tiles_during_frame = true;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn push_tile_from_jpeg(
|
||||
&mut self,
|
||||
cell: &HEALPixFreqCell,
|
||||
decoded_bytes: Box<[u8]>,
|
||||
size: (u32, u32, u32),
|
||||
time_request: Time,
|
||||
) -> Result<(), JsValue> {
|
||||
self.push_cell(cell, time_request)?;
|
||||
|
||||
let texture = self.textures.get_mut(cell).unwrap_abort();
|
||||
|
||||
// And copy the image in that cubic tile
|
||||
texture.set_data_from_jpeg(decoded_bytes, size)?;
|
||||
self.available_tiles_during_frame = true;
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -3,7 +3,10 @@ pub mod texture;
|
||||
|
||||
use crate::downloader::request::allsky::AllskyRequest;
|
||||
use crate::healpix::moc::FreqSpaceMoc;
|
||||
use crate::math::angle::ToAngle;
|
||||
use crate::math::lonlat::LonLatT;
|
||||
use crate::math::spectra::SpectralUnit;
|
||||
use crate::LonLat;
|
||||
|
||||
use crate::tile_fetcher::TileFetcherQueue;
|
||||
use al_api::hips::DataproductType;
|
||||
@@ -78,18 +81,7 @@ pub fn get_raster_shader<'a>(
|
||||
crate::shader::get_shader(gl, shaders, "hips3d_raster.vert", "hips3d_f32.frag")
|
||||
}
|
||||
// color case
|
||||
_ => {
|
||||
if cmap.label() == "native" {
|
||||
crate::shader::get_shader(gl, shaders, "hips3d_raster.vert", "hips3d_rgba.frag")
|
||||
} else {
|
||||
crate::shader::get_shader(
|
||||
gl,
|
||||
shaders,
|
||||
"hips3d_raster.vert",
|
||||
"hips3d_rgba2cmap.frag",
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => crate::shader::get_shader(gl, shaders, "hips3d_raster.vert", "hips3d_red.frag"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +114,8 @@ pub struct HiPS3D {
|
||||
cells: Vec<HEALPixFreqCell>,
|
||||
// flag to forcing the mesh to be rebuilt
|
||||
move_freq: bool,
|
||||
// The location of the cursor to extract the spectra
|
||||
cursor_location: LonLatT<f64>,
|
||||
}
|
||||
|
||||
use super::HpxTileBuffer;
|
||||
@@ -176,6 +170,7 @@ impl HiPS3D {
|
||||
let moc = None;
|
||||
let hpx_cells_in_view = vec![];
|
||||
let move_freq = false;
|
||||
let cursor_location = LonLatT::new(0.0.to_angle(), 0.0.to_angle());
|
||||
// request the allsky texture
|
||||
Ok(Self {
|
||||
// The image survey texture buffer
|
||||
@@ -198,6 +193,7 @@ impl HiPS3D {
|
||||
cells,
|
||||
num_indices,
|
||||
move_freq,
|
||||
cursor_location,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -344,6 +340,29 @@ impl HiPS3D {
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the spectra under the cursor location
|
||||
pub fn read_spectra(&self, camera: &CameraViewPort) {
|
||||
// 1. Get the HEALPixFreq cell containing the cursor location
|
||||
let s_order = camera.get_tile_depth();
|
||||
let f_max_order = self.get_config().max_depth_freq.unwrap_abort();
|
||||
let s_max_order = self.get_config().max_depth_tile;
|
||||
|
||||
let f_order = f_max_order - (s_max_order - s_order);
|
||||
|
||||
let cell = HEALPixFreqCell::from_lonlat(self.cursor_location, self.freq, s_order, f_order);
|
||||
|
||||
// 2. Iterate through the cells on the frequency axis at that spatial location to construct the spectra around the (cursor, freq) point
|
||||
let f_hash_min = (cell.f_hash as i64 - 4).max(0) as u64;
|
||||
let f_hash_max = (cell.f_hash + 4)
|
||||
.max(Frequency::<u64>::n_cells_max() >> (Frequency::<u64>::MAX_DEPTH - f_order));
|
||||
|
||||
//(f_hash_min..f_hash_max).map(|f_hash| {})
|
||||
}
|
||||
|
||||
pub fn set_cursor_location(&mut self, lonlat: LonLatT<f64>) {
|
||||
self.cursor_location = lonlat;
|
||||
}
|
||||
|
||||
pub fn set_freq(&mut self, f: Freq) {
|
||||
self.freq = f;
|
||||
|
||||
@@ -788,19 +807,29 @@ impl HiPS3D {
|
||||
.push_tile_slice(cell, image, time_request, slice_idx)
|
||||
}
|
||||
|
||||
pub fn push_tile<I: Image>(
|
||||
pub fn push_tile_from_fits(
|
||||
&mut self,
|
||||
cell: &HEALPixFreqCell,
|
||||
// the image slice
|
||||
cube: I,
|
||||
data: js_sys::Uint8Array,
|
||||
size: (u32, u32, u32),
|
||||
time_request: Time,
|
||||
) -> Result<(), JsValue> {
|
||||
self.buffer.push_tile(cell, cube, time_request)
|
||||
self.buffer
|
||||
.push_tile_from_fits(cell, data, size, time_request)
|
||||
}
|
||||
|
||||
/*pub fn add_allsky(&mut self, allsky: AllskyRequest) -> Result<(), JsValue> {
|
||||
self.buffer.push_allsky(allsky)
|
||||
}*/
|
||||
pub fn push_tile_from_jpeg(
|
||||
&mut self,
|
||||
cell: &HEALPixFreqCell,
|
||||
// the image slice
|
||||
data: Box<[u8]>,
|
||||
size: (u32, u32, u32),
|
||||
time_request: Time,
|
||||
) -> Result<(), JsValue> {
|
||||
self.buffer
|
||||
.push_tile_from_jpeg(cell, data, size, time_request)
|
||||
}
|
||||
|
||||
/* Accessors */
|
||||
#[inline]
|
||||
|
||||
@@ -4,13 +4,83 @@ use crate::{healpix::cell::HEALPixCell, time::Time};
|
||||
use crate::renderable::hips::config::HiPSConfig;
|
||||
use crate::Abort;
|
||||
use crate::WebGlContext;
|
||||
use al_core::image::Image;
|
||||
use al_core::image::fits::FitsImage;
|
||||
use al_core::image::raw::ImageBuffer;
|
||||
use al_core::image::{Image, ImageType};
|
||||
use al_core::texture::format::{PixelType, R16I, R32F, R32I, R8U, RGB8U, RGBA8U};
|
||||
use al_core::texture::Texture3D;
|
||||
use al_core::webgl_ctx::WebGlRenderingCtx;
|
||||
use cgmath::Vector3;
|
||||
use fitsrs::hdu::header::extension::bintable::L;
|
||||
use fitsrs::hdu::header::Bitpix;
|
||||
use std::cmp::Ordering;
|
||||
use wasm_bindgen::JsValue;
|
||||
use std::ops::Range;
|
||||
use wasm_bindgen::{Clamped, JsValue};
|
||||
|
||||
pub enum HpxFreqData {
|
||||
Fits {
|
||||
// The raw bytes of the whole cubic FITS file, data big endian
|
||||
raw_bytes: Box<[u8]>,
|
||||
// Offset to the data bytes of the cubic tile
|
||||
data_byte_offset: Range<usize>,
|
||||
// Number of bytes per pixel (deduced from the bitpix)
|
||||
bitpix: Bitpix,
|
||||
// Triming offset indices when reading the data
|
||||
trim: (u32, u32, u32),
|
||||
// Naxis
|
||||
naxis: (u32, u32, u32),
|
||||
},
|
||||
Jpeg {
|
||||
data: Box<[u8]>,
|
||||
size: (u32, u32, u32),
|
||||
},
|
||||
}
|
||||
|
||||
enum Pixel {
|
||||
F32(f32),
|
||||
I32(i32),
|
||||
I16(i16),
|
||||
U8(u8),
|
||||
}
|
||||
|
||||
impl HpxFreqData {
|
||||
pub fn read_pixel(&self, x: u32, y: u32, z: u32) -> Pixel {
|
||||
match self {
|
||||
HpxFreqData::Fits {
|
||||
raw_bytes,
|
||||
data_byte_offset,
|
||||
bitpix,
|
||||
trim,
|
||||
naxis,
|
||||
} => {
|
||||
let x = x - trim.0;
|
||||
let y = y - trim.1;
|
||||
let z = z - trim.2;
|
||||
|
||||
let data_raw_bytes = &raw_bytes[data_byte_offset.clone()];
|
||||
|
||||
let pixel_bytes_off = (x + y * naxis.0 + z * (naxis.0 * naxis.1)) as usize;
|
||||
|
||||
let bytes_per_pixel = bitpix.byte_size();
|
||||
let p = &data_raw_bytes[pixel_bytes_off..(pixel_bytes_off + bytes_per_pixel)];
|
||||
match bitpix {
|
||||
Bitpix::U8 => Pixel::U8(p[0]),
|
||||
Bitpix::I16 => Pixel::I16(i16::from_be_bytes([p[0], p[1]])),
|
||||
Bitpix::I32 => Pixel::I32(i32::from_be_bytes([p[0], p[1], p[2], p[3]])),
|
||||
Bitpix::F32 => Pixel::F32(f32::from_be_bytes([p[0], p[1], p[2], p[3]])),
|
||||
// Texture are converted to
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
HpxFreqData::Jpeg { data, size } => {
|
||||
let pixel_bytes_off = (x + y * size.0 + z * (size.0 * size.1)) as usize;
|
||||
|
||||
let p = data[pixel_bytes_off];
|
||||
Pixel::U8(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HpxFreqTex {
|
||||
pub cell: HEALPixFreqCell,
|
||||
@@ -39,6 +109,10 @@ pub struct HpxFreqTex {
|
||||
/// The webgl2 3D texture of the cubic tile
|
||||
pub texture: Texture3D,
|
||||
|
||||
data: Option<HpxFreqData>,
|
||||
|
||||
// The real image data for accessing the pixel values
|
||||
//data: ImageType,
|
||||
/// A bitvector keeping track of the slices that have been inserted into the 3D texture
|
||||
/// It is limited to a cube depth of 256 (~ to the max texture size).
|
||||
slice_idx: [u32; 8],
|
||||
@@ -49,270 +123,6 @@ pub struct HpxFreqTex {
|
||||
num_stored_slices: u16,
|
||||
}
|
||||
|
||||
/*
|
||||
impl HpxFreqTex {
|
||||
pub fn new(cell: HEALPixCell, time_request: Time) -> Self {
|
||||
let start_time = None;
|
||||
let uniq = cell.uniq();
|
||||
let textures = std::iter::repeat_n(None, 512).collect();
|
||||
let blocks = [0; 512];
|
||||
let block_indices = Vec::new();
|
||||
Self {
|
||||
cell,
|
||||
uniq,
|
||||
time_request,
|
||||
start_time,
|
||||
textures,
|
||||
blocks,
|
||||
block_indices,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_nearest_slice(&self, slice: u16) -> Option<u16> {
|
||||
let block_idx = (slice >> 5) as usize;
|
||||
|
||||
match self.block_indices.binary_search(&block_idx) {
|
||||
Ok(_) => {
|
||||
if self.contains_slice(slice) {
|
||||
Some(slice)
|
||||
} else {
|
||||
// the slice is not present but we know there is one in the block
|
||||
let block = self.blocks[block_idx];
|
||||
|
||||
let slice_idx = (slice & 0x1f) as u32;
|
||||
|
||||
let m2 = if slice_idx == 31 {
|
||||
0
|
||||
} else {
|
||||
0xffffffff >> (slice_idx + 1)
|
||||
};
|
||||
let m1 = (!m2) & !(1 << (31 - slice_idx));
|
||||
|
||||
let lb = (block & m1) >> (32 - slice_idx);
|
||||
let rb = block & m2;
|
||||
|
||||
let lb_trailing_zeros = (lb.trailing_zeros() as u16).min(slice_idx as u16);
|
||||
let rb_leading_zeros = (rb.leading_zeros() - slice_idx - 1) as u16;
|
||||
|
||||
let no_more_left_bits = slice_idx - (lb_trailing_zeros as u32) == 0;
|
||||
let no_more_right_bits = slice_idx + (rb_leading_zeros as u32) == 31;
|
||||
|
||||
match (no_more_left_bits, no_more_right_bits) {
|
||||
(false, false) => {
|
||||
if lb_trailing_zeros <= rb_leading_zeros {
|
||||
Some(slice - lb_trailing_zeros - 1)
|
||||
} else {
|
||||
Some(slice + rb_leading_zeros + 1)
|
||||
}
|
||||
}
|
||||
(false, true) => {
|
||||
if lb_trailing_zeros <= rb_leading_zeros {
|
||||
Some(slice - lb_trailing_zeros - 1)
|
||||
} else {
|
||||
// explore next block
|
||||
if block_idx == self.blocks.len() - 1 {
|
||||
// no after block
|
||||
Some(slice - lb_trailing_zeros - 1)
|
||||
} else {
|
||||
// get the next block
|
||||
let next_block = self.blocks[block_idx + 1];
|
||||
|
||||
let num_bits_to_next_block =
|
||||
next_block.leading_zeros() as u16 + rb_leading_zeros;
|
||||
|
||||
if num_bits_to_next_block < lb_trailing_zeros {
|
||||
Some(slice + num_bits_to_next_block + 1)
|
||||
} else {
|
||||
Some(slice - lb_trailing_zeros - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(true, false) => {
|
||||
if rb_leading_zeros <= lb_trailing_zeros {
|
||||
Some(slice + rb_leading_zeros + 1)
|
||||
} else {
|
||||
// explore previous block
|
||||
if block_idx == 0 {
|
||||
// no after block
|
||||
Some(slice + rb_leading_zeros + 1)
|
||||
} else {
|
||||
// get the next block
|
||||
let prev_block = self.blocks[block_idx - 1];
|
||||
|
||||
let num_bits_from_prev_block =
|
||||
prev_block.trailing_zeros() as u16 + lb_trailing_zeros;
|
||||
if num_bits_from_prev_block < rb_leading_zeros {
|
||||
Some(slice - num_bits_from_prev_block - 1)
|
||||
} else {
|
||||
Some(slice + rb_leading_zeros + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(true, true) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(i) => {
|
||||
let prev_block = if i > 0 {
|
||||
self.block_indices.get(i - 1)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let cur_block = self.block_indices.get(i);
|
||||
match (prev_block, cur_block) {
|
||||
(Some(b_idx_1), Some(b_idx_2)) => {
|
||||
let b1 = self.blocks[*b_idx_1];
|
||||
let b2 = self.blocks[*b_idx_2];
|
||||
|
||||
let b1_tz = b1.trailing_zeros() as usize;
|
||||
let b2_lz = b2.leading_zeros() as usize;
|
||||
|
||||
let slice_b1 = ((*b_idx_1 << 5) + 32 - b1_tz - 1) as u16;
|
||||
let slice_b2 = ((*b_idx_2 << 5) + b2_lz) as u16;
|
||||
if slice - slice_b1 <= slice_b2 - slice {
|
||||
// the nearest slice is in b1
|
||||
Some(slice_b1)
|
||||
} else {
|
||||
// the nearest slice is in b2
|
||||
Some(slice_b2)
|
||||
}
|
||||
}
|
||||
(None, Some(b_idx_2)) => {
|
||||
let b2 = self.blocks[*b_idx_2];
|
||||
let b2_lz = b2.leading_zeros() as usize;
|
||||
|
||||
Some(((*b_idx_2 << 5) + b2_lz) as u16)
|
||||
}
|
||||
(Some(b_idx_1), None) => {
|
||||
let b1 = self.blocks[*b_idx_1];
|
||||
let b1_tz = b1.trailing_zeros() as usize;
|
||||
|
||||
Some(((*b_idx_1 << 5) + 32 - b1_tz - 1) as u16)
|
||||
}
|
||||
(None, None) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_3d_block_from_slice(&self, slice: u16) -> Option<&Texture3D> {
|
||||
let block_idx = (slice >> 5) as usize;
|
||||
|
||||
self.textures[block_idx].as_ref()
|
||||
}
|
||||
|
||||
pub fn extract_2d_slice_texture(&self, slice: u16) -> Option<HpxTex> {
|
||||
// Find the good sub cube containing the slice
|
||||
let block_idx = (slice >> 5) as usize;
|
||||
let slice_idx = (slice & 0x1f) as u8;
|
||||
|
||||
// check the texture is there
|
||||
if self.blocks[block_idx] & (1 << (31 - slice_idx)) != 0 {
|
||||
Some(HpxTex::new(&self.cell, slice_idx as i32, self.time_request))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// Panic if cell is not contained in the texture
|
||||
// Do nothing if the texture is full
|
||||
// Return true if the tile is newly added
|
||||
pub fn append<I: Image>(
|
||||
&mut self,
|
||||
image: I,
|
||||
slice: u16,
|
||||
cfg: &HiPSConfig,
|
||||
gl: &WebGlContext,
|
||||
) -> Result<(), JsValue> {
|
||||
let block_idx = (slice >> 5) as usize;
|
||||
|
||||
let texture = if let Some(texture) = self.textures[block_idx].as_ref() {
|
||||
texture
|
||||
} else {
|
||||
let tile_size = cfg.get_tile_size();
|
||||
let params = &[
|
||||
(
|
||||
WebGlRenderingCtx::TEXTURE_MIN_FILTER,
|
||||
WebGlRenderingCtx::NEAREST,
|
||||
),
|
||||
(
|
||||
WebGlRenderingCtx::TEXTURE_MAG_FILTER,
|
||||
WebGlRenderingCtx::NEAREST,
|
||||
),
|
||||
// Prevents s-coordinate wrapping (repeating)
|
||||
(
|
||||
WebGlRenderingCtx::TEXTURE_WRAP_S,
|
||||
WebGlRenderingCtx::CLAMP_TO_EDGE,
|
||||
),
|
||||
// Prevents t-coordinate wrapping (repeating)
|
||||
(
|
||||
WebGlRenderingCtx::TEXTURE_WRAP_T,
|
||||
WebGlRenderingCtx::CLAMP_TO_EDGE,
|
||||
),
|
||||
// Prevents r-coordinate wrapping (repeating)
|
||||
(
|
||||
WebGlRenderingCtx::TEXTURE_WRAP_R,
|
||||
WebGlRenderingCtx::CLAMP_TO_EDGE,
|
||||
),
|
||||
];
|
||||
|
||||
let texture = match cfg.get_format().get_pixel_format() {
|
||||
PixelType::RGBA8U => {
|
||||
Texture3D::create_empty::<RGBA8U>(gl, tile_size, tile_size, 32, params)
|
||||
}
|
||||
PixelType::RGB8U => {
|
||||
Texture3D::create_empty::<RGB8U>(gl, tile_size, tile_size, 32, params)
|
||||
}
|
||||
PixelType::R32F => {
|
||||
Texture3D::create_empty::<R32F>(gl, tile_size, tile_size, 32, params)
|
||||
}
|
||||
PixelType::R8U => {
|
||||
Texture3D::create_empty::<R8U>(gl, tile_size, tile_size, 32, params)
|
||||
}
|
||||
PixelType::R16I => {
|
||||
Texture3D::create_empty::<R16I>(gl, tile_size, tile_size, 32, params)
|
||||
}
|
||||
PixelType::R32I => {
|
||||
Texture3D::create_empty::<R32I>(gl, tile_size, tile_size, 32, params)
|
||||
}
|
||||
};
|
||||
self.textures[block_idx] = Some(texture?);
|
||||
|
||||
self.textures[block_idx].as_ref().unwrap()
|
||||
};
|
||||
|
||||
let slice_idx = slice & 0x1f;
|
||||
|
||||
// if there is already something, do not tex sub
|
||||
if self.blocks[block_idx] & (1 << (31 - slice_idx)) == 0 {
|
||||
image.insert_into_3d_texture(texture, &Vector3::<i32>::new(0, 0, slice_idx as i32))?;
|
||||
|
||||
match self.block_indices.binary_search(&block_idx) {
|
||||
Ok(_) => {} // element already in vector @ `pos`
|
||||
Err(i) => self.block_indices.insert(i, block_idx),
|
||||
}
|
||||
|
||||
self.blocks[block_idx] |= 1 << (31 - slice_idx);
|
||||
}
|
||||
|
||||
self.start_time = Some(Time::now());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Cell must be contained in the texture
|
||||
pub fn contains_slice(&self, slice: u16) -> bool {
|
||||
let block_idx = (slice >> 5) as usize;
|
||||
let idx_in_block = slice & 0x1f;
|
||||
|
||||
(self.blocks[block_idx] >> (31 - idx_in_block)) & 0x1 == 1
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
const TEX_PARAMS: &[(u32, u32)] = &[
|
||||
(
|
||||
WebGlRenderingCtx::TEXTURE_MIN_FILTER,
|
||||
@@ -358,14 +168,14 @@ impl HpxFreqTex {
|
||||
let start_time = None;
|
||||
|
||||
let texture = match pixel_format {
|
||||
PixelType::RGBA8U => Texture3D::create_empty::<RGBA8U>(
|
||||
PixelType::RGBA8U => Texture3D::create_empty::<R8U>(
|
||||
gl,
|
||||
tile_size as i32,
|
||||
tile_size as i32,
|
||||
num_slices as i32,
|
||||
TEX_PARAMS,
|
||||
),
|
||||
PixelType::RGB8U => Texture3D::create_empty::<RGB8U>(
|
||||
PixelType::RGB8U => Texture3D::create_empty::<R8U>(
|
||||
gl,
|
||||
tile_size as i32,
|
||||
tile_size as i32,
|
||||
@@ -400,8 +210,11 @@ impl HpxFreqTex {
|
||||
num_slices as i32,
|
||||
TEX_PARAMS,
|
||||
),
|
||||
// No color cubes
|
||||
_ => unreachable!(),
|
||||
}?;
|
||||
|
||||
let data = None;
|
||||
let num_stored_slices = 0;
|
||||
let slice_idx = [0x0; 8];
|
||||
Ok(Self {
|
||||
@@ -409,151 +222,68 @@ impl HpxFreqTex {
|
||||
slice_idx,
|
||||
time_request,
|
||||
start_time,
|
||||
data,
|
||||
texture,
|
||||
num_slices,
|
||||
num_stored_slices,
|
||||
})
|
||||
}
|
||||
|
||||
/*pub fn find_nearest_slice(&self, slice: u16) -> Option<u16> {
|
||||
let block_idx = (slice >> 5) as usize;
|
||||
|
||||
match self.block_indices.binary_search(&block_idx) {
|
||||
Ok(_) => {
|
||||
if self.contains_slice(slice) {
|
||||
Some(slice)
|
||||
} else {
|
||||
// the slice is not present but we know there is one in the block
|
||||
let block = self.blocks[block_idx];
|
||||
|
||||
let slice_idx = (slice & 0x1f) as u32;
|
||||
|
||||
let m2 = if slice_idx == 31 {
|
||||
0
|
||||
} else {
|
||||
0xffffffff >> (slice_idx + 1)
|
||||
};
|
||||
let m1 = (!m2) & !(1 << (31 - slice_idx));
|
||||
|
||||
let lb = (block & m1) >> (32 - slice_idx);
|
||||
let rb = block & m2;
|
||||
|
||||
let lb_trailing_zeros = (lb.trailing_zeros() as u16).min(slice_idx as u16);
|
||||
let rb_leading_zeros = (rb.leading_zeros() - slice_idx - 1) as u16;
|
||||
|
||||
let no_more_left_bits = slice_idx - (lb_trailing_zeros as u32) == 0;
|
||||
let no_more_right_bits = slice_idx + (rb_leading_zeros as u32) == 31;
|
||||
|
||||
match (no_more_left_bits, no_more_right_bits) {
|
||||
(false, false) => {
|
||||
if lb_trailing_zeros <= rb_leading_zeros {
|
||||
Some(slice - lb_trailing_zeros - 1)
|
||||
} else {
|
||||
Some(slice + rb_leading_zeros + 1)
|
||||
}
|
||||
}
|
||||
(false, true) => {
|
||||
if lb_trailing_zeros <= rb_leading_zeros {
|
||||
Some(slice - lb_trailing_zeros - 1)
|
||||
} else {
|
||||
// explore next block
|
||||
if block_idx == self.blocks.len() - 1 {
|
||||
// no after block
|
||||
Some(slice - lb_trailing_zeros - 1)
|
||||
} else {
|
||||
// get the next block
|
||||
let next_block = self.blocks[block_idx + 1];
|
||||
|
||||
let num_bits_to_next_block =
|
||||
next_block.leading_zeros() as u16 + rb_leading_zeros;
|
||||
|
||||
if num_bits_to_next_block < lb_trailing_zeros {
|
||||
Some(slice + num_bits_to_next_block + 1)
|
||||
} else {
|
||||
Some(slice - lb_trailing_zeros - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(true, false) => {
|
||||
if rb_leading_zeros <= lb_trailing_zeros {
|
||||
Some(slice + rb_leading_zeros + 1)
|
||||
} else {
|
||||
// explore previous block
|
||||
if block_idx == 0 {
|
||||
// no after block
|
||||
Some(slice + rb_leading_zeros + 1)
|
||||
} else {
|
||||
// get the next block
|
||||
let prev_block = self.blocks[block_idx - 1];
|
||||
|
||||
let num_bits_from_prev_block =
|
||||
prev_block.trailing_zeros() as u16 + lb_trailing_zeros;
|
||||
if num_bits_from_prev_block < rb_leading_zeros {
|
||||
Some(slice - num_bits_from_prev_block - 1)
|
||||
} else {
|
||||
Some(slice + rb_leading_zeros + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(true, true) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(i) => {
|
||||
let prev_block = if i > 0 {
|
||||
self.block_indices.get(i - 1)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let cur_block = self.block_indices.get(i);
|
||||
match (prev_block, cur_block) {
|
||||
(Some(b_idx_1), Some(b_idx_2)) => {
|
||||
let b1 = self.blocks[*b_idx_1];
|
||||
let b2 = self.blocks[*b_idx_2];
|
||||
|
||||
let b1_tz = b1.trailing_zeros() as usize;
|
||||
let b2_lz = b2.leading_zeros() as usize;
|
||||
|
||||
let slice_b1 = ((*b_idx_1 << 5) + 32 - b1_tz - 1) as u16;
|
||||
let slice_b2 = ((*b_idx_2 << 5) + b2_lz) as u16;
|
||||
if slice - slice_b1 <= slice_b2 - slice {
|
||||
// the nearest slice is in b1
|
||||
Some(slice_b1)
|
||||
} else {
|
||||
// the nearest slice is in b2
|
||||
Some(slice_b2)
|
||||
}
|
||||
}
|
||||
(None, Some(b_idx_2)) => {
|
||||
let b2 = self.blocks[*b_idx_2];
|
||||
let b2_lz = b2.leading_zeros() as usize;
|
||||
|
||||
Some(((*b_idx_2 << 5) + b2_lz) as u16)
|
||||
}
|
||||
(Some(b_idx_1), None) => {
|
||||
let b1 = self.blocks[*b_idx_1];
|
||||
let b1_tz = b1.trailing_zeros() as usize;
|
||||
|
||||
Some(((*b_idx_1 << 5) + 32 - b1_tz - 1) as u16)
|
||||
}
|
||||
(None, None) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
pub fn append_tile<I: Image>(
|
||||
pub fn set_data_from_fits(
|
||||
&mut self,
|
||||
// the tile image
|
||||
image: I,
|
||||
cfg: &HiPSConfig,
|
||||
gl: &WebGlContext,
|
||||
// the tile image of the whole cubic tile
|
||||
raw_bytes: js_sys::Uint8Array,
|
||||
// size of the cube
|
||||
size: (u32, u32, u32),
|
||||
) -> Result<(), JsValue> {
|
||||
image.insert_into_3d_texture(&self.texture, &Vector3::<i32>::new(0, 0, 0))?;
|
||||
let raw_bytes = raw_bytes.to_vec().into_boxed_slice();
|
||||
|
||||
let (trim1, trim2, trim3, width, height, depth, bitpix, data_byte_offset) = {
|
||||
let fits = FitsImage::from_raw_bytes(&raw_bytes[..])?;
|
||||
fits[0].insert_into_3d_texture(&self.texture, &Vector3::<i32>::new(0, 0, 0))?;
|
||||
|
||||
(
|
||||
fits[0].trim1,
|
||||
fits[0].trim2,
|
||||
fits[0].trim3,
|
||||
fits[0].width,
|
||||
fits[0].height,
|
||||
fits[0].depth,
|
||||
fits[0].bitpix,
|
||||
fits[0].data_byte_offset.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
let trim = (trim1, trim2, trim3);
|
||||
let naxis = (width, height, depth);
|
||||
|
||||
self.data = Some(HpxFreqData::Fits {
|
||||
raw_bytes,
|
||||
data_byte_offset: data_byte_offset.clone(),
|
||||
bitpix,
|
||||
trim,
|
||||
naxis,
|
||||
});
|
||||
self.num_stored_slices = self.num_slices;
|
||||
self.start_time = Some(Time::now());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_data_from_jpeg(
|
||||
&mut self,
|
||||
// the tile image of the whole cubic tile
|
||||
decoded_bytes: Box<[u8]>,
|
||||
// size of the cube
|
||||
size: (u32, u32, u32),
|
||||
) -> Result<(), JsValue> {
|
||||
let cubic_tile = ImageBuffer::<R8U>::new(decoded_bytes, size.0, size.1, size.2);
|
||||
cubic_tile.insert_into_3d_texture(&self.texture, &Vector3::<i32>::new(0, 0, 0))?;
|
||||
|
||||
self.data = Some(HpxFreqData::Jpeg {
|
||||
data: cubic_tile.data,
|
||||
size,
|
||||
});
|
||||
self.num_stored_slices = self.num_slices;
|
||||
self.start_time = Some(Time::now());
|
||||
|
||||
@@ -563,14 +293,13 @@ impl HpxFreqTex {
|
||||
// Panic if cell is not contained in the texture
|
||||
// Do nothing if the texture is full
|
||||
// Return true if the tile is newly added
|
||||
// Used by HiPS Cubes
|
||||
pub fn append_tile_slice<I: Image>(
|
||||
&mut self,
|
||||
// the tile image
|
||||
// the tile image of 1 slice
|
||||
image: I,
|
||||
// the slice offset in the cubic tile
|
||||
offset: u16,
|
||||
cfg: &HiPSConfig,
|
||||
gl: &WebGlContext,
|
||||
) -> Result<(), JsValue> {
|
||||
// If there is already something, do not tex sub
|
||||
let block_idx = (offset >> 5) as usize;
|
||||
|
||||
@@ -13,8 +13,19 @@ uniform float reversed;
|
||||
#include ../decode.glsl;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
/// RGBA sampler
|
||||
/// RED sampler
|
||||
vec4 uvw2c_r(vec3 uv) {
|
||||
float v = texture(tex, uv).r;
|
||||
|
||||
v = transfer_func(H, v, min_value, max_value);
|
||||
|
||||
// apply reversed
|
||||
v = mix(v, 1.0 - v, reversed);
|
||||
|
||||
return apply_tonal(colormap_f(v));
|
||||
}
|
||||
|
||||
/// RGBA sampler
|
||||
vec4 uvw2c_rgba(vec3 uv) {
|
||||
vec4 c = texture(tex, uv).rgba;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ uniform float opacity;
|
||||
|
||||
void main() {
|
||||
vec3 uv = vec3(frag_uv.xyz);
|
||||
vec4 color = uvw2c_rgba(uv);
|
||||
vec4 color = uvw2c_r(uv);
|
||||
|
||||
out_frag_color = color;
|
||||
out_frag_color.a = opacity * out_frag_color.a;
|
||||
@@ -1,20 +0,0 @@
|
||||
#version 300 es
|
||||
precision lowp float;
|
||||
precision lowp sampler3D;
|
||||
|
||||
uniform sampler3D tex;
|
||||
|
||||
in vec3 frag_uv;
|
||||
|
||||
out vec4 out_frag_color;
|
||||
uniform float opacity;
|
||||
|
||||
#include ../hips/color.glsl;
|
||||
|
||||
void main() {
|
||||
vec3 uv = vec3(frag_uv.xyz);
|
||||
vec4 color = uvw2cmap_rgba(uv);
|
||||
|
||||
out_frag_color = color;
|
||||
out_frag_color.a = opacity * out_frag_color.a;
|
||||
}
|
||||
Reference in New Issue
Block a user