diff --git a/libopenlibm.a b/libopenlibm.a new file mode 100644 index 0000000..acf105b Binary files /dev/null and b/libopenlibm.a differ diff --git a/makefile b/makefile index fcd22d6..66f5177 100644 --- a/makefile +++ b/makefile @@ -33,10 +33,10 @@ BUILD_X86_ASM = 1 #BUILD_VS_XP_TARGET = 1 # Include 7-zip support -INCLUDE_7Z_SUPPORT = 1 +#INCLUDE_7Z_SUPPORT = 1 # Include AVI recording support (uses Video For Windows) -INCLUDE_AVI_RECORDING = 1 +#INCLUDE_AVI_RECORDING = 1 # Include LUA support (on Windows Standalone, LUA is enabled regardless) #INCLUDE_LUA_SUPPORT = 1 @@ -68,7 +68,7 @@ PERL = 1 LSB_FIRST = 1 # Include png.h from burner.h -INCLUDE_LIB_PNGH = 1 +# INCLUDE_LIB_PNGH = 1 # Enable CRT resolution switching # INCLUDE_SWITCHRES = 1 diff --git a/makefile.sdl2 b/makefile.sdl2 index dbc0de0..ccbbb34 100644 --- a/makefile.sdl2 +++ b/makefile.sdl2 @@ -50,7 +50,7 @@ srcdir = src/ include makefile.burn_rules # Platform stuff -alldir += burner burner/sdl burner/sdl dep/libs/libspng dep/libs/lib7z dep/libs/zlib intf intf/video \ +alldir += burner burner/sdl burner/sdl dep/libs/zlib intf intf/video \ intf/video/scalers intf/video/sdl intf/audio intf/audio/sdl intf/input intf/input/sdl intf/cd intf/cd/sdl \ intf/perfcount intf/perfcount/sdl dep/generated @@ -61,14 +61,12 @@ depobj += neocdlist.o \ adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o gzwrite.o infback.o inffast.o inflate.o inftrees.o \ trees.o uncompr.o zutil.o \ \ - spng.o \ - \ aud_dsp.o aud_interface.o cd_interface.o inp_interface.o interface.o lowpass2.o vid_interface.o \ vid_support.o \ \ inp_sdl2.o aud_sdl.o support_paths.o ips_manager.o scrn.o localise_gamelist.o romdata.o \ cd_sdl2.o config.o main.o run.o stringset.o bzip.o drv.o media.o sdl2_gui_ingame.o sdl2_gui_common.o \ - inpdipsw.o vid_sdl2opengl.o vid_sdl2.o inputbuf.o replay.o sdl2_gui.o sdl2_inprint.o input_sdl2.o stated.o + inpdipsw.o vid_sdl2opengl.o vid_sdl2.o inputbuf.o replay.o sdl2_gui.o sdl2_inprint.o input_sdl2.o stated.o util.o ifdef FORCE_PULSE_AUDIO alldir += intf/audio/linux @@ -100,7 +98,7 @@ lib = -lstdc++ `sdl2-config --libs` -lopengl32 -lSDL2_image -lm else ifdef DARWIN lib = -lstdc++ `sdl2-config --libs` -lSDL2_image -lm -lpthread else -lib = -lstdc++ `sdl2-config --libs` -lGL -lSDL2_image -lm -lpthread +lib = -lstdc++ `sdl2-config --libs` -lGL -lSDL2_image libopenlibm.a endif ifdef FORCE_PULSE_AUDIO @@ -191,13 +189,13 @@ endif #LDFLAGS = -static -CFLAGS = -O2 -fomit-frame-pointer -Wno-write-strings \ +CFLAGS = -Wl,--section-start=.text=0x1004000 -Wl,--section-start=.plt=0x1002020 -no-pie -O0 -mno-mmx -mno-red-zone -fomit-frame-pointer -Wno-write-strings \ -Wall -Wno-long-long -Wno-sign-compare -Wno-uninitialized -Wno-unused \ -Wno-conversion -Wno-attributes \ -Wno-unused-parameter -Wno-unused-value -std=c99 \ $(PLATFLAGS) $(DEF) $(incdir) -CXXFLAGS = -O2 -fomit-frame-pointer -Wno-write-strings \ +CXXFLAGS = -Wl,--section-start=.text=0x1004000 -Wl,--section-start=.plt=0x1002020 -no-pie -O0 -mno-mmx -mno-red-zone -fomit-frame-pointer -Wno-write-strings \ -Wall -W -Wno-long-long -Wno-sign-compare \ -Wunknown-pragmas -Wundef -Wconversion -Wno-missing-braces \ -Wuninitialized -Wpointer-arith -Winline -Wno-multichar \ @@ -287,7 +285,7 @@ ifdef SYMBOL ASFLAGS += -g DEF := $(DEF) -D_DEBUG else - LDFLAGS += -s + #LDFLAGS += -s endif ifdef PROFILE diff --git a/src/burn/devices/thready.h b/src/burn/devices/thready.h index 8e02aa3..82fd5d9 100644 --- a/src/burn/devices/thready.h +++ b/src/burn/devices/thready.h @@ -26,7 +26,7 @@ #if defined(__APPLE__) #define THREADY THREADY_PTHREADAPL #else - #define THREADY THREADY_PTHREAD + #define THREADY THREADY_0THREAD #endif #include #include diff --git a/src/burner/image.cpp b/src/burner/image.cpp index b74ec67..cf4536e 100644 --- a/src/burner/image.cpp +++ b/src/burner/image.cpp @@ -1,5 +1,4 @@ #include "burner.h" -#include "spng.h" #define PNG_SIG_LEN (8) const UINT8 PNG_SIG[8] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }; @@ -428,202 +427,15 @@ bool PNGIsImage(FILE* fp) const char *color_type_str(int color_type) { - switch(color_type) - { - case SPNG_COLOR_TYPE_GRAYSCALE: return "grayscale"; - case SPNG_COLOR_TYPE_TRUECOLOR: return "truecolor"; - case SPNG_COLOR_TYPE_INDEXED: return "indexed color"; - case SPNG_COLOR_TYPE_GRAYSCALE_ALPHA: return "grayscale with alpha"; - case SPNG_COLOR_TYPE_TRUECOLOR_ALPHA: return "truecolor with alpha"; - default: return "(invalid)"; - } + return "(invalid)"; } INT32 PNGLoad(IMAGE* img, FILE* fp, INT32 nPreset) { - IMAGE temp_img; - INT32 width = 0, height = 0; - int ret; - - if (fp) { - // check signature - UINT8 pngsig[PNG_SIG_LEN]; - fread(pngsig, 1, PNG_SIG_LEN, fp); - if (png_sig_check(pngsig)) { - return 1; - } - rewind(fp); - - spng_ctx *ctx = NULL; - struct spng_ihdr ihdr; - - ctx = spng_ctx_new(0); - spng_set_crc_action(ctx, SPNG_CRC_USE, SPNG_CRC_USE); - size_t limit = 1024 * 1024 * 64; - spng_set_chunk_limits(ctx, limit, limit); - spng_set_png_file(ctx, fp); - ret = spng_get_ihdr(ctx, &ihdr); - - if (ret) { - spng_ctx_free(ctx); - return 1; - } - -#if 0 - // debuggy stuff - const char *color_name = color_type_str(ihdr.color_type); - - bprintf(0, _T("width: %u\n" - "height: %u\n" - "bit depth: %u\n" - "color type: %u - %S\n"), - ihdr.width, ihdr.height, ihdr.bit_depth, ihdr.color_type, color_name); - - bprintf(0, _T("compression method: %u\n" - "filter method: %u\n" - "interlace method: %u\n"), - ihdr.compression_method, ihdr.filter_method, ihdr.interlace_method); - - struct spng_plte plte = { 0 }; - ret = spng_get_plte(ctx, &plte); - if (!ret) bprintf(0, _T("palette entries: %u\n"), plte.n_entries); -#endif - - size_t image_size = 0, image_width_bytes = 0; - int fmt = SPNG_FMT_RGB8; - - ret = spng_decoded_image_size(ctx, fmt, &image_size); - ret = spng_decode_image(ctx, NULL, 0, fmt, SPNG_DECODE_PROGRESSIVE | SPNG_DECODE_TRNS ); - - image_width_bytes = image_size / ihdr.height; // it's the width * 3 (1 for each RGB) - - memset(&temp_img, 0, sizeof(IMAGE)); - temp_img.width = ihdr.width; - temp_img.height = ihdr.height; - - if (img_alloc(&temp_img)) { - spng_ctx_free(ctx); - return 1; - } - - struct spng_row_info row_info = {0}; - - // deal with transparency that decodes to non-black - // testcases: dacholer, dowild, ... - int trans_to_black = 0; - struct spng_plte plte; - struct spng_trns trns; - - trans_to_black = - (ihdr.color_type == SPNG_COLOR_TYPE_INDEXED) && - (spng_get_plte(ctx, &plte) == 0) && - (spng_get_trns(ctx, &trns) == 0); - - do { - if ((ret = spng_get_row_info(ctx, &row_info)) != 0) break; - - ret = spng_decode_row(ctx, temp_img.rowptr[row_info.row_num], image_width_bytes); - - for (int i = 0; i < temp_img.width * 3; i += 3) { - int r = temp_img.rowptr[row_info.row_num][i + 0]; - int g = temp_img.rowptr[row_info.row_num][i + 1]; - int b = temp_img.rowptr[row_info.row_num][i + 2]; - - if (trans_to_black) { - for(int j = 0; j < trns.n_type3_entries; j++) - { - if(trns.type3_alpha[j] < 20 && - plte.entries[trns.type3_alpha[j]].red == r && - plte.entries[trns.type3_alpha[j]].green == g && - plte.entries[trns.type3_alpha[j]].blue == b) - { - r = r * trns.type3_alpha[j] / 20; - g = g * trns.type3_alpha[j] / 20; - b = b * trns.type3_alpha[j] / 20; - } - } - } - - temp_img.rowptr[row_info.row_num][i + 0] = b; - temp_img.rowptr[row_info.row_num][i + 1] = g; - temp_img.rowptr[row_info.row_num][i + 2] = r; - } - } while (ret == 0); - - spng_ctx_free(ctx); - } else { - -#ifdef BUILD_WIN32 - // Find resource - HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(BMP_SPLASH), RT_BITMAP); - HGLOBAL hglobal = LoadResource(NULL, (HRSRC)hrsrc); - BYTE* pResourceData = (BYTE*)LockResource(hglobal); - - BITMAPINFOHEADER* pbmih = (BITMAPINFOHEADER*)LockResource(hglobal); - - // Allocate a new image - memset(&temp_img, 0, sizeof(IMAGE)); - temp_img.width = pbmih->biWidth; - temp_img.height = pbmih->biHeight; - temp_img.bmpbits = pResourceData + pbmih->biSize; - img_alloc(&temp_img); - -#else - return 1; -#endif - - } - - if (img_process(&temp_img, img->width ? img->width : temp_img.width, img->height ? img->height : temp_img.height, nPreset, false)) { - img_free(&temp_img); - return 1; - } - - bPngImageOrientation = 0; - if (height && width && height > width) bPngImageOrientation = 1; - - memcpy(img, &temp_img, sizeof(IMAGE)); - return 0; } INT32 PNGGetInfo(IMAGE* img, FILE *fp) { - IMAGE temp_img = { 0, 0, 0, 0, NULL, NULL, 0 }; - - if (fp) { - // check signature - UINT8 pngsig[PNG_SIG_LEN]; - fread(pngsig, 1, PNG_SIG_LEN, fp); - if (png_sig_check(pngsig)) { - return 1; - } - rewind(fp); - - spng_ctx *ctx = NULL; - struct spng_ihdr ihdr; - - ctx = spng_ctx_new(0); - spng_set_crc_action(ctx, SPNG_CRC_USE, SPNG_CRC_USE); - size_t limit = 1024 * 1024 * 64; - spng_set_chunk_limits(ctx, limit, limit); - spng_set_png_file(ctx, fp); - int ret = spng_get_ihdr(ctx, &ihdr); - - if (ret) { - // can't decode header info's - bad png - return 1; - } - - memset(&temp_img, 0, sizeof(IMAGE)); - temp_img.width = ihdr.width; - temp_img.height = ihdr.height; - - spng_ctx_free(ctx); - } - - memcpy(img, &temp_img, sizeof(IMAGE)); - img_free(&temp_img); - return 0; } diff --git a/src/burner/sdl/util.cpp b/src/burner/sdl/util.cpp new file mode 100644 index 0000000..827f0a6 --- /dev/null +++ b/src/burner/sdl/util.cpp @@ -0,0 +1,72 @@ +#include "burner.h" + +int clamp(int val, int min_val, int max_val) { + if (val < min_val) return min_val; + if (val > max_val) return max_val; + return val; +} + +#define BLUE 1 +#define GREEN 2 +#define RED 4 + +static const uint8_t bayer8[8][8] = { + { 0, 48, 12, 60, 3, 51, 15, 63}, + {32, 16, 44, 28, 35, 19, 47, 31}, + { 8, 56, 4, 52, 11, 59, 7, 55}, + {40, 24, 36, 20, 43, 27, 39, 23}, + { 2, 50, 14, 62, 1, 49, 13, 61}, + {34, 18, 46, 30, 33, 17, 45, 29}, + {10, 58, 6, 54, 9, 57, 5, 53}, + {42, 26, 38, 22, 41, 25, 37, 21} +}; + +int rgba_to_4bpp(int x, int y, int d, UINT32 pixel) +{ + int b = pixel & 0xff; + int g = (pixel >> 8) & 0xff; + int r = (pixel >> 16) & 0xff; + if (d) { + int threshold = (bayer8[y & 7][x & 7] - 32) * 2; + b = clamp(b + threshold, 0, 255); + g = clamp(g + threshold, 0, 255); + r = clamp(r + threshold, 0, 255); + } + int res = 0; + if (sqrt(r) + sqrt(g) + sqrt(b) >= sqrt(0x80)) { + res = 8; + res |= b >= 0x80 ? BLUE : 0; + res |= g >= 0x80 ? GREEN : 0; + res |= r >= 0x80 ? RED : 0; + } else { + res |= b >= 0x40 ? BLUE : 0; + res |= g >= 0x40 ? GREEN : 0; + res |= r >= 0x40 ? RED : 0; + } + return res; +} + +int rgb565_to_4bpp(int x, int y, int d, UINT16 pixel) +{ + int b = ((pixel & 0x1f) * 255) / 31; + int g = (((pixel >> 5) & 0x3f) * 255) / 63; + int r = (((pixel >> 11) & 0x1f) * 255) / 31; + if (d) { + int threshold = (bayer8[y & 7][x & 7] - 32) * 2; + b = clamp(b + threshold, 0, 255); + g = clamp(g + threshold, 0, 255); + r = clamp(r + threshold, 0, 255); + } + int res = 0; + if (sqrt(r) + sqrt(g) + sqrt(b) >= sqrt(0x80)) { + res = 8; + res |= b >= 0x80 ? BLUE : 0; + res |= g >= 0x80 ? GREEN : 0; + res |= r >= 0x80 ? RED : 0; + } else { + res |= b >= 0x40 ? BLUE : 0; + res |= g >= 0x40 ? GREEN : 0; + res |= r >= 0x40 ? RED : 0; + } + return res; +} diff --git a/src/burner/sshot.cpp b/src/burner/sshot.cpp index 05915a0..7e57cd4 100644 --- a/src/burner/sshot.cpp +++ b/src/burner/sshot.cpp @@ -1,5 +1,4 @@ #include "burner.h" -#include "spng.h" #define SSHOT_NOERROR 0 #define SSHOT_ERROR_BPP_NOTSUPPORTED 1 @@ -30,218 +29,5 @@ static void free_temp_imagen() INT32 MakeScreenShot(INT32 bType) { - char szAuthor[256]; char szDescription[256]; char szCopyright[256]; char szTime[256]; char szSoftware[256]; char szSource[256]; - spng_text text_ptr[8]; - INT32 num_text = 8; - - time_t currentTime; - tm* tmTime; - - char szSShotName[MAX_PATH] = { 0, }; - INT32 w, h; - - if (pVidImage == NULL) { - return SSHOT_OTHER_ERROR; - } - - if (nVidImageBPP < 2 || nVidImageBPP > 4) { - return SSHOT_ERROR_BPP_NOTSUPPORTED; - } - - BurnDrvGetVisibleSize(&w, &h); - - pSShot = pVidImage; - - // Convert the image to 32-bit - if (nVidImageBPP < 4) { - UINT8* pTemp = (UINT8*)malloc(w * h * sizeof(INT32)); - - pFreeMe[0] = pTemp; - - if (nVidImageBPP == 2) { - for (INT32 i = 0; i < h * w; i++) { - UINT16 nColour = ((UINT16*)pSShot)[i]; - - // Red - *(pTemp + i * 4 + 0) = (UINT8)((nColour & 0x1F) << 3); - *(pTemp + i * 4 + 0) |= *(pTemp + 4 * i + 0) >> 5; - - if (nVidImageDepth == 15) { - // Green - *(pTemp + i * 4 + 1) = (UINT8)(((nColour >> 5) & 0x1F) << 3); - *(pTemp + i * 4 + 1) |= *(pTemp + i * 4 + 1) >> 5; - // Blue - *(pTemp + i * 4 + 2) = (UINT8)(((nColour >> 10)& 0x1F) << 3); - *(pTemp + i * 4 + 2) |= *(pTemp + i * 4 + 2) >> 5; - } - - if (nVidImageDepth == 16) { - // Green - *(pTemp + i * 4 + 1) = (UINT8)(((nColour >> 5) & 0x3F) << 2); - *(pTemp + i * 4 + 1) |= *(pTemp + i * 4 + 1) >> 6; - // Blue - *(pTemp + i * 4 + 2) = (UINT8)(((nColour >> 11) & 0x1F) << 3); - *(pTemp + i * 4 + 2) |= *(pTemp + i * 4 + 2) >> 5; - } - } - } else { - memset(pTemp, 0, w * h * sizeof(INT32)); - for (INT32 i = 0; i < h * w; i++) { - *(pTemp + i * 4 + 0) = *(pSShot + i * 3 + 0); - *(pTemp + i * 4 + 1) = *(pSShot + i * 3 + 1); - *(pTemp + i * 4 + 2) = *(pSShot + i * 3 + 2); - } - } - - pSShot = pTemp; - } - - // Rotate and flip the image - if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { - UINT8* pTemp = (UINT8*)malloc(w * h * sizeof(INT32)); - - pFreeMe[1] = pTemp; - - for (INT32 x = 0; x < h; x++) { - if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { - for (INT32 y = 0; y < w; y++) { - ((UINT32*)pTemp)[(w - y - 1) + x * w] = ((UINT32*)pSShot)[x + y * h]; - } - } else { - for (INT32 y = 0; y < w; y++) { - ((UINT32*)pTemp)[y + (h - x - 1) * w] = ((UINT32*)pSShot)[x + y * h]; - } - } - } - - pSShot = pTemp; - } - else if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { // fixed rotation by regret - UINT8* pTemp = (UINT8*)malloc(w * h * sizeof(INT32)); - - pFreeMe[1] = pTemp; - - for (INT32 y = h - 1; y >= 0; y--) { - for (INT32 x = w - 1; x >= 0; x--) { - ((UINT32*)pTemp)[(w - x - 1) + (h - y - 1) * w] = ((UINT32*)pSShot)[x + y * w]; - } - } - - pSShot = pTemp; - } - - { - UINT8* pTemp = (UINT8*)malloc(w * h * 3); // bgrbgrbgr... - - pFreeMe[2] = pTemp; - - // convert (int*)argb to bgr as needed by libspng - for (int i = 0; i < w * h; i++) { - int r = pSShot[i * 4 + 0]; // (int)ARGB (little endian) - int g = pSShot[i * 4 + 1]; - int b = pSShot[i * 4 + 2]; - - pTemp[i * 3 + 0] = b; // BGR (byte order) - pTemp[i * 3 + 1] = g; - pTemp[i * 3 + 2] = r; - } - - pSShot = pTemp; - } - - - // Get the time - time(¤tTime); - tmTime = localtime(¤tTime); - //png_convert_from_time_t(&png_time_now, currentTime); - -#if defined(BUILD_SDL2) && !defined(SDL_WINDOWS) - SSHOT_DIRECTORY = SDL_GetPrefPath("fbneo", "screenshots"); -#endif - - if (bType == 0) { - // construct our filename -> "romname-mm-dd-hms.png" - sprintf(szSShotName,"%s%s-%.2d-%.2d-%.2d%.2d%.2d.png", SSHOT_DIRECTORY, BurnDrvGetTextA(DRV_NAME), tmTime->tm_mon + 1, tmTime->tm_mday, tmTime->tm_hour, tmTime->tm_min, tmTime->tm_sec); - } - else if (bType == 1) { - sprintf(szSShotName,"%s%s.png", _TtoA(szAppTitlesPath), BurnDrvGetTextA(DRV_NAME)); - } - else { - sprintf(szSShotName,"%s%s.png", _TtoA(szAppPreviewsPath), BurnDrvGetTextA(DRV_NAME)); - } - //sprintf(szTime,"%.2d-%.2d-%.2d %.2d:%.2d:%.2d", tmTime->tm_mon + 1, tmTime->tm_mday, tmTime->tm_year, tmTime->tm_hour, tmTime->tm_min, tmTime->tm_sec); - sprintf(szTime, "%s", asctime(tmTime)); -#if defined(BUILD_SDL2) && !defined(SDL_WINDOWS) - SDL_free(SSHOT_DIRECTORY); -#endif - - ff = fopen(szSShotName, "wb"); - if (ff == NULL) { - free_temp_imagen(); - - return SSHOT_OTHER_ERROR; - } - - // Fill the PNG text fields -#ifdef _UNICODE - sprintf(szAuthor, APP_TITLE " v%.20ls", szAppBurnVer); -#else - sprintf(szAuthor, APP_TITLE " v%.20s", szAppBurnVer); -#endif - sprintf(szDescription, "Screenshot of %s", DecorateGameName(nBurnDrvActive)); - sprintf(szCopyright, "%s %s", BurnDrvGetTextA(DRV_DATE), BurnDrvGetTextA(DRV_MANUFACTURER)); -#ifdef _UNICODE - sprintf(szSoftware, APP_TITLE " v%.20ls using LibSPNG v%d.%d.%d", szAppBurnVer, SPNG_VERSION_MAJOR, SPNG_VERSION_MINOR, SPNG_VERSION_PATCH); -#else - sprintf(szSoftware, APP_TITLE " v%.20s using LibSPNG v%d.%d.%d", szAppBurnVer, SPNG_VERSION_MAJOR, SPNG_VERSION_MINOR, SPNG_VERSION_PATCH); -#endif - sprintf(szSource, "%s video game hardware", BurnDrvGetTextA(DRV_SYSTEM)); - - memset(text_ptr, 0, sizeof(text_ptr)); - - strcpy(text_ptr[0].keyword, "Title"); text_ptr[0].text = BurnDrvGetTextA(DRV_FULLNAME); - strcpy(text_ptr[1].keyword, "Author"); text_ptr[1].text = szAuthor; - strcpy(text_ptr[2].keyword, "Description"); text_ptr[2].text = szDescription; - strcpy(text_ptr[3].keyword, "Copyright"); text_ptr[3].text = szCopyright; - strcpy(text_ptr[4].keyword, "Creation Time"); text_ptr[4].text = szTime; - strcpy(text_ptr[5].keyword, "Software"); text_ptr[5].text = szSoftware; - strcpy(text_ptr[6].keyword, "Source"); text_ptr[6].text = szSource; - strcpy(text_ptr[7].keyword, "Comment"); text_ptr[7].text = "This screenshot was created by running the game in an emulator; it might not accurately reflect the actual hardware the game was designed to run on."; - - for (int i = 0; i < num_text; i++) { - text_ptr[i].type = SPNG_TEXT; - text_ptr[i].length = strlen(text_ptr[i].text); - } - - // png it on! (dink was here) - spng_ctx *ctx = NULL; - struct spng_ihdr ihdr = { 0 }; - - ctx = spng_ctx_new(SPNG_CTX_ENCODER); - spng_set_png_file(ctx, ff); - - int rv = spng_set_text(ctx, &text_ptr[0], num_text); - if (rv) { - bprintf(0, _T("spng_set_text() error: %d / %S\n"), rv, spng_strerror(rv)); - } - - ihdr.width = w; - ihdr.height = h; - ihdr.color_type = SPNG_COLOR_TYPE_TRUECOLOR; - ihdr.bit_depth = 8; - spng_set_ihdr(ctx, &ihdr); - - rv = spng_encode_image(ctx, pSShot, w * h * 3, SPNG_FMT_PNG, SPNG_ENCODE_FINALIZE); - - if (rv) { - bprintf(0, _T("spng_encode_image() error: %d / %S\n"), rv, spng_strerror(rv)); - } - - spng_ctx_free(ctx); - - fclose(ff); - - free_temp_imagen(); - return SSHOT_NOERROR; }