1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::os::raw::{c_void};
use std::io::{self, Write};
use core::{slice};
use crate::utils::LockedData;
use lazy_bytes_cast::slice::AsByteSlice;
const HEADER_SIZE: u32 = 14;
#[repr(C)]
#[derive(Clone, Copy)]
struct BmpHeader {
signature: u16,
size: u32,
reserved: u32,
offset: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
struct Bmp {
header: BmpHeader,
dib: *const winapi::um::wingdi::BITMAPINFOHEADER
}
pub struct Image {
bmp: Bmp,
_guard: LockedData,
}
impl Image {
pub(crate) fn from_handle(handle: *mut c_void) -> io::Result<Self> {
let (data, _guard) = LockedData::new(handle)?;
let dib = data.as_ptr();
let mut bmp = Bmp {
header: BmpHeader {
signature: 0x4D42,
size: 0,
reserved: 0,
offset: 0
},
dib,
};
bmp.header.offset = unsafe {
HEADER_SIZE + (*dib).biSize
};
bmp.header.size = unsafe {
(*bmp.dib).biSizeImage + bmp.header.offset
};
Ok(Self {
bmp,
_guard
})
}
pub fn as_bytes(&self) -> &[u8] {
let size = unsafe { winapi::um::winbase::GlobalSize(self._guard.0) };
let data_ptr = self.bmp.dib as *const u8;
unsafe {
slice::from_raw_parts(data_ptr, size)
}
}
#[inline]
pub fn size(&self) -> usize {
self.bmp.header.size as usize
}
pub fn write<W: Write>(&self, storage: &mut W) -> io::Result<usize> {
storage.write_all(self.bmp.header.signature.as_slice())?;
storage.write_all(self.bmp.header.size.as_slice())?;
storage.write_all(self.bmp.header.reserved.as_slice())?;
storage.write_all(self.bmp.header.offset.as_slice())?;
let dib = unsafe {
&*self.bmp.dib
};
storage.write_all(dib.biSize.as_slice())?;
storage.write_all(dib.biWidth.as_slice())?;
storage.write_all(dib.biHeight.as_slice())?;
storage.write_all(dib.biPlanes.as_slice())?;
storage.write_all(dib.biBitCount.as_slice())?;
storage.write_all(dib.biCompression.as_slice())?;
storage.write_all(dib.biSizeImage.as_slice())?;
storage.write_all(dib.biXPelsPerMeter.as_slice())?;
storage.write_all(dib.biYPelsPerMeter.as_slice())?;
storage.write_all(dib.biClrUsed.as_slice())?;
storage.write_all(dib.biClrImportant.as_slice())?;
let image_data = unsafe {
let image_ptr = self.bmp.dib.add(1) as *const u8;
slice::from_raw_parts(image_ptr, dib.biSizeImage as usize)
};
storage.write_all(image_data)?;
Ok(self.size())
}
pub fn to_vec(&self) -> Vec<u8> {
let mut data = Vec::with_capacity(self.size());
let _ = self.write(&mut data);
data
}
}