Accessing to Raster Image Data

ImageLock class

In PixelLive SDK, since each Image classes stores its image data in its own way, you could not obtain the raster data stored in an Image instance directly. Instead of directly accessing to the raster data of an Image instance, you can access the raster data (or sometimes a projection of the data) by creating an ImageLock instance from the Image instance.

    AutoPtr<ImageLock> lock = image->lock();

An ImageLock instance does:

and since it implements Referable class, the lifetime of ImageLock instances can be managed by AutoPtr.
Anyway, it is the time to load the raster data onto the memory that you can directly access to. This operation is done by ImageLock::read functions. There are 2 versions of ImageLock::read :

    const u8* read(
        ssize_t *outRowStride,
        const Rect& inRect,
        RenderingMode inRenderMode = rmDefault);

    void read(
            const Rect& inRect,
            void* inFirstLinePtr,
            ssize_t inRowStride,
            RenderingMode inRenderMode = rmDefault);

With the first one, you can get a pointer to the first line of the raster data of the specified area. For example, if you want to access to the area of 300x200 starts from (100,100), write code as follows:

    ssize_t rowStride;
    const u8 *ptrImage = lock->read(&rowStride, Rect(100, 100, 300, 200));

You can obtain the pointer to the nth (n is 0-origin) line by the following code:

    const u8 *line_n = ptrImage + n * rowStride;

With some Image classes or in some special conditions, the nth line is placed on higher address than the n+1 th line (stored as reverse order) and then rowStride is a negative value. Images in such a layout is called bottom-up image. Windows GDI DIB (Device-Independent Bitmaps) is usually stored as bottom-up image.

That's all for the row-stride, but you may want to know why you receive the row-stride value from the function. For the question, you should understand the internals of the ImageLock::read function.

Row-Stride Basics

The rowStride, usually called row-stride or stride, as shown above is usually described as the offset value to the next line. This value depends on the internal raster image layout and it could not be estimated by any outer functions.
Assume that you provides an Image class that serves a bitmap of m_width x m_height and implementing the ImageLock::read function of the first one. And then it extracts a portion of inRect.

cliprect.png

In this case, you can adopt one of the following two choices:

If you adopt the first one, then the rowStride value returned from the ImageLock::read function should be the native row-stride value that is calculated from the original bitmap size m_width.

    ssize_t rowStride = (ssize_t)(m_width * bytes_per_pixel);

In the code above, bytes_per_pixel depends on the photometric of the image, it is usually obtained by PixelAttributes::getBytesPerPixel function. And anyway, the code does not suppose any alignment issues, for more information about alignment, see Alignment Issues.

Anyway, the pointer to the portion is calculated as follows:

    const u8 *ptrPortion = m_imageBuffer + rowStride * inRect.top + bytes_per_pixel * inRect.left;

The m_imageBuffer in the code is the pointer to the buffer that stores the internal bitmap.

That's all for the first version of ImageLock::read . Everything is quite easy and you may notice what is row-stride.

The whole code of the function is shown below:

const u8* SampleImageLock::read(
    ssize_t *outRowStride,
    const Rect& inRect,
    ImageLock::RenderingMode inRenderMode = rmDefault)
{
    size_t rowStride = (ssize_t)(m_width * m_bytesPerPixel);
    const u8 *ptrPortion
        = m_imageBuffer + rowStride * inRect.top + bytes_per_pixel * inRect.left;
    *outRowStride = rowStride;
    return ptrPortion;
}

The Other Version of ImageLock::read

The second ImageLock::read function does the second choice of the section above, it creates a temporary buffer and copies the portion of the image to the buffer. With the function, although you should allocate the memory block by yourself, you can specify the row-stride for the clipped portion.

As for Windows, almost all Win32 API functions requires the DIB (Device-Independent Bitmaps) to be 4byte aligned and they also prefers the bottom-up ones to the top-down ones. To deal with such functions, you should explicitly specify the row-stride. Since Windows does not support the images other than RGB, we assume the image is RGB 8bit/channel (If you want to convert any photometic images into RGB, see ToSRGB, PhotometricTransform.), and then the row-stride that should be passed to ImageLock::read is calculated by the following code:

    ssize_t rowStride = -((inRect.width * 3 + 3) & ~3);
The row-stride value is negative since the DIB should be bottom-up. And then, the most important thing is that the second parameter inFirstLinePtr of the function is not the pointer to the top of the buffer. It should point to the first (0-th) line of the image. If the pointer to the buffer is provided by pBuffer, the following code calculates it:
    u8 *firstLinePtr = (u8 *)pBuffer + (inRect.height - 1) * (-rowStride);
For the whole code that creates Win32 DIB, see Creating Windows DIB.

See also:
ToSRGB, PhotometricTransform

Windows GDI - Device-Independent Bitmaps

Creating Windows DIB

Alignment Issues

...
This document is automatically generated using doxygen 1.5.4 at Fri Jun 27 18:22:54 2008.