|
I believe you need to write out the following
file header
info header
palette
image data
the palette is a series of colors (RGB), but this is only used if you're using a palette. if you choose 8-bit color, then your image data will consist of indices into this palette.
in your example, however, you showed 24-bit color. this means you don't need a palette. instead your image data specifies the red-green-blue for each pixel. so for a 24-bit image, i think you'd write the following to the file:"
file header
info header
image data
when you write out the image data, you write each row of pixels. after each row, you may need to write padding bytes as I _think_ each row needs to be aligned on certain byte boundary (not 100% certain about this, but I remember somewhere having to do this). for each pixel, you'll write out 1 byte each for red green and blue (can't remember the order) value.
|
|
|
|
|
again, thank you Dave for your reply
ok I found how to write data into the file and I removed the palette. The result is a bitmap but the colors seems to be "random". I suppose it's because of the order of the bits and the byte boundary you were talking about
so whit a small 2x2 image, these value:
hp[0] = 0xFF;
hp[1] = 0x00;
hp[2] = 0x00;
hp[4] = 0xFF;
hp[5] = 0x00;
hp[6] = 0x00;
hp[9] = 0xFF;
hp[10] = 0x00;
hp[11] = 0x00;
hp[13] = 0xFF;
hp[14] = 0x00;
hp[15] = 0x00;
Gave me a
Magnenta - Orange
Blue - Magnenta
but it was supposed to be the same color everywhere. Do you have a clue on this?
|
|
|
|
|
If you're not seeing the same color throughout the image, then as you said its probably an alignment issue. I looked around and was unable to find the docs I used way back when when I was doing something similar.
Note that there might be an easier way to do this. The CImage class will save to the DIB (.bmp) file as well as a ton of other formats. So, if you can get your image into a CImage, you can then let it do the saving for you.
Since you're writing directly to the bits, I'd say get your image into a DIB section and select that DIB section into a device context. Then create a regular bitmap of the same size and select that into another device context. Then just blt from the one to the other. Now you could use the CImage stuff to save it to disk and not worry about the file format stuff.
Granted, this assumes you've correctly constructed the image in memory to begin with, which won't be the case if you don't properly align each row of pixels in memory. So, you still have to solve that problem, but this would at least do the file format stuff for you. Plus it opens up t he other file formats (.jpg, .gif, .png, etc.).
|
|
|
|
|
I finally got it to, but i dont really know how. Now my code look like this and it saves a beautiful fractal image. Maybe my alignement issue was just a syntax error :s... but... I wonder where is the byte alignement in this code ...??? I'm computing each point at a time, and I write 3 BYTEs (for R , G, B) in a byte array, then i write the whole thing in the file.
int xsize = 1000;
int ysize = 1000;
BYTE* a = new BYTE[xsize*ysize*4*3];
int smaller;
if (ysize < xsize)
smaller = ysize;
else
smaller = xsize;
double value = 1/double(smaller);
for(int y = -ysize; y < ysize; ++y){
for(int x = -xsize; x < xsize; ++x){
double realx = double(x)*value;
double realy = double(y)*value;
int iteration = Mandelbrot( realx, -realy, 1024);
COLORREF color;
color = ColorSelector(iteration,0,512,
0,true,0,255,0);
a[((y+ysize)*(xsize*2)+(x+xsize))*3] = GetBValue(color);
a[((y+ysize)*(xsize*2)+(x+xsize))*3+1] = GetGValue(color);
a[((y+ysize)*(xsize*2)+(x+xsize))*3+2] = GetRValue(color);
}
}
BITMAPFILEHEADER hdr;
BITMAPINFOHEADER bi;
CFile file;
file.Open( "C:\\test.dib", CFile::modeWrite|CFile::modeCreate);
bi.biBitCount = 24;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
bi.biCompression = BI_RGB;
bi.biHeight = -ysize*2;
bi.biPlanes = 1;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biSizeImage = 0;
bi.biWidth = xsize*2;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
hdr.bfType= ((WORD) ('M' << 8) | 'B');
hdr.bfSize= sizeof(bi) + sizeof(hdr);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits= (DWORD) (sizeof(hdr) + bi.biSize);
file.Write( &hdr, sizeof(hdr) );
file.Write( &bi, sizeof(bi) );
file.Write( a, sizeof(BYTE)*xsize*ysize*4*3 );
file.Close();
I would like to try the CImage trick, cause i don't feel 100% confortable manually playing with bytes... but is it a .NET feature? Cause im still using VC6.
|
|
|
|
|
|
I have a COM dialog where the enter (Return) key kills the dialog rather than activiating the focused button. I cant figure out whats wrong. Any ideas?
GER
-- modified at 19:18 Friday 25th August, 2006
The app is VC++6.0 using MFC
Ger
|
|
|
|
|
Just a guess, but see here[^].
I Dream of Absolute Zero
|
|
|
|
|
Do you manually set focus using SetFocus() instead of WM_NEXTDLGCTL? Is the button a standard button that is returning DLGC_BUTTON in response to WM_GETDLGCODE?
|
|
|
|
|
Could somebody explain how this works and what it does. I know it can be used to declare a base class, but I have now come across it in another location and I can't work out what it does.
class Error<br />
{<br />
public:<br />
Error(const int nErrCode, char* szErrMess);<br />
Error(const Error& e);<br />
private:<br />
int mnErrCode;<br />
char* mpszErrMess;<br />
};<br />
<br />
Error::Error(const int nErrCode,char* szErrMess) : mnErrCode(nErrCode)<br />
{<br />
}<br />
<br />
Error::Error(const Error& e) : mnErrCode(e.mnErrCode)<br />
{<br />
}
|
|
|
|
|
Hi,
I believe you mean the two following occurances
waldermort wrote: Error::Error(const int nErrCode,char* szErrMess) : mnErrCode(nErrCode)
...
Error::Error(const Error& e) : mnErrCode(e.mnErrCode)
When using the colon ':' after a constructor you open an initialisation list.
This means that member like mnErrCode are initialised with the given error code even before you enter the scope of the constructor.
codito ergo sum
|
|
|
|
|
So it's basically the same as placing mnErrCode = nErrCode; inside the c'tor? I have to ask, what is the point of doing this?
|
|
|
|
|
In this case, probably just convenience. But lets say you have a member that is a class object that doesn't have a default constructor.
|
|
|
|
|
supose the following situation
class A
{
public:
A(int i)
{
_i = i;
}
int _i;
};
class B
{
public:
B() {}
A _a;
};
class C
{
public:
C() : _a(1) {}
A _a;
};
Now when maken an object of the type C the default constructor (of C) will initialize _a and
calling the correct constructor of the member _a
You might want to check the following http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6[^]
codito ergo sum
|
|
|
|
|
Ahhh, I understand perfectly now. Thankyou for the explanation.
Infact I now remember seeing and using this before, when using STL containers within a class, I remember first having to initialize them like this before being able to use them.
-- modified at 20:20 Friday 25th August, 2006
|
|
|
|
|
Hello All,
Can someone recommend a great skinning software that is stable, compatible with VC++ and MFC, works, and has a good collection of stock skins? I need it for a project and I am having a difficult time finding a good skinning package.
Any help or direction you provide would be greatly appreciated.
Thanks,
BP
|
|
|
|
|
|
I'm using SHFileOperation to copy some files. If I set pFrom to a string with multiple, fully quailified filenames, seperated by a NULL with an additional NULL character at the end and pTo to a string with a fully qualified directory with the extra NULL character, it works fine.
If my pFrom is only 1 fully quailified filename with the extra NULL character at the end, SHFileOperation instead makes a file with the pTo directory name of the size of the source file.
Example...
pFrom = c:\pictures\pic1.jpg, c:\pictures\pic2.jpg, etc...
pTo = d:\jpg
When I check the drive, I'll have d:\jpg folder containing all my files pic1.jpg, pic2.jpg, etc.
If I'm only copying 1 file,
pFrom = c:\pictures\pic1.jpg
pTo = d:\jpg
This time, I'll check the drive and I'll have file called jpg in d:\ with the size of pic1.jpg. I'm pulling my hair out trying to figure out whats going on. I've checked and I have the buffers set up correctly with additional NULLs at the ends etc. Anyone know what the problem is?
Thanks,
Steve
|
|
|
|
|
I don't think much of the title to your post!
|
|
|
|
|
Sorry, I was pretty frustrated when I wrote it.
|
|
|
|
|
Have you tried sticking a '\' at the back of pTo? eg. pTo = d:\jpg\.
|
|
|
|
|
Thanks. I tried that and it and with the extra "\", it's not a vailid file name and generates an error.
|
|
|
|
|
Then I guess that your only alternative is to set pTo to d:\jpg\pic1.jpg
|
|
|
|
|
I need help. How can I use Visual C++ to copy a bitmap to the clipboard using OLE?
|
|
|
|
|
|
I tried the following:
BOOL CMyFormView::PutDataToClipboard(CBitmap *pBmp)
{
COleDataSource *pods = new COleDataSource;;
HBITMAP hBmp = (HBITMAP) *pBmp;
int i = sizeof(*pBmp);
HANDLE hData = ::GlobalAlloc(GMEM_FIXED, sizeof(*pBmp));
CBitmap* pData = (CBitmap*) ::GlobalLock (hData);
pData = pBmp;
BOOL l = ::GlobalUnlock(hData);
STGMEDIUM stg;
stg.tymed = TYMED_GDI;
stg.hBitmap = hBmp;
stg.pUnkForRelease = NULL;
// Place the data object on the OLE clipboard.
CFormApp* ab = (CFormApp*)AfxGetApp();
pods->CacheData(CF_BITMAP, &stg);
pods->SetClipboard();
//ab->pods->CacheData (CF_BITMAP, &stg);
//ab->pods->SetClipboard ();
delete pods;
return TRUE;
}
I'm unable to paste the bitmap in mspaint (and other places). Any ideas?
-- modified at 15:20 Tuesday 29th August, 2006
|
|
|
|