Bug in Util.BitmapToBMPFile

I programmed a EMX based webserver which can also show pictures which ultimately should come from a webcam. To test the code i used a bmp file as resource and also used the same file renamed as bin file. If i send the bin file straight into the socket i get the correct result. However if i retreive the bitmap as bitmap resource and use the Util.BitmapToBMPFile as described in the API example i get a scrambled image with firefox and the internet explorer terminates the connection right after the first 1024 bites.

Code:

if (requestLine[1] == “/image.bmp”)
{
//byte[] pictureBuffer = Resources.GetBytes(Resources.BinaryResources.imageBin);

Bitmap image = Resources.GetBitmap(Resources.BitmapResources.image);
byte[] pictureBuffer = new byte[image.Width * image.Height * 3 + 54];
Util.BitmapToBMPFile(image.GetBitmap(), image.Width, image.Height, pictureBuffer);
                                                                  
string header = "";

header += "HTTP/1.1 200 OK" + "\r\n";
header += "Content-Type: image/bmp" + "\r\n";
header += "Content-Length: " + pictureBuffer.Length + "\r\n";
header += "\r\n";

byte[] sendBuffer = new byte[1024];
int sendOffset = 0;

while (sendOffset < (Encoding.UTF8.GetBytes(header).Length + pictureBuffer.Length) )
{
	int length = System.Math.Min(sendBuffer.Length, (Encoding.UTF8.GetBytes(header).Length + pictureBuffer.Length) - sendOffset);

	sendBuffer = null;
	sendBuffer = new byte[length];

	byte[] outputArray = new byte[Encoding.UTF8.GetBytes(header).Length + pictureBuffer.Length];
	Encoding.UTF8.GetBytes(header).CopyTo(outputArray, 0);
	pictureBuffer.CopyTo(outputArray, Encoding.UTF8.GetBytes(header).Length);

	Array.Copy(outputArray, sendOffset, sendBuffer, 0, length);

	sendOffset += length;

	clientSock.Send(sendBuffer);
}

clientSock.Close();

}

Welcome to the forum.

Save BitmapToBMPFile generated file into a bmp file and examine it on your PC. Just to make sure that file is ok when it is generated.

I also saved the output of

Util.BitmapToBMPFile(image.GetBitmap(), image.Width, image.Height, pictureBuffer);

onto a SD card like shown in the GHI API example of Util.BitmapToBMPFile however windows was not able to open the picture at all. As mentioned the internet explorer aborded the data transfer outright only the mozilla product was willing to accept the file. I also monitored the socket with socketsniff and compared the two cases:

What is obvious is that in both cases the BMP file header is valid. However using the Util.BitmapToBMPFile method a slightly larger amount of data is put into the bmp file. In both cases the datafield of the bitmap starts after 0x79 send bytes. My guess is that the Util.BitmapToBMPFile can only handle bitmaps which are created by drawing it with the EMX and not a file loaded from the resources.

1: First 1024 bytes of transmitted date when the bin file was used

