Re: [GD-DEVEL] [proposal] Attach DIB section buffer to gdImage
[email protected] (Markus Fleck-Graffe)
| Newsgroups | php.gd.devel |
|---|---|
| Message-ID | <[email protected]> |
Pierre Joye wrote:
>>> I'm finishing the initial support of the new formats. The two most
>>> important additions for you and other users are the true 8bit per
>>> channel (alpha) and the contiguous buffer instead of per row
>>> allocation. It will let you use a DIB/BMP (or any compatible buffer)
>>> directly without any extra allocations or loop. It will require a lof
>>> tests and work to get stable enough for 2.1.x :)
There is this very powerful "iterator" abstraction used, for example,
by the Fltk GUI toolkit, and by Python's "NumPy" matrix calculation
library as well[1].
It supports basically all kinds of contiguous buffer schemes (including
the Windows DIB one), and has excellent performance characteristics.
Basically, you store the following data for each image:
- "topleft": a pointer to the memory location that stores the first
(top-left) pixel of the image
- "buffer": a pointer to the (contiguous) memory buffer (which will
be used mainly just for eventually free()'ing the buffer)
- "depth": pixel depth (in bytes, or maybe even in bits),
e.g. 3 (bytes) for plain 24-bit RGB, or 4 (bytes) for 32-bit RGBA
- "w", "h": actual (logical) image width and height (in pixels)
- "dy" byte offset to the next scan line (for "vertical" iteration)
- "dx" byte offset to the next pixel (for "horizontal" iteration)
Ideally, for a contiguous RGB(A) buffer, "dx" would be equal
to "depth", "dy" would be equal to "width", and "topleft" would
be equal to "buffer".
Now:
- if scanlines must be "padded" to satisfy some alignment constraints,
"dy" may be made larger than "width"
- in case of "upside-down" storage (such as with Windows DIB bitmaps),
"dy" must be made negative, and the initial image pointer ("topleft")
must be calculated to point to the beginning of the "last" DIB
scanline in memory (which is actually the "topmost" scanline of
the corresponding image).
The memory position of each pixel can then be calculated at any
time, using either absolute or relative pointer arithmetics,
based only on the above small (and fixed) set of metadata.
It is also possible to very efficiently (and safely) perform
BITBLT-style operations using fast block copy operations, just by
calculating the corresponding topleft/width/height/dx/dy values,
for any rectangular region inside an image. (In fact, multiple
overlapping images could even share the same data buffer,
which may be useful e.g. for showing a scrollable rectangular
clipped "view" of a larger image in a GUI toolkit, as Fltk can,
or for processing very large 2D arrays or matrices, as NumPy can.)
Now the question is: are there any GD users who depend on the
peculiarities and availability of the current tpixels array
(probably for non-contiguous in-memory images whose buffers
have not been created by GD itself)? Would it be an option
to get rid of "tpixels" for GD 3.x, for the sake of
significantly improving performance?
Yours,
Markus.
[1] The 1997 O'Reilly book "Beautiful Code", in chapter 19, contains
a description of offset iterators for managing multi-dimensional
arrays in NumPy. (ISBN 0-5965-1004-7)