|
The book 3D Computer Graphics, by Alan Watt, published by Addison Wesley, is really excellent.
|
|
|
|
|
I'm using GDI+, and want to edit the pixels of an 8 bit-per-pixel, grayscale bitmap which I read from a file. I can get the pixels using the Bitmap::LockBits and BitmapUnlockBits methods and a BitmapData object. However, there doesn't seem to be any support for 8 bit-per-pixel bitmaps that do not necessarily use a palette (i.e. grayscale).
I see that the pixel format can be set to PixelFormat8bppIndexed, and used along with a palette (the palette type can even be set to PaletteFlagsGrayScale). However, it is unnecessary to use a palette with these bitmaps, as the palette just contains all possible gray levels. It seems inefficient to have to associate a palette with these bitmaps and pass it back and forth each time the pixels are retrieved (the pixels are frequently and repeatedly passed back and forth for editing in my program).
Does anyone know:
1) Are there any other flags or methods for using BitmapData objects with 8 bit-per-pixel grayscale bitmaps but without a palette?
2) When the PaletteFlagsGrayScale flag is used, can I assume the palette entries are always the same (all possible gray levels)? Or can they be re-scaled? (I understand that these entries are DWORDs using alpha | red | green | blue, with the red, green and blue values equal to each other.)
Thanks!
|
|
|
|
|
Hi,
I have a windows CE device for which I am wrinting a C# .Net CF 2.0 application.
This device has an inclinometer chip connected to it, which reads the angles my device is at, and sends me the X and Y tilt values of the inclinometer.
Depending on those values, I want to display a picture. (.png). For now now I'm just using the X value (tiltX global variable)
The image is being updated every 150ms
So for a prototype I've being doing the following:
//TiltX is being passed in to RotateGauge as an Int.
private void RotateGauge(int side)
{
if (side > -5 & side < 5)
{
string number = Convert.ToString(side);
Stream sidePic = _assembly.GetManifestResourceStream("Rotate_Test.images.gauge.sideTilt" + (number) + ".png");
Bitmap bmp = new Bitmap(sidePic);
Graphics g = CreateGraphics();
g.DrawImage(bmp, 42,116); //draw image
bmp.Dispose();
sidePic.Close();
g.Dispose();
}
}
The above function RotateGauge() gets called from a timer. (interival 150ms)
The problem is its using up a lot of memory. I don't think I'm properly disposing of things.
Any suggestions how to : Efficiently rewrite the above code so when something gets created on a timer_tick it also gets disposed of properly
|
|
|
|
|
Hi,
I don't see anything wrong with your object disposal, so I expect the garbage collector
will clean up memory if need be.
However I think you are spending way too much CPU power to achieve your goals. This is
how I would do it:
- replace the PictureBox by a simple Panel (or an inherited Panel that sets its
ControlStyles to double-buffered for better graphics);
- do the drawing in the Panel's OnPaint method, based on a single class member (int side);
it gives you a Graphics for free (which you should not dispose!);
- when you want to change the gauge, change the variable (side) and call your Panel's
Invalidate method
If you only have a dozen PNG images, you may even consider keeping them alive in memory
all the time.
|
|
|
|
|
Hey Luc. Congratulations on your MVP status. It's well deserved.
|
|
|
|
|
Hi Pete, thanks. Congrats to you too.
I see several of us have reached the next station.
Mine came as a surprise, wasn't aware how many there would be, but even then...
|
|
|
|
|
Luc Pattyn wrote: Mine came as a surprise
Not to me. I had good money riding on you getting it.
It's nice not to have the yokel icon beside the names now. I like being a yellow diamond.
|
|
|
|
|
Pete O'Hanlon wrote: I had good money riding on you getting it.
Who is taking those bets? is that what is going on in the dark hours at the lounge?
Pete O'Hanlon wrote: It's nice not to have the yokel icon beside the names now. I like being a yellow diamond
Had to look that up, but I fully agree; it was/is not the nicest icon available.
BTW I think the golden diamond writer personality title I currently carry is the one I
like most (prolific fixture sounds really weird to me, I'll try to avoid it).
|
|
|
|
|
forgot to mention, I did notice how you skilfully reverted the topic to make it really fit
the graphics forum. A worthy diamond.
|
|
|
|
|
Hi Luc,
Thanks for your reply. I got overly excited when I saw 6 replies to my post as i've spent a lot of time trying to figure this out.
I attempted what you suggested, however the Compact Framework has me limited in what I can do.
The line of code I hoped to use for drawing in the panel is
g = panel1.CreateGraphics();
however, CreateGraphics is not availble to my panel in the CF. I'll keep looking, I'm very new to c# (programming in general) so there may be a solution for me somewhere.
Regards
Gemma
|
|
|
|
|
Hi, maybe you should read my original reply once more. The whole point was NOT to use
CreateGraphics, but OnPaint() instead.
|
|
|
|
|
Hi Luc,
I've since gone off and done some reading on .net CF graphics, in the process I came across some code which I've implemented into my project.
private Bitmap LoadBitmapResource(string strName)
{
Assembly assembly = Assembly.GetExecutingAssembly();
string strRes = "Rotate_Test.images.gauge." + strName;
Stream stream = assembly.GetManifestResourceStream(strRes);
Bitmap bmp = null;
try
{
bmp = new Bitmap(stream);
}
catch { }
stream.Close();
return bmp;
}
private void DisposeBitmap(ref Bitmap bmp)
{
if (bmp != null)
{
bmp.Dispose();
}
bmp = null;
}
In the Panel Paint method I have the following.
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
DisposeBitmap(ref bmpDraw);
//Get the Bitmap to draw
bmpDraw = LoadBitmapResource("backTilt" + (strResNum) + ".bmp");
g.DrawImage(bmpDraw, 10, 10);
}
The above is still using up memory for every image which is displayed, it seems like nothing is being freed up. I haven't started looking at double buffering as for now I'm more concerned with relasing the memory used.
Thanks for your suggestion
regards
Gemma
|
|
|
|
|
Hi Gemma,
1.
your code looks fine to me, with one comment: if every OnPaint does a Disposeand a Load,
and assuming bmpDraw is not used elsewhere, why not do it after the DrawImage (hence:
load,draw,dispose)?
2.
calling Dispose is good, it frees unmanaged resources immediately (if any), and marks
managed objects for garbage collection, which only occurs when the garbage collector feels
a need (i.e. when memory is low when a new object is being created, say in a "new" statement).
So it is not abnormal to see a high memory usage, as long as it comes down every so often,
and does not lead to an "out of memory" situation.
As a test, you could add a big object to your main class (to occupy memory) and see
how well the app does under those circumstances, so add a line such as:
private byte[] dummyBytes=new byte[1024*1024]; // permanently occupies 1MB
3.
If you are still not satisfied, here are some questions:
- what is it that makes you worry?
- how many images are there?
- how big is each image (in pixels and in file size)?
Luc Pattyn [Forum Guidelines] [My Articles]
This month's tips:
- before you ask a question here, search CodeProject, then Google;
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get;
- use PRE tags to preserve formatting when showing multi-line code snippets.
|
|
|
|
|
Thanks for the useful information and checking my code for me.
I've no peers to learn from or show my code to, (one man show here) so its great to get advice.
|
|
|
|
|
You're welcome.
Luc Pattyn [Forum Guidelines] [My Articles]
This month's tips:
- before you ask a question here, search CodeProject, then Google;
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get;
- use PRE tags to preserve formatting when showing multi-line code snippets.
|
|
|
|
|
Below is the code snippet i use to create the gray scale image (8bpp) from scratch using CreateDIBSection and displays it onto the screen.
Image that is displayed has most of it data grey in color and the image data seems to be merged with lot of noise... I doubt the issue is with the image creation....
need some help on this, all help appreciated
Let me know the flaws in the code, I am new to Windows graphic programming.
btw, i work with MFC
Code :
struct ImageData
{
int rows;
int cols;
int bpp;
.
.
.
.
.
.
}; // Other fields are not relevant for Image Display
int pixmap[256]; // Palette to be used
ImageData curimage; // Member Variable in the App Dialog Class
void CExampleDlg::SetBitmapInfo (LPBITMAPINFO DIB_info, ImageData *imageptr)
{
DIB_info->bmiHeader.biSize = 40;
DIB_info->bmiHeader.biPlanes = 1;
DIB_info->bmiHeader.biBitCount = imageptr->bpp; // only 8 (handling only 8bpp images)
DIB_info->bmiHeader.biWidth = imageptr->cols;
DIB_info->bmiHeader.biHeight = imageptr->rows;
DIB_info->bmiHeader.biCompression = BI_RGB;
DIB_info->bmiHeader.biSizeImage = imageptr->rows * imageptr->cols;
DIB_info->bmiHeader.biXPelsPerMeter = 0;//0xb12; //(72ppi)
DIB_info->bmiHeader.biYPelsPerMeter = 0;//0xb12;
DIB_info->bmiHeader.biClrUsed = 256;
DIB_info->bmiHeader.biClrImportant = 256;
DIB_info->bmiColors[0].rgbBlue = 0;
DIB_info->bmiColors[0].rgbGreen = 0;
DIB_info->bmiColors[0].rgbRed = 0;
DIB_info->bmiColors[0].rgbReserved = 0;
}
void CExampleDlg::GetDIBmp (unsigned char *bmp,
CBitmap *pimage,
ImageData *imageptr,
int height,
int width)
{
BITMAPINFO DIB_info;
HBITMAP hBitmap = NULL;
HDC hMemDC = NULL;
HGDIOBJ hOldObj = NULL;
// Set the BitmapInfo
SetBitmapInfo (&DIB_info, imageptr);
DIB_info.bmiHeader.biHeight = height;
DIB_info.bmiHeader.biWidth = width;
hMemDC = ::CreateCompatibleDC(NULL);
// create device independent bitmap section
hBitmap = ::CreateDIBSection(hMemDC,
&DIB_info,
DIB_RGB_COLORS,
NULL,
NULL,
SRCCOPY);
if ( !hBitmap )
{
exit (-1);
}
DIB_info.bmiHeader.biHeight = imageptr->rows;
DIB_info.bmiHeader.biWidth = imageptr->cols;
//CreateDIBTable (DIB_info,hMemDC,bmp);
hOldObj = ::SelectObject(hMemDC, hBitmap);
StretchDIBits(hMemDC, 0, 0,
width, height, 0, 0,
DIB_info.bmiHeader.biWidth,
DIB_info.bmiHeader.biHeight,
bmp,&DIB_info,
DIB_RGB_COLORS,
SRCCOPY);
// restore DC object
::SelectObject(hMemDC, hOldObj);
// clean up
::DeleteObject(hMemDC);
pimage->Attach(hBitmap);
}
void CExampleDlg::GetPalette (BITMAPINFO DIB_info,
CBitmap *bitmap,
CPalette *pal)
{
unsigned long nColors = DIB_info.bmiHeader.biClrUsed;
// Create a halftone palette if colors > 256.
CClientDC dc(NULL); // Desktop DC
if( nColors > 256 )
pal->CreateHalftonePalette( &dc );
else
{
// Create the palette
RGBQUAD *pRGB = new RGBQUAD[nColors];
CDC memDC;
memDC.CreateCompatibleDC(&dc);
memDC.SelectObject( bitmap );
::GetDIBColorTable( memDC, 0, nColors, pRGB );
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries = nColors;
for( int i=0; i < nColors; i++)
{
pLP->palPalEntry[i].peRed = pixmap[i];
pLP->palPalEntry[i].peGreen = pixmap[i];
pLP->palPalEntry[i].peBlue = pixmap[i];
pLP->palPalEntry[i].peFlags = 0;
}
pal->CreatePalette( pLP );
delete[] pLP;
delete[] pRGB;
}
}
void CExampleDlg::CreateDIBTable (BITMAPINFO DIB_info,HDC hMemDC,
unsigned char *bmp)
{
if (DIB_info.bmiHeader.biBitCount <= 8)
{
HPALETTE hPalette =
(HPALETTE) GetCurrentObject(hMemDC, OBJ_PAL);
if (hPalette)
{
PALETTEENTRY pPaletteEntries[0x100];
UINT nEntries = GetPaletteEntries(hPalette,
0, DIB_info.bmiHeader.biClrUsed,
pPaletteEntries);
if (nEntries)
{
ASSERT(nEntries <= 0x100);
for (UINT nIndex = 0; nIndex < nEntries; nIndex++)
{
pPaletteEntries[nIndex].peRed = pixmap [nIndex];
pPaletteEntries[nIndex].peGreen = pixmap [nIndex];
pPaletteEntries[nIndex].peBlue = pixmap [nIndex];
pPaletteEntries[nIndex].peFlags = 0;
}
int entries = SetDIBColorTable(hMemDC, 0,
0x100, (RGBQUAD*) pPaletteEntries);
VERIFY(entries == nEntries);
}
}
}
}
void CExampleDlg::ShowImage()
{
unsigned char *bmp;
CGdiObject *oldDC;
BITMAPINFO dib;
bmp = ViewImage(&curimage);
CBitmap *pimage = new CBitmap;
GetDIBmp (bmp,pimage,&curimage,
100 /* Height */,
100 /* Width */);
// Identifies the device context(dialog) of client area
CPaintDC dc(this);
CDC pMemDC;
pMemDC.CreateCompatibleDC ( &dc );
oldDC = pMemDC.SelectObject ( pimage );
CPalette pal;
this->GetPalette (dib,pimage,&pal);
if((dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE) && pal.m_hObject != NULL )
{
dc.SelectPalette( &pal, FALSE );
int entry = dc.RealizePalette();
}
dc.StretchBlt (30,30,
100,
100,
&pMemDC,
0,
0,
curimage.cols,
curimage.rows,
SRCCOPY);
::SelectObject (pMemDC.m_hDC,oldDC);
DeleteObject (pMemDC.m_hDC);
delete []bmp;
delete pimage;
}
|
|
|
|
|
There's a bunch of problems there, but the biggest one I immediately
see is in CExampleDlg::GetDIBmp().
Instead of
BITMAPINFO DIB_info;
you need to add room for the 256 entry color table you've specified when
creating the DIBSection, something like:
BITMAPINFO *pDIB_info = (BITMAPINFO *)new BYTE[sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255];
...
delete[] (BYTE*)pDIB_info;
You can then iterate through the DIB_info->bmiColors[] array and set the
color table to grayscale values...
for (int i = 0; i < 256; i++)
{
DIB_info->bmiColors[i].rgbBlue = i;
DIB_info->bmiColors[i].rgbGreen = i;
DIB_info->bmiColors[i].rgbRed = i;
DIB_info->bmiColors[i].rgbReserved = 0;
}
Then create the DIB section.
You may be able to simplify this whole thing....
What format is the ImageData pixels data? Is it already 8-bit grayscale
or is it 8-bit indexes into a color palette? Do you eventually want to be able to
convert 24-bit RGB to 8 bit grayscale?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
ImageData contains 8bpp image without palette entries(Raw Data)...and thanks now my image is being displayed without any color blended with it.. but i am curious about other flaws in the code.. I would be grateful if you may take your time to point out few i know you are really busy out there but it would help a rookie to learn
|
|
|
|
|
my lighting model is happy when rendering built in object such as teapot. My own model is tesselated and does not repond properly to the same material settings. ie: dull,no specular response other than utter glare and in general the object ( a gear) is washed out.
I have the text books but examples are limited.
Any advice appreciated.
Bill
|
|
|
|
|
Do you have the normals set properly in your model? How does the size of your model compare to the size of the teapot, i.e. is it larger so that you're now too close to the light(s)?
|
|
|
|
|
Thank you Tim.
The size and position were correct as I made them that way to discover the possibilty you mentioned.
The normals; oh the normals, I had them wrong polarity pointing to the inside of my model. All three planes were wrong and now they are not. Thanks again.
Bill P
|
|
|
|
|
Hi all,
I have a problem that the directshow graph signals complete before the source file has ended.
The code looks like this:
while (nCode != EC_COMPLETE)
{
pMediaEvent->WaitForCompletion(1000, &nCode);
....
}
pMediaControl->StopWhenReady()
So, when I am getting the EC_COMPLETE from the graph I stop it. The only problem is that the encoding still in progress and the file is still (half) full.
I realy want to know how this event works? Who/What signals it? Is it a Mux/sink filter responsibility or the source filter/Demux responsibility?
Thanks,
Y
|
|
|
|
|
HI
check for EC_ERRORABORT also
The filter grapg manager sends this notification to the application when all streams are completely rendered.
|
|
|
|
|
Hi all,
I am new in DirectX.
I am using Axiom Engine to develop small 3D application using DirectX 9 (February 2007) released with C#.
I wana load .X File in my application.
But how can load?
is there any source code or link for DirectX C#?
Can any one please help me.
Thanks in advance.
|
|
|
|
|
Im not sure about examples using that engine, but a quick google search comes up with plenty of beginner tutorials for DirectX.
If your using C++ I'd recommend this site which provides step by step explanations of the basics.
If you using C# I'd recommend downloading the XNA framework, learning the basics there, and then maybe later working your way back into the more difficult languages. DirectX in C++ in particular can be a big learning curve and the endless errors may eat away at your motivation. XNA is pretty easy and has alot of good examples and (easily understood) documentation, so the fun aspect will stick.
If your still content on using DirectX instead of XNA in C#, then I used the rocket commander tutorials on the microsoft website (coding for fun section).
Mark.
|
|
|
|
|