|
-
November 5th, 2007, 10:24 AM
#1
convert bmp to monochrome
Hi,
all i basically want to do is convert an already existing bitmap to greyscale.
to do this i assume i will have to create a new bimapeaderinfo, fill in the needed details and then look at and convert each pixel in the exisiting image.
can anyone help me to do this? also am i calculating the width size of the destination bmp correctly?
Code:
BOOL CBitmapOCR::ConvertBitmap(LPTSTR path, LPTSTR dest, DWORD wBpp, int rVal, int gVal, int bVal)
{
// Make sure bits per pixel is valid
if (wBpp <= 1) wBpp = 1;
else if (wBpp <= 4) wBpp = 4;
else if (wBpp <= 8) wBpp = 8;
else if (wBpp <= 16)wBpp = 16;
else if (wBpp <= 24)wBpp = 24;
else wBpp = 32;
//load the bitmap
CString szFilename(path);
HBITMAP hBmp = (HBITMAP)::LoadImage(NULL,szFilename,
IMAGE_BITMAP,0,0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);
BITMAP WorkBmp;
GetObject(hBmp, sizeof(WorkBmp), &WorkBmp);
//create the new bitmap
BITMAPINFOHEADER head;
// set the correct bpp value
switch (wBpp)
{
case 1:
head.biClrUsed = 2;
break;
case 4:
head.biClrUsed = 16;
break;
case 8:
head.biClrUsed = 256;
break;
default:
head.biClrUsed = 0;
}
int dActualWidth = (WorkBmp.bmWidth * WorkBmp.bmBitsPixel + 3)&(~3);
head.biSize = sizeof(BITMAPINFOHEADER);
head.biWidth = WorkBmp.bmWidth / WorkBmp.bmBitsPixel ;
head.biHeight = WorkBmp.bmHeight;
head.biPlanes = 1;
head.biBitCount = (WORD)wBpp;
head.biCompression = BI_RGB;
head.biSizeImage = WorkBmp.bmHeight * WorkBmp.bmWidth;
head.biXPelsPerMeter = 0;
head.biYPelsPerMeter = 0;
head.biClrImportant = 0;
BITMAPINFO * pBmiSrc = ( BITMAPINFO * ) new BYTE[ WorkBmp.bmHeight * WorkBmp.bmWidth ];
int x, y;
int r,g,b;
for(x=0;x<WorkBmp.bmWidth;x++)
{
for (y=0; y<WorkBmp.bmHeight;y++)
{
r = *((BYTE*)WorkBmp.bmBits + y * dActualWidth + x * WorkBmp.bmBitsPixel + 2);
g = *((BYTE*)WorkBmp.bmBits + y * dActualWidth + x * WorkBmp.bmBitsPixel + 1);
b = *((BYTE*)WorkBmp.bmBits + y * dActualWidth + x * WorkBmp.bmBitsPixel + 0);
if(r==rVal && g==gVal && b==bVal)
{
//set pixel to be black
}
else
{
//set pixel to be white
}
}
}
return true;
}
many thanks,
Matt.
Last edited by flynny1st; November 6th, 2007 at 11:02 AM.
-
November 5th, 2007, 11:23 AM
#2
Re: convert bmp to grayscale
what's the problem? you don't know which grey to assign given a r,g,b pixel?
-
November 5th, 2007, 01:05 PM
#3
Re: convert bmp to grayscale
Here is a formula that converts RGB to greyscale.
Code:
static const int REDCON = 299;
static const int GRNCON = 587;
static const int BLUCON = 114;
#define ComputeMono() (BYTE)((Red * REDCON + Green * GRNCON + Blue * BLUCON)/1000)
-
November 5th, 2007, 03:16 PM
#4
Re: convert bmp to grayscale
flynny1st,
do you want a grayscale bitmap or a monochrome one? You seem to only end up with 2 colors (black and white).
Also, you should be careful using that code to read the bitmap pixels. It will only work if you can guarantee that WorkBmp has 24 or 32 bpp.
-
November 5th, 2007, 04:31 PM
#5
Re: convert bmp to grayscale
 Originally Posted by flynny1st
