fix screenshot functionality

This commit is contained in:
Wolfvak 2019-05-25 10:34:29 -03:00 committed by d0k3
parent 6823e15584
commit a42dbedf82
6 changed files with 50 additions and 95 deletions

View File

@ -4,60 +4,69 @@
#include "vff.h" #include "vff.h"
#include "png.h" #include "png.h"
static void Screenshot_CvtAndTranspose(u8 *dest, u16 *fb, u32 w, u32 stride)
{
for (u32 y = 0; y < SCREEN_HEIGHT; y++) {
for (u32 x = 0; x < w; x++) {
u8 r, g, b;
u16 rgb_s = GetColor(fb, x, y);
void CreateScreenshot() { r = ((rgb_s >> 11) & 0x1F) << 3;
const u32 snap_size = SCREEN_SIZE_TOP * 2, snap_width = SCREEN_WIDTH_TOP, snap_height = SCREEN_HEIGHT * 2; g = ((rgb_s >> 5) & 0x3F) << 2;
u8 *png_data = NULL; b = (rgb_s & 0x1F) << 3;
size_t png_size;
char filename[64]; *(dest++) = r;
*(dest++) = g;
*(dest++) = b;
}
dest += stride;
}
}
void CreateScreenshot(void) {
DsTime dstime; DsTime dstime;
size_t png_size;
u8 *png, *buffer;
char filename[64];
u32 snapbuf_size, snap_w, snap_h, bot_offset;
snapbuf_size = (SCREEN_WIDTH_TOP * SCREEN_HEIGHT * 3) * 2;
snap_w = SCREEN_WIDTH_TOP;
snap_h = SCREEN_HEIGHT * 2;
fvx_rmkdir(OUTPUT_PATH); fvx_rmkdir(OUTPUT_PATH);
get_dstime(&dstime); get_dstime(&dstime);
snprintf(filename, 64, OUTPUT_PATH "/snap_%02X%02X%02X%02X%02X%02X.png", snprintf(filename, 64, OUTPUT_PATH "/snap_%02X%02X%02X%02X%02X%02X.png",
dstime.bcd_Y, dstime.bcd_M, dstime.bcd_D, dstime.bcd_Y, dstime.bcd_M, dstime.bcd_D,
dstime.bcd_h, dstime.bcd_m, dstime.bcd_s); dstime.bcd_h, dstime.bcd_m, dstime.bcd_s);
filename[63] = '\0';
u8* buffer = (u8*) malloc(snap_size); buffer = malloc(snapbuf_size);
if (!buffer) return; if (!buffer) return;
u8* buffer_t = buffer; memset(buffer, 0x1F, snapbuf_size); // gray background
u8* buffer_b = buffer + SCREEN_SIZE_TOP;
memset(buffer, 0x1F, snap_size); // gray background bot_offset = ((400 * SCREEN_HEIGHT) + 40) * 3;
for (u32 x = 0; x < 400; x++) { Screenshot_CvtAndTranspose(buffer, TOP_SCREEN, SCREEN_WIDTH_TOP, 0);
for (u32 y = 0; y < 240; y++) { Screenshot_CvtAndTranspose(buffer + bot_offset, BOT_SCREEN, SCREEN_WIDTH_BOT, 80 * 3);
buffer_t[(y * SCREEN_WIDTH_TOP + x) * 3 + 0] = *(TOP_SCREEN + (((x * 240) + (239 - y)) * 3) + 2);
buffer_t[(y * SCREEN_WIDTH_TOP + x) * 3 + 1] = *(TOP_SCREEN + (((x * 240) + (239 - y)) * 3) + 1);
buffer_t[(y * SCREEN_WIDTH_TOP + x) * 3 + 2] = *(TOP_SCREEN + (((x * 240) + (239 - y)) * 3) + 0);
}
}
for (u32 x = 0; x < 320; x++) { png = PNG_Compress(buffer, snap_w, snap_h, &png_size);
for (u32 y = 0; y < 240; y++) {
buffer_b[(y * SCREEN_WIDTH_TOP + x + 40) * 3 + 0] = *(BOT_SCREEN + (((x * 240) + (239 - y)) * 3) + 2);
buffer_b[(y * SCREEN_WIDTH_TOP + x + 40) * 3 + 1] = *(BOT_SCREEN + (((x * 240) + (239 - y)) * 3) + 1);
buffer_b[(y * SCREEN_WIDTH_TOP + x + 40) * 3 + 2] = *(BOT_SCREEN + (((x * 240) + (239 - y)) * 3) + 0);
}
}
png_data = PNG_Compress(buffer, snap_width, snap_height, &png_size); if (png && png_size) {
fvx_qwrite(filename, png, 0, png_size, NULL);
if (png_data && png_size) {
fvx_qwrite(filename, png_data, 0, png_size, NULL);
// "snap effect" // "snap effect"
memcpy(buffer_b, BOT_SCREEN, SCREEN_SIZE_BOT); /*memcpy(buffer_b, BOT_SCREEN, SCREEN_SIZE_BOT);
memcpy(buffer_t, TOP_SCREEN, SCREEN_SIZE_TOP); memcpy(buffer_t, TOP_SCREEN, SCREEN_SIZE_TOP);
memset(BOT_SCREEN, 0, SCREEN_SIZE_BOT); memset(BOT_SCREEN, 0, SCREEN_SIZE_BOT);
memset(TOP_SCREEN, 0, SCREEN_SIZE_TOP); memset(TOP_SCREEN, 0, SCREEN_SIZE_TOP);
memcpy(BOT_SCREEN, buffer_b, SCREEN_SIZE_BOT); memcpy(BOT_SCREEN, buffer_b, SCREEN_SIZE_BOT);
memcpy(TOP_SCREEN, buffer_t, SCREEN_SIZE_TOP); memcpy(TOP_SCREEN, buffer_t, SCREEN_SIZE_TOP);*/
} }
// what to do on error...? // what to do on error...?
free(buffer); free(buffer);
if (png_data) free(png_data); free(png);
} }

