use crate::bindgen::{
fpdf_page_t__, FPDF_DOCUMENT, FPDF_IMAGEOBJ_METADATA, FPDF_PAGE, FPDF_PAGEOBJECT,
};
use crate::bindings::PdfiumLibraryBindings;
use crate::error::{PdfiumError, PdfiumInternalError};
use crate::pdf::bitmap::PdfBitmap;
use crate::pdf::bitmap::Pixels;
use crate::pdf::color_space::PdfColorSpace;
use crate::pdf::document::page::object::private::internal::PdfPageObjectPrivate;
use crate::pdf::document::page::object::PdfPageObjectOwnership;
use crate::pdf::document::PdfDocument;
use crate::pdf::matrix::{PdfMatrix, PdfMatrixValue};
use crate::pdf::points::PdfPoints;
use crate::pdfium::PdfiumLibraryBindingsAccessor;
use crate::utils::mem::create_byte_buffer;
use crate::{create_transform_getters, create_transform_setters};
use std::convert::TryInto;
use std::marker::PhantomData;
use std::ops::{Range, RangeInclusive};
use std::os::raw::{c_int, c_void};
#[cfg(not(target_arch = "wasm32"))]
use {
crate::utils::files::get_pdfium_file_accessor_from_reader,
std::fs::File,
std::io::{Read, Seek},
std::path::Path,
};
#[cfg(feature = "image_api")]
use {
crate::pdf::bitmap::PdfBitmapFormat,
crate::utils::pixels::{
aligned_bgr_to_rgba, aligned_grayscale_to_unaligned, bgra_to_rgba, rgba_to_bgra,
},
};
#[cfg(feature = "image_025")]
use image_025::{DynamicImage, EncodableLayout, GrayImage, RgbaImage};
#[cfg(feature = "image_024")]
use image_024::{DynamicImage, EncodableLayout, GrayImage, RgbaImage};
#[cfg(feature = "image_023")]
use image_023::{DynamicImage, EncodableLayout, GenericImageView, GrayImage, RgbaImage};
#[cfg(doc)]
use {
crate::pdf::document::page::object::PdfPageObject,
crate::pdf::document::page::object::PdfPageObjectType,
crate::pdf::document::page::objects::common::PdfPageObjectsCommon,
crate::pdf::document::page::PdfPage,
};
pub struct PdfPageImageObject<'a> {
object_handle: FPDF_PAGEOBJECT,
ownership: PdfPageObjectOwnership,
lifetime: PhantomData<&'a FPDF_PAGEOBJECT>,
}
impl<'a> PdfPageImageObject<'a> {
#[inline]
pub(crate) fn from_pdfium(
object_handle: FPDF_PAGEOBJECT,
ownership: PdfPageObjectOwnership,
) -> Self {
PdfPageImageObject {
object_handle,
ownership,
lifetime: PhantomData,
}
}
#[cfg(feature = "image_api")]
#[inline]
pub fn new(document: &PdfDocument<'a>, image: &DynamicImage) -> Result<Self, PdfiumError> {
let mut result = Self::new_from_handle(document.handle(), document.bindings());
if let Ok(result) = result.as_mut() {
result.set_image(image)?;
}
result
}
#[cfg(not(feature = "image_api"))]
pub fn new(document: &PdfDocument<'a>) -> Result<Self, PdfiumError> {
Self::new_from_handle(document.handle(), document.bindings())
}
#[cfg(not(target_arch = "wasm32"))]
pub fn new_from_jpeg_file(
document: &PdfDocument<'a>,
path: &(impl AsRef<Path> + ?Sized),
) -> Result<Self, PdfiumError> {
Self::new_from_jpeg_reader(document, File::open(path).map_err(PdfiumError::IoError)?)
}
#[cfg(not(target_arch = "wasm32"))]
pub fn new_from_jpeg_reader<R: Read + Seek>(
document: &PdfDocument<'a>,
reader: R,
) -> Result<Self, PdfiumError> {
let object = Self::new_from_handle(document.handle(), document.bindings())?;
let mut reader = get_pdfium_file_accessor_from_reader(reader);
let result = unsafe {
document.bindings().FPDFImageObj_LoadJpegFileInline(
std::ptr::null_mut(),
0,
object.object_handle(),
reader.as_fpdf_file_access_mut_ptr(),
)
};
if object.bindings().is_true(result) {
Ok(object)
} else {
Err(PdfiumError::PdfiumLibraryInternalError(
PdfiumInternalError::Unknown,
))
}
}
pub(crate) fn new_from_handle(
document: FPDF_DOCUMENT,
bindings: &'a dyn PdfiumLibraryBindings,
) -> Result<Self, PdfiumError> {
let handle = unsafe { bindings.FPDFPageObj_NewImageObj(document) };
if handle.is_null() {
Err(PdfiumError::PdfiumLibraryInternalError(
PdfiumInternalError::Unknown,
))
} else {
Ok(PdfPageImageObject {
object_handle: handle,
ownership: PdfPageObjectOwnership::unowned(),
lifetime: PhantomData,
})
}
}
#[cfg(feature = "image_api")]
pub fn new_with_width(
document: &PdfDocument<'a>,
image: &DynamicImage,
width: PdfPoints,
) -> Result<Self, PdfiumError> {
let aspect_ratio = image.height() as f32 / image.width() as f32;
let height = width * aspect_ratio;
Self::new_with_size(document, image, width, height)
}
#[cfg(feature = "image_api")]
pub fn new_with_height(
document: &'a PdfDocument<'a>,
image: &DynamicImage,
height: PdfPoints,
) -> Result<Self, PdfiumError> {
let aspect_ratio = image.height() as f32 / image.width() as f32;
let width = height / aspect_ratio;
Self::new_with_size(document, image, width, height)
}
#[cfg(feature = "image_api")]
#[inline]
pub fn new_with_size(
document: &PdfDocument<'a>,
image: &DynamicImage,
width: PdfPoints,
height: PdfPoints,
) -> Result<Self, PdfiumError> {
let mut result = Self::new(document, image)?;
result.scale(width.value, height.value)?;
Ok(result)
}
pub fn get_raw_bitmap(&self) -> Result<PdfBitmap<'_>, PdfiumError> {
Ok(PdfBitmap::from_pdfium(unsafe {
self.bindings().FPDFImageObj_GetBitmap(self.object_handle())
}))
}
#[cfg(feature = "image_api")]
#[inline]
pub fn get_raw_image(&self) -> Result<DynamicImage, PdfiumError> {
self.get_image_from_bitmap(&self.get_raw_bitmap()?)
}
#[inline]
pub fn get_processed_bitmap(
&self,
document: &PdfDocument,
) -> Result<PdfBitmap<'_>, PdfiumError> {
let (width, height) = self.get_current_width_and_height_from_metadata()?;
self.get_processed_bitmap_with_size(document, width, height)
}
#[cfg(feature = "image_api")]
#[inline]
pub fn get_processed_image(&self, document: &PdfDocument) -> Result<DynamicImage, PdfiumError> {
let (width, height) = self.get_current_width_and_height_from_metadata()?;
self.get_processed_image_with_size(document, width, height)
}
#[inline]
pub fn get_processed_bitmap_with_width(
&self,
document: &PdfDocument,
width: Pixels,
) -> Result<PdfBitmap<'_>, PdfiumError> {
let (current_width, current_height) = self.get_current_width_and_height_from_metadata()?;
let aspect_ratio = current_width as f32 / current_height as f32;
self.get_processed_bitmap_with_size(
document,
width,
((width as f32 / aspect_ratio) as u32)
.try_into()
.map_err(|_| PdfiumError::ImageSizeOutOfBounds)?,
)
}
#[cfg(feature = "image_api")]
#[inline]
pub fn get_processed_image_with_width(
&self,
document: &PdfDocument,
width: Pixels,
) -> Result<DynamicImage, PdfiumError> {
let (current_width, current_height) = self.get_current_width_and_height_from_metadata()?;
let aspect_ratio = current_width as f32 / current_height as f32;
self.get_processed_image_with_size(
document,
width,
((width as f32 / aspect_ratio) as u32)
.try_into()
.map_err(|_| PdfiumError::ImageSizeOutOfBounds)?,
)
}
#[inline]
pub fn get_processed_bitmap_with_height(
&self,
document: &PdfDocument,
height: Pixels,
) -> Result<PdfBitmap<'_>, PdfiumError> {
let (current_width, current_height) = self.get_current_width_and_height_from_metadata()?;
let aspect_ratio = current_width as f32 / current_height as f32;
self.get_processed_bitmap_with_size(
document,
((height as f32 * aspect_ratio) as u32)
.try_into()
.map_err(|_| PdfiumError::ImageSizeOutOfBounds)?,
height,
)
}
#[cfg(feature = "image_api")]
#[inline]
pub fn get_processed_image_with_height(
&self,
document: &PdfDocument,
height: Pixels,
) -> Result<DynamicImage, PdfiumError> {
let (current_width, current_height) = self.get_current_width_and_height_from_metadata()?;
let aspect_ratio = current_width as f32 / current_height as f32;
self.get_processed_image_with_size(
document,
((height as f32 * aspect_ratio) as u32)
.try_into()
.map_err(|_| PdfiumError::ImageSizeOutOfBounds)?,
height,
)
}
pub fn get_processed_bitmap_with_size(
&self,
document: &PdfDocument,
width: Pixels,
height: Pixels,
) -> Result<PdfBitmap<'_>, PdfiumError> {
let mut matrix = self.matrix()?;
let original_matrix = matrix;
if matrix.a() < 0f32 {
matrix.set_a(-matrix.a());
self.reset_matrix_impl(matrix)?;
}
if matrix.d() < 0f32 {
matrix.set_d(-matrix.d());
self.reset_matrix_impl(matrix)?;
}
let page_handle = match self.ownership() {
PdfPageObjectOwnership::Page(ownership) => Some(ownership.page_handle()),
PdfPageObjectOwnership::AttachedAnnotation(ownership) => Some(ownership.page_handle()),
_ => None,
};
let bitmap_handle = match page_handle {
Some(page_handle) => unsafe {
self.bindings().FPDFImageObj_GetRenderedBitmap(
document.handle(),
page_handle,
self.object_handle(),
)
},
None => unsafe {
self.bindings().FPDFImageObj_GetRenderedBitmap(
document.handle(),
std::ptr::null_mut::<fpdf_page_t__>(),
self.object_handle(),
)
},
};
if bitmap_handle.is_null() {
self.reset_matrix_impl(original_matrix)?;
return Err(PdfiumError::PdfiumLibraryInternalError(
PdfiumInternalError::Unknown,
));
}
let result = PdfBitmap::from_pdfium(bitmap_handle);
if width == result.width() && height == result.height() {
self.reset_matrix_impl(original_matrix)?;
Ok(result)
} else {
self.transform_impl(
width as PdfMatrixValue / result.width() as PdfMatrixValue,
0.0,
0.0,
height as PdfMatrixValue / result.height() as PdfMatrixValue,
0.0,
0.0,
)?;
let result = PdfBitmap::from_pdfium(match page_handle {
Some(page_handle) => unsafe {
self.bindings().FPDFImageObj_GetRenderedBitmap(
document.handle(),
page_handle,
self.object_handle(),
)
},
None => unsafe {
self.bindings().FPDFImageObj_GetRenderedBitmap(
document.handle(),
std::ptr::null_mut::<fpdf_page_t__>(),
self.object_handle(),
)
},
});
self.reset_matrix_impl(original_matrix)?;
Ok(result)
}
}
#[cfg(feature = "image_api")]
#[inline]
pub fn get_processed_image_with_size(
&self,
document: &PdfDocument,
width: Pixels,
height: Pixels,
) -> Result<DynamicImage, PdfiumError> {
self.get_processed_bitmap_with_size(document, width, height)
.and_then(|bitmap| self.get_image_from_bitmap(&bitmap))
}
#[cfg(feature = "image_api")]
pub(crate) fn get_image_from_bitmap(
&self,
bitmap: &PdfBitmap,
) -> Result<DynamicImage, PdfiumError> {
let handle = bitmap.handle();
let width = unsafe { self.bindings().FPDFBitmap_GetWidth(handle) };
let height = unsafe { self.bindings().FPDFBitmap_GetHeight(handle) };
let stride = unsafe { self.bindings().FPDFBitmap_GetStride(handle) };
let format =
PdfBitmapFormat::from_pdfium(
unsafe { self.bindings().FPDFBitmap_GetFormat(handle) } as u32
)?;
#[cfg(not(target_arch = "wasm32"))]
let buffer = unsafe { self.bindings().FPDFBitmap_GetBuffer_as_slice(handle) };
#[cfg(target_arch = "wasm32")]
let buffer_vec = unsafe { self.bindings().FPDFBitmap_GetBuffer_as_vec(handle) };
#[cfg(target_arch = "wasm32")]
let buffer = buffer_vec.as_slice();
match format {
#[allow(deprecated)]
PdfBitmapFormat::BGRA | PdfBitmapFormat::BGRx => {
RgbaImage::from_raw(width as u32, height as u32, bgra_to_rgba(buffer))
.map(DynamicImage::ImageRgba8)
}
PdfBitmapFormat::BGR => RgbaImage::from_raw(
width as u32,
height as u32,
aligned_bgr_to_rgba(buffer, width as usize, stride as usize),
)
.map(DynamicImage::ImageRgba8),
PdfBitmapFormat::Gray => GrayImage::from_raw(
width as u32,
height as u32,
aligned_grayscale_to_unaligned(buffer, width as usize, stride as usize),
)
.map(DynamicImage::ImageLuma8),
}
.ok_or(PdfiumError::ImageError)
}
pub fn get_raw_image_data(&self) -> Result<Vec<u8>, PdfiumError> {
let buffer_length = unsafe {
self.bindings().FPDFImageObj_GetImageDataRaw(
self.object_handle(),
std::ptr::null_mut(),
0,
)
};
if buffer_length == 0 {
return Ok(Vec::new());
}
let mut buffer = create_byte_buffer(buffer_length as usize);
let result = unsafe {
self.bindings().FPDFImageObj_GetImageDataRaw(
self.object_handle(),
buffer.as_mut_ptr() as *mut c_void,
buffer_length,
)
};
assert_eq!(result, buffer_length);
Ok(buffer)
}
pub(crate) fn get_current_width_and_height_from_metadata(
&self,
) -> Result<(Pixels, Pixels), PdfiumError> {
let width = self.get_raw_metadata().and_then(|metadata| {
metadata
.width
.try_into()
.map_err(|_| PdfiumError::ImageSizeOutOfBounds)
})?;
let height = self.get_raw_metadata().and_then(|metadata| {
metadata
.height
.try_into()
.map_err(|_| PdfiumError::ImageSizeOutOfBounds)
})?;
Ok((width, height))
}
#[inline]
pub fn width(&self) -> Result<Pixels, PdfiumError> {
self.get_current_width_and_height_from_metadata()
.map(|(width, _height)| width)
}
#[inline]
pub fn height(&self) -> Result<Pixels, PdfiumError> {
self.get_current_width_and_height_from_metadata()
.map(|(_width, height)| height)
}
#[cfg(feature = "image_api")]
pub fn set_image(&mut self, image: &DynamicImage) -> Result<(), PdfiumError> {
let width: Pixels = image
.width()
.try_into()
.map_err(|_| PdfiumError::ImageSizeOutOfBounds)?;
let height: Pixels = image
.height()
.try_into()
.map_err(|_| PdfiumError::ImageSizeOutOfBounds)?;
let bitmap = PdfBitmap::empty(width, height, PdfBitmapFormat::BGRA, self.bindings())?;
let buffer = if let Some(image) = image.as_rgba8() {
rgba_to_bgra(image.as_bytes())
} else {
let image = image.to_rgba8();
rgba_to_bgra(image.as_bytes())
};
if !(unsafe {
self.bindings()
.FPDFBitmap_SetBuffer(bitmap.handle(), buffer.as_slice())
}) {
return Err(PdfiumError::PdfiumLibraryInternalError(
PdfiumInternalError::Unknown,
));
}
self.set_bitmap(&bitmap)
}
pub fn set_bitmap(&mut self, bitmap: &PdfBitmap) -> Result<(), PdfiumError> {
if self.bindings().is_true(unsafe {
self.bindings().FPDFImageObj_SetBitmap(
std::ptr::null_mut::<FPDF_PAGE>(),
0,
self.object_handle(),
bitmap.handle(),
)
}) {
Ok(())
} else {
Err(PdfiumError::PdfiumLibraryInternalError(
PdfiumInternalError::Unknown,
))
}
}
pub(crate) fn get_raw_metadata(&self) -> Result<FPDF_IMAGEOBJ_METADATA, PdfiumError> {
let mut metadata = FPDF_IMAGEOBJ_METADATA {
width: 0,
height: 0,
horizontal_dpi: 0.0,
vertical_dpi: 0.0,
bits_per_pixel: 0,
colorspace: 0,
marked_content_id: 0,
};
let page_handle = match self.ownership() {
PdfPageObjectOwnership::Page(ownership) => Some(ownership.page_handle()),
PdfPageObjectOwnership::AttachedAnnotation(ownership) => Some(ownership.page_handle()),
_ => None,
};
let result = unsafe {
self.bindings().FPDFImageObj_GetImageMetadata(
self.object_handle(),
match page_handle {
Some(page_handle) => page_handle,
None => std::ptr::null_mut::<fpdf_page_t__>(),
},
&mut metadata,
)
};
if self.bindings().is_true(result) {
Ok(metadata)
} else {
Err(PdfiumError::PdfiumLibraryInternalError(
PdfiumInternalError::Unknown,
))
}
}
#[inline]
pub fn horizontal_dpi(&self) -> Result<f32, PdfiumError> {
self.get_raw_metadata()
.map(|metadata| metadata.horizontal_dpi)
}
#[inline]
pub fn vertical_dpi(&self) -> Result<f32, PdfiumError> {
self.get_raw_metadata()
.map(|metadata| metadata.vertical_dpi)
}
#[inline]
pub fn bits_per_pixel(&self) -> Result<u8, PdfiumError> {
self.get_raw_metadata()
.map(|metadata| metadata.bits_per_pixel as u8)
}
#[inline]
pub fn color_space(&self) -> Result<PdfColorSpace, PdfiumError> {
self.get_raw_metadata()
.and_then(|metadata| PdfColorSpace::from_pdfium(metadata.colorspace as u32))
}
#[inline]
pub fn filters(&self) -> PdfPageImageObjectFilters<'_> {
PdfPageImageObjectFilters::new(self)
}
create_transform_setters!(
&mut Self,
Result<(), PdfiumError>,
"this [PdfPageImageObject]",
"this [PdfPageImageObject].",
"this [PdfPageImageObject],"
);
create_transform_getters!(
"this [PdfPageImageObject]",
"this [PdfPageImageObject].",
"this [PdfPageImageObject],"
);
}
impl<'a> PdfPageObjectPrivate<'a> for PdfPageImageObject<'a> {
#[inline]
fn object_handle(&self) -> FPDF_PAGEOBJECT {
self.object_handle
}
#[inline]
fn ownership(&self) -> &PdfPageObjectOwnership {
&self.ownership
}
#[inline]
fn set_ownership(&mut self, ownership: PdfPageObjectOwnership) {
self.ownership = ownership;
}
}
impl<'a> Drop for PdfPageImageObject<'a> {
fn drop(&mut self) {
self.drop_impl();
}
}
impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfPageImageObject<'a> {}
#[cfg(feature = "thread_safe")]
unsafe impl<'a> Send for PdfPageImageObject<'a> {}
#[cfg(feature = "thread_safe")]
unsafe impl<'a> Sync for PdfPageImageObject<'a> {}
pub type PdfPageImageObjectFilterIndex = usize;
pub struct PdfPageImageObjectFilters<'a> {
object: &'a PdfPageImageObject<'a>,
}
impl<'a> PdfPageImageObjectFilters<'a> {
#[inline]
pub(crate) fn new(object: &'a PdfPageImageObject<'a>) -> Self {
PdfPageImageObjectFilters { object }
}
pub fn len(&self) -> usize {
(unsafe {
self.object
.bindings()
.FPDFImageObj_GetImageFilterCount(self.object.object_handle())
}) as usize
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn as_range(&self) -> Range<PdfPageImageObjectFilterIndex> {
0..self.len()
}
#[inline]
pub fn as_range_inclusive(&self) -> RangeInclusive<PdfPageImageObjectFilterIndex> {
if self.is_empty() {
0..=0
} else {
0..=(self.len() - 1)
}
}
pub fn get(
&self,
index: PdfPageImageObjectFilterIndex,
) -> Result<PdfPageImageObjectFilter, PdfiumError> {
if index >= self.len() {
return Err(PdfiumError::ImageObjectFilterIndexOutOfBounds);
}
let buffer_length = unsafe {
self.object.bindings().FPDFImageObj_GetImageFilter(
self.object.object_handle(),
index as c_int,
std::ptr::null_mut(),
0,
)
};
if buffer_length == 0 {
return Err(PdfiumError::ImageObjectFilterIndexInBoundsButFilterUndefined);
}
let mut buffer = create_byte_buffer(buffer_length as usize);
let result = unsafe {
self.object.bindings().FPDFImageObj_GetImageFilter(
self.object.object_handle(),
index as c_int,
buffer.as_mut_ptr() as *mut c_void,
buffer_length,
)
};
assert_eq!(result, buffer_length);
Ok(PdfPageImageObjectFilter::new(
String::from_utf8(buffer)
.map(|str| str.trim_end_matches(char::from(0)).to_owned())
.unwrap_or_default(),
))
}
#[inline]
pub fn iter(&self) -> PdfPageImageObjectFiltersIterator<'_> {
PdfPageImageObjectFiltersIterator::new(self)
}
}
pub struct PdfPageImageObjectFilter {
name: String,
}
impl PdfPageImageObjectFilter {
#[inline]
pub(crate) fn new(name: String) -> Self {
PdfPageImageObjectFilter { name }
}
pub fn name(&self) -> &str {
self.name.as_str()
}
}
pub struct PdfPageImageObjectFiltersIterator<'a> {
filters: &'a PdfPageImageObjectFilters<'a>,
next_index: PdfPageImageObjectFilterIndex,
}
impl<'a> PdfPageImageObjectFiltersIterator<'a> {
#[inline]
pub(crate) fn new(filters: &'a PdfPageImageObjectFilters<'a>) -> Self {
PdfPageImageObjectFiltersIterator {
filters,
next_index: 0,
}
}
}
impl<'a> Iterator for PdfPageImageObjectFiltersIterator<'a> {
type Item = PdfPageImageObjectFilter;
fn next(&mut self) -> Option<Self::Item> {
let next = self.filters.get(self.next_index);
self.next_index += 1;
next.ok()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::*;
use crate::utils::test::test_bind_to_pdfium;
#[test]
fn test_page_image_object_retains_format() -> Result<(), PdfiumError> {
let pdfium = test_bind_to_pdfium();
let image = pdfium
.load_pdf_from_file("./test/path-test.pdf", None)?
.pages()
.get(0)?
.render_with_config(&PdfRenderConfig::new().set_target_width(1000))?
.as_image()?;
let mut document = pdfium.create_new_pdf()?;
let mut page = document
.pages_mut()
.create_page_at_end(PdfPagePaperSize::a4())?;
let object = page.objects_mut().create_image_object(
PdfPoints::new(100.0),
PdfPoints::new(100.0),
&image,
Some(PdfPoints::new(image.width() as f32)),
Some(PdfPoints::new(image.height() as f32)),
)?;
let raw_image = object.as_image_object().unwrap().get_raw_image()?;
let processed_image = object
.as_image_object()
.unwrap()
.get_processed_image(&document)?;
assert!(compare_equality_of_byte_arrays(
image.as_bytes(),
raw_image.into_rgba8().as_raw().as_slice()
));
assert!(compare_equality_of_byte_arrays(
image.as_bytes(),
processed_image.into_rgba8().as_raw().as_slice()
));
Ok(())
}
fn compare_equality_of_byte_arrays(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false;
}
for index in 0..a.len() {
if a[index] != b[index] {
return false;
}
}
true
}
#[test]
fn test_image_scaling_keeps_aspect_ratio() -> Result<(), PdfiumError> {
let pdfium = test_bind_to_pdfium();
let mut document = pdfium.create_new_pdf()?;
let mut page = document
.pages_mut()
.create_page_at_end(PdfPagePaperSize::a4())?;
let image = DynamicImage::new_rgb8(100, 200);
let object = page.objects_mut().create_image_object(
PdfPoints::new(0.0),
PdfPoints::new(0.0),
&image,
Some(PdfPoints::new(image.width() as f32)),
Some(PdfPoints::new(image.height() as f32)),
)?;
let image_object = object.as_image_object().unwrap();
assert_eq!(
image_object
.get_processed_bitmap_with_width(&document, 50)?
.height(),
100
);
assert_eq!(
image_object
.get_processed_image_with_width(&document, 50)?
.height(),
100
);
assert_eq!(
image_object
.get_processed_bitmap_with_height(&document, 50)?
.width(),
25
);
assert_eq!(
image_object
.get_processed_image_with_height(&document, 50)?
.width(),
25
);
Ok(())
}
}