linebender / linebender/piet

`Wrong size` error when rendering PNG via CoreGraphics

Open
#481 3 comments 0 reactions 0 assignees View on GitHub

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`.

Screenshot of a hex editor showing contents of the buffer described above

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.