Can I dynamically make a bitmap to send over Ethernet?

The operative word here is make. I'm asking how a program might generate a properly formatted bitmap array /sequence /file so that it might be streamed via Ethernet from an Uno web server. So for a simple example, if I create 10,000 bytes each containing the value 128, I'd generate and stream a 100 x 100 pixel mid grey square to someone's web browser. Clearly in view of the limited resources that image would have to be streamed sequentially rather than generated as a whole in RAM then streamed.

A non compressed BMP image seems the simplest computationally, but even then the file structure requires some work. Is there a library out there? Perhaps something that can generate the header portion? If I search for one, all you get are those for dealing with static pre generated files. Can I make one dynamically without having to code the bitmap format myself?

I'm not asking how to read a bitmap from an SD card and then send it.

That's a task far more suited to a RaspberryPi or other similar *nix powered board, not an Arduino with 32k of flash and 2k of ram.

It is possible if the dynamic graphic is really small. See this example:

I have sent really small logo graphics in web pages without an SD card read. I saved them as small PNG files and then converted them to hex with a tool like tomeko:

Then just stored them in program memory with

static const unsigned char PROGMEM logo[] = {//hex data for PNG file here//};

and printed them out to the web client when requested.

For very small, like 100x100, then uncompresed BMP is one of the easiest formats to create from scratch. PNG is also very simple and doesn't require hex conversion.

Keep looking, there must be libraries out there.

Once, I even created binary Excel files.

MorganS:
For very small, like 100x100, then uncompresed BMP is one of the easiest formats to create from scratch.

Thanks. Just an afterthought. Looking at the format below, it seems to be of fixed size if the image is a fixed size. Assume my image is always 100 * 100 grey scale pixels. Could I create a BMP with Photoshop, then strip off the fixed header and just reattach it to whatever image array I make (as long as it stays 100 * 100 pixels)? The images will always be a fixed size in my use case.

Second afterthought. SVG is text based. Perhaps that's the way to go...

Yes, making the BMP with Photoshop and copying that header will work.

I did something like that for a project last year. The following code creates a BMP and saves it to an ESP8266's "SPIFFS" memory, to be served on a web page later. You could output it bytes (or chunks) at a time instead of saving it to a file.

With a fixed image size, you could also simplify the header and "info header" part.

I created the code with the help of:
http://forum.arduino.cc/index.php?topic=177361.0
http://forum.arduino.cc/index.php?topic=112733.0

//*******************************************************************
void readTFTwriteBMP()
{
  const int imageW = 480;   // in pixels
  const int imageH = 320;
  byte colorByteH, colorByteL;

  yield();

  fs::File outFile = SPIFFS.open("/graph.bmp", "w");  // <-----fs:: added for compatibility with SdFat ------

  // file header
  unsigned char bmFlHdr[14] = {
    'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0
  };
  // 54 = std total "old" Windows BMP file header size = 14 + 40

  unsigned long fileSize = 2ul * imageH * imageW + 54; // pix data + 54 byte hdr

  bmFlHdr[ 2] = (unsigned char)(fileSize      ); // all ints stored little-endian
  bmFlHdr[ 3] = (unsigned char)(fileSize >>  8); // i.e., LSB first
  bmFlHdr[ 4] = (unsigned char)(fileSize >> 16);
  bmFlHdr[ 5] = (unsigned char)(fileSize >> 24);


  //info header
  unsigned char bmInHdr[40] = {
    40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 16, 0
  };
  // 40 = info header size
  //  1 = num of color planes
  // 16 = bits per pixel
  // all other header info = 0, including RI_RGB (no compr), DPI resolution, except...
  bmInHdr[ 4] = (unsigned char)(       imageW      );
  bmInHdr[ 5] = (unsigned char)(       imageW >>  8);
  bmInHdr[ 6] = (unsigned char)(       imageW >> 16);
  bmInHdr[ 7] = (unsigned char)(       imageW >> 24);
  bmInHdr[ 8] = (unsigned char)(       imageH      );
  bmInHdr[ 9] = (unsigned char)(       imageH >>  8);
  bmInHdr[10] = (unsigned char)(       imageH >> 16);
  bmInHdr[11] = (unsigned char)(       imageH >> 24);

  outFile.write(bmFlHdr, sizeof(bmFlHdr));
  outFile.write(bmInHdr, sizeof(bmInHdr));

  for (int i = imageH - 1; i >= 0; i--) {  
    for (int j = 0; j < imageW; j++) {     

      uint16_t rgb = readPixB(j, i, 24000000); // get pix color in rgb565 format <----24 MHz----

      colorByteH = (rgb & 0xFF00) >> 8; 
      colorByteL = rgb & 0x00FF;        

      //RGB565 to RGB555 conversion... 555 is default for uncompressed BMP
      //this conversion is from ...Arduino forum topic=177361.0
      colorByteL = (colorByteH << 7) | ((colorByteL & 0xC0) >> 1) | (colorByteL & 0x1f);
      colorByteH = colorByteH >> 1;

      outFile.write(colorByteL); outFile.write(colorByteH);
    }
    yield(); // no need to yield every pixel...just every row or col <---------------------------
  }
  outFile.close();
} // end readTFTwriteBMP

cossoft:
Second afterthought. SVG is text based. Perhaps that's the way to go...

I've used SVG and found it quite easy to use. My SVG was generated by PHP script, but as you say it's text, so no reason an Arduino sketch could not do the same, if the size of the data is not a problem.

But you have not really explained your project yet, or what this image represents, and why/if it needs to be a pixel grid verses something drawn with lines/shapes/text.

Consider upgrading your "Arduino" to something with more speed & ram. Esp8266?

I suppose if you knew up front what size and resolution you could just build the BMP header in a 54 byte array to start.

#define wid 100      //width of image in pixels
#define hei 100      //height of image in pixels
#define img 100*100  //size of image array
#define fsize 54+img //size of BMP file
/* Define BMP Header */
unsigned char header[54] = {'B','M',fsize,fsize>>8,fsize>>16,fsize>>24,0,0,0,0,54,0,0,0,40,0,0,0,wid,wid>>8,wid>>16,wid>>24,hei,hei>>8,hei>>16,hei>>24,1,0,8,0,0,0,0,0,img,img>>8,0,0};

But SVG makes graphics so much easier to build out for web pages. Same 100x100 gray box.

<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300" version="1.1">
  <rect x="0" y="0" width="100" height="100" fill="rgb(128,128,128)" />
</svg>

PaulRB:
Esp8266?

Yeh, I'm really a wired kind of guy. Wireless waves can make you sterile :frowning:

The image is to represent entropy /randomness as in a true random number generator. I haven't quite figured out what the image would show as that's the arty bit I'm not very good at... Perhaps some sort of values graph /random walk? The data would be streamed in and out so a great deal of RAM isn't necessary. The important bit is that the entropy is represented graphically. Textually just doesn't cut it for me. All the code snippets are very much appreciated.

Anyway I expect the W5100 chip's throughput will be the bottleneck.

Thanks for the context! Cool idea. You should Google ESP8266. It could certainly host a dynamic 100x100 image web page given people are building web cams with them. You could even grow beyond grey scale and add color as yet another dimension of your random world. Sounds like some form of a virtual lava lamp.

cossoft:
Second afterthought. SVG is text based. Perhaps that's the way to go...

I've just looked at Google Charts. It would be pretty simple to configure the web server to spit out a JSON data file for ingestion by the API's JavaScript function. It should not be too resource intensive to repetitively generate the JSON row data. The actual rendering is client side. All's needed is to point the URL to my server as:-

function drawChart() {
      var jsonData = $.ajax({
          url: "MY-SERVER.COM",
          dataType: "json",
          async: false
          }).responseText;