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.
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.m_width x m_height and implementing the ImageLock::read function of the first one. And then it extracts a portion of inRect.
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; }
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);
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: For the whole code that creates Win32 DIB, see Creating Windows DIB.