diff --git a/Makefile.common b/Makefile.common index 4623cf11e3..b1a0dbe006 100644 --- a/Makefile.common +++ b/Makefile.common @@ -772,7 +772,6 @@ ifeq ($(HAVE_7ZIP),1) OBJ += $(7ZOBJ) endif - OBJ += libretro-common/formats/tga/tga_decode.o ifeq ($(HAVE_ZLIB), 1) OBJ += libretro-common/file/file_extract.o @@ -796,6 +795,8 @@ ifeq ($(HAVE_RPNG), 1) OBJ += libretro-common/formats/png/rpng.o \ libretro-common/formats/png/rpng_encode.o endif +OBJ += libretro-common/formats/bmp/rbmp_encode.o \ + libretro-common/formats/tga/tga_decode.o ifdef HAVE_COMPRESSION DEFINES += -DHAVE_COMPRESSION diff --git a/griffin/griffin.c b/griffin/griffin.c index dd6eb151c9..a345da577c 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -178,6 +178,8 @@ VIDEO IMAGE #include "../libretro-common/formats/png/rpng_encode.c" #endif +#include "../libretro-common/formats/bmp/rbmp_encode.c" + /*============================================================ VIDEO DRIVER ============================================================ */ diff --git a/libretro-common/formats/bmp/rbmp_encode.c b/libretro-common/formats/bmp/rbmp_encode.c new file mode 100644 index 0000000000..d2d8b43292 --- /dev/null +++ b/libretro-common/formats/bmp/rbmp_encode.c @@ -0,0 +1,171 @@ +/* Copyright (C) 2010-2015 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (rbmp_encode.c). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include +#include + +static bool write_header_bmp(RFILE *file, unsigned width, unsigned height) +{ + unsigned line_size = (width * 3 + 3) & ~3; + unsigned size = line_size * height + 54; + unsigned size_array = line_size * height; + + /* Generic BMP stuff. */ + const uint8_t header[] = { + 'B', 'M', + (uint8_t)(size >> 0), (uint8_t)(size >> 8), + (uint8_t)(size >> 16), (uint8_t)(size >> 24), + 0, 0, 0, 0, + 54, 0, 0, 0, + 40, 0, 0, 0, + (uint8_t)(width >> 0), (uint8_t)(width >> 8), + (uint8_t)(width >> 16), (uint8_t)(width >> 24), + (uint8_t)(height >> 0), (uint8_t)(height >> 8), + (uint8_t)(height >> 16), (uint8_t)(height >> 24), + 1, 0, + 24, 0, + 0, 0, 0, 0, + (uint8_t)(size_array >> 0), (uint8_t)(size_array >> 8), + (uint8_t)(size_array >> 16), (uint8_t)(size_array >> 24), + 19, 11, 0, 0, + 19, 11, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + }; + + return retro_fwrite(file, header, sizeof(header)) == sizeof(header); +} + +static void dump_lines_file(RFILE *file, uint8_t **lines, + size_t line_size, unsigned height) +{ + unsigned i; + + for (i = 0; i < height; i++) + retro_fwrite(file, lines[i], line_size); +} + +static void dump_line_bgr(uint8_t *line, const uint8_t *src, unsigned width) +{ + memcpy(line, src, width * 3); +} + +static void dump_line_16(uint8_t *line, const uint16_t *src, unsigned width) +{ + unsigned i; + + for (i = 0; i < width; i++) + { + uint16_t pixel = *src++; + uint8_t b = (pixel >> 0) & 0x1f; + uint8_t g = (pixel >> 5) & 0x3f; + uint8_t r = (pixel >> 11) & 0x1f; + *line++ = (b << 3) | (b >> 2); + *line++ = (g << 2) | (g >> 4); + *line++ = (r << 3) | (r >> 2); + } +} + +static void dump_line_32(uint8_t *line, const uint32_t *src, unsigned width) +{ + unsigned i; + + for (i = 0; i < width; i++) + { + uint32_t pixel = *src++; + *line++ = (pixel >> 0) & 0xff; + *line++ = (pixel >> 8) & 0xff; + *line++ = (pixel >> 16) & 0xff; + } +} + +static void dump_content(RFILE *file, const void *frame, + int width, int height, int pitch, bool bgr24, bool xrgb8888) +{ + size_t line_size; + int i, j; + union + { + const uint8_t *u8; + const uint16_t *u16; + const uint32_t *u32; + } u; + uint8_t **lines = (uint8_t**)calloc(height, sizeof(uint8_t*)); + + if (!lines) + return; + + u.u8 = (const uint8_t*)frame; + line_size = (width * 3 + 3) & ~3; + + for (i = 0; i < height; i++) + { + lines[i] = (uint8_t*)calloc(1, line_size); + if (!lines[i]) + goto end; + } + + if (bgr24) /* BGR24 byte order. Can directly copy. */ + { + for (j = 0; j < height; j++, u.u8 += pitch) + dump_line_bgr(lines[j], u.u8, width); + } + else if (xrgb8888) + { + for (j = 0; j < height; j++, u.u8 += pitch) + dump_line_32(lines[j], u.u32, width); + } + else /* RGB565 */ + { + for (j = 0; j < height; j++, u.u8 += pitch) + dump_line_16(lines[j], u.u16, width); + } + + dump_lines_file(file, lines, line_size, height); + +end: + for (i = 0; i < height; i++) + free(lines[i]); + free(lines); +} + +bool rbmp_save_image(const char *filename, const void *frame, + unsigned width, unsigned height, + unsigned pitch, bool bgr24, bool xrgb8888) +{ + bool ret; + RFILE *file = retro_fopen(filename, RFILE_MODE_WRITE, -1); + if (!file) + return false; + + ret = write_header_bmp(file, width, height); + + if (ret) + dump_content(file, frame, width, height, pitch, bgr24, xrgb8888); + + retro_fclose(file); + + return ret; +} diff --git a/libretro-common/include/formats/rbmp.h b/libretro-common/include/formats/rbmp.h new file mode 100644 index 0000000000..1a2ee3a6d0 --- /dev/null +++ b/libretro-common/include/formats/rbmp.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2010-2015 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (rbmp.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LIBRETRO_SDK_FORMAT_RBMP_H__ +#define __LIBRETRO_SDK_FORMAT_RBMP_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool rbmp_save_image(const char *filename, const void *frame, + unsigned width, unsigned height, + unsigned pitch, bool bgr24, bool xrgb8888); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/screenshot.c b/screenshot.c index 0b57d59889..205b39a556 100644 --- a/screenshot.c +++ b/screenshot.c @@ -34,6 +34,7 @@ #if defined(HAVE_ZLIB_DEFLATE) && defined(HAVE_RPNG) #include #endif +#include #include "general.h" #include "msg_hash.h" @@ -51,131 +52,6 @@ #define IMG_EXT "png" #else #define IMG_EXT "bmp" - -static bool write_header_bmp(RFILE *file, unsigned width, unsigned height) -{ - unsigned line_size = (width * 3 + 3) & ~3; - unsigned size = line_size * height + 54; - unsigned size_array = line_size * height; - - /* Generic BMP stuff. */ - const uint8_t header[] = { - 'B', 'M', - (uint8_t)(size >> 0), (uint8_t)(size >> 8), - (uint8_t)(size >> 16), (uint8_t)(size >> 24), - 0, 0, 0, 0, - 54, 0, 0, 0, - 40, 0, 0, 0, - (uint8_t)(width >> 0), (uint8_t)(width >> 8), - (uint8_t)(width >> 16), (uint8_t)(width >> 24), - (uint8_t)(height >> 0), (uint8_t)(height >> 8), - (uint8_t)(height >> 16), (uint8_t)(height >> 24), - 1, 0, - 24, 0, - 0, 0, 0, 0, - (uint8_t)(size_array >> 0), (uint8_t)(size_array >> 8), - (uint8_t)(size_array >> 16), (uint8_t)(size_array >> 24), - 19, 11, 0, 0, - 19, 11, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 - }; - - return retro_fwrite(file, header, sizeof(header)) == sizeof(header); -} - -static void dump_lines_file(RFILE *file, uint8_t **lines, - size_t line_size, unsigned height) -{ - unsigned i; - - for (i = 0; i < height; i++) - retro_fwrite(file, lines[i], line_size); -} - -static void dump_line_bgr(uint8_t *line, const uint8_t *src, unsigned width) -{ - memcpy(line, src, width * 3); -} - -static void dump_line_16(uint8_t *line, const uint16_t *src, unsigned width) -{ - unsigned i; - - for (i = 0; i < width; i++) - { - uint16_t pixel = *src++; - uint8_t b = (pixel >> 0) & 0x1f; - uint8_t g = (pixel >> 5) & 0x3f; - uint8_t r = (pixel >> 11) & 0x1f; - *line++ = (b << 3) | (b >> 2); - *line++ = (g << 2) | (g >> 4); - *line++ = (r << 3) | (r >> 2); - } -} - -static void dump_line_32(uint8_t *line, const uint32_t *src, unsigned width) -{ - unsigned i; - - for (i = 0; i < width; i++) - { - uint32_t pixel = *src++; - *line++ = (pixel >> 0) & 0xff; - *line++ = (pixel >> 8) & 0xff; - *line++ = (pixel >> 16) & 0xff; - } -} - -static void dump_content(RFILE *file, const void *frame, - int width, int height, int pitch, bool bgr24) -{ - size_t line_size; - int i, j; - union - { - const uint8_t *u8; - const uint16_t *u16; - const uint32_t *u32; - } u; - uint8_t **lines = (uint8_t**)calloc(height, sizeof(uint8_t*)); - - if (!lines) - return; - - u.u8 = (const uint8_t*)frame; - line_size = (width * 3 + 3) & ~3; - - for (i = 0; i < height; i++) - { - lines[i] = (uint8_t*)calloc(1, line_size); - if (!lines[i]) - goto end; - } - - if (bgr24) /* BGR24 byte order. Can directly copy. */ - { - for (j = 0; j < height; j++, u.u8 += pitch) - dump_line_bgr(lines[j], u.u8, width); - } - else if (video_driver_get_pixel_format() == RETRO_PIXEL_FORMAT_XRGB8888) - { - for (j = 0; j < height; j++, u.u8 += pitch) - dump_line_32(lines[j], u.u32, width); - } - else /* RGB565 */ - { - for (j = 0; j < height; j++, u.u8 += pitch) - dump_line_16(lines[j], u.u16, width); - } - - dump_lines_file(file, lines, line_size, height); - -end: - for (i = 0; i < height; i++) - free(lines[i]); - free(lines); -} #endif static bool take_screenshot_viewport(void) @@ -370,13 +246,9 @@ bool screenshot_dump(const char *folder, const void *frame, surf->Release(); if(ret == S_OK) - { - RARCH_LOG("Screenshot saved: %s.\n", filename); - rarch_main_msg_queue_push("Screenshot saved.", 1, 30, false); - return true; - } - - ret = false; + ret = true; + else + ret = false; #elif defined(HAVE_ZLIB_DEFLATE) && defined(HAVE_RPNG) out_buffer = (uint8_t*)malloc(width * height * 3); if (!out_buffer) @@ -406,27 +278,13 @@ bool screenshot_dump(const char *folder, const void *frame, RARCH_LOG("Using RPNG for PNG screenshots.\n"); ret = rpng_save_image_bgr24(filename, out_buffer, width, height, width * 3); - if (!ret) - RARCH_ERR("Failed to take screenshot.\n"); free(out_buffer); #else - file = retro_fopen(filename, RFILE_MODE_WRITE, -1); - if (!file) - { - RARCH_ERR("Failed to open file \"%s\" for screenshot.\n", filename); - return false; - } - - ret = write_header_bmp(file, width, height); - - if (ret) - dump_content(file, frame, width, height, pitch, bgr24); - else - RARCH_ERR("Failed to write image header.\n"); - - retro_fclose(file); + ret = rbmp_save_image(filename, frame, width, height, pitch, bgr24, + (video_driver_get_pixel_format() == RETRO_PIXEL_FORMAT_XRGB8888) ); #endif + if (!ret) + RARCH_ERR("Failed to take screenshot.\n"); return ret; } -