Home > Archive > VC Language > May 2006 > Grabbing the pixels of a bmp
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Grabbing the pixels of a bmp
|
|
|
| Hi,
I wonder how to grab the 'current' pixel of a bitmap
say
*****************
*((**************)
is the bitmap
I want to get the first row, first column pixel value
How do I do that in VC++?
Thanks
Jack
| |
| doug mansell 2006-05-25, 8:16 am |
| Jack wrote:
> Hi,
> I wonder how to grab the 'current' pixel of a bitmap
> say
> *****************
> *((**************)
>
> is the bitmap
> I want to get the first row, first column pixel value
> How do I do that in VC++?
> Thanks
> Jack
>
>
You could read about this function: GetBitmapBits
| |
|
|
"doug mansell" <doug_mansell@hotmail.com>
???????:umIGUg$fGHA.3916@TK2MSFTNGP04.phx.gbl...
> Jack wrote:
>
> You could read about this function: GetBitmapBits
pBitmap->GetBitmapBits(1, (LPVOID)???);
What should I put into LPVOID? is it assumed that DWORD is used for count.
like this?
Thanks
Jack
| |
|
|
"doug mansell" <doug_mansell@hotmail.com>
???????:umIGUg$fGHA.3916@TK2MSFTNGP04.phx.gbl...
> Jack wrote:
>
> You could read about this function: GetBitmapBits
doesn't work either
pBitmap->GetBitmap(&bmpX);
BYTE* bmpBuffer = (BYTE *)GlobalAlloc (GPTR, bmpX.bmWidth*bmpX.bmHeight);
for (int i = 0; i < ds.dsBm.bmHeight; i++) {
for (int j = 0; i < ds.dsBm.bmWidth; j++) {
if (bmpBuffer[i*ds.dsBm.bmHeight+j] == RGB(255,255,0))
AfxMessageBox ("Hit it", MB_OK, NULL);
}
}
}
| |
|
| Now i have this
===========================
pBitmap->GetBitmap(&bmpX);
LPVOID bmpinfo;
pBitmap->GetObject(sizeof(BITMAP), bmpinfo);
BYTE* bmpBuffer = (BYTE *)GlobalAlloc (GPTR, bmpX.bmWidth*bmpX.bmHeight);
pBitmap->GetBitmapBits(bmpX.bmWidthBytes*bmpX.bmHeight,bmpBuffer);
for (int i = 0; i < ds.dsBm.bmHeight; i++) {
for (int j = 0; j < ds.dsBm.bmWidth; j++) {
if (bmpBuffer[i*ds.dsBm.bmHeight+j] == RGB(255,255,0)
AfxMessageBox ("Hit it", MB_OK, NULL);
-===============================
"Jack" <jl@knight.com> 撰寫於郵件新聞:OjJxcaGgGHA.1204@TK2MSFTNGP02.phx.gbl...
>
> "doug mansell" <doug_mansell@hotmail.com>
> ???????:umIGUg$fGHA.3916@TK2MSFTNGP04.phx.gbl...
>
> doesn't work either
> pBitmap->GetBitmap(&bmpX);
> BYTE* bmpBuffer = (BYTE *)GlobalAlloc (GPTR, bmpX.bmWidth*bmpX.bmHeight);
> for (int i = 0; i < ds.dsBm.bmHeight; i) {
> for (int j = 0; i < ds.dsBm.bmWidth; j) {
> if (bmpBuffer[i*ds.dsBm.bmHeight] == RGB(255,255,0))
> AfxMessageBox ("Hit it", MB_OK, NULL);
> }
> }
> }
>
>
| |
|
| The problem I am having now is the bitmap pointer is byte-based.
I want to read 24 to 32 bit bitmaps
Any comments?
Jack
"Jack" <jl@knight.com> 撰寫於郵件新聞:OjJxcaGgGHA.1204@TK2MSFTNGP02.phx.gbl...
>
> "doug mansell" <doug_mansell@hotmail.com>
> ???????:umIGUg$fGHA.3916@TK2MSFTNGP04.phx.gbl...
>
> doesn't work either
> pBitmap->GetBitmap(&bmpX);
> BYTE* bmpBuffer = (BYTE *)GlobalAlloc (GPTR, bmpX.bmWidth*bmpX.bmHeight);
> for (int i = 0; i < ds.dsBm.bmHeight; i) {
> for (int j = 0; i < ds.dsBm.bmWidth; j) {
> if (bmpBuffer[i*ds.dsBm.bmHeight] == RGB(255,255,0))
> AfxMessageBox ("Hit it", MB_OK, NULL);
> }
> }
> }
>
>
| |
|
| Still doesn't work
pBitmap->GetBitmap(&bmpX);
//LPVOID bmpinfo = new BYTE[sizeof(BITMAP)];
//pBitmap->GetObject(sizeof(BITMAP), bmpinfo);
BYTE* bmpBuffer = (BYTE *)GlobalAlloc (GPTR,
bmpX.bmWidth*bmpX.bmHeight);
pBitmap->GetBitmapBits(bmpX.bmWidthBytes*bmpX.bmHeight,bmpBuffer);
for (int i = 0; i < ds.dsBm.bmHeight; i++) {
for (int j = 0; j < ds.dsBm.bmWidth; j+=4) { // 32 bit bitmap
if (bmpBuffer[i*ds.dsBm.bmHeight+j] == 0 &&
bmpBuffer[i*ds.dsBm.bmHeight+j+1] == 0 &&
bmpBuffer[i*ds.dsBm.bmHeight+j+2] == 255)
AfxMessageBox ("Hit it", MB_OK, NULL);
----------------------------------------
"Jack" <jl@knight.com> 撰寫於郵件新聞:%23i33krGgGHA.4172@TK2MSFTNGP04.phx.gbl...
> The problem I am having now is the bitmap pointer is byte-based.
> I want to read 24 to 32 bit bitmaps
> Any comments?
> Jack
>
> "Jack" <jl@knight.com> ???gco?l¥o·s?D:OjJxcaGgGHA.1204@TK2MSFTNGP02.phx.gbl...
>
>
>
| |
|
| ==================== still no good
pBitmap->GetBitmap(&bmpX);
//LPVOID bmpinfo = new BYTE[sizeof(BITMAP)];
//pBitmap->GetObject(sizeof(BITMAP), bmpinfo);
BYTE* bmpBuffer = (BYTE *)GlobalAlloc (GPTR, bmpX.bmWidth*bmpX.bmHeight);
pBitmap->GetBitmapBits(bmpX.bmWidthBytes*bmpX.bmHeight,bmpBuffer);
for (int i = 0; i < ds.dsBm.bmHeight; i++) {
for (int j = 0; j < ds.dsBm.bmWidth; j+=4) { // 32 bit bitmap
if (bmpBuffer[i*ds.dsBm.bmHeight+j] == 255 &&
bmpBuffer[i*ds.dsBm.bmHeight+j+1] == 0 &&
bmpBuffer[i*ds.dsBm.bmHeight+j+2] == 0 &&
bmpBuffer[i*ds.dsBm.bmHeight+j+3] == 255)
AfxMessageBox ("Hit it", MB_OK, NULL);
=====================
"Jack" <jl@knight.com> 撰寫於郵件新聞:uUwxK2GgGHA.1204@TK2MSFTNGP02.phx.gbl...
> Still doesn't work
> pBitmap->GetBitmap(&bmpX);
> //LPVOID bmpinfo = new BYTE[sizeof(BITMAP)];
> //pBitmap->GetObject(sizeof(BITMAP), bmpinfo);
> BYTE* bmpBuffer = (BYTE *)GlobalAlloc (GPTR,
> bmpX.bmWidth*bmpX.bmHeight);
> pBitmap->GetBitmapBits(bmpX.bmWidthBytes*bmpX.bmHeight,bmpBuffer);
> for (int i = 0; i < ds.dsBm.bmHeight; i) {
> for (int j = 0; j < ds.dsBm.bmWidth; j=4) { // 32 bit bitmap
> if (bmpBuffer[i*ds.dsBm.bmHeight] == 0 && bmpBuffer[i*ds.dsBm.bmHeight_(
> == 0 &&
> bmpBuffer[i*ds.dsBm.bmHeight_( == 255)
> AfxMessageBox ("Hit it", MB_OK, NULL);
>
>
>
> ----------------------------------------
> "Jack" <jl@knight.com> ???gco?l¥o·s?D:%23i33krGgGHA.4172@TK2MSFTNGP04.phx.gbl...
>
>
>
| |
| Tim Roberts 2006-05-26, 4:13 am |
| "Jack" <jl@knight.com> wrote:
>
>The problem I am having now is the bitmap pointer is byte-based.
>I want to read 24 to 32 bit bitmaps
>Any comments?
"Pointer is byte-based" doesn't really mean anything. Every bitmap is just
a string of bytes. It just so happens that, in a 24-bit DIB, a pixel is
spread across three bytes.
[color=darkred]
You don't need to allocate any space. The BITMAP structure contains a
pointer to the bytes of the bitmap.
[color=darkred]
How much C experience do you have? Both of those for loops are infinite
loops. You aren't bumping your loop counter. Plus, in the second one,
you're testing the wrong variable.
[color=darkred]
Every pixel in a 24-bit DIB occupies three bytes. So, pixel X,Y is at
((Y * width) + X) * 3
However, there may be padding at the end of each scanline. The actual
distance from the start of one scanline to the start of the next is in
bmWidthBytes.
pBitmap->GetBitmap(&bmpX);
BYTE* bmpBuffer = bmpX.bmBits;
for (int i = 0; i < bmpX.bmHeight; i++) {
for (int j = 0; j < bmpX.bmWidth; j++) {
int iPixelOffset =
j * bmpX.bmWidthBytes +
i * bmpX.bmBitsPixel / 8;
unsigned long pixel = *(unsigned long *)(bmpBuffer + iPixelOffset) &
0xffffff;
if (pixel == RGB(255,255,0))
AfxMessageBox ("Hit it", MB_OK, NULL);
}
}
--
- Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.
| |
| Tamas Demjen 2006-05-26, 7:09 pm |
| Jack wrote:
>
>
> pBitmap->GetBitmapBits(1, (LPVOID)???);
> What should I put into LPVOID? is it assumed that DWORD is used for count.
> like this?
If the image is a bitmap residing in the video memory, the system first
has to transfer the image from the VRAM to the RAM. Therefore you must
use GetDIBits. That LPVOID is basically a void*. You have to allocate
enough memory to hold the bitmap that you're retrieving, and pass a
pointer to that buffer to GetDIBits.
On the other hand, if the bitmap is a DIB, residing in the physical RAM,
GetDIBits is redundant. It performs an unnecessary copy, which slows
down your code unreasonably. In this case you can use GetObject to get a
pointer to the bitmap already in the memory. GetObject can be used to
convert an HBITMAP to a BITMAP. BITMAP contains the width, height,
bits_per_pixel value, and gives you a raw pointer to the bitmap's bits.
You don't allocate any memory in this case, it's a pointer to the bitmap
itself.
The meaning of the bitmap's bits depends on the type of the bitmap (and
the bits per pixel value). It can be monochrome, 4-bit, 8-bit, 16-bit,
24-bit, or 32-bit. It's your job to decode the information. Take a looks
at BITMAPINFOHEADER on MSDN. Also the bitmap is upside down. The pixels
are always tightly packed within a row, but each row begins at a DWORD
bound. This means that there is usually 0-3 bytes of empty space after
the end of each line, before the begining of the next line. Here's the
magic formula to calculate the number of bytes per line:
BytesPerRow = (Width * BitsPerPixel + 31) / 32 * 4;
Then you can calculate the beginning of a row:
RowPtr = BitmapPtr + BytesPerRow * (Height - 1 - Row);
// Height - 1 because it's upside down
Here I assume that each pointer is an unsigned char *. That's the
easiest way to work with bitmap. If it's monochrome, each byte encodes 8
pixels. If it's grayscale, each byte encodes a pixel. If it's 24 or
32-bit, each byte encodes a color component.
Tom
| |
|
|
"Tim Roberts" <timr@probo.com>
???????:h43d72lq9o6vf1263umhq7hm1hj6dm0b24@4ax.com...
> "Jack" <jl@knight.com> wrote:
>
> "Pointer is byte-based" doesn't really mean anything. Every bitmap is
> just
> a string of bytes. It just so happens that, in a 24-bit DIB, a pixel is
> spread across three bytes.
>
>
> You don't need to allocate any space. The BITMAP structure contains a
> pointer to the bytes of the bitmap.
>
>
> How much C experience do you have? Both of those for loops are infinite
> loops. You aren't bumping your loop counter. Plus, in the second one,
> you're testing the wrong variable.
>
>
> Every pixel in a 24-bit DIB occupies three bytes. So, pixel X,Y is at
>
> ((Y * width) + X) * 3
>
> However, there may be padding at the end of each scanline. The actual
> distance from the start of one scanline to the start of the next is in
> bmWidthBytes.
>
> pBitmap->GetBitmap(&bmpX);
> BYTE* bmpBuffer = bmpX.bmBits;
> for (int i = 0; i < bmpX.bmHeight; i++) {
> for (int j = 0; j < bmpX.bmWidth; j++) {
> int iPixelOffset =
> j * bmpX.bmWidthBytes +
> i * bmpX.bmBitsPixel / 8;
> unsigned long pixel = *(unsigned long *)(bmpBuffer + iPixelOffset) &
> 0xffffff; <<<<<<<<<<<<<<<<<<<<<<< AV Error
> if (pixel == RGB(255,255,0))
> AfxMessageBox ("Hit it", MB_OK, NULL);
> }
> }
Dear Tim,
I still got a access violation error on the line shown above (accessing
image 0x01800000 + offset 0xe1000)
Thanks
Jack
> --
> - Tim Roberts, timr@probo.com
> Providenza & Boekelheide, Inc.
| |
| Tim Roberts 2006-05-27, 10:06 pm |
| "Jack" <jl@knight.com> wrote:
>
>Dear Tim,
>I still got a access violation error on the line shown above (accessing
>image 0x01800000 + offset 0xe1000)
Yes. I have row and column swapped in the iPixelOffset computation. That's
why it's better to use either "x" and "y" or "row" and "column" for the
variables.
for (int i = 0; i < bmpX.bmHeight; i++) {
for (int j = 0; j < bmpX.bmWidth; j++) {
int iPixelOffset =
i * bmpX.bmWidthBytes +
j * bmpX.bmBitsPixel / 8;
--
- Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.
| |
| Jerry Coffin 2006-05-28, 7:13 pm |
| In article <OBZiKA#fGHA.4172@TK2MSFTNGP04.phx.gbl>,
jl@knight.com says...
> Hi,
> I wonder how to grab the 'current' pixel of a bitmap
> say
> *****************
> *((**************)
>
> is the bitmap
> I want to get the first row, first column pixel value
> How do I do that in VC++?
If you only need to get one or a few pixels from the
bitmap, it's usually easiest to use GetPixel.
If you need to work with most or all of a the pixels in a
bitmap, I'd consider using a DIB section. GetBitmapBits
creates an extra copy of the pixels that make up the
bitmap, but a DIB section gives you access to the
original pixels instead.
--
Later,
Jerry.
The universe is a figment of its own imagination.
|
|
|
|
|