Skip to content

Instantly share code, notes, and snippets.

@gyk
Created December 24, 2021 03:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gyk/3d97c516ae0aa7bcd745fff10e21c825 to your computer and use it in GitHub Desktop.
Save gyk/3d97c516ae0aa7bcd745fff10e21c825 to your computer and use it in GitHub Desktop.
Code snippet for loading and resize images
// Improvements over NWG's built-in implementation:
//
// - High quality interpolation mode
// - Crop non-square images
fn load_and_resize_image(decoder: &nwg::ImageDecoder, data: &[u8]) -> Result<Bitmap> {
use winapi::shared::windef::{HBITMAP, HDC};
use winapi::um::wincodec::{
IWICBitmapScaler, IWICBitmapSource, WICBitmapInterpolationModeHighQualityCubic,
};
use winapi::um::wingdi::{
BitBlt, CreateCompatibleBitmap, CreateCompatibleDC, DeleteDC, SelectObject, SRCCOPY,
};
let image_frame = decoder.from_stream(data)?.frame(0)?;
// Resize
let (w, h) = image_frame.size();
let thumb_size = scaled_thumb_size();
let (w, h) = if w >= h {
(thumb_size * w / h, thumb_size)
} else {
(thumb_size, thumb_size * h / w)
};
let bitmap = unsafe {
let mut scaler: *mut IWICBitmapScaler = ptr::null_mut();
(&*decoder.factory).CreateBitmapScaler(&mut scaler);
let image_source = image_frame.frame as *const IWICBitmapSource;
(&*scaler).Initialize(
image_source,
w,
h,
WICBitmapInterpolationModeHighQualityCubic,
);
nwg::ImageData {
frame: scaler as *mut IWICBitmapSource,
}
.as_bitmap()?
};
if w == thumb_size && h == thumb_size {
return Ok(bitmap);
}
// Crop
unsafe {
let hdc_null: HDC = mem::zeroed();
let hdc_src = CreateCompatibleDC(hdc_null);
let bmp_src = bitmap.handle;
SelectObject(hdc_src, bmp_src);
let hdc_dst = CreateCompatibleDC(hdc_null);
let bmp_dst: HBITMAP =
CreateCompatibleBitmap(hdc_src, thumb_size as i32, thumb_size as i32);
SelectObject(hdc_dst, bmp_dst as *mut _);
BitBlt(
hdc_dst,
0,
0,
thumb_size as i32,
thumb_size as i32,
hdc_src,
(w - thumb_size) as i32 / 2,
(h - thumb_size) as i32 / 2,
SRCCOPY,
);
DeleteDC(hdc_src);
DeleteDC(hdc_dst);
#[allow(dead_code)]
struct MyBitmap {
handle: *mut std::ffi::c_void,
owned: bool,
}
let my_bmp = MyBitmap {
handle: bmp_dst as *mut _,
owned: true,
};
let bmp: Bitmap = mem::transmute(my_bmp);
Ok(bmp)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment