By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,171 Members | 1,390 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,171 IT Pros & Developers. It's quick & easy.

Bitmap.Clone

P: n/a
The following code throws a out of memory exception, I have another function
that does the same thing using the bitmap lock but its way slow. Anyone
know how to fix this one?

public static Bitmap GetClonedBitmap(int width, int height, string str, Font
font, StringAlignment Alignment)
{
Rectangle r = new Rectangle(1, 1, width-1, height-1);
using (Bitmap tmpBmp = new Bitmap(width, height))
{
using (Graphics g = Graphics.FromImage(tmpBmp))
{
g.FillRectangle(Brushes.White, r);
using (StringFormat sf = new
StringFormat(StringFormat.GenericDefault))
{
sf.Alignment = Alignment;
sf.Trimming = StringTrimming.None;
sf.LineAlignment = StringAlignment.Center;
sf.FormatFlags = StringFormatFlags.NoWrap;
g.DrawString(str, font, Brushes.Black, r, sf);

return tmpBmp.Clone(r, PixelFormat.Format1bppIndexed);
}
}
}
}

Regards,
John
May 10 '06 #1
Share this Question
Share on Google+
4 Replies


P: n/a
You can't change the bitmap pixel format like that. That's where the error
is coming from.

If you want to convert an arbitrary bitmap to 1bpp indexed see the GDI+ FAQ.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

"John J. Hughes II" <no@invalid.com> wrote in message
news:u9**************@TK2MSFTNGP03.phx.gbl...
The following code throws a out of memory exception, I have another
function that does the same thing using the bitmap lock but its way slow.
Anyone know how to fix this one?

public static Bitmap GetClonedBitmap(int width, int height, string str,
Font font, StringAlignment Alignment)
{
Rectangle r = new Rectangle(1, 1, width-1, height-1);
using (Bitmap tmpBmp = new Bitmap(width, height))
{
using (Graphics g = Graphics.FromImage(tmpBmp))
{
g.FillRectangle(Brushes.White, r);
using (StringFormat sf = new
StringFormat(StringFormat.GenericDefault))
{
sf.Alignment = Alignment;
sf.Trimming = StringTrimming.None;
sf.LineAlignment = StringAlignment.Center;
sf.FormatFlags = StringFormatFlags.NoWrap;
g.DrawString(str, font, Brushes.Black, r, sf);

return tmpBmp.Clone(r, PixelFormat.Format1bppIndexed);
}
}
}
}

Regards,
John

May 10 '06 #2

P: n/a
Thanks for the comments. Yes I am currently doing something similar to the
code on your website but it way to slow. I have to convert 28 128/16
bitmaps and it takes too long on my computer so I know my customers are
going to scream. I'm pretty sure it was faster in .NET 1.1 then 2 but it
what we have now so I was looking for a faster method.

It seemed based on the direction for the Bitmap.Clone function it would
change the pixel format, must have misunderstood.

From BOL:
"Bitmap.Clone (RectangleF, PixelFormat)
Creates a copy of the section of this Bitmap defined with a specified
PixelFormat enumeration."

"Bob Powell [MVP]" <bob@_spamkiller_.bobpowell.net> wrote in message
news:%2******************@TK2MSFTNGP05.phx.gbl...
You can't change the bitmap pixel format like that. That's where the error
is coming from.

If you want to convert an arbitrary bitmap to 1bpp indexed see the GDI+
FAQ.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

"John J. Hughes II" <no@invalid.com> wrote in message
news:u9**************@TK2MSFTNGP03.phx.gbl...
The following code throws a out of memory exception, I have another
function that does the same thing using the bitmap lock but its way slow.
Anyone know how to fix this one?

public static Bitmap GetClonedBitmap(int width, int height, string str,
Font font, StringAlignment Alignment)
{
Rectangle r = new Rectangle(1, 1, width-1, height-1);
using (Bitmap tmpBmp = new Bitmap(width, height))
{
using (Graphics g = Graphics.FromImage(tmpBmp))
{
g.FillRectangle(Brushes.White, r);
using (StringFormat sf = new
StringFormat(StringFormat.GenericDefault))
{
sf.Alignment = Alignment;
sf.Trimming = StringTrimming.None;
sf.LineAlignment = StringAlignment.Center;
sf.FormatFlags = StringFormatFlags.NoWrap;
g.DrawString(str, font, Brushes.Black, r, sf);

return tmpBmp.Clone(r, PixelFormat.Format1bppIndexed);
}
}
}
}

Regards,
John


May 10 '06 #3

