mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
fix screenshot functionality
This commit is contained in:
parent
6823e15584
commit
a42dbedf82
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
void CreateScreenshot();
|
void CreateScreenshot(void);
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user