Created
December 24, 2021 03:19
-
-
Save gyk/3d97c516ae0aa7bcd745fff10e21c825 to your computer and use it in GitHub Desktop.
Code snippet for loading and resize images
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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