P: n/a
"Bob Powell [MVP]" <bob@_spamkiller_.bobpowell.net> wrote:
If you want to convert an arbitrary bitmap to 1bpp indexed see the GDI+ FAQ.


The GDI+ FAQ says to iterate "for y=0 to height, for x=0 to width"
which is terribly slow. This is a shame, because Windows already
contains built-in functionality to convert from arbitrary pixelformat
into 1bpp pixelformat. And it's fast -- my laptop takes just 50ms to
convert a 1024x768 bitmap into monochrome, or just 5ms to convert a
200x200 bitmap.

Here's the code for it. I've written it in C++ using native win32
calls. Hopefully someone can turn it into C#. (I had trouble turning
it into C#, because I couldn't find how to construct a Bitmap() object
from an existing HBITMAP, and I couldn't find how to BitBlt/DrawImage
onto an existing 1bpp Bitmap object.)

HBITMAP CreateMonochromeCopy(HBITMAP hbm_src)
{
// retrieve the size of the original bitmap
DIBSECTION dibs; GetObject(hbm_src,sizeof(dibs),&dibs);
int width=dibs.dsBm.bmWidth, height=dibs.dsBm.bmHeight;
//
// create a new bitmap of the same dimensions with a 1bpp monchrome
palette
typedef struct {BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[2];}
MONOBITMAPINFO;
MONOBITMAPINFO bmi; ZeroMemory(&bmi,sizeof(bmi));
bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth=width;
bmi.bmiHeader.biHeight=height;
bmi.bmiHeader.biPlanes=1;
bmi.bmiHeader.biBitCount=1;
bmi.bmiHeader.biCompression=BI_RGB;
bmi.bmiHeader.biSizeImage=((width+7)&0xFFFFFFF8)*h eight/8;
bmi.bmiHeader.biXPelsPerMeter=1000000;
bmi.bmiHeader.biYPelsPerMeter=1000000;
bmi.bmiHeader.biClrUsed=2;
bmi.bmiHeader.biClrImportant=2;
bmi.bmiColors[0].rgbRed=0; bmi.bmiColors[0].rgbGreen=0;
bmi.bmiColors[0].rgbBlue=0; bmi.bmiColors[0].rgbReserved=0;

bmi.bmiColors[1].rgbRed=255;bmi.bmiColors[1].rgbGreen=255;bmi.bmiColors[1].rgbBlue=255;bmi.bmiColors[1].rgbReserved=0;
void *bits; HBITMAP hbm_dst =
CreateDIBSection(0,(BITMAPINFO*)&bmi,DIB_RGB_COLOR S,&bits,0,0);
//
// BitBlt the original image into the new one. Windows and the
// graphics accelerator will take care of color thresholds &c.
HDC sdc = GetDC(0);
HDC hdc_src = CreateCompatibleDC(sdc);
HDC hdc_dst = CreateCompatibleDC(sdc);
SelectObject(hdc_src,hbm_src);
SelectObject(hdc_dst,hbm_dst);
BitBlt(hdc_dst,0,0,width,height,hdc_src,0,0,SRCCOP Y);
DeleteDC(hdc_src);
DeleteDC(hdc_dst);
ReleaseDC(0,sdc);
//
return hbm_dst;
}

Here's a complete program to watch it in action:

#include <windows.h>

int main()
{ HDC sdc = GetDC(0);
HBITMAP hbm = CreateCompatibleBitmap(sdc,1024,768);
HDC hdc = CreateCompatibleDC(sdc);
SelectObject(hdc,hbm);
RECT rc; rc.left=0; rc.top=0; rc.right=1024; rc.bottom=768;
FillRect(hdc,&rc,(HBRUSH)GetStockObject(WHITE_BRUS H));
SetTextColor(hdc,RGB(255,0,0));
TextOut(hdc,10,10,L"Hello World",11);
DeleteDC(hdc);
//
HBITMAP hbmi[100];
unsigned int time1=GetTickCount();
for (int i=0; i<100; i++) hbmi[i] = CreateMonochromeCopy(hbm);
unsigned int time2=GetTickCount();
unsigned int diff = time2-time1;
//
hdc = CreateCompatibleDC(sdc);
SelectObject(hdc,hbmi[0]);
BitBlt(sdc,0,0,200,200,hdc,0,0,SRCCOPY);
DeleteDC(hdc);
ReleaseDC(0,sdc);
DeleteObject(hbm);
for (int i=0; i<100; i++) DeleteObject(hbmi[i]);
Sleep(2000);
return 0;
}
--
Lucian
May 10 '06 #4

P: n/a
Thanks, will look into it.

