Description
When using Image::from_bytes() or Image::from_path() with SlideContent::add_image(), the generated PPTX file contains gray placeholder rectangles with a 📷 emoji and filename text, instead of the actual embedded images.
Steps to Reproduce
use ppt_rs::generator::{create_pptx_with_content, Image, SlideContent};
let image_bytes = std::fs::read("photo.png").unwrap();
let img = Image::from_bytes(image_bytes, 7_600_000, 5_700_000, "PNG")
.position(700_000, 1_600_000);
let slide = SlideContent::new("My Slide").add_image(img);
let pptx = create_pptx_with_content("Test", vec![slide]).unwrap();
std::fs::write("output.pptx", pptx).unwrap();
Opening output.pptx in PowerPoint shows a gray rectangle with text 📷 image_xxx.png instead of the actual image.
Root Cause
The library has all the correct building blocks for image embedding, but they are not wired together in the builder pipeline:
-
images_xml.rs — Has correct implementations:
generate_image_xml() — generates proper <p:pic> with <a:blip r:embed="rIdN"/>
generate_image_relationship() — generates image relationship XML
generate_image_content_type() — generates content type entries
-
slide_xml/content.rs — render_additional_content() calls generate_image_placeholder() which creates a gray <p:sp> shape with <a:solidFill><a:srgbClr val="E0E0E0"/> instead of calling generate_image_xml().
-
builder.rs — The builder never:
- Calls
image.get_bytes() to retrieve image data
- Writes image bytes to
ppt/media/imageN.ext in the ZIP
- Adds image relationships (
<Relationship ... Type=".../image" .../>) to slide .rels files
- Adds image content type defaults (
<Default Extension="png" ContentType="image/png"/>) to [Content_Types].xml
Expected Behavior
The generated PPTX should contain:
<p:pic> elements with <a:blip r:embed="rIdN"/> in slide XML (not gray <p:sp> placeholders)
- Actual image bytes in
ppt/media/imageN.ext
- Image relationships in
ppt/slides/_rels/slideN.xml.rels
- Image MIME type entries in
[Content_Types].xml
Suggested Fix
In render_additional_content() (content.rs), replace the call to generate_image_placeholder() with generate_image_xml() from images_xml.rs, and add image embedding logic to builder.rs:
- Replace
generate_image_placeholder() with generate_image_xml() in content.rs
- In
builder.rs, iterate slide images, call image.get_bytes(), and write to ppt/media/
- Add image relationships to each slide's
.rels file (using generate_image_relationship())
- Add image content type defaults to
[Content_Types].xml (using generate_image_content_type())
Environment
- ppt-rs version: 0.2.6
- Rust edition: 2024
Description
When using
Image::from_bytes()orImage::from_path()withSlideContent::add_image(), the generated PPTX file contains gray placeholder rectangles with a 📷 emoji and filename text, instead of the actual embedded images.Steps to Reproduce
Opening
output.pptxin PowerPoint shows a gray rectangle with text📷 image_xxx.pnginstead of the actual image.Root Cause
The library has all the correct building blocks for image embedding, but they are not wired together in the builder pipeline:
images_xml.rs— Has correct implementations:generate_image_xml()— generates proper<p:pic>with<a:blip r:embed="rIdN"/>generate_image_relationship()— generates image relationship XMLgenerate_image_content_type()— generates content type entriesslide_xml/content.rs—render_additional_content()callsgenerate_image_placeholder()which creates a gray<p:sp>shape with<a:solidFill><a:srgbClr val="E0E0E0"/>instead of callinggenerate_image_xml().builder.rs— The builder never:image.get_bytes()to retrieve image datappt/media/imageN.extin the ZIP<Relationship ... Type=".../image" .../>) to slide.relsfiles<Default Extension="png" ContentType="image/png"/>) to[Content_Types].xmlExpected Behavior
The generated PPTX should contain:
<p:pic>elements with<a:blip r:embed="rIdN"/>in slide XML (not gray<p:sp>placeholders)ppt/media/imageN.extppt/slides/_rels/slideN.xml.rels[Content_Types].xmlSuggested Fix
In
render_additional_content()(content.rs), replace the call togenerate_image_placeholder()withgenerate_image_xml()fromimages_xml.rs, and add image embedding logic tobuilder.rs:generate_image_placeholder()withgenerate_image_xml()incontent.rsbuilder.rs, iterate slide images, callimage.get_bytes(), and write toppt/media/.relsfile (usinggenerate_image_relationship())[Content_Types].xml(usinggenerate_image_content_type())Environment