Hi,
The compact framework does not currently implement the image.save
method, try this code snippet instead...fortunately I don't work for
Microsoft and am not MSFT, just a meer grunt ;P
Chris.
/// <summary>
/// Saves an image (image) at the location defined (szPath). This
uses the generic
/// 24-bit format, so the image is not compressed.
/// </summary>
/// <param name="image">The bitmap image to store</param>
/// <param name="szPath">The path to save at</param>
public void SaveBitmapToFile(Image image, string szPath)
{
FileStream fs = File.Create(szPath);
SaveBitmapToStream(image, fs);
fs.Close();
}
/// <summary>
/// Saves an image (image) at the location defined (szPath). This
uses the generic
/// 24-bit format, so the image is not compressed.
/// </summary>
/// <param name="image">The bitmap image to store</param>
/// <param name="stream">The stream to save to</param>
public void SaveBitmapToStream(Image image, Stream stream)
{
/*
* Sort of from
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_4v1h.asp.
* The below is hardcoded to support saving a 24-bit bitmap. Slight
changes would be made to certain
* constants in order to save 16-bit or 256-color (8-bit) or
whatever. The resulting file is probably
* the largest of any image format, which is at the benefit of
speed. There are other ways of saving
* bitmaps (such as using color indexing) which will reduce the
bitmap size, but they also add
* performance hits.
*
* ---Data--- ---Bytes---
* "BM" 0x00-0x01
* File Size 0x02-0x05
* Reserved 1 0x06-0x07
* Reserved 2 0x08-0x09
* Constant 0x36 0x0A
* Constant 0x00 0x0B-0x0D
* Constant 0x28 0x0E (This byte is always 0x28)
* Constant 0x00 0x0F-0x11 (These bytes are always 0x00)
* Bitmap Width 0x12-0x15
* Bitmap Height 0x16-0x19
* Constant 0x01 0x1A
* Constant 0x00 0x1B
* Constant 0x18 0x1C
* Constant 0x00 0x1D-0x21
* Image byte size 0x22-0x25
* Constant 0x00 0x26-0x35
* Pixels 0x36-Rest
* These are 3-byte RGB values for pixels starting at bottom left,
moving right.
* They are in G-B-R order, and you have to remember to make the
full stride (row) a
* multiple of 4, meaning that if you have a width of 3, that's only
9 bytes and you
* have to pad with 3 to round it to the next multiple of 4.
*/
// This should probably be done a little more carefully
Bitmap bm = (Bitmap) image;
const int BYTES_PER_PIXEL = 3;
// Need 0x36 bytes for the headers, plus all of the pixel data, so
round up to nearest 4
int nBytes = 0x36 + (bm.Height * ((BYTES_PER_PIXEL * bm.Width) +
0x03) & ~0x03);
byte[] BitmapData = new byte[nBytes];
BitmapData[0x00] = (byte) 'B';
BitmapData[0x01] = (byte) 'M';
// I'm sure there's a better way to do this but I didn't look up
the C# equiv of memcpy
BitmapData[0x02] = (byte) nBytes;
BitmapData[0x03] = (byte) (nBytes >> 8);
BitmapData[0x04] = (byte) (nBytes >> 16);
BitmapData[0x05] = (byte) (nBytes >> 24);
BitmapData[0x0A] = 0x36;
BitmapData[0x0E] = 0x28;
BitmapData[0x12] = (byte) bm.Width;
BitmapData[0x13] = (byte) (bm.Width >> 8);
BitmapData[0x14] = (byte) (bm.Width >> 16);
BitmapData[0x15] = (byte) (bm.Width >> 24);
BitmapData[0x16] = (byte) bm.Height;
BitmapData[0x17] = (byte) (bm.Height >> 8);
BitmapData[0x18] = (byte) (bm.Height >> 16);
BitmapData[0x19] = (byte) (bm.Height >> 24);
BitmapData[0x1A] = 0x01;
BitmapData[0x1C] = 0x18;
BitmapData[0x22] = (byte) (nBytes - 0x36);
BitmapData[0x23] = (byte) ((nBytes - 0x36) >> 8);
BitmapData[0x24] = (byte) ((nBytes - 0x36) >> 16);
BitmapData[0x25] = (byte) ((nBytes - 0x36) >> 24);
// Stripping bitmap from bottom left, moving right through the row,
then up to the next row
int index = 0x36;
for (int h = bm.Height - 1; h >= 0; h--)
{
for (int w = 0; w < bm.Width; w++)
{
int c = bm.GetPixel(w, h).ToArgb();
if (c == -16777216)
{
// MessageBox.Show(c.ToString());
BitmapData[index++] = (byte) c;
BitmapData[index++] = (byte) (c >> 8);
BitmapData[index++] = (byte) (c >> 16);
}
else
{
//BitmapData[index++] = (byte) 255;
//BitmapData[index++] = (byte) (255 >> 8);
//BitmapData[index++] = (byte) (255 >> 16);
BitmapData[index++] = (byte) 255;
BitmapData[index++] = (byte) 255;
BitmapData[index++] = (byte) 255;
}
}
// Padding the end of the row
// (if I RTFM'd this wouldn't have taken so long to figure out
int xtra = (bm.Width * 3) % 4;
if (xtra != 0)
{
index += 4 - xtra;
}
}
// Write the bytes to the stream
stream.Write(BitmapData, 0, BitmapData.Length);
}
}