RGB565 The RGB565 color format is the same as the RGB555 color format, except that 6 bits are used for the green value instead of 5. Therefore, all 16 bits are in use. The organization of the pixels in the image buffer is from left to right and bottom up. Memory Layout 图1 As illustrated above, the 5 least significant bits of the WORD correspond to the blue value, bits 5 - 10 correspond to the green value and bits 11 to 15 correspond to the red value. Please note that on the x86 architecture WORDs are stored in little-endian order, which means the LOW BYTE is saved first. This is important when accessing the image data with a byte pointer. How to read and write pixel data A video capture device, video format, FrameHandlerSink with a MemBufferCollection, which defines the image data color format must first have been setup. The following code fragments show step-by-step how to access and manipulate the pixel data of RGB555. First of all, we have to capture an image. Otherwise, the image buffer would be empty. To do so, we start live mode and call Grabber::snapImages. Accessing the buffer The following code retrieves a pointer to the image data. Please note, that getPtr() returns a BYTE pointer, which will be type-casted to a WORD pointer. This makes it much easier to access the pixel data since RGB565 is a 16 bit color format. WORD* pwImgData = (WORD*) pActiveBuf->getPtr(); In this example, we want to output the first (upper left hand) pixel of the image and manipulate the first 3. As previously mentioned, the image data is stored bottom up. Therefore, pwImgData points to the first byte of the first pixel of the last line in the buffer. To get access to this first byte, the following calculation has to be performed:
At first, we retrieve the width and height of the image in terms of pixels. Then, the offset to the upper left pixel is calculated. Please note that we multiply with Width * 1 and not Width * 2. This is because we use a WORD pointer to access the image data. Of course, the multiplication by 1 is just for illustration and can be left out. (Height-1) * Width Now that we have the offset to the the first pixel, we can read it out:
As seen in the code above, we perform a binary AND operation with the appropriate pixel mask on the current pixel to extract the color value. After that, the values for red and green must be shifted to the right to get the correct value (otherwise the value would be 2048 (32 times too big)). Manipulating Image Data Shifting is also important when assigning values. For example, if 7 is assigned to the red value, it must be shifted 11 times to the left. Instead of writing: // Assign 7 to the red value pwImgData[iOffsUpperLeft] = 7; // this is WRONG which assigns 7 to the blue value, the following code should be used: // Assign 7 to the red value pwImgData[iOffsUpperLeft] = 7 << 11; Another important thing to note is that the assignment above will overwrite the values for green and blue. To prevent this, the value must be ORed to the pixel data as the following code will show: // Clear the red value (set all bits to 0) pwImgData[iOffsUpperLeft] &= ~eRGB565_R; // Assign 7 to the red value without overwriting green and blue values pwImgData[iOffsUpperLeft] |= 7 << 11; Please note that all bits of the appropriate color should be set to 0, as the code above does. Consider, for example, that the previous red value could have been 16 (or 10000 binary). If we then perform a binary OR operation with 7 (or 111 binary), the result will be 23 (or 10111 binary). Therefore, it is better to set all bits of the appropriate channel to 0. Now we set the upper left hand pixel to red, the next to green and the third to blue.
上面的都是废话,言归正传,要使用DirectDraw显示RGB565: pixel格式设置是这样的 如下:
其次:由于DirectDraw的显示顺序是从上到下,从左到右的方式,而BMP位图的数据存储方式是像素从下到上,从左到右, 所以要在位图数据拷贝到离屏面时要注意,否则显示出的图像是倒过来的。 具体如下:
执行一下你的程序吧,如果成功,恭喜你!如何弹出非法错误,通过调试跟踪我们发现问题出现在上面的循环。可能大家都会知道这里的Pitch值在不同的电脑上的值是不一样的,一般情况下大家认为Plitch=ddsd.lPitch/2=ScreenW(当然这只是16位的情况),具体什么含义参考MSDN.如何Pitch的值大于ScreenW那么上面的操作肯定会发生内存溢出。所以修改为*(lpSurface + y*Pitch + x)=*(lpbmpdata +( ScreenH-y-1)*ScreenW + x);// 在什么电脑上都不会有问题了,除非你的显卡支持RGB555,不支持RGB565. 以上只介绍关键步骤,如需完整代码学习,请留言。 (秩名) |