Solved

create a bmp header at byte level

Posted on 2004-04-28
9
465 Views
Last Modified: 2012-06-21
hi,
I'm relateively new to C# and very new to it's byte and stream methods so this task is beyond me.
What I'm trying to do is read image information out of a sql DB stored as byte data.  The image information is raw dib.  I'd like to convert this to bmp and post it to a form image box so i need at add bmp header information to it.  This is where I'm lost.  I've done this is PHP but I don't know how to convert it to C#.  Here's the PHP code:

$info = unpack("lwidth/lhight/Splanes/Sbitcount/Lcompression/Lsizeimage/lxpelspermeter/lypelspermeter/Lclrused/lclrimportant",$av_image);
$offset = 54 + ($info['clrused'] * 4);
$header = pack("cclssL", ord('B'), ord('M'), strlen($av_image)+14, 0, 0, $offset, 40); // type(2), size, reserved, reserved, offset, header_size

So basically what I am doing is extracting the "clrused" value (unsigned long, 4 bytes) information from the dib and using the value to create "offset".  Then creating the header (char, char, long, short shot, long).

This header is then added to a memory stream followed by the dib data.

This is what I have so far, but it's a mess and no where near complete:

byte[] data = (byte[])myCommand.ExecuteScalar();
MessageBox.Show(Convert.ToString(data.Length), "Database");
if(data.Length > 0)
{                        
// Open a stream for the image and write the bytes into it
System.IO.MemoryStream stream = new System.IO.MemoryStream(data, true);
stream.Write(data, 0, data.Length);

byte[] clrused = new byte[4];
stream.Read(clrused, 28, 4);
int offset = 54 + (Convert.ToInt32(clrused) * 4);
                              
//stream.Write(data, 0, data.Length);
           
// Create a bitmap from the stream
Bitmap bmp = new Bitmap(stream);

// Close the stream
stream.Close();

return bmp;
}

Thanks for the help!
0
Comment
Question by:NGDESL
  • 4
  • 3
9 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 10945812
If this information is raw dib, possibly bitmap header is kept in the BITMAPINFO structure. In this case you can create such bitmap using CreateDIBSection API and fill it's bits using SetBitmapBits function. After this you can create Bitmap from HBITMAP.
0
 

Author Comment

by:NGDESL
ID: 10948989
bump, with point increase.  Need some help, even if it's just pointing me in the right direction.
0
 

Author Comment

by:NGDESL
ID: 10950465
sorry, i'm not to familiar with this.  Are there any code examples i can look at?
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
LVL 48

Expert Comment

by:AlexFM
ID: 10951380
Can you describe format of this image? What is "raw dib"?
0
 

Author Comment

by:NGDESL
ID: 10951822
The image has the BITMAPINFOHEADER data already incorporated into it.  BITMAPINFOHEADER  is the following:

private class BITMAPINFOHEADER
               {
                    public int          biSize;
                    public int          biWidth;
                    public int          biHeight;
                    public short     biPlanes;
                    public short     biBitCount;
                    public int          biCompression;
                    public int          biSizeImage;
                    public int          biXPelsPerMeter;
                    public int          biYPelsPerMeter;
                    public int          biClrUsed;
                    public int          biClrImportant;
               }

Basically, I'm just trying to add the BITMAPFILEHEADER information to the beginning of the byte stream:

private class BITMAPFILEHEADER
               {
                    [MarshalAs( UnmanagedType.ByValArray, SizeConst=2)]
                    public Char[]     Type;
                    public Int32     Size;
                    public Int16     reserved1;
                    public Int16     reserved2;
                    public Int32     OffBits;
               }

I don't think this is very complicated, but I haven't delt with byte data in C# so I'm not really sure how to go about this.  Is BITMAPFILEHEADER a known struct type or do you have to declare it?  Thanks
0
 

Author Comment

by:NGDESL
ID: 10954143
Here's what I have come up with:

byte[] data = (byte[])myCommand.ExecuteScalar();
System.IO.MemoryStream stream = new System.IO.MemoryStream(data.Length);
int offset = 54 + (BitConverter.ToInt32(data, 28) * 4);
stream.Write(BitConverter.GetBytes('B'), 0, BitConverter.GetBytes('B').Length);
stream.Write(BitConverter.GetBytes('M'), 0, BitConverter.GetBytes('M').Length);
stream.Write(BitConverter.GetBytes(data.Length+14), 0, BitConverter.GetBytes(data.Length+14).Length);
stream.Write(BitConverter.GetBytes(0), 0, 4);
stream.Write(BitConverter.GetBytes(0), 0, 4);
stream.Write(BitConverter.GetBytes(offset), 0, 4);
stream.Write(BitConverter.GetBytes(40), 0, 4);
stream.Write(data, 0, data.Length);
Bitmap bmp = new Bitmap(stream);

it throws an ArgumentException every time on the "Bitmap bmp = new Bitmap(stream);" line and i have no idea why.
0
 
LVL 48

Accepted Solution

by:
AlexFM earned 500 total points
ID: 10958096
Bitmap file has the following structure:

1) BITMAPFILEHEADER structure.
Type is BM
bfSize is whole bitmap file size - you need to count it
bfOffBits is offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits - you need to count it.

2) BITMAPINFO structure which contains:

BITMAPINFOHEADER structure - this is what you already have
RGBQUAD structure - 4 bytes.

If bitmap has color palette, palette members are placed immidiately after BITMAPINFO structure. For example, if bitmap has 256-colors palette, additional 255 RGBQUAD structures are placed after BITMAPINFO (BITMAPINFO contains one structure). If bitmap doesn't contain palette, BITMAPINFO still contails one RGBQUAD member (not used).

3) Bitmap bits which are placed immidialely after color palette or BITMAPINFO structure.

Your stream contains BITMAPINFOHEADER structure. Nice, does it contain also color palette and bitmap bits? Assuming that it contains all this exactly as in bitmap file, all you need is to add BITMAPFILEHEADER to the beginning and count it's bfSize and bfOffBits members. Possibly bfSize is equal to stream size + sizeof(BITMAPINFOHEADER). To count bfOffBits, you need to use BITMAPINFOHEADER.biClrUsed member. Read it's description in MSDN.
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
We all know that functional code is the leg that any good program stands on when it comes right down to it, however, if your program lacks a good user interface your product may not have the appeal needed to keep your customers happy. This issue can…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

789 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question