1#![forbid(elided_lifetimes_in_paths)]
2#![cfg_attr(debug_assertions, allow(dead_code, unreachable_code))]
3
4pub use crate::image::prelude::*;
5pub use crate::pixel::prelude::*;
6
7mod image;
8mod pixel;
9
10use std::ffi::c_void;
11use std::mem;
12
13use gl::types::GLenum;
14
15pub type RgbaImageData = ImageData<Rgba>;
16pub type RgbImageData = ImageData<Rgb>;
17
18pub type BgraImageData = ImageData<Bgra>;
19pub type BgrImageData = ImageData<Bgr>;
20
21#[derive(PartialEq, Eq, Clone, Copy, Debug)]
22pub enum CaptureFormat {
23 Rgba,
24 Rgb,
25 Bgra,
26 Bgr,
27}
28
29impl CaptureFormat {
30 pub fn allocate_pixel_data(self, (w, h): (u32, u32)) -> Vec<u8> {
31 let size = (w as usize) * (h as usize) * self.channel_count();
32 vec![0; size]
33 }
34
35 pub const fn to_gl_format(self) -> GLenum {
36 match self {
37 Self::Rgba => gl::RGBA,
38 Self::Rgb => gl::RGB,
39 Self::Bgra => gl::BGRA,
40 Self::Bgr => gl::BGR,
41 }
42 }
43
44 pub const fn channel_count(self) -> usize {
45 match self {
46 Self::Rgba | Self::Bgra => 4,
47 Self::Rgb | Self::Bgr => 3,
48 }
49 }
50
51 pub const fn pixel_size(self) -> usize {
53 match self {
54 Self::Rgba | Self::Bgra => mem::size_of::<[u8; 4]>(),
55 Self::Rgb | Self::Bgr => mem::size_of::<[u8; 3]>(),
56 }
57 }
58}
59
60pub unsafe fn capture() -> RgbImageData {
61 let mut viewport = [0; 4];
62 gl::GetIntegerv(gl::VIEWPORT, viewport.as_mut_ptr());
63
64 let size = (viewport[2] as u32, viewport[3] as u32);
65 let mut img = RgbImageData::new(size);
66 capture_into(&mut img);
67 img
68}
69
70pub unsafe fn capture_into<P>(img: &mut ImageData<P>)
71where
72 P: Pixel,
73{
74 read_pixels_ptr(
75 (0, 0),
76 img.size,
77 P::FORMAT,
78 img.data.as_mut_ptr() as *mut c_void,
79 );
80 img.flip_vertically();
81}
82
83pub unsafe fn read_pixels(
86 (x, y): (u32, u32),
87 (w, h): (u32, u32),
88 format: CaptureFormat,
89 data: &mut [u8],
90) {
91 assert!(w <= (i32::MAX as u32));
92 assert!(h <= (i32::MAX as u32));
93
94 let min_len = (w as usize) * (h as usize) * format.channel_count();
95 assert!(data.len() <= min_len);
96
97 read_pixels_ptr((x, y), (w, h), format, data.as_mut_ptr() as *mut c_void);
98}
99
100pub unsafe fn read_pixels_ptr(
101 (x, y): (u32, u32),
102 (w, h): (u32, u32),
103 format: CaptureFormat,
104 data: *mut c_void,
105) {
106 gl::PixelStorei(gl::PACK_ALIGNMENT, 1);
107 gl::ReadPixels(
108 x as i32,
109 y as i32,
110 w as i32,
111 h as i32,
112 format.to_gl_format(),
113 gl::UNSIGNED_BYTE,
114 data,
115 );
116}