`Wrong size` error when rendering PNG via CoreGraphics
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 1.4k
- Forks
- 98
- PR merge metrics
- No merged PRs in 30d
Description
I'm trying to replicate the results of the example file in `piet-coregraphics`. I'm unable to render an empty PNG file.
```
use eyre::{Context, Result};
use piet::kurbo::Size;
use std::fs::File;
use std::io::BufWriter;
use core_graphics::color_space::CGColorSpace;
use core_graphics::context::CGContext;
use piet::{Color, RenderContext};
use piet_coregraphics::CoreGraphicsContext;
fn main() -> Result<()> {
let size = Size {
width: 1.0,
height: 1.0,
};
let mut cg_ctx = make_cg_ctx(size);
let mut piet_context = CoreGraphicsContext::new_y_up(&mut cg_ctx, size.height, None);
draw(&mut piet_context).wrap_err("failed to draw file")?;
piet_context
.finish()
.map_err(|e| eyre::eyre!("{}", e))
.wrap_err("failed to finalize piet context")?;
std::mem::drop(piet_context);
let mut data = cg_ctx.data();
let file = File::create("out.png").wrap_err("failed to create output file")?;
let w = BufWriter::new(file);
dbg!(data.len());
let mut encoder = png::Encoder::new(w, dbg!(size.width as u32), dbg!(size.height as u32));
encoder.set_color(png::ColorType::Rgba);
encoder.set_depth(png::BitDepth::Eight);
let mut writer = encoder
.write_header()
.wrap_err("failed to write png header")?;
piet_coregraphics::unpremultiply_rgba(&mut data);
writer
.write_image_data(&data)
.wrap_err("failed to write image data")?;
Ok(())
}
fn make_cg_ctx(size: Size) -> CGContext {
dbg!(&size);
let cg_ctx = CGContext::create_bitmap_context(
None,
size.width as usize,
size.height as usize,
8,
0,
&CGColorSpace::create_device_rgb(),
core_graphics::base::kCGImageAlphaPremultipliedLast,
);
cg_ctx
}
fn draw(rc: &mut impl RenderContext) -> Result<()> {
rc.clear(None, Color::WHITE);
Ok(())
}
```
I'm using these crates:
```
core-graphics = "0.22.3"
eyre = "0.6.5"
piet = "0.5.0"
piet-coregraphics = "0.5.0"
png = "0.17.2"
```
Running the above example, I get the following output:
```
[examples/render-test.rs:51] &size = 1.0W×1.0H
[examples/render-test.rs:33] data.len() = 64
[examples/render-test.rs:35] size.width as u32 = 1
[examples/render-test.rs:35] size.height as u32 = 1
Error: failed to write image data
Caused by:
wrong data size, expected 4 got 64
Location:
examples/render-test.rs:45:10
```
The PNG crate expects the image buffer to be 4 bytes long, which makes sense considering it's an RGBA image with 4 bytes per pixel, and it contains only one pixel. I'm not sure why piet is returning a 64-byte image buffer, and I don't really know enough about image formats to make a good guess. I opened the raw buffer in a hex editor, and it contains `0xff 0xff 0xff 0xff` followed by 60 bytes of `0x00`.

Is there some trimming that I'm supposed to do, or is there a settings mismatch in my code between png and piet?
EDIT: it seems there may be some minimum image size that I'm not exceeding. If I change the size to 100x400, it seems to work just fine. Is this restriction coming from piet, coregraphics, or png?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue from examples/render-test.rs, starting with make_cg_ctx, CoreGraphicsContext::new_y_up, and the png encoder. Compare the 1×1 CGContext buffer length with the PNG input requirement, then determine whether the mismatch belongs to piet, core-graphics, or the example. Done means the source of the extra buffer data and the correct handling are documented or fixed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- computer-graphics
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100