kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
Pi Firmware: Switched screen capture to LodePNG
Change-Id: I622da201a530fc14d827f1357ba7924609a3f51cpull/45/head^2
rodzic
563e199967
commit
562fcf8f4d
|
@ -105,6 +105,9 @@ file( GLOB core_files
|
|||
# File system functions
|
||||
filesystem.c
|
||||
filesystem.h
|
||||
# LodePNG Library
|
||||
lodepng.c
|
||||
lodepng.h
|
||||
# Tiny PNG Output Library
|
||||
tiny_png_out.c
|
||||
tiny_png_out.h
|
||||
|
|
188
src/filesystem.c
188
src/filesystem.c
|
@ -3,19 +3,140 @@
|
|||
#include <string.h>
|
||||
#include "logging.h"
|
||||
#include "fatfs/ff.h"
|
||||
#include "tiny_png_out.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#define USE_LODEPNG
|
||||
|
||||
#ifdef USE_LODEPNG
|
||||
#include "lodepng.h"
|
||||
#else
|
||||
#include "tiny_png_out.h"
|
||||
#endif
|
||||
|
||||
#define CAPTURE_BASE "capture"
|
||||
|
||||
static FATFS fsObject;
|
||||
static int capture_id = -1;
|
||||
|
||||
#ifdef USE_LODEPNG
|
||||
|
||||
// TODO: Using LCT_PALETTE colour type we can almost point LodePNG directly
|
||||
// at the frame buffer. The only thing stopping us is the pitch != width.
|
||||
// Would be interesting to experiment using this.
|
||||
|
||||
static uint8_t rgb8_buffer[8 * 1024 * 1024] __attribute__((aligned(0x4000)));
|
||||
|
||||
static int generate_png(capture_info_t *capinfo, uint8_t **png, unsigned int *png_len ) {
|
||||
|
||||
// TODO: Take account of current palette
|
||||
|
||||
uint8_t *pp = rgb8_buffer;
|
||||
|
||||
for (int y = 0; y < capinfo->height; y++) {
|
||||
uint8_t *fp = capinfo->fb + capinfo->pitch * y;
|
||||
if (capinfo->bpp == 8) {
|
||||
for (int x = 0; x < capinfo->width; x++) {
|
||||
uint8_t single_pixel = *fp++;
|
||||
*pp++ = (single_pixel & 0x01) ? 255 : 0;
|
||||
*pp++ = (single_pixel & 0x02) ? 255 : 0;
|
||||
*pp++ = (single_pixel & 0x04) ? 255 : 0;
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < capinfo->width << 1; x++) {
|
||||
uint8_t double_pixel = *fp++;
|
||||
*pp++ = (double_pixel & 0x10) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x20) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x40) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x01) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x02) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x04) ? 255 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned result = lodepng_encode_memory(png, png_len, rgb8_buffer, capinfo->width, capinfo->height, LCT_RGB, 8);
|
||||
|
||||
if (result) {
|
||||
log_warn("lodepng_encode32 failed (result = %d)", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void free_png(uint8_t *png) {
|
||||
if (png) {
|
||||
free(png);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// TODO: Fix hard-coded max H resolution of 4096
|
||||
static uint8_t pixels[3 * 4096];
|
||||
|
||||
// TODO: Fix hard-coded buffer size if 8MB
|
||||
static uint8_t png_buffer[8 * 1024 * 1024] __attribute__((aligned(32)));
|
||||
static uint8_t png_buffer[8 * 1024 * 1024] __attribute__((aligned(0x4000)));
|
||||
|
||||
static int generate_png(capture_info_t *capinfo, uint8_t **png, unsigned int *png_len ) {
|
||||
enum TinyPngOut_Status result;
|
||||
struct TinyPngOut state;
|
||||
|
||||
*png = NULL;
|
||||
*png_len = 0;
|
||||
|
||||
result = TinyPngOut_init(&state, capinfo->width, capinfo->height, png_buffer);
|
||||
|
||||
if (result != TINYPNGOUT_OK) {
|
||||
|
||||
log_warn("TinyPngOut_init failed (result = %d)", result);
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
|
||||
// TODO: Take account of current palette
|
||||
|
||||
for (int y = 0; y < capinfo->height; y++) {
|
||||
uint8_t *fp = capinfo->fb + capinfo->pitch * y;
|
||||
uint8_t *pp = pixels;
|
||||
if (capinfo->bpp == 8) {
|
||||
for (int x = 0; x < capinfo->width; x++) {
|
||||
uint8_t single_pixel = *fp++;
|
||||
*pp++ = (single_pixel & 0x01) ? 255 : 0;
|
||||
*pp++ = (single_pixel & 0x02) ? 255 : 0;
|
||||
*pp++ = (single_pixel & 0x04) ? 255 : 0;
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < capinfo->width << 1; x++) {
|
||||
uint8_t double_pixel = *fp++;
|
||||
*pp++ = (double_pixel & 0x10) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x20) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x40) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x01) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x02) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x04) ? 255 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
result = TinyPngOut_write(&state, pixels, capinfo->width);
|
||||
|
||||
if (result != TINYPNGOUT_OK) {
|
||||
log_warn("TinyPngOut_write failed (result = %d)", result);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*png = png_buffer;
|
||||
*png_len = state.output_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_png(uint8_t *png) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static FATFS fsObject;
|
||||
static int capture_id = -1;
|
||||
|
||||
static void initialize_capture_id() {
|
||||
FRESULT result;
|
||||
|
@ -89,10 +210,10 @@ void close_filesystem() {
|
|||
|
||||
void capture_screenshot(capture_info_t *capinfo) {
|
||||
FRESULT result;
|
||||
enum TinyPngOut_Status tiny_result;
|
||||
struct TinyPngOut tiny_state;
|
||||
char path[100];
|
||||
FIL file;
|
||||
uint8_t *png;
|
||||
unsigned int png_len;
|
||||
|
||||
init_filesystem();
|
||||
|
||||
|
@ -109,57 +230,24 @@ void capture_screenshot(capture_info_t *capinfo) {
|
|||
}
|
||||
capture_id++;
|
||||
|
||||
tiny_result = TinyPngOut_init(&tiny_state, capinfo->width, capinfo->height, png_buffer);
|
||||
if (generate_png(capinfo, &png, &png_len)) {
|
||||
|
||||
if (tiny_result != TINYPNGOUT_OK) {
|
||||
|
||||
log_warn("TinyPngOut_init failed (result = %d)", tiny_result);
|
||||
log_warn("generate_png failed, not writing data");
|
||||
|
||||
} else {
|
||||
|
||||
// TODO: Take account of current palette
|
||||
log_info("Screen capture PNG length = %d, writing data...", png_len);
|
||||
|
||||
for (int y = 0; y < capinfo->height; y++) {
|
||||
uint8_t *fp = capinfo->fb + capinfo->pitch * y;
|
||||
uint8_t *pp = pixels;
|
||||
if (capinfo->bpp == 8) {
|
||||
for (int x = 0; x < capinfo->width; x++) {
|
||||
uint8_t single_pixel = *fp++;
|
||||
*pp++ = (single_pixel & 0x01) ? 255 : 0;
|
||||
*pp++ = (single_pixel & 0x02) ? 255 : 0;
|
||||
*pp++ = (single_pixel & 0x04) ? 255 : 0;
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < capinfo->width << 1; x++) {
|
||||
uint8_t double_pixel = *fp++;
|
||||
*pp++ = (double_pixel & 0x10) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x20) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x40) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x01) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x02) ? 255 : 0;
|
||||
*pp++ = (double_pixel & 0x04) ? 255 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
tiny_result = TinyPngOut_write(&tiny_state, pixels, capinfo->width);
|
||||
|
||||
if (tiny_result != TINYPNGOUT_OK) {
|
||||
log_warn("TinyPngOut_write failed (result = %d)", tiny_result);
|
||||
break;
|
||||
}
|
||||
UINT num_written = 0;
|
||||
result = f_write(&file, png, png_len, &num_written);
|
||||
if (result != FR_OK) {
|
||||
log_warn("Failed to write capture file %s (result = %d)", path, result);
|
||||
} else if (num_written != png_len) {
|
||||
log_warn("Capture file %s incomplete (%d < %d bytes)", path, num_written, png_len);
|
||||
}
|
||||
}
|
||||
|
||||
int png_len = tiny_state.output_len;
|
||||
log_info("Screen capture PNG length = %d, writing data...", png_len);
|
||||
|
||||
UINT num_written = 0;
|
||||
result = f_write(&file, png_buffer, png_len, &num_written);
|
||||
if (result != FR_OK) {
|
||||
log_warn("Failed to write capture file %s (result = %d)", path, result);
|
||||
} else if (num_written != png_len) {
|
||||
log_warn("Capture file %s incomplete (%d < %d bytes)", path, num_written, png_len);
|
||||
}
|
||||
free_png(png);
|
||||
|
||||
result = f_close(&file);
|
||||
if (result != FR_OK) {
|
||||
|
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Ładowanie…
Reference in New Issue