View File

@ -1,3 +1,3 @@
#pragma once #pragma once
void CreateScreenshot(); void CreateScreenshot(void);

View File

@ -5220,15 +5220,6 @@ static void filterScanline(unsigned char* out, const unsigned char* scanline, co
} }
} }
/* log2 approximation. A slight bit faster than std::log. */
static float flog2(float f)
{
float result = 0;
while(f > 32) { result += 4; f /= 16; }
while(f > 2) { ++result; f /= 2; }
return result + 1.442695f * (f * f * f / 3 - 3 * f * f / 2 + 3 * f - 1.83333f);
}
static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h,
const LodePNGColorMode* info, const LodePNGEncoderSettings* settings) const LodePNGColorMode* info, const LodePNGEncoderSettings* settings)
{ {
@ -5336,52 +5327,6 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w,
for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
} }
else if(strategy == LFS_ENTROPY)
{
float sum[5];
unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
float smallest = 0;
unsigned type, bestType = 0;
unsigned count[256];
for(type = 0; type != 5; ++type)
{
attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
if(!attempt[type]) return 83; /*alloc fail*/
}
for(y = 0; y != h; ++y)
{
/*try the 5 filter types*/
for(type = 0; type != 5; ++type)
{
filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
for(x = 0; x != 256; ++x) count[x] = 0;
for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]];
++count[type]; /*the filter type itself is part of the scanline*/
sum[type] = 0;
for(x = 0; x != 256; ++x)
{
float p = count[x] / (float)(linebytes + 1);
sum[type] += count[x] == 0 ? 0 : flog2(1 / p) * p;
}
/*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
if(type == 0 || sum[type] < smallest)
{
bestType = type;
smallest = sum[type];
}
}
prevline = &in[y * linebytes];
/*now fill the out values*/
out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
}
for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
}
else if(strategy == LFS_PREDEFINED) else if(strategy == LFS_PREDEFINED)
{ {
for(y = 0; y != h; ++y) for(y = 0; y != h; ++y)

View File

@ -558,9 +558,6 @@ typedef enum LodePNGFilterStrategy
LFS_ZERO, LFS_ZERO,
/*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/ /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/
LFS_MINSUM, LFS_MINSUM,
/*Use the filter type that gives smallest Shannon entropy for this scanline. Depending
on the image, this is better or worse than minsum.*/
LFS_ENTROPY,
/* /*
Brute-force-search PNG filters by compressing each filter for each scanline. Brute-force-search PNG filters by compressing each filter for each scanline.
Experimental, very slow, and only rarely gives better compression than MINSUM. Experimental, very slow, and only rarely gives better compression than MINSUM.

View File

@ -21,9 +21,10 @@ u8 *PNG_Decompress(const u8 *png, size_t png_len, u32 *w, u32 *h)
u32 res; u32 res;
size_t w_, h_; size_t w_, h_;
img = NULL;
res = lodepng_decode24(&img, &w_, &h_, png, png_len); res = lodepng_decode24(&img, &w_, &h_, png, png_len);
if (res) { if (res) {
if (img) free(img); free(img);
return NULL; return NULL;
} }
_rgb_swap(img, w_ * h_ * 3); _rgb_swap(img, w_ * h_ * 3);
@ -33,18 +34,21 @@ u8 *PNG_Decompress(const u8 *png, size_t png_len, u32 *w, u32 *h)
return img; return img;
} }
u8 *PNG_Compress(u8 *fb, u32 w, u32 h, size_t *png_sz) u8 *PNG_Compress(const u8 *fb, u32 w, u32 h, size_t *png_sz)
{ {
u8 *img;
u32 res; u32 res;
size_t png_size; size_t png_size;
u8 *img;
img = NULL;
res = lodepng_encode24(&img, &png_size, fb, w, h); res = lodepng_encode24(&img, &png_size, fb, w, h);
if (res) { if (res) {
if (img) free(img); free(img);
return NULL; return NULL;
} }
if (png_sz) *png_sz = png_size;
if (png_sz)
*png_sz = png_size;
return img; return img;
} }

View File

@ -7,4 +7,4 @@
#define PNG_MAGIC 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A #define PNG_MAGIC 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A
u8 *PNG_Decompress(const u8 *png, size_t png_len, u32 *w, u32 *h); u8 *PNG_Decompress(const u8 *png, size_t png_len, u32 *w, u32 *h);
u8 *PNG_Compress(u8 *fb, u32 w, u32 h, size_t *png_sz); u8 *PNG_Compress(const u8 *fb, u32 w, u32 h, size_t *png_sz);