Skip to content

Add PixelBuffer#to_bytes for zero-overhead pixel access#2387

Merged
klayoutmatthias merged 3 commits into
KLayout:masterfrom
querielo:kirill/pixelbuffer-to-bytes
Jul 16, 2026
Merged

Add PixelBuffer#to_bytes for zero-overhead pixel access#2387
klayoutmatthias merged 3 commits into
KLayout:masterfrom
querielo:kirill/pixelbuffer-to-bytes

Conversation

@querielo

@querielo querielo commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Exposes a GSI method on tl::PixelBuffer that returns the raw ARGB32 contents as a byte vector (4 bytes per pixel, row-major, top to bottom) via a single memcpy. Unlike to_png_data this skips all image encoding, which is useful when the caller just wants direct pixel data.

Exposes a GSI method on tl::PixelBuffer that returns the raw ARGB32
contents as a byte vector (4 bytes per pixel, row-major, top to bottom)
via a single memcpy. Unlike to_png_data this skips all image encoding,
which is useful when the caller just wants direct pixel data.
@querielo querielo changed the title Add PixelBuffer#to_bytes for zero-overhead RGBA pixel access Add PixelBuffer#to_bytes for zero-overhead pixel access Jul 6, 2026
@klayoutmatthias

Copy link
Copy Markdown
Collaborator

Hi @querielo,

thanks for the PR.

I'd like to ask to include a test and maybe one small enhancement: If you add width and height as 32bit numbers at the beginning of the bitstream, it would be possible also to deserialize a PixelBuffer from that bitstream (i.e. a corresponding "from_bytes" method). Also, when you receive the bitstream, you can cross check it against the expected width and height on the receiver's end.

Is that possible?

Matthias

@querielo

Copy link
Copy Markdown
Contributor Author

Hi @klayoutmatthias,

Thanks for the review! A few open questions:

  1. Sanity limits for dimensions: A broken or malicious header could contain very large width or height value. Should we also add a maximum size limit or an overflow check before allocating memory?
  2. Endianness: to_bytes writes the raw ARGB32 pixels in the native byte order (it is a direct memory copy, so there is no extra overhead). This means the format only works between systems with the same architecture. Is that OK, or would you prefer a fixed byte order for the whole format?
  3. Transparency flag: The transparency flag is not stored in the byte stream. In from_bytes, I return a transparent buffer so the alpha channel is preserved. Is this OK?

@klayoutmatthias

Copy link
Copy Markdown
Collaborator

Hi @querielo,

Sorry for the late reply and thanks for coming back.

You're right about these points. I basically don't expect that to be a file format, but you can never know. I think a reasonable limit is 64k by 64k, but some people use the drawing feature to produce very finely resolved images. So as of now, I'd propose to limit to 64k x 64k in the reader, and "unlimited" (i.e. 32bit) in the writer. I'd throw an exception if that dimension is exceeded in the "from_bytes" method.

Regarding endianess, I'd just use native order (little endian) as AFAIK big endian is only used in network protocols, but does not play a role anymore in memory representation (at least in our domain).

And thanks for mentioning the transparency mask. Yes, that is a good idea to maintain it.

I mean, the idea is not to establish a new image format, but to enable more use cases. Please don't waste too much time on that - I just like symmetry :)

Matthias

querielo pushed a commit to querielo/klayout that referenced this pull request Jul 16, 2026
Following review feedback, the reader now rejects a header claiming a
width or height beyond 65536, guarding against malformed byte streams
that would otherwise trigger an unreasonable allocation. The writer
stays full 32-bit ('unlimited'), and native little-endian order and the
transparency mask are kept as-is. Adds Ruby and Python tests for the
oversized-header rejection.

Ref: KLayout#2387 (comment)
@querielo

Copy link
Copy Markdown
Contributor Author

@klayoutmatthias Done.

querielo added 2 commits July 16, 2026 19:03
Following review feedback, the reader now rejects a header claiming a
width or height beyond 65536, guarding against malformed byte streams
that would otherwise trigger an unreasonable allocation. The writer
stays full 32-bit ('unlimited'), and native little-endian order and the
transparency mask are kept as-is. Adds Ruby and Python tests for the
oversized-header rejection.

Ref: KLayout#2387 (comment)
@querielo
querielo force-pushed the kirill/pixelbuffer-to-bytes branch from 02ab312 to 9a606ec Compare July 16, 2026 17:04
@klayoutmatthias

Copy link
Copy Markdown
Collaborator

Perfect! Thanks!

I'll merge the PR.

Matthias

@klayoutmatthias
klayoutmatthias merged commit 3c6b342 into KLayout:master Jul 16, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants