Issues converting BMP to XBM in arduino

68 Views Asked by At

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.

0

There are 0 best solutions below