I've been working on trying to display a 1 bit depth bmp image onto my arduino's monitor, but I've gotten stuck. I can download the image and acess it via the stream, but I tried using adafruitGFX to display it and wasn't getting any luck. I have then implemented code to parse the image data away from the BMP header and then write this data to XBM which I have had sucess displaying in the past. I tried just skipping the BMP process altogether, but downloading multiple files this way took much longer than downloading the bmp instead.
Below is my code:
badappler.ino
#include "badapple.h"
#include "path to conv.cpp"
#include <Arduino.h>
#include <string>
#include <Wire.h>
#define SCREEN_WIDTH 128 // OLED display width, change according to your display
#define SCREEN_HEIGHT 64 // OLED display height, change according to your display
SSD1306Wire display(0x3c, 12, 14);
void setup() {
Serial.begin(115200);
setupWiFi();
fetchAndDisplayFrame();
}
void fetchAndDisplayFrame() {
Serial.println("start fetch");
WiFiClientSecure wifiClient;
wifiClient.setInsecure();
String url = "https://raw.githubusercontent.com/drewreno/badapp/bmptesting/frame_145.bmp";
HTTPClient http;
http.begin(wifiClient, url);
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK) {
WiFiClient *stream = http.getStreamPtr();
size_t bytesRead = 0;
while (stream->available() && bytesRead < SIZE) {
buffer[bytesRead++] = stream->read();
}
Serial.println("Buffer Data:");
for (int i = 0; i < SIZE; i++) {
Serial.printf("0x%02X ,", buffer[i]);
if ((i + 1) % 16 == 0) Serial.println();
}
Serial.println("Drawing the bitmap");
convertBMPtoXBM(buffer, SIZE);
display.clear();
display.drawXbm(0, 0, image_width, image_height, xbmData);
display.display();
} else {
Serial.printf("Error on HTTP request, code: %d\n", httpCode);
}
http.end(); // Free the resources
}
void convertBMPtoXBM(byte* bmpData, int bmpSize) {
ReadBMP(bmpData);
// Create a buffer for XBM data
byte xbmData[SIZE];
memset(xbmData, 0, SIZE);
// Convert BMP data to monochrome and store in XBM format
for (int i = 0; i < bmpSize; i++) {
// Simplified: Assuming each pixel is a single byte for this example
byte pixel = bmpData[i];
// Convert to monochrome (this is highly simplified)
bool isWhite = pixel > 128; // Example threshold
// Set the corresponding bit in the XBM data
int xbmIndex = i / 8;
int bitIndex = i % 8;
if (isWhite) {
xbmData[xbmIndex] |= (1 << bitIndex);
}
}
}
void loop() {
// nothing to do here
}
badapple.h
#ifndef BAD_APPLE_H
#define BAD_APPLE_H
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ESP8266HTTPClient.h>
#include <Wire.h>
#include <SSD1306Wire.h>
#define image_width 86
#define image_height 64
#define SIZE ((image_width * image_height) / 8) // Round up if there's a remainder
#define FRAME_SIZE SIZE
String payload;
uint8_t buffer[SIZE];
uint8_t xbmData[SIZE];
int currentIndex = 0; // To keep track of the current index in the array
// WiFi credentials
const char* ssid = "my schoo's public ssid";
const char* password = "";
// Constants for frame handling
const unsigned long FrameINT = 100000; // Interval between frames in milliseconds
int frameNumber = 60; // Current frame number
// WiFi setup function
void setupWiFi() {
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi");
}
#endif // BAD_APPLE_H
conv.cpp
#include <cstdint>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <fstream>
#define SIZE 688
struct BMPHeader {
uint16_t fileType;
uint32_t fileSize;
uint16_t reserved1;
uint16_t reserved2;
uint32_t dataOffset;
};
struct BMPdefined {
uint32_t size;
int32_t width;
int32_t height;
uint16_t planes;
uint16_t bitCount;
// Other fields are not used here
};
struct BMPFile {
BMPHeader header;
BMPdefined defined;
std::vector<uint8_t> imageData;
};
BMPFile ReadBMP(const uint8_t* data) {
BMPFile bmpFile;
// Reading BMPHeader
bmpFile.header.fileType = *((uint16_t*)data);
bmpFile.header.fileSize = *((uint32_t*)(data + 2));
bmpFile.header.reserved1 = *((uint16_t*)(data + 6));
bmpFile.header.reserved2 = *((uint16_t*)(data + 8));
bmpFile.header.dataOffset = *((uint32_t*)(data + 10));
// Reading BMPdefined
memcpy(&bmpFile.defined, data + 14, sizeof(BMPdefined));
// Calculating the size of the image data
size_t rowSize = (bmpFile.defined.width * bmpFile.defined.bitCount + 31) / 32 * 4;
size_t dataSize = rowSize * abs(bmpFile.defined.height);
// Reading the image data
bmpFile.imageData.resize(dataSize);
memcpy(bmpFile.imageData.data(), data + bmpFile.header.dataOffset, dataSize);
return bmpFile;
}
Was able to get the file downloaded and then sent to the XBM converter. But whenever this happened the arduino's memory leaked or overflowed and made it reset. I think it has something to do with memory allocation for each of the parts.