00000000 48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D HTTP/1.1 200 OK.
00000010 0A 43 6F 6E 74 65 6E 74 2D 54 79 70 65 3A 20 69 .Content-Type: i
00000020 6D 61 67 65 2F 62 6D 70 0D 0A 43 6F 6E 74 65 6E mage/bmp…Conten
00000030 74 2D 4C 65 6E 67 74 68 3A 20 31 35 31 39 32 39 t-Length: 151929
00000040 0D 0A 0D 0A 42 4D 79 51 02 00 00 00 00 00 36 00 …BMyQ…6.
00000050 00 00 28 00 00 00 E1 00 00 00 1F FF FF FF 01 00 …(…
00000060 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
00000070 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF …
00000080 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000090 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000100 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000110 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000120 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000130 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000140 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000150 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000160 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000170 FF F8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000180 FF FF F0 F8 F0 F0 FF FF F0 FF FF EF FF F0 EF FF …
00000190 F0 F0 FF FF EF FF FF F0 FF FF FF FF FF FF FF FF …
000001A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000001B0 FF FF FF F8 FF FF F8 FF FF FF FF FF FF FF FF FF …
000001C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000001D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000001E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000001F0 FF FF FF FF FF FF FF FF FF FF F0 FF FF F0 FF FF …
00000200 FF FF FF FF FF FF FF F8 FF FF F7 FF FF F8 FF FF …
00000210 FF FF FF FF FF FF F8 FF FF F7 FF FF F8 FF FF FF …
00000220 FF F0 FF FF F0 FF FF F0 FF FF FF FF FF FF FF FF …
00000230 FF FF FF FF F8 FF FF F8 FF FF F8 FF FF F8 FF FF …
00000240 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000250 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000260 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000270 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000280 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000290 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000300 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000310 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000320 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000330 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000340 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000350 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000360 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000370 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000380 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000390 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …

  1. First 1024 bytes of transmitted date when the Util.BitmapToBMPFile method was used

00000000 48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D HTTP/1.1 200 OK.
00000010 0A 43 6F 6E 74 65 6E 74 2D 54 79 70 65 3A 20 69 .Content-Type: i
00000020 6D 61 67 65 2F 62 6D 70 0D 0A 43 6F 6E 74 65 6E mage/bmp…Conten
00000030 74 2D 4C 65 6E 67 74 68 3A 20 31 35 32 31 35 34 t-Length: 152154
00000040 0D 0A 0D 0A 42 4D 5A 52 02 00 00 00 00 00 36 00 …BMZR…6.
00000050 00 00 28 00 00 00 E1 00 00 00 E1 00 00 00 01 00 …(…
00000060 18 00 00 00 00 00 00 00 00 00 C4 0E 00 00 C4 0E …
00000070 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF …
00000080 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000090 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000000F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000100 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000110 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000120 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000130 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FE FF …
00000140 FF FE FF FF FE FF FF FF FF FF FF FF FF FF FF FF …
00000150 FF FF FD FF FF FD FF FF FD FF FF FD FF FF FD FF …
00000160 FF FD FF FF FD FF FF FD FF FF FD FF FF FD FF FF …
00000170 FD FF FF FF FE FF FF FE FF FF FE FF FF FE FF FF …
00000180 FE FF FF FE FF FF FE FF FF FE FF FF FE FF FF FF …
00000190 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FE …
000001A0 FF FF FF FF FF FE FF FF FF FF FF FE FF FF FF FF …
000001B0 FF FE FF FF FF FF FF FE FF FF FF FF FF FE FF FF …
000001C0 FF FF FF FE FF FF FF FF FF FF FF FF FF FF FF FF …
000001D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000001E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000001F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000200 FD FF FF FD FF FF FD FF FF FD FF FF FD FF FF FD …
00000210 FF FF FD FF FF FD FF FF FF FE FF FF FE FF FF FE …
00000220 FF FF FE FF FF FE FF FF FF FF FB FF FF FA FF FF …
00000230 FB FF FF FD FF FF FF FF FF FF FF FF FF FE FF FF …
00000240 FE FF FF FE FF FF FE FF FF FE FF FF FE FF FF FE …
00000250 FF FD FF FF FB FF FF FB FF FF FF FF FF FF FF FF …
00000260 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000270 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000280 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000290 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000002F0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000300 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000310 FF FF FF FF FF FF FF FF FF FF FF FF FF 00 FF FF …
00000320 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000330 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000340 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000350 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000360 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000370 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000380 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
00000390 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003A0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003B0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF …
000003D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FE …
000003E0 FF FF FD FF FF FD FF FF FD FF FF FE FF FF FE FF …
000003F0 FF FE FF FF FE FF FB FF FF FA FF FF F8 FF FF F8 …

Can you try it on a 320x240 pixel image please?

  1. Make a 320x240 pixel Bitmap object
  2. save to card
  3. flush the data and close the file handle
  4. test on a PC

If you have problems, we need your complete code. Please start new project and only include the absolutely necessary code.

I had the same idea. I tried the code example below in an empty solution with only the necessary assemblies and red the file on the sd card which worked. Then i created a bitmap picture using ms paint and saved it as a 24bit bmp and included it as resource and substituted this with “Bitmap image”. The picture was square shaped and worked when red on the sd card. However i did the same procedure with another picture which had odd length and width. The picture which ended up on the sd drive was not readable for windows.

My guess is the problem occurs when a picture with odd dimensions is used. I will repeat the experiment with the dimensions you suggested and different color tables and let you know the results.

Code:

using System;
using System.IO;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.System;

public class Program
{
public static void Main()
{
// init SD card
PersistentStorage ps = new PersistentStorage(“SD”);
ps.MountFileSystem();

    // assume we have some image
    Bitmap image = new Bitmap(320, 240);
    image.DrawRectangle(Colors.Blue, 1, 0, 0, 320, 240, 0, 0, Colors.Blue, 0, 0, Colors.Blue, 0, 0, Bitmap.OpacityOpaque);
    image.DrawLine(Colors.Orange, 1, 0, 0, 320 - 1, 0);
    image.DrawLine(Colors.Red, 1, 0, 0, 0, 240-1);
    image.DrawLine(Colors.Yellow, 1, 320-1, 240-1, 0, 240-1);
    image.DrawLine(Colors.Magenta, 1, 320-1, 240-1, 320 - 1, 0);
    image.DrawEllipse(Colors.Red, 320/2, 240/2, 50, 50);

    // allocate buffer
    byte[] outputFile = new byte[image.Width * image.Height * 3 + 54];

    // convert to BMP file
    Util.BitmapToBMPFile(image.GetBitmap(), image.Width, image.Height, outputFile);

    // save image
    File.WriteAllBytes("\\SD\\CreatedBMPFile.bmp", outputFile);

    ps.Dispose();
}

}

@ MB

You can enclose the code with code tags and it will be more readable.

Bitmap lines must be divisible by 4 regardless of size. This is why padding is added to lines depending on their length. I haven’t used this util so I dont know if it does it or not. I just recall dealing with that issue when I added the ability to Spiral.

Double post. Blame my iPhone.

@ skewworks - What software are you using on your phone to read this forum? Is there one for Android you recommend?

@ Ian I always found the default browser on Android worked just fine with the forum.

Oh, I thought you guys had found some slick forum reader app :frowning:

There a NETMF one over on the code section :wink: