use super::*;
impl<'a> VipsImage<'a> {
pub fn tile_size(&self) -> Option<(u32, u32)> {
let (width, height) = unsafe {
(
vips_sys::vips_image_get_tile_width(self.as_ptr()),
vips_sys::vips_image_get_tile_height(self.as_ptr()),
)
};
(width > 0 && height > 0).then_some((width as u32, height as u32))
}
pub fn gainmap(&self) -> Result<Option<VipsImage<'a>>> {
let present = unsafe {
vips_sys::vips_image_get_typeof(self.as_ptr(), c"gainmap".as_ptr()) != 0
|| vips_sys::vips_image_get_typeof(self.as_ptr(), c"gainmap-data".as_ptr()) != 0
};
if !present {
return Ok(None);
}
result(unsafe { vips_sys::vips_image_get_gainmap(self.as_ptr()) }).map(Some)
}
pub fn dcrawload_file(path: impl AsRef<Path>) -> Result<VipsImage<'static>> {
let path = path_to_cstring(path.as_ref())?;
let mut out = null_mut();
let rc =
unsafe { vips_sys::vips_dcrawload(path.as_ptr(), &mut out, null() as *const c_char) };
result_with_ret(out, rc)
}
pub fn dcrawload_buffer(buf: &'a [u8]) -> Result<VipsImage<'a>> {
let mut out = null_mut();
let rc = unsafe {
vips_sys::vips_dcrawload_buffer(
buf.as_ptr().cast_mut().cast(),
buf.len(),
&mut out,
null() as *const c_char,
)
};
result_with_ret(out, rc)
}
pub fn uhdrload_file(path: impl AsRef<Path>) -> Result<VipsImage<'static>> {
let path = path_to_cstring(path.as_ref())?;
let mut out = null_mut();
let rc =
unsafe { vips_sys::vips_uhdrload(path.as_ptr(), &mut out, null() as *const c_char) };
result_with_ret(out, rc)
}
pub fn uhdrload_buffer(buf: &'a [u8]) -> Result<VipsImage<'a>> {
let mut out = null_mut();
let rc = unsafe {
vips_sys::vips_uhdrload_buffer(
buf.as_ptr().cast_mut().cast(),
buf.len(),
&mut out,
null() as *const c_char,
)
};
result_with_ret(out, rc)
}
pub fn write_uhdr(&self, path: impl AsRef<Path>, quality: i32) -> Result<()> {
validate_quality(quality)?;
let path = path_to_cstring(path.as_ref())?;
let rc = unsafe {
vips_sys::vips_uhdrsave(
self.as_ptr(),
path.as_ptr(),
c"Q".as_ptr(),
quality,
null() as *const c_char,
)
};
ffi::ret_to_result(rc)
}
pub fn write_uhdr_buffer(&self, quality: i32) -> Result<crate::VipsOwnedBuffer> {
validate_quality(quality)?;
let mut ptr = null_mut();
let mut len = 0;
let rc = unsafe {
vips_sys::vips_uhdrsave_buffer(
self.as_ptr(),
&mut ptr,
&mut len,
c"Q".as_ptr(),
quality,
null() as *const c_char,
)
};
let buffer = unsafe { crate::VipsOwnedBuffer::from_raw(ptr, len) }?;
ffi::ret_to_result(rc)?;
Ok(buffer)
}
}
macro_rules! colour_op {
($name:ident, $ffi:ident, $doc:literal) => {
impl<'a> VipsImage<'a> {
#[doc = $doc]
pub fn $name(&self) -> Result<VipsImage<'a>> {
let mut out = null_mut();
let rc =
unsafe { vips_sys::$ffi(self.as_ptr(), &mut out, null() as *const c_char) };
result_with_ret(out, rc)
}
}
};
}
colour_op!(
uhdr2scrgb,
vips_uhdr2scRGB,
"Apply an UltraHDR gainmap and convert to linear scRGB."
);
colour_op!(
oklab2xyz,
vips_Oklab2XYZ,
"Convert Oklab pixels to XYZ (libvips 8.18+)."
);
colour_op!(
xyz2oklab,
vips_XYZ2Oklab,
"Convert XYZ pixels to Oklab (libvips 8.18+)."
);
colour_op!(
oklab2oklch,
vips_Oklab2Oklch,
"Convert Oklab pixels to Oklch (libvips 8.18+)."
);
colour_op!(
oklch2oklab,
vips_Oklch2Oklab,
"Convert Oklch pixels to Oklab (libvips 8.18+)."
);
fn validate_quality(quality: i32) -> Result<()> {
if !(1..=100).contains(&quality) {
return Err(Error::Other("UltraHDR quality must be in 1..=100".into()));
}
Ok(())
}