I try to load images from the IStream and render them onto a dc. The code below works fine
pub fn to_GDI_bitmap(&mut self, ctx: *mut HDC__, hMEM_BUFF: &MEM_BUFF, (flip_hor, flip_vert): (bool, bool)) -> *mut HBITMAP__ {
let hStream: HIStream = unsafe {
SHCreateMemStream(hMEM_BUFF.get_buf_ptr(), hMEM_BUFF.get_size() as u32)
};
self.reset_converter();
let decoder: *mut IWICBitmapDecoder = unsafe {
let mut ret: *mut IWICBitmapDecoder = zeroed() ;
let hr = self.factory
.as_ref()
.unwrap()
.CreateDecoderFromStream(
hStream,
null_mut(),
WICDecodeMetadataCacheOnDemand, &mut ret as *mut *mut IWICBitmapDecoder,
);
assert_eq!(hr, S_OK);
ret
};
let frame = unsafe {
let mut pFrame: *mut IWICBitmapFrameDecode = zeroed();
let hr = decoder.as_ref()
.unwrap().GetFrame(
{
let mut idx: UINT = zeroed();
let hr = decoder.as_ref()
.unwrap()
.GetFrameCount(&mut idx as *mut UINT);
assert_eq!(hr, S_OK);
idx-1
},
&mut pFrame as *mut *mut IWICBitmapFrameDecode
);
assert_eq!(hr, S_OK);
pFrame
};
let (width, height) = unsafe {
let (mut width, mut height): (UINT, UINT) = (0, 0);
frame.as_ref().unwrap().GetSize(&mut width as *mut UINT, &mut height as *mut UINT);
(width, height)
};
let hr = unsafe {
self.fmt_converter
.as_ref()
.unwrap()
.Initialize(
&**frame
.as_ref()
.unwrap() as *const IWICBitmapSource,
&GUID_WICPixelFormat24bppBGR,
WICBitmapDitherTypeNone,
null_mut(),
0.0 as c_double,
WICBitmapPaletteTypeMedianCut
)
};
assert_eq!(hr, S_OK);
let flip = |thing: u32| {
let mut pFlipRotator: *mut IWICBitmapFlipRotator = unsafe { zeroed() };
let hr = unsafe {
self.factory.as_ref().unwrap().CreateBitmapFlipRotator(
&mut pFlipRotator as *mut *mut IWICBitmapFlipRotator
)
};
assert_eq!(hr, S_OK);
assert!(!pFlipRotator.is_null());
let hr = unsafe {
pFlipRotator
.as_ref()
.unwrap()
.Initialize(
&**frame
.as_ref()
.unwrap() as *const IWICBitmapSource,
thing,
)
};
assert_eq!(hr, S_OK);
};
if flip_hor {
flip(0x00000008);
}
if flip_vert {
flip(0x00000010);
}
let mut buff = unsafe {
let mut buff: Vec<u8> = Vec::with_capacity(width as usize * height as usize * 3);
buff.fill(0);
let rect: WICRect = WICRect {
X: 0,
Y: 0,
Width: width as i32,
Height: height as i32,
};
let hr = frame
.as_ref()
.unwrap()
.CopyPixels(
&rect,
width * 3,
width * height * 3,
buff.as_mut_ptr()
);
assert_eq!(hr, S_OK);
buff
};
unsafe {
let bmp_iheader: BITMAPINFOHEADER = BITMAPINFOHEADER {
biSize: size_of::<BITMAPINFOHEADER>() as u32,
biWidth: width as i32,
biHeight: height as i32,
biPlanes: 1,
biBitCount: 24,
biCompression: BI_RGB,
biSizeImage: 0,
biXPelsPerMeter: GetDeviceCaps(ctx, HORZRES),
biYPelsPerMeter: GetDeviceCaps(ctx, VERTRES),
biClrUsed: 0,
biClrImportant: 0
};
let bmp_i: BITMAPINFO = BITMAPINFO {
bmiHeader: bmp_iheader.clone(),
bmiColors: [RGBQUAD::default();1],
};
CreateDIBitmap(ctx,
&bmp_iheader,
CBM_INIT,
buff.as_ptr() as *const _ as *const c_void,
&bmp_i,
DIB_RGB_COLORS)
}
}
pub fn transfer(&self, srcBmp: *mut HBITMAP__ , destDC: *mut HDC__, (x, y): (c_int, c_int), size: SIZE) {
let temp_dc = unsafe { CreateCompatibleDC(null_mut()) };
unsafe {
DeleteObject(SelectObject(temp_dc, srcBmp as HGDIOBJ));
};
let outcome: BOOL = unsafe {
GdiTransparentBlt(destDC,
x.into(),
y.into(),
size.cx,
size.cy,
temp_dc,
0,
0,
size.cx,
size.cy,
RGB(255, 255, 255),
)
};
assert!(outcome.is_positive());
let outcome: BOOL = unsafe { DeleteDC(temp_dc) };
}
except for the fact that the rendered image is flipped upside down like so:
As you see in the code I've tried to implement a system to flip the images to make a "dirty" fix which weirdly doesn't seem to result in any visible effect (that probably indicates that something is wrong - but If I could figure that out, I wouldn't be asking it here).
Another thing I tried to resolve the bug is to reverse the pixel buffer used to copy pixels from WICFrameDecode onto DIBitmap.