I am trying to convert a BMP file into a char array so I can then convert that array into Base64. I found this old forum topic and implemented it exactly: https://forum.arduino.cc/t/sd-file-read-to-char/355318. It should be noted, this is 9kb .bmp file on an ESP8266 so RAM shouldn't be a concern.
this is the output on the Serial using the original code :
14:25:14.618 -> Initializing filesystem...
14:30:49.532 -> File is open
14:30:49.532 -> BM⸮
14:30:49.532 -> 4
It doesn't look like the file was fully converted as only the first three characters are shown on the Serial.println. I added in a Serial.println(sizeof(pBuffer)); and you can see it only says 4.
Why didn't the file convert? Is there another way?
Or is there a better way to get the BMP into an array to then run through Base64 encoding?
Unless the bitmap consists of printable ASCII characters, this line makes no sense. Serial.print() expects ASCII character strings, or numerical variables.
So then how do I print the pBuffer to see the results? How do I verify that the pBuffer was filled with the BMP's bytes because right now it does not look to be the case. Better yet, what if anything in the code needs to change to make it work? Would appreciate comments on both versions. I still need to encode it with Base64.
Always post ALL the code.
I didn't think it was necessary when only the relevant block changed.
We consider it necessary, because we know that people repeatedly make mistakes, as you clearly do in the "snippet". You are the one asking for help. From volunteers.
Binary, of course, with lots of unprintable characters and zeros to confound attempts to print them as if they are C-strings. Incidentally, the BMP file header contains, cleverly enough, the characters "BM", which explains this:
Okay, so we've established that I have a pointer and that is 4 bytes. What I'm not reading is an explanation as to why the code - either option - are not giving me the expected results. I would like to know how to make the code work as I'd like in addition to pointing out the errors.
I appreciate the help of the volunteers helping novices likemyself.
Thank you for posting the full code. There are several technical problems with it. But first, you need to explain what this code is supposed to do.
What I'm not reading is an explanation as to why the code - either option - are not giving me the expected results.
What are those "expected results"?
A BMP image file is not a printable file. It contains raw image data to be sent to a display. Please explain why are you trying to print the file on the serial monitor.
Please also explain why you want to convert this file to Base64 representation.
As indicated in the first post, I'm trying to get a BMP image into a char array so that array can then be run through Base64 to upload to Google Drive. The printing was incidental, just to see if the conversion worked and the bitmap printed as a char string. My difficulty and where I was hoping to get some guidance is knowing if my two code options for conversion are correct and having a way to verify it.
I wonder if it is, despite that bold claim. Your first code doesn't check if malloc() returned a null pointer. Your second code creates the array on the stack which probably lets you overwrite it into some other area.
I'd try something like (compiles, untested):
#include "Arduino.h"
#include <SdFat.h>
#include <memory>
using namespace sdfat;
#define SD_FAT_TYPE 1
void setup() {
const uint8_t sdCs = 2;
SdFs sd;
FsFile dataFile;
if (!sd.begin(sdCs)) {
Serial.println("SD begin() failed");
while (true) {
yield();
}
}
Serial.println("SD Started");
dataFile = sd.open("wales.bmp", FILE_READ);
if (!dataFile) {
Serial.println("Unable to open file");
while (true) {
yield();
}
}
Serial.println("File opened");
size_t fileSize = dataFile.size();
if (fileSize == 0) {
Serial.println("File is empty");
while (true) {
yield();
}
}
Serial.printf("File Size = %d\n", fileSize);
std::unique_ptr<uint8_t[]> ptr { new (std::nothrow) uint8_t[fileSize] };
if (ptr.get() == nullptr) {
Serial.println("Unable to allocate array memory");
while (true) {
yield();
}
}
Serial.println("Array allocated");
uint8_t c;
for (size_t i = 0; i < fileSize; i++) {
c = dataFile.read();
Serial.print(c, HEX);
Serial.print(" ");
ptr[i] = c;
}
dataFile.close();
}
void loop() {
}
I too reconsidered if i got ahead of myself on the memory available but as my previous test had showed that the file size of 8,420 is easily handled with the onboard 4mb of memory. Nonetheless, your code compiled and output the same as my second option. I did not understand this part of your code:
std::unique_ptr<uint8_t[]> ptr { new (std::nothrow) uint8_t[fileSize] };
Is it doing the same job as this from my code:
pBuffer = (char*)malloc(fileSize + 1);
I also noticed you did not have the trailing '\0'. I got the impression from many other topics on this forum that it was pretty essential.
However, the code from post #3 still does not work (see the error message above) and I would like to know why. It looks as if I'm doing the exact same thing except not using a pointer char * for the pBuffer. It compiles and crashes.