"Lucian Wischik" <lu***@wischik.com> wrote in message
news:jg********************************@4ax.com...
"Bob Powell [MVP]" <bob@_spamkiller_.bobpowell.net> wrote:
If you want to convert an arbitrary bitmap to 1bpp indexed see the GDI+
FAQ.


The GDI+ FAQ says to iterate "for y=0 to height, for x=0 to width"
which is terribly slow. This is a shame, because Windows already
contains built-in functionality to convert from arbitrary pixelformat
into 1bpp pixelformat. And it's fast -- my laptop takes just 50ms to
convert a 1024x768 bitmap into monochrome, or just 5ms to convert a
200x200 bitmap.

Here's the code for it. I've written it in C++ using native win32
calls. Hopefully someone can turn it into C#. (I had trouble turning
it into C#, because I couldn't find how to construct a Bitmap() object
from an existing HBITMAP, and I couldn't find how to BitBlt/DrawImage
onto an existing 1bpp Bitmap object.)

HBITMAP CreateMonochromeCopy(HBITMAP hbm_src)
{
// retrieve the size of the original bitmap
DIBSECTION dibs; GetObject(hbm_src,sizeof(dibs),&dibs);
int width=dibs.dsBm.bmWidth, height=dibs.dsBm.bmHeight;
//
// create a new bitmap of the same dimensions with a 1bpp monchrome
palette
typedef struct {BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[2];}
MONOBITMAPINFO;
MONOBITMAPINFO bmi; ZeroMemory(&bmi,sizeof(bmi));
bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth=width;
bmi.bmiHeader.biHeight=height;
bmi.bmiHeader.biPlanes=1;
bmi.bmiHeader.biBitCount=1;
bmi.bmiHeader.biCompression=BI_RGB;
bmi.bmiHeader.biSizeImage=((width+7)&0xFFFFFFF8)*h eight/8;
bmi.bmiHeader.biXPelsPerMeter=1000000;
bmi.bmiHeader.biYPelsPerMeter=1000000;
bmi.bmiHeader.biClrUsed=2;
bmi.bmiHeader.biClrImportant=2;
bmi.bmiColors[0].rgbRed=0; bmi.bmiColors[0].rgbGreen=0;
bmi.bmiColors[0].rgbBlue=0; bmi.bmiColors[0].rgbReserved=0;

bmi.bmiColors[1].rgbRed=255;bmi.bmiColors[1].rgbGreen=255;bmi.bmiColors[1].rgbBlue=255;bmi.bmiColors[1].rgbReserved=0;
void *bits; HBITMAP hbm_dst =
CreateDIBSection(0,(BITMAPINFO*)&bmi,DIB_RGB_COLOR S,&bits,0,0);
//
// BitBlt the original image into the new one. Windows and the
// graphics accelerator will take care of color thresholds &c.
HDC sdc = GetDC(0);
HDC hdc_src = CreateCompatibleDC(sdc);
HDC hdc_dst = CreateCompatibleDC(sdc);
SelectObject(hdc_src,hbm_src);
SelectObject(hdc_dst,hbm_dst);
BitBlt(hdc_dst,0,0,width,height,hdc_src,0,0,SRCCOP Y);
DeleteDC(hdc_src);
DeleteDC(hdc_dst);
ReleaseDC(0,sdc);
//
return hbm_dst;
}

Here's a complete program to watch it in action:

#include <windows.h>

int main()
{ HDC sdc = GetDC(0);
HBITMAP hbm = CreateCompatibleBitmap(sdc,1024,768);
HDC hdc = CreateCompatibleDC(sdc);
SelectObject(hdc,hbm);
RECT rc; rc.left=0; rc.top=0; rc.right=1024; rc.bottom=768;
FillRect(hdc,&rc,(HBRUSH)GetStockObject(WHITE_BRUS H));
SetTextColor(hdc,RGB(255,0,0));
TextOut(hdc,10,10,L"Hello World",11);
DeleteDC(hdc);
//
HBITMAP hbmi[100];
unsigned int time1=GetTickCount();
for (int i=0; i<100; i++) hbmi[i] = CreateMonochromeCopy(hbm);
unsigned int time2=GetTickCount();
unsigned int diff = time2-time1;
//
hdc = CreateCompatibleDC(sdc);
SelectObject(hdc,hbmi[0]);
BitBlt(sdc,0,0,200,200,hdc,0,0,SRCCOPY);
DeleteDC(hdc);
ReleaseDC(0,sdc);
DeleteObject(hbm);
for (int i=0; i<100; i++) DeleteObject(hbmi[i]);
Sleep(2000);
return 0;
}
--
Lucian

May 11 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.