2020-11-24 22:12:23 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <time.h>
|
2021-02-09 03:52:39 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/stat.h>
|
2020-11-24 22:12:23 +00:00
|
|
|
|
2022-06-14 00:49:09 +00:00
|
|
|
#include <png.h>
|
2020-11-24 22:12:23 +00:00
|
|
|
|
2022-07-13 20:46:33 +00:00
|
|
|
#include <libreborn/libreborn.h>
|
2020-11-24 22:12:23 +00:00
|
|
|
#include <GLES/gl.h>
|
2022-07-13 20:46:33 +00:00
|
|
|
#include <mods/screenshot/screenshot.h>
|
2020-11-24 22:12:23 +00:00
|
|
|
|
2021-08-27 02:52:18 +00:00
|
|
|
// Ensure Screenshots Folder Exists
|
|
|
|
static void ensure_screenshots_folder(char *screenshots) {
|
|
|
|
// Check Screenshots Folder
|
|
|
|
struct stat obj;
|
|
|
|
if (stat(screenshots, &obj) != 0 || !S_ISDIR(obj.st_mode)) {
|
|
|
|
// Create Screenshots Folder
|
|
|
|
int ret = mkdir(screenshots, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
|
|
|
if (ret != 0) {
|
|
|
|
// Unable To Create Folder
|
|
|
|
ERR("Error Creating Directory: %s: %s", screenshots, strerror(errno));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-09 03:52:39 +00:00
|
|
|
// 4 (Year) + 1 (Hyphen) + 2 (Month) + 1 (Hyphen) + 2 (Day) + 1 (Underscore) + 2 (Hour) + 1 (Period) + 2 (Minute) + 1 (Period) + 2 (Second) + 1 (Null Terminator)
|
2020-11-24 22:12:23 +00:00
|
|
|
#define TIME_SIZE 20
|
|
|
|
|
|
|
|
// Take Screenshot
|
2022-06-14 00:49:09 +00:00
|
|
|
static int save_png(const char *filename, unsigned char *pixels, int line_size, int width, int height) {
|
|
|
|
// Return value
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
// Variables
|
|
|
|
png_structp png = NULL;
|
|
|
|
png_infop info = NULL;
|
|
|
|
FILE *file = NULL;
|
|
|
|
png_colorp palette = NULL;
|
|
|
|
png_bytep rows[height];
|
|
|
|
for (int i = 0; i < height; ++i) {
|
|
|
|
rows[height - i - 1] = (png_bytep) (&pixels[i * line_size]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init
|
|
|
|
png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
|
|
if (!png) {
|
|
|
|
ret = 1;
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
info = png_create_info_struct(png);
|
|
|
|
if (!info) {
|
|
|
|
ret = 1;
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open File
|
|
|
|
file = fopen(filename, "wb");
|
|
|
|
if (!file) {
|
|
|
|
ret = 1;
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prepare To Write
|
|
|
|
png_init_io(png, file);
|
|
|
|
png_set_IHDR(png, info, width, height, 8 /* Depth */, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
|
|
|
palette = (png_colorp) png_malloc(png, PNG_MAX_PALETTE_LENGTH * sizeof(png_color));
|
|
|
|
if (!palette) {
|
|
|
|
ret = 1;
|
|
|
|
goto ret;
|
|
|
|
}
|
|
|
|
png_set_PLTE(png, info, palette, PNG_MAX_PALETTE_LENGTH);
|
|
|
|
png_write_info(png, info);
|
|
|
|
png_set_packing(png);
|
|
|
|
|
|
|
|
// Write
|
|
|
|
png_write_image(png, rows);
|
|
|
|
png_write_end(png, info);
|
|
|
|
|
|
|
|
ret:
|
|
|
|
// Free
|
|
|
|
if (palette != NULL) {
|
|
|
|
png_free(png, palette);
|
|
|
|
}
|
|
|
|
if (file != NULL) {
|
|
|
|
fclose(file);
|
|
|
|
}
|
|
|
|
if (png != NULL) {
|
|
|
|
png_destroy_write_struct(&png, &info);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return
|
|
|
|
return ret;
|
|
|
|
}
|
2022-07-13 20:46:33 +00:00
|
|
|
void screenshot_take(char *home) {
|
2021-08-27 02:52:18 +00:00
|
|
|
// Get Directory
|
|
|
|
char *screenshots = NULL;
|
|
|
|
safe_asprintf(&screenshots, "%s/screenshots", home);
|
|
|
|
|
|
|
|
// Get Timestamp
|
2020-11-24 22:12:23 +00:00
|
|
|
time_t rawtime;
|
|
|
|
struct tm *timeinfo;
|
|
|
|
time(&rawtime);
|
|
|
|
timeinfo = localtime(&rawtime);
|
|
|
|
char time[TIME_SIZE];
|
|
|
|
strftime(time, TIME_SIZE, "%Y-%m-%d_%H.%M.%S", timeinfo);
|
|
|
|
|
2021-08-27 02:52:18 +00:00
|
|
|
// Ensure Screenshots Folder Exists
|
|
|
|
ensure_screenshots_folder(screenshots);
|
2020-11-24 22:12:23 +00:00
|
|
|
|
2021-08-27 02:52:18 +00:00
|
|
|
// Prevent Overwriting Screenshots
|
2020-11-24 22:12:23 +00:00
|
|
|
int num = 1;
|
|
|
|
char *file = NULL;
|
2021-06-17 21:32:24 +00:00
|
|
|
safe_asprintf(&file, "%s/%s.png", screenshots, time);
|
2020-11-24 22:12:23 +00:00
|
|
|
while (access(file, F_OK) != -1) {
|
2021-06-17 21:32:24 +00:00
|
|
|
free(file);
|
|
|
|
file = NULL;
|
|
|
|
safe_asprintf(&file, "%s/%s-%i.png", screenshots, time, num);
|
2020-11-24 22:12:23 +00:00
|
|
|
num++;
|
|
|
|
}
|
|
|
|
|
2021-08-27 02:52:18 +00:00
|
|
|
// Get Image Size
|
2020-11-24 22:12:23 +00:00
|
|
|
GLint viewport[4];
|
|
|
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
|
|
|
int x = viewport[0];
|
|
|
|
int y = viewport[1];
|
|
|
|
int width = viewport[2];
|
|
|
|
int height = viewport[3];
|
|
|
|
|
2021-08-27 02:52:18 +00:00
|
|
|
// Get Line Size
|
2022-05-29 22:44:27 +00:00
|
|
|
int line_size = width * 4;
|
2021-09-15 23:12:03 +00:00
|
|
|
{
|
|
|
|
// Handle Alignment
|
|
|
|
int alignment;
|
|
|
|
glGetIntegerv(GL_PACK_ALIGNMENT, &alignment);
|
|
|
|
// Round
|
|
|
|
int diff = line_size % alignment;
|
|
|
|
if (diff > 0) {
|
|
|
|
line_size = line_size + (alignment - diff);
|
|
|
|
}
|
|
|
|
}
|
2020-11-24 22:12:23 +00:00
|
|
|
int size = height * line_size;
|
|
|
|
|
2021-08-27 02:52:18 +00:00
|
|
|
// Read Pixels
|
2023-08-02 05:08:31 +00:00
|
|
|
unsigned char *pixels = (unsigned char *) malloc(size);
|
|
|
|
ALLOC_CHECK(pixels);
|
2022-05-29 22:44:27 +00:00
|
|
|
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
2020-11-24 22:12:23 +00:00
|
|
|
|
2021-08-27 02:52:18 +00:00
|
|
|
// Save Image
|
2022-06-14 00:49:09 +00:00
|
|
|
if (save_png(file, pixels, line_size, width, height)) {
|
2022-07-09 02:40:56 +00:00
|
|
|
WARN("Screenshot Failed: %s", file);
|
2020-11-24 22:12:23 +00:00
|
|
|
} else {
|
|
|
|
INFO("Screenshot Saved: %s", file);
|
|
|
|
}
|
|
|
|
|
2021-08-27 02:52:18 +00:00
|
|
|
// Free
|
2020-11-24 22:12:23 +00:00
|
|
|
free(file);
|
|
|
|
free(screenshots);
|
2023-08-02 05:08:31 +00:00
|
|
|
free(pixels);
|
2020-11-24 22:12:23 +00:00
|
|
|
}
|