From a42dbedf82e89047887bd3b9def9f820a75bd5f4 Mon Sep 17 00:00:00 2001 From: Wolfvak Date: Sat, 25 May 2019 10:34:29 -0300 Subject: [PATCH] fix screenshot functionality --- arm9/source/common/screenshot.c | 69 +++++++++++++++++++-------------- arm9/source/common/screenshot.h | 2 +- arm9/source/lodepng/lodepng.c | 55 -------------------------- arm9/source/lodepng/lodepng.h | 3 -- arm9/source/system/png.c | 14 ++++--- arm9/source/system/png.h | 2 +- 6 files changed, 50 insertions(+), 95 deletions(-) diff --git a/arm9/source/common/screenshot.c b/arm9/source/common/screenshot.c index b5393d3..0661cf1 100644 --- a/arm9/source/common/screenshot.c +++ b/arm9/source/common/screenshot.c @@ -4,60 +4,69 @@ #include "vff.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() { - const u32 snap_size = SCREEN_SIZE_TOP * 2, snap_width = SCREEN_WIDTH_TOP, snap_height = SCREEN_HEIGHT * 2; - u8 *png_data = NULL; - size_t png_size; + r = ((rgb_s >> 11) & 0x1F) << 3; + g = ((rgb_s >> 5) & 0x3F) << 2; + b = (rgb_s & 0x1F) << 3; - char filename[64]; + *(dest++) = r; + *(dest++) = g; + *(dest++) = b; + } + + dest += stride; + } +} + +void CreateScreenshot(void) { 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); get_dstime(&dstime); snprintf(filename, 64, OUTPUT_PATH "/snap_%02X%02X%02X%02X%02X%02X.png", dstime.bcd_Y, dstime.bcd_M, dstime.bcd_D, 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; - u8* buffer_t = buffer; - u8* buffer_b = buffer + SCREEN_SIZE_TOP; + memset(buffer, 0x1F, snapbuf_size); // gray background - memset(buffer, 0x1F, snap_size); // gray background + bot_offset = ((400 * SCREEN_HEIGHT) + 40) * 3; - for (u32 x = 0; x < 400; x++) { - for (u32 y = 0; y < 240; y++) { - 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); - } - } + Screenshot_CvtAndTranspose(buffer, TOP_SCREEN, SCREEN_WIDTH_TOP, 0); + Screenshot_CvtAndTranspose(buffer + bot_offset, BOT_SCREEN, SCREEN_WIDTH_BOT, 80 * 3); - for (u32 x = 0; x < 320; x++) { - 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 = PNG_Compress(buffer, snap_w, snap_h, &png_size); - png_data = PNG_Compress(buffer, snap_width, snap_height, &png_size); - - if (png_data && png_size) { - fvx_qwrite(filename, png_data, 0, png_size, NULL); + if (png && png_size) { + fvx_qwrite(filename, png, 0, png_size, NULL); // "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); memset(BOT_SCREEN, 0, SCREEN_SIZE_BOT); memset(TOP_SCREEN, 0, SCREEN_SIZE_TOP); 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...? free(buffer); - if (png_data) free(png_data); + free(png); } diff --git a/arm9/source/common/screenshot.h b/arm9/source/common/screenshot.h index b094f5c..b78486f 100644 --- a/arm9/source/common/screenshot.h +++ b/arm9/source/common/screenshot.h @@ -1,3 +1,3 @@ #pragma once -void CreateScreenshot(); +void CreateScreenshot(void); diff --git a/arm9/source/lodepng/lodepng.c b/arm9/source/lodepng/lodepng.c index 598354a..441c9ce 100644 --- a/arm9/source/lodepng/lodepng.c +++ b/arm9/source/lodepng/lodepng.c @@ -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, 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]); } - 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) { for(y = 0; y != h; ++y) diff --git a/arm9/source/lodepng/lodepng.h b/arm9/source/lodepng/lodepng.h index 14846f9..b86c37c 100644 --- a/arm9/source/lodepng/lodepng.h +++ b/arm9/source/lodepng/lodepng.h @@ -558,9 +558,6 @@ typedef enum LodePNGFilterStrategy LFS_ZERO, /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/ 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. Experimental, very slow, and only rarely gives better compression than MINSUM. diff --git a/arm9/source/system/png.c b/arm9/source/system/png.c index a8ee83c..c606e3c 100644 --- a/arm9/source/system/png.c +++ b/arm9/source/system/png.c @@ -21,9 +21,10 @@ u8 *PNG_Decompress(const u8 *png, size_t png_len, u32 *w, u32 *h) u32 res; size_t w_, h_; + img = NULL; res = lodepng_decode24(&img, &w_, &h_, png, png_len); if (res) { - if (img) free(img); + free(img); return NULL; } _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; } -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; size_t png_size; - u8 *img; + img = NULL; res = lodepng_encode24(&img, &png_size, fb, w, h); if (res) { - if (img) free(img); + free(img); return NULL; } - if (png_sz) *png_sz = png_size; + + if (png_sz) + *png_sz = png_size; return img; } diff --git a/arm9/source/system/png.h b/arm9/source/system/png.h index 819b047..06a02a5 100644 --- a/arm9/source/system/png.h +++ b/arm9/source/system/png.h @@ -7,4 +7,4 @@ #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_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);