Speeding up base64 encoding from SD card to ethernet

Hi,
I am trying to do the following:

  1. read a file from an Sd card
  2. base64 Encode it on the fly.
  3. use Client.write() to send it to an email address using SMTP commands.

i was able to do this using the below code:

  int clientCount = 0;
  myFile = SD.open("picture2.jpg");

  if (myFile) {
      encode();
    }
void encodeblock(unsigned char in[3], unsigned char out[4], int len) {
  out[0] = cb64[in[0] >> 2]; out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4)];
  out[2] = (unsigned char) (len > 1 ? cb64[((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6)] : '=');
  out[3] = (unsigned char) (len > 2 ? cb64[in[2] & 0x3F] : '=');
}

void encode() {
  unsigned char in[3], out[4]; int i, len, blocksout = 0;
  while (myFile.available() != 0) {
    len = 0; for (i = 0; i < 3; i++) {
      in[i] = (unsigned char) myFile.read();
      if (myFile.available() != 0) len++;
      else in[i] = 0;
    }
    if (len) {
      encodeblock(in, out, len);
      for (i = 0; i < 4; i++) client.write(out[i]);
      blocksout++;
    }
    if (blocksout >= 19 || myFile.available() == 0) {
      if (blocksout) client.print("\r\n");
      blocksout = 0;
    }
  }
}

This however takes quite some time because the code reads byte by byte from the SD card.
Then i found this:

  int clientCount = 0;

  myFile = SD.open("picture2.jpg");
  if (myFile) {
    while (myFile.available()) {
      clientCount = myFile.read(tBuf, 64);
      client.write((byte*)tBuf, clientCount);
    }
    myFile.close();
  }

This function is much faster as it reads from card and writes to buffer.

My question is how can I combine this with the encode function?
Currently, the encode function reads every single byte from the Sd card decoded, goes back and repeats till it reaches the end.
I want the encode function to read from buffer instead to speed things up.

Any help will be much appreciated.

Since the conversion is done three bytes at a time you should probably make your buffer a multiple of three bytes. I don't know what you are supposed to do if your file is not a multiple of three bytes in length.

johnwasser:
Since the conversion is done three bytes at a time you should probably make your buffer a multiple of three bytes. I don't know what you are supposed to do if your file is not a multiple of three bytes in length.

Normally it is padded with zero's

robtillaart:
Normally it is padded with zero's

That would create ambiguity since one would not be able to tell the difference between terminal real zeros and padded zeros. The Base64 spec (see Base64 - Wikipedia) converts each 3 bytes to 4 bytes with the last block of 4 bytes being xxxx, xx== or xxx= (x being a base 64 character). This removes the ambiguity.

You're right it's padding with = chars!