1use std::{fmt::Debug, marker::PhantomData};
7
8use crate::{
9 error::Result,
10 image::internal::DistinctRowsIndexes,
11 util::{CACHE_LINE_BYTE_SIZE, MemoryGuard, MemoryTracker, tracing_wrappers::*},
12};
13
14use super::{ImageDataType, OwnedRawImage, RawImageRect, RawImageRectMut, Rect};
15
16#[cfg(feature = "allow-unsafe")]
23#[inline(always)]
24pub(super) fn cast_row<T: ImageDataType>(row: &[u8]) -> &[T] {
25 let new_len = row.len() / std::mem::size_of::<T>();
26 debug_assert!(row.len().is_multiple_of(std::mem::size_of::<T>()));
27 debug_assert!((row.as_ptr() as usize).is_multiple_of(std::mem::align_of::<T>()));
28 #[allow(unsafe_code)]
29 unsafe {
35 std::slice::from_raw_parts(row.as_ptr().cast::<T>(), new_len)
36 }
37}
38
39#[cfg(not(feature = "allow-unsafe"))]
40#[inline(always)]
41pub(super) fn cast_row<T: ImageDataType>(row: &[u8]) -> &[T] {
42 bytemuck::cast_slice(row)
43}
44
45#[cfg(feature = "allow-unsafe")]
47#[inline(always)]
48pub(super) fn cast_row_mut<T: ImageDataType>(row: &mut [u8]) -> &mut [T] {
49 let new_len = row.len() / std::mem::size_of::<T>();
50 debug_assert!(row.len().is_multiple_of(std::mem::size_of::<T>()));
51 debug_assert!((row.as_ptr() as usize).is_multiple_of(std::mem::align_of::<T>()));
52 #[allow(unsafe_code)]
53 unsafe {
55 std::slice::from_raw_parts_mut(row.as_mut_ptr().cast::<T>(), new_len)
56 }
57}
58
59#[cfg(not(feature = "allow-unsafe"))]
60#[inline(always)]
61pub(super) fn cast_row_mut<T: ImageDataType>(row: &mut [u8]) -> &mut [T] {
62 bytemuck::cast_slice_mut(row)
63}
64
65#[repr(transparent)]
66pub struct Image<T: ImageDataType> {
67 raw: OwnedRawImage,
69 _ph: PhantomData<T>,
70}
71
72impl<T: ImageDataType> Image<T> {
73 #[instrument(ret, err)]
74 pub fn new_with_padding(
75 size: (usize, usize),
76 offset: (usize, usize),
77 padding: (usize, usize),
78 ) -> Result<Image<T>> {
79 let s = T::DATA_TYPE_ID.size();
80 let img = OwnedRawImage::new_zeroed_with_padding(
81 (size.0 * s, size.1),
82 (offset.0 * s, offset.1),
83 (padding.0 * s, padding.1),
84 )?;
85 Ok(Self::from_raw(img))
86 }
87
88 #[instrument(ret, err)]
89 pub fn new(size: (usize, usize)) -> Result<Image<T>> {
90 Self::new_with_padding(size, (0, 0), (0, 0))
91 }
92
93 pub fn new_uninit(size: (usize, usize)) -> Result<Image<T>> {
101 let s = T::DATA_TYPE_ID.size();
102 let img = OwnedRawImage::new_uninit((size.0 * s, size.1))?;
103 Ok(Self::from_raw(img))
104 }
105
106 pub fn new_with_value(size: (usize, usize), value: T) -> Result<Image<T>> {
107 let mut ret = Self::new(size)?;
110 ret.fill(value);
111 Ok(ret)
112 }
113
114 pub fn allocation_size(size: (usize, usize)) -> u64 {
117 let (width, height) = size;
118 if width == 0 || height == 0 {
119 return 0;
120 }
121 let bytes_per_row = width.saturating_mul(T::DATA_TYPE_ID.size());
122 let bytes_between_rows =
123 bytes_per_row.div_ceil(CACHE_LINE_BYTE_SIZE) * CACHE_LINE_BYTE_SIZE;
124 let total = (height - 1)
125 .saturating_mul(bytes_between_rows)
126 .saturating_add(bytes_per_row);
127 total as u64
128 }
129
130 #[instrument(ret, err)]
133 pub fn new_tracked(size: (usize, usize), tracker: &MemoryTracker) -> Result<Image<T>> {
134 let alloc_size = Self::allocation_size(size);
135 tracker.try_allocate(alloc_size)?;
136 let guard = MemoryGuard::new(tracker.clone(), alloc_size);
138 let mut img = Self::new(size)?;
139 img.raw.set_tracker(tracker.clone(), alloc_size);
140 guard.disarm(); Ok(img)
142 }
143
144 #[instrument(ret, err)]
147 pub fn new_with_padding_tracked(
148 size: (usize, usize),
149 offset: (usize, usize),
150 padding: (usize, usize),
151 tracker: &MemoryTracker,
152 ) -> Result<Image<T>> {
153 let total_width = size.0.saturating_add(offset.0).saturating_add(padding.0);
154 let total_height = size.1.saturating_add(offset.1).saturating_add(padding.1);
155 let alloc_size = Self::allocation_size((total_width, total_height));
156 tracker.try_allocate(alloc_size)?;
157 let guard = MemoryGuard::new(tracker.clone(), alloc_size);
158 let mut img = Self::new_with_padding(size, offset, padding)?;
159 img.raw.set_tracker(tracker.clone(), alloc_size);
160 guard.disarm();
161 Ok(img)
162 }
163
164 #[inline]
165 pub fn size(&self) -> (usize, usize) {
166 (
167 self.raw.byte_size().0 / T::DATA_TYPE_ID.size(),
168 self.raw.byte_size().1,
169 )
170 }
171
172 pub fn offset(&self) -> (usize, usize) {
173 (
174 self.raw.byte_offset().0 / T::DATA_TYPE_ID.size(),
175 self.raw.byte_offset().1,
176 )
177 }
178
179 pub fn padding(&self) -> (usize, usize) {
180 (
181 self.raw.byte_padding().0 / T::DATA_TYPE_ID.size(),
182 self.raw.byte_padding().1,
183 )
184 }
185
186 pub fn fill(&mut self, v: T) {
187 if self.size().0 == 0 {
188 return;
189 }
190 for y in 0..self.size().1 {
191 self.row_mut(y).fill(v);
192 }
193 }
194
195 #[inline]
196 pub fn get_rect_including_padding_mut(&mut self, rect: Rect) -> ImageRectMut<'_, T> {
197 ImageRectMut::from_raw(
198 self.raw
199 .get_rect_including_padding_mut(rect.to_byte_rect(T::DATA_TYPE_ID)),
200 )
201 }
202
203 #[inline]
204 pub fn get_rect_including_padding(&mut self, rect: Rect) -> ImageRect<'_, T> {
205 ImageRect::from_raw(
206 self.raw
207 .get_rect_including_padding(rect.to_byte_rect(T::DATA_TYPE_ID)),
208 )
209 }
210
211 #[inline]
212 pub fn get_rect_mut(&mut self, rect: Rect) -> ImageRectMut<'_, T> {
213 ImageRectMut::from_raw(self.raw.get_rect_mut(rect.to_byte_rect(T::DATA_TYPE_ID)))
214 }
215
216 #[inline]
217 pub fn get_rect(&self, rect: Rect) -> ImageRect<'_, T> {
218 ImageRect::from_raw(self.raw.get_rect(rect.to_byte_rect(T::DATA_TYPE_ID)))
219 }
220
221 pub fn try_clone(&self) -> Result<Self> {
222 Ok(Self::from_raw(self.raw.try_clone()?))
223 }
224
225 pub fn into_raw(self) -> OwnedRawImage {
226 self.raw
227 }
228
229 pub fn from_raw(raw: OwnedRawImage) -> Self {
230 const { assert!(CACHE_LINE_BYTE_SIZE.is_multiple_of(T::DATA_TYPE_ID.size())) };
231 assert!(raw.data.is_aligned(T::DATA_TYPE_ID.size()));
232 Image {
233 raw,
234 _ph: PhantomData,
235 }
236 }
237
238 #[inline(always)]
239 pub fn row(&self, row: usize) -> &[T] {
240 cast_row(self.raw.row(row))
241 }
242
243 #[inline(always)]
244 pub fn row_mut(&mut self, row: usize) -> &mut [T] {
245 cast_row_mut(self.raw.row_mut(row))
246 }
247
248 #[inline(always)]
252 pub fn distinct_full_rows_mut<I: DistinctRowsIndexes>(
253 &mut self,
254 rows: I,
255 ) -> I::CastOutput<'_, T> {
256 let rows = self.raw.data.distinct_rows_mut(rows);
257 I::cast_rows(rows)
258 }
259
260 pub fn all_rows_mut(&mut self) -> Vec<&mut [T]> {
264 let (bytes_per_row, num_rows, bytes_between_rows) = self.raw.data.dimensions();
265 if num_rows == 0 {
266 return Vec::new();
267 }
268 let data = self.raw.data.data_slice_mut();
269 let mut result = Vec::with_capacity(num_rows);
272 split_rows_into(
273 data,
274 bytes_per_row,
275 bytes_between_rows,
276 num_rows,
277 &mut result,
278 );
279 result
280 }
281}
282
283fn split_rows_into<'a, T: ImageDataType>(
291 data: &'a mut [u8],
292 bytes_per_row: usize,
293 bytes_between_rows: usize,
294 num_rows: usize,
295 out: &mut Vec<&'a mut [T]>,
296) {
297 let mut remaining: Option<&'a mut [u8]> = Some(data);
298 for i in 0..num_rows {
299 let data = remaining.take().unwrap();
300 if i < num_rows - 1 {
301 let (head, tail) = data.split_at_mut(bytes_between_rows);
302 out.push(cast_row_mut(&mut head[..bytes_per_row]));
303 remaining = Some(tail);
304 } else {
305 out.push(cast_row_mut(&mut data[..bytes_per_row]));
306 }
307 }
308}
309
310#[derive(Clone, Copy)]
311pub struct ImageRect<'a, T: ImageDataType> {
312 raw: RawImageRect<'a>,
314 _ph: PhantomData<T>,
315}
316
317impl<'a, T: ImageDataType> ImageRect<'a, T> {
318 #[inline(always)]
319 pub fn rect(&self, rect: Rect) -> ImageRect<'a, T> {
320 Self::from_raw(self.raw.rect(rect.to_byte_rect(T::DATA_TYPE_ID)))
321 }
322
323 #[inline]
324 pub fn size(&self) -> (usize, usize) {
325 (
326 self.raw.byte_size().0 / T::DATA_TYPE_ID.size(),
327 self.raw.byte_size().1,
328 )
329 }
330
331 #[inline(always)]
332 pub fn row(&self, row: usize) -> &'a [T] {
333 cast_row(self.raw.row(row))
336 }
337
338 pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
339 (0..self.size().1).flat_map(|x| self.row(x).iter().cloned())
340 }
341
342 pub fn into_raw(self) -> RawImageRect<'a> {
343 self.raw
344 }
345
346 #[inline]
347 pub fn from_raw(raw: RawImageRect<'a>) -> Self {
348 const { assert!(CACHE_LINE_BYTE_SIZE.is_multiple_of(T::DATA_TYPE_ID.size())) };
349 assert!(raw.is_aligned(T::DATA_TYPE_ID.size()));
350 ImageRect {
351 raw,
352 _ph: PhantomData,
353 }
354 }
355}
356
357pub struct ImageRectMut<'a, T: ImageDataType> {
358 raw: RawImageRectMut<'a>,
360 _ph: PhantomData<T>,
361}
362
363impl<'a, T: ImageDataType> ImageRectMut<'a, T> {
364 #[inline]
365 pub fn rect(&'a mut self, rect: Rect) -> ImageRectMut<'a, T> {
366 Self::from_raw(self.raw.rect_mut(rect.to_byte_rect(T::DATA_TYPE_ID)))
367 }
368
369 #[inline]
370 pub fn size(&self) -> (usize, usize) {
371 (
372 self.raw.byte_size().0 / T::DATA_TYPE_ID.size(),
373 self.raw.byte_size().1,
374 )
375 }
376
377 #[inline(always)]
378 pub fn row(&mut self, row: usize) -> &mut [T] {
379 cast_row_mut(self.raw.row(row))
380 }
381
382 pub fn as_rect(&'a self) -> ImageRect<'a, T> {
383 ImageRect::from_raw(self.raw.as_rect())
384 }
385
386 pub fn into_raw(self) -> RawImageRectMut<'a> {
387 self.raw
388 }
389
390 #[inline]
391 pub fn from_raw(raw: RawImageRectMut<'a>) -> Self {
392 const { assert!(CACHE_LINE_BYTE_SIZE.is_multiple_of(T::DATA_TYPE_ID.size())) };
393 assert!(raw.is_aligned(T::DATA_TYPE_ID.size()));
394 ImageRectMut {
395 raw,
396 _ph: PhantomData,
397 }
398 }
399}
400
401impl<T: ImageDataType> Debug for Image<T> {
402 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
403 write!(
404 f,
405 "{:?} {}x{}",
406 T::DATA_TYPE_ID,
407 self.size().0,
408 self.size().1
409 )
410 }
411}
412
413impl<T: ImageDataType> Debug for ImageRect<'_, T> {
414 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
415 write!(
416 f,
417 "{:?} rect {}x{}",
418 T::DATA_TYPE_ID,
419 self.size().0,
420 self.size().1
421 )
422 }
423}
424
425impl<T: ImageDataType> Debug for ImageRectMut<'_, T> {
426 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
427 write!(
428 f,
429 "{:?} mutrect {}x{}",
430 T::DATA_TYPE_ID,
431 self.size().0,
432 self.size().1
433 )
434 }
435}