am i calculating the width size of the destination bmp correctly?
not 100% sure what you mean by this, but a couple of things looked odd to me.
head.biWidth should just be = WorkBmp.bmWidth
the extra considerations about the number of bits per pixel are taken care of by biBitCount = 24 or whatever...
the heights are the same as you have realised. the structure of each line depends on how many bits per pixel. each line must be padded with 'endbytes' to make each line up to a multiple of 4 bytes
e.g. for 8-bit:
biSizeImage = HEIGHT * (WIDTH+endbytes);
for 24-bit:
biSizeImage = HEIGHT * ((3*WIDTH)+endbytes);
where endbytes can be calculated like this:
Code:
int CalculateEndbytes(int bitcount, int width)
{
int endbytes = 0;
if (bitcount == 8)
{
endbytes = 4 - (width % 4);
if (endbytes == 4){endbytes = 0;}
}
if (bitcount == 24)
{
endbytes = 4 - (3*width % 4);
if (endbytes == 4){endbytes = 0;}
}
return endbytes;
}
again, this only takes care of 24 bit or 8 bit, but it should give you a starting point...
-
November 6th, 2007, 05:17 AM
#6
Re: convert bmp to grayscale
Hi guys thanks for the reply sorry yes i want to be able to read in a color bitmap from a file and convert this to a monochromed one (this can be a seperate file if need be.
-
November 6th, 2007, 06:11 AM
#7
Re: convert bmp to grayscale
i found an artice that does the job i'm looking for here.
http://support.microsoft.com/kb/77282/en-us
this uses the getdibits to copy the imag bits across reather than iterate through doing the conversion that i was hoping to do.
Does this solution sound more efficient than my original approach?
many thanks,
Matt.
-
November 6th, 2007, 06:43 AM
#8
Re: convert bmp to grayscale
sorry, whilst the above link did work i wasn't thinking about it properly.
for example, if the colour i wanted to highlight as black was white, then method wouldn't work, so it looks like i will have to iterate through rather than use getdibits after all.
-
November 6th, 2007, 10:32 AM
#9
Re: convert bmp to grayscale
hi guys i've stripped away the unecessary stuff i added.
Code:
BOOL CBitmapOCR::HiglightImage(LPTSTR path, int rVal, int gVal, int bVal)
{
//load the bitmap
CString szFilename(path);
HBITMAP hBmp = (HBITMAP)::LoadImage(NULL,szFilename,
IMAGE_BITMAP,0,0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);
BITMAP WorkBmp;
GetObject(hBmp, sizeof(WorkBmp), &WorkBmp);
//create the new bitmap
BITMAPINFOHEADER head;
head.biSize = sizeof(BITMAPINFOHEADER);
head.biWidth = WorkBmp.bmWidth;
head.biHeight = WorkBmp.bmHeight;
head.biPlanes = 1;
head.biBitCount = WorkBmp.bmPlanes * WorkBmp.bmBitsPixel;
head.biCompression = 0;
head.biSizeImage = WorkBmp.bmHeight * WorkBmp.bmWidth;
head.biXPelsPerMeter = 0;
head.biYPelsPerMeter = 0;
head.biClrImportant = 0;
//pad so multiple of 4
int dActualWidth = WorkBmp.bmWidth * WorkBmp.bmPlanes; dActualWidth = dActualWidth + CalculateEndbytes(head.biBitCount, head.biWidth);
int bitsPerPixel = WorkBmp.bmBitsPixel/8;
BYTE* pBmiSrc = new BYTE[ WorkBmp.bmHeight * WorkBmp.bmWidth ];
int x, y;
int r,g,b;
int count = 0;
for(x=0;x<WorkBmp.bmWidth;x++)
{
for (y=0; y<WorkBmp.bmHeight;y++)
{
r = *((BYTE*)WorkBmp.bmBits + y * dActualWidth + x * bitsPerPixel + 2);
g = *((BYTE*)WorkBmp.bmBits + y * dActualWidth + x * bitsPerPixel + 1);
b = *((BYTE*)WorkBmp.bmBits + y * dActualWidth + x * bitsPerPixel + 0);
if(r==rVal && g==gVal && b==bVal)
{
pBmiSrc[count] = 0;
//set pixel to be black
}
else
{
pBmiSrc[count] = 1;
//set pixel to be white
}
count++;
}
}
//how do i now save the bitmapinfoheader and byte array to a bitmap
return false;
}
int CBitmapOCR::CalculateEndbytes(int bitcount, int width)
{
int endbytes = 0;
if (bitcount == 8)
{
endbytes = 4 - (width % 4);
if (endbytes == 4){endbytes = 0;}
}
if (bitcount == 16)
{
endbytes = 4 - (2*width % 4);
if (endbytes == 4){endbytes = 0;}
}
if (bitcount == 24)
{
endbytes = 4 - (3*width % 4);
if (endbytes == 4){endbytes = 0;}
}
if (bitcount == 32)
{
endbytes = 4 - (4*width % 4);
if (endbytes == 4){endbytes = 0;}
}
return endbytes;
}
how can i now save the created bitmap?
many thanks matt
Last edited by flynny1st; November 6th, 2007 at 11:39 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|