init
This commit is contained in:
137
src/image_processor.cpp
Normal file
137
src/image_processor.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "image_processor.h"
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
|
||||
void ImageProcessor::processAndPrint(const CameraService::Frame &frame, PrinterService &printer, const AppSettings &settings)
|
||||
{
|
||||
if (!frame.isValid())
|
||||
return;
|
||||
|
||||
// 1. Setup Dimensions (Rotate 90 degrees)
|
||||
// Camera is 320x240 (Landscape) -> Printer is 384 wide (Portrait)
|
||||
// We will map Camera Height (240) to Printer Width.
|
||||
// Since 240 < 384, the image will be centered or small.
|
||||
// If you want full width, we must scale, but rotation is cheaper.
|
||||
const int width = frame.getHeight(); // 240
|
||||
const int height = frame.getWidth(); // 320
|
||||
|
||||
// 2. Allocate Buffer in PSRAM
|
||||
// We need int16_t to handle the overflow error during calculation
|
||||
size_t bufSize = width * height * sizeof(int16_t);
|
||||
int16_t *pixels = (int16_t *)heap_caps_malloc(bufSize, MALLOC_CAP_SPIRAM);
|
||||
|
||||
if (!pixels)
|
||||
{
|
||||
Serial.println("[ERR] PSRAM Alloc Failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Rotate & Load
|
||||
const uint8_t *src = frame.getData();
|
||||
// Pre-calculate to save cycles in loop
|
||||
const int srcWidth = frame.getWidth();
|
||||
|
||||
for (int y = 0; y < srcWidth; y++)
|
||||
{ // 320 (Source Y)
|
||||
for (int x = 0; x < width; x++)
|
||||
{ // 240 (Source X)
|
||||
// 90 Deg Rotation Logic
|
||||
// Dest(x, y) = Src(y, srcWidth - x - 1)
|
||||
// We are mapping the camera buffer to our Dithering Buffer
|
||||
uint8_t val = src[x * srcWidth + y];
|
||||
pixels[y * width + x] = static_cast<int16_t>(val);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Floyd-Steinberg Dithering
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int16_t oldPixel = pixels[y * width + x];
|
||||
int16_t newPixel = (oldPixel > 128) ? 255 : 0;
|
||||
|
||||
pixels[y * width + x] = newPixel;
|
||||
int16_t error = oldPixel - newPixel;
|
||||
|
||||
// Distribute Error (Bit shifting is faster than division)
|
||||
// Right: 7/16
|
||||
if (x + 1 < width)
|
||||
pixels[y * width + (x + 1)] += (error * 7) >> 4;
|
||||
|
||||
// Bottom-Left: 3/16
|
||||
if (y + 1 < height)
|
||||
{
|
||||
if (x - 1 >= 0)
|
||||
pixels[(y + 1) * width + (x - 1)] += (error * 3) >> 4;
|
||||
|
||||
// Bottom: 5/16
|
||||
pixels[(y + 1) * width + x] += (error * 5) >> 4;
|
||||
|
||||
// Bottom-Right: 1/16
|
||||
if (x + 1 < width)
|
||||
pixels[(y + 1) * width + (x + 1)] += (error * 1) >> 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Pack & Print
|
||||
// We pack 8 pixels into 1 byte.
|
||||
// The Adafruit library expects a full bitmap array.
|
||||
// Optimization: We reuse the PSRAM allocation or alloc a smaller one.
|
||||
|
||||
// Row stride must be multiple of 8
|
||||
int rowBytes = (width + 7) / 8;
|
||||
size_t bitmapSize = rowBytes * height;
|
||||
uint8_t *bitmap = (uint8_t *)heap_caps_calloc(bitmapSize, 1, MALLOC_CAP_SPIRAM);
|
||||
|
||||
if (!bitmap)
|
||||
{
|
||||
free(pixels);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
if (pixels[y * width + x] == 0)
|
||||
{ // If black
|
||||
bitmap[y * rowBytes + (x / 8)] |= (1 << (7 - (x % 8)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printer.setHeat(settings.heatTime);
|
||||
printer.wake();
|
||||
printer.printBitmap(width, height, bitmap);
|
||||
printer.feed(3);
|
||||
printer.sleep();
|
||||
|
||||
// 6. Cleanup (RAII handled elsewhere, but raw pointers need free)
|
||||
free(pixels);
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
void ImageProcessor::uploadImage(const uint8_t *bitmap, int size, const String &url)
|
||||
{
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
return;
|
||||
|
||||
HTTPClient http;
|
||||
http.begin(url);
|
||||
http.addHeader("Content-Type", "application/octet-stream");
|
||||
|
||||
int responseCode = http.POST((uint8_t *)bitmap, size);
|
||||
|
||||
if (responseCode > 0)
|
||||
{
|
||||
Serial.printf("[Upload] Success: %d\n", responseCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("[Upload] Failed: %s\n", http.errorToString(responseCode).c_str());
|
||||
}
|
||||
|
||||
http.end();
|
||||
}
|
||||
Reference in New Issue
Block a user