ofx/
image.rs

1use enums::{BitDepth, ImageComponent};
2use std::marker::PhantomData;
3use types::*;
4
5pub trait ChannelFormat {
6	fn range_max() -> f32;
7	fn from_f32(src: f32) -> Self;
8	fn to_f32(&self) -> f32;
9}
10
11impl ChannelFormat for f32 {
12	#[inline]
13	fn range_max() -> f32 {
14		1.0
15	}
16	#[inline]
17	fn from_f32(src: f32) -> Self {
18		src
19	}
20	#[inline]
21	fn to_f32(&self) -> f32 {
22		*self
23	}
24}
25
26impl ChannelFormat for u16 {
27	#[inline]
28	fn range_max() -> f32 {
29		f32::from(std::u16::MAX)
30	}
31	fn from_f32(src: f32) -> Self {
32		let clamp = Self::range_max();
33		clamp.min(src * clamp) as Self
34	}
35	#[inline]
36	fn to_f32(&self) -> f32 {
37		f32::from(*self) / Self::range_max()
38	}
39}
40
41impl ChannelFormat for u8 {
42	#[inline]
43	fn range_max() -> f32 {
44		f32::from(std::u8::MAX)
45	}
46	#[inline]
47	fn from_f32(src: f32) -> Self {
48		let clamp = Self::range_max();
49		clamp.min(src * clamp) as Self
50	}
51	#[inline]
52	fn to_f32(&self) -> f32 {
53		f32::from(*self) / Self::range_max()
54	}
55}
56
57pub trait PixelFormatRGB: PixelFormat {
58	fn r(&self) -> &Self::ChannelValue;
59	fn r_mut(&mut self) -> &mut Self::ChannelValue;
60	fn g(&self) -> &Self::ChannelValue;
61	fn g_mut(&mut self) -> &mut Self::ChannelValue;
62	fn b(&self) -> &Self::ChannelValue;
63	fn b_mut(&mut self) -> &mut Self::ChannelValue;
64}
65
66pub trait PixelFormatRGBA: PixelFormatRGB {
67	fn new(
68		r: Self::ChannelValue,
69		g: Self::ChannelValue,
70		b: Self::ChannelValue,
71		a: Self::ChannelValue,
72	) -> Self;
73	fn a(&self) -> &Self::ChannelValue;
74	fn a_mut(&mut self) -> &mut Self::ChannelValue;
75}
76pub trait PixelFormatAlpha: PixelFormat + ChannelFormat {}
77
78pub trait ScaleMix {
79	fn scaled(&self, scale: &RGBAColourD) -> Self;
80	fn mix(&self, wet: &Self, mix: f32) -> Self;
81}
82
83impl<T> ScaleMix for T
84where
85	T: PixelFormatRGBA,
86{
87	fn scaled(&self, scale: &RGBAColourD) -> Self {
88		T::new(
89			T::ChannelValue::from_f32(self.r().to_f32() * scale.r as f32),
90			T::ChannelValue::from_f32(self.g().to_f32() * scale.g as f32),
91			T::ChannelValue::from_f32(self.b().to_f32() * scale.b as f32),
92			T::ChannelValue::from_f32(self.a().to_f32() * scale.a as f32),
93		)
94	}
95
96	fn mix(&self, wet: &Self, mix: f32) -> Self {
97		if mix <= 0.0 {
98			*self
99		} else if mix >= 1.0 {
100			*wet
101		} else {
102			let a0 = mix;
103			let a1 = 1.0 - a0;
104			T::new(
105				T::ChannelValue::from_f32(wet.r().to_f32() * a0 + self.r().to_f32() * a1),
106				T::ChannelValue::from_f32(wet.g().to_f32() * a0 + self.g().to_f32() * a1),
107				T::ChannelValue::from_f32(wet.b().to_f32() * a0 + self.b().to_f32() * a1),
108				T::ChannelValue::from_f32(wet.a().to_f32() * a0 + self.a().to_f32() * a1),
109			)
110		}
111	}
112}
113
114impl ScaleMix for f32 {
115	fn scaled(&self, scale: &RGBAColourD) -> Self {
116		*self * scale.a as f32
117	}
118
119	fn mix(&self, wet: &Self, mix: f32) -> Self {
120		if mix <= 0.0 {
121			*self
122		} else if mix >= 1.0 {
123			*wet
124		} else {
125			let a0 = mix;
126			let a1 = 1.0 - a0;
127			wet.to_f32() * a0 + self.to_f32() * a1
128		}
129	}
130}
131
132impl ScaleMix for u8 {
133	fn scaled(&self, scale: &RGBAColourD) -> Self {
134		u8::from_f32(self.to_f32() * scale.a as f32)
135	}
136
137	fn mix(&self, wet: &Self, mix: f32) -> Self {
138		if mix <= 0.0 {
139			*self
140		} else if mix >= 1.0 {
141			*wet
142		} else {
143			let a0 = mix;
144			let a1 = 1.0 - a0;
145			u8::from_f32(wet.to_f32() * a0 + self.to_f32() * a1)
146		}
147	}
148}
149
150impl ScaleMix for u16 {
151	fn scaled(&self, scale: &RGBAColourD) -> Self {
152		u16::from_f32(self.to_f32() * scale.a as f32)
153	}
154
155	fn mix(&self, wet: &Self, mix: f32) -> Self {
156		if mix <= 0.0 {
157			*self
158		} else if mix >= 1.0 {
159			*wet
160		} else {
161			let a0 = mix;
162			let a1 = 1.0 - a0;
163			u16::from_f32(wet.to_f32() * a0 + self.to_f32() * a1)
164		}
165	}
166}
167
168pub trait PixelFormat: Sized + Copy + Clone {
169	type ChannelValue: ChannelFormat;
170
171	#[inline]
172	fn num_components() -> usize {
173		std::mem::size_of::<Self>() / std::mem::size_of::<Self::ChannelValue>()
174	}
175
176	#[inline]
177	fn components() -> ImageComponent {
178		match Self::num_components() {
179			1 => ImageComponent::Alpha,
180			3 => ImageComponent::RGB,
181			4 => ImageComponent::RGBA,
182			_ => ImageComponent::RGBA, //?
183		}
184	}
185
186	fn channel(&self, i: usize) -> &Self::ChannelValue;
187	fn channel_mut(&mut self, i: usize) -> &mut Self::ChannelValue;
188
189	#[inline]
190	fn num_bits_depth() -> usize {
191		8 * std::mem::size_of::<Self::ChannelValue>()
192	}
193
194	#[inline]
195	fn bit_depth() -> BitDepth {
196		match Self::num_bits_depth() {
197			8 => BitDepth::Byte,
198			16 => BitDepth::Short,
199			32 => BitDepth::Float,
200			_ => BitDepth::Float,
201		}
202	}
203}
204
205macro_rules! pixel_format_rgba {
206	($rgba:ty, $channel_value:ty) => {
207		impl PixelFormat for $rgba {
208			type ChannelValue = $channel_value;
209			fn channel(&self, i: usize) -> &Self::ChannelValue {
210				match i {
211					0 => &self.r,
212					1 => &self.g,
213					2 => &self.b,
214					3 => &self.a,
215					_ => panic!("Index out of range"),
216				}
217			}
218			fn channel_mut(&mut self, i: usize) -> &mut Self::ChannelValue {
219				match i {
220					0 => &mut self.r,
221					1 => &mut self.g,
222					2 => &mut self.b,
223					3 => &mut self.a,
224					_ => panic!("Index out of range"),
225				}
226			}
227		}
228
229		impl PixelFormatRGB for $rgba {
230			#[inline]
231			fn r(&self) -> &Self::ChannelValue {
232				&self.r
233			}
234			#[inline]
235			fn r_mut(&mut self) -> &mut Self::ChannelValue {
236				&mut self.r
237			}
238			#[inline]
239			fn g(&self) -> &Self::ChannelValue {
240				&self.g
241			}
242			#[inline]
243			fn g_mut(&mut self) -> &mut Self::ChannelValue {
244				&mut self.g
245			}
246			#[inline]
247			fn b(&self) -> &Self::ChannelValue {
248				&self.b
249			}
250			#[inline]
251			fn b_mut(&mut self) -> &mut Self::ChannelValue {
252				&mut self.b
253			}
254		}
255
256		impl PixelFormatRGBA for $rgba {
257			fn new(
258				r: Self::ChannelValue,
259				g: Self::ChannelValue,
260				b: Self::ChannelValue,
261				a: Self::ChannelValue,
262			) -> Self {
263				let mut instance: $rgba = unsafe { std::mem::uninitialized() };
264				instance.r = r;
265				instance.g = g;
266				instance.b = b;
267				instance.a = a;
268				instance
269			}
270
271			#[inline]
272			fn a(&self) -> &Self::ChannelValue {
273				&self.a
274			}
275			#[inline]
276			fn a_mut(&mut self) -> &mut Self::ChannelValue {
277				&mut self.a
278			}
279		}
280	};
281}
282
283macro_rules! pixel_format_yuva {
284	($yuva:ty, $channel_value:ty) => {
285		impl PixelFormat for $yuva {
286			type ChannelValue = $channel_value;
287			fn channel(&self, i: usize) -> &Self::ChannelValue {
288				match i {
289					0 => &self.y,
290					1 => &self.u,
291					2 => &self.v,
292					3 => &self.a,
293					_ => panic!("Index out of range"),
294				}
295			}
296			fn channel_mut(&mut self, i: usize) -> &mut Self::ChannelValue {
297				match i {
298					0 => &mut self.y,
299					1 => &mut self.u,
300					2 => &mut self.v,
301					3 => &mut self.a,
302					_ => panic!("Index out of range"),
303				}
304			}
305		}
306	};
307}
308
309macro_rules! pixel_format_rgb {
310	($rgb:ty, $channel_value:ty) => {
311		impl PixelFormat for $rgb {
312			type ChannelValue = $channel_value;
313			fn channel(&self, i: usize) -> &Self::ChannelValue {
314				match i {
315					0 => &self.r,
316					1 => &self.g,
317					2 => &self.b,
318					_ => panic!("Index out of range"),
319				}
320			}
321			fn channel_mut(&mut self, i: usize) -> &mut Self::ChannelValue {
322				match i {
323					0 => &mut self.r,
324					1 => &mut self.g,
325					2 => &mut self.b,
326					_ => panic!("Index out of range"),
327				}
328			}
329		}
330
331		impl PixelFormatRGB for $rgb {
332			#[inline]
333			fn r(&self) -> &Self::ChannelValue {
334				&self.r
335			}
336			#[inline]
337			fn r_mut(&mut self) -> &mut Self::ChannelValue {
338				&mut self.r
339			}
340			#[inline]
341			fn g(&self) -> &Self::ChannelValue {
342				&self.g
343			}
344			#[inline]
345			fn g_mut(&mut self) -> &mut Self::ChannelValue {
346				&mut self.g
347			}
348			#[inline]
349			fn b(&self) -> &Self::ChannelValue {
350				&self.b
351			}
352			#[inline]
353			fn b_mut(&mut self) -> &mut Self::ChannelValue {
354				&mut self.b
355			}
356		}
357	};
358}
359
360macro_rules! pixel_format_alpha {
361	($channel_value:ty) => {
362		impl PixelFormat for $channel_value {
363			type ChannelValue = $channel_value;
364			fn channel(&self, i: usize) -> &Self::ChannelValue {
365				self
366			}
367			fn channel_mut(&mut self, i: usize) -> &mut Self::ChannelValue {
368				self
369			}
370		}
371
372		impl PixelFormatAlpha for $channel_value {}
373	};
374}
375
376pixel_format_rgba!(RGBAColourB, u8);
377pixel_format_rgba!(RGBAColourS, u16);
378pixel_format_rgba!(RGBAColourF, f32);
379pixel_format_rgb!(RGBColourB, u8);
380pixel_format_rgb!(RGBColourS, u16);
381pixel_format_rgb!(RGBColourF, f32);
382pixel_format_alpha!(u8);
383pixel_format_alpha!(u16);
384pixel_format_alpha!(f32);
385pixel_format_yuva!(YUVAColourB, u8);
386pixel_format_yuva!(YUVAColourS, u16);
387pixel_format_yuva!(YUVAColourF, f32);
388
389pub struct ImageBuffer<'a, T>
390where
391	T: PixelFormat,
392{
393	bounds: RectI,
394	row_bytes: isize,
395	t_size: usize,
396	data: &'a mut u8,
397	pixel_type: PhantomData<T>,
398}
399
400impl<'a, T> Clone for ImageBuffer<'a, T>
401where
402	T: PixelFormat,
403{
404	fn clone(&self) -> Self {
405		// TODO: possibly unsound
406		let data = self.data as *const u8;
407		ImageBuffer {
408			bounds: self.bounds,
409			row_bytes: self.row_bytes,
410			t_size: self.t_size,
411			data: unsafe { &mut *(data as *mut u8) },
412			pixel_type: PhantomData,
413		}
414	}
415}
416
417impl<'a, T> ImageBuffer<'a, T>
418where
419	T: PixelFormat,
420{
421	fn new(bounds: RectI, row_bytes: Int, data: *mut u8) -> Self {
422		let t_size = std::mem::size_of::<T>();
423		ImageBuffer {
424			bounds,
425			row_bytes: row_bytes as isize,
426			t_size,
427			data: unsafe { &mut *data },
428			pixel_type: PhantomData,
429		}
430	}
431
432	#[inline]
433	fn byte_offset(&self, x: Int, y: Int) -> isize {
434		(y - self.bounds.y1) as isize * self.row_bytes + (x - self.bounds.x1) as isize
435	}
436
437	fn bounds(&self) -> RectI {
438		self.bounds
439	}
440
441	fn bytes(&self) -> usize {
442		self.row_bytes.abs() as usize * (self.bounds.y2 - self.bounds.y1) as usize
443	}
444
445	fn dimensions(&self) -> (u32, u32) {
446		(
447			(self.bounds.x2 - self.bounds.x1) as u32,
448			(self.bounds.y2 - self.bounds.y1) as u32,
449		)
450	}
451
452	fn pixel_bytes(&self) -> usize {
453		self.t_size
454	}
455
456	fn ptr(&self, offset: isize) -> *const u8 {
457		unsafe {
458			let ptr: *const u8 = &*self.data;
459			ptr.offset(offset)
460		}
461	}
462
463	fn ptr_mut(&mut self, offset: isize) -> *mut u8 {
464		unsafe {
465			let ptr: *mut u8 = &mut *self.data;
466			ptr.offset(offset)
467		}
468	}
469
470	fn make_slice(&self, x: Int, y: Int, length: usize) -> &[T] {
471		let start = self.byte_offset(x, y);
472		unsafe { std::slice::from_raw_parts(self.ptr(start) as *const T, length) }
473	}
474
475	fn make_slice_mut(&mut self, x: Int, y: Int, length: usize) -> &mut [T] {
476		let start = self.byte_offset(x, y);
477		unsafe { std::slice::from_raw_parts_mut(self.ptr_mut(start) as *mut T, length) }
478	}
479
480	fn row(&self, y: Int) -> &[T] {
481		self.make_slice(
482			self.bounds.x1,
483			y,
484			(self.bounds.x2 - self.bounds.x1) as usize,
485		)
486	}
487
488	fn row_mut(&mut self, y: Int) -> &mut [T] {
489		let x1 = self.bounds.x1;
490		let x2 = self.bounds.x2;
491		self.make_slice_mut(x1, y, (x2 - x1) as usize)
492	}
493
494	fn chunk(&mut self, y1: Int, y2: Int) -> Self {
495		let y1 = y1.max(self.bounds.y1);
496		let y2 = y2.min(self.bounds.y2);
497		let bounds = RectI {
498			x1: self.bounds.x1,
499			y1,
500			x2: self.bounds.x2,
501			y2,
502		};
503		debug!("Chunk {}-{}", y1, y2);
504		// TODO: potentially unsound
505		let offset = self.byte_offset(self.bounds.x1, y1);
506		let ptr_mut = self.ptr_mut(offset);
507		let data = unsafe { &mut *ptr_mut };
508		ImageBuffer {
509			bounds,
510			row_bytes: self.row_bytes,
511			t_size: self.t_size,
512			data,
513			pixel_type: PhantomData,
514		}
515	}
516
517	pub fn chunks_mut(mut self, chunk_size: usize) -> impl Iterator<Item = ImageBuffer<'a, T>> {
518		let rows = (self.bounds.y2 - self.bounds.y1) as usize;
519		let n_chunks = (rows + chunk_size - 1) / chunk_size;
520		let rows_per_chunk = chunk_size;
521		let y1 = self.bounds.y1;
522		(0..n_chunks).map(move |chunk| {
523			self.chunk(
524				y1 + (chunk * rows_per_chunk) as Int,
525				y1 + ((chunk + 1) * rows_per_chunk) as Int,
526			)
527		})
528	}
529}
530
531pub struct Row<'a, T>
532where
533	T: PixelFormat,
534{
535	y: Int,
536	data: ImageBuffer<'a, T>,
537}
538
539pub struct RowWalk<'a, T>
540where
541	T: PixelFormat,
542{
543	data: ImageBuffer<'a, T>,
544	y: Int,
545	last_y: Int,
546}
547
548impl<'a, T> RowWalk<'a, T> where T: PixelFormat {}
549
550impl<'a, T> Iterator for RowWalk<'a, T>
551where
552	T: PixelFormat,
553{
554	type Item = Row<'a, T>;
555
556	fn next(&mut self) -> Option<Row<'a, T>> {
557		if self.y < self.last_y {
558			let row = Row {
559				data: self.data.clone(),
560				y: self.y,
561			};
562			self.y += 1;
563			Some(row)
564		} else {
565			None
566		}
567	}
568}
569
570#[derive(Clone)]
571pub struct ImageDescriptor<'a, T>
572where
573	T: PixelFormat,
574{
575	data: ImageBuffer<'a, T>,
576}
577
578pub struct ImageDescriptorMut<'a, T>
579where
580	T: PixelFormat,
581{
582	data: ImageBuffer<'a, T>,
583}
584
585pub struct ImageTileMut<'a, T>
586where
587	T: PixelFormat,
588{
589	pub y1: Int,
590	pub y2: Int,
591	data: ImageBuffer<'a, T>,
592}
593
594impl<'a, T> ImageDescriptor<'a, T>
595where
596	T: PixelFormat,
597{
598	pub fn new(bounds: RectI, row_bytes: Int, ptr: VoidPtrMut) -> Self {
599		ImageDescriptor {
600			data: ImageBuffer::new(bounds, row_bytes, ptr as *mut u8),
601		}
602	}
603
604	pub fn row(&self, y: Int) -> &[T] {
605		self.data.row(y)
606	}
607
608	pub fn row_range(&self, x1: Int, x2: Int, y: Int) -> &[T] {
609		let slice = self.row(y);
610		&slice[(x1 - self.data.bounds.x1) as usize..(x2 - self.data.bounds.x1) as usize]
611	}
612}
613
614impl<'a, T> ImageDescriptorMut<'a, T>
615where
616	T: PixelFormat,
617{
618	pub fn new(bounds: RectI, row_bytes: Int, ptr: VoidPtrMut) -> Self {
619		ImageDescriptorMut {
620			data: ImageBuffer::new(bounds, row_bytes, ptr as *mut u8),
621		}
622	}
623
624	pub fn row(&mut self, y: Int) -> &mut [T] {
625		self.data.row_mut(y)
626	}
627
628	pub fn row_range(&mut self, x1: Int, x2: Int, y: Int) -> &mut [T] {
629		let x0 = self.data.bounds.x1;
630		let slice = self.row(y);
631		let x1 = (x1 - x0) as usize;
632		let x2 = (x2 - x0) as usize;
633		&mut slice[x1..x2]
634	}
635
636	pub fn into_tiles(self, n_chunks: usize) -> Vec<ImageTileMut<'a, T>> {
637		let (width, height) = self.data.dimensions();
638		let rows_per_chunk = height as usize / n_chunks;
639		self.data
640			.chunks_mut(rows_per_chunk as usize)
641			.enumerate()
642			.map(|(chunk_index, chunk)| {
643				let y1 = (chunk_index * rows_per_chunk) as Int;
644				let y2 = (height as Int).min(y1 + rows_per_chunk as Int);
645				ImageTileMut::new(y1, y2, chunk)
646			})
647			.collect()
648	}
649}
650
651impl<'a, T> ImageTileMut<'a, T>
652where
653	T: PixelFormat,
654{
655	pub fn new(y1: Int, y2: Int, data: ImageBuffer<'a, T>) -> Self {
656		ImageTileMut { y1, y2, data }
657	}
658
659	pub fn row(&mut self, y: Int) -> &mut [T] {
660		self.data.row_mut(y)
661	}
662
663	pub fn row_range(&mut self, x1: Int, x2: Int, y: Int) -> &mut [T] {
664		let x0 = self.data.bounds.x1;
665		let slice = self.row(y);
666		let x1 = (x1 - x0) as usize;
667		let x2 = (x2 - x0) as usize;
668		&mut slice[x1..x2]
669	}
670}