From 5a330803ec5bea2ca7b6b30bf7972b11753b571d Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 29 Jan 2020 13:47:55 -0300 Subject: [PATCH 1/6] Local Color Table for GIF movie mode --- src/d_netcmd.c | 1 + src/m_anigif.c | 89 ++++++++++++++++++++++++++++++++++++++------------ src/m_anigif.h | 2 +- 3 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 23ec00b2e..8d36cb058 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -669,6 +669,7 @@ void D_RegisterClientCommands(void) // GIF variables CV_RegisterVar(&cv_gif_optimize); CV_RegisterVar(&cv_gif_downscale); + CV_RegisterVar(&cv_gif_localcolortable); #ifdef WALLSPLATS CV_RegisterVar(&cv_splats); diff --git a/src/m_anigif.c b/src/m_anigif.c index 32fc2746d..bd90f6675 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -19,6 +19,7 @@ #include "v_video.h" #include "i_video.h" #include "m_misc.h" +#include "st_stuff.h" // st_palette #ifdef HWRENDER #include "hardware/hw_main.h" @@ -29,10 +30,12 @@ consvar_t cv_gif_optimize = {"gif_optimize", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_gif_localcolortable = {"gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifdef HAVE_ANIGIF static boolean gif_optimize = false; // So nobody can do something dumb static boolean gif_downscale = false; // like changing cvars mid output +static boolean gif_localcolortable = false; static RGBA_t *gif_palette = NULL; static FILE *gif_out = NULL; @@ -393,6 +396,41 @@ const UINT8 gifhead_nsid[19] = {0x21,0xFF,0x0B, // extension block + size 0x4E,0x45,0x54,0x53,0x43,0x41,0x50,0x45,0x32,0x2E,0x30, // NETSCAPE2.0 0x03,0x01,0xFF,0xFF,0x00}; // sub-block, repetitions + +// +// GIF_setpalette +// determine the gif palette. +// +static void GIF_setpalette(void) +{ + // In hardware mode, uses the master palette + size_t palnum = (rendermode == render_soft) ? ((gif_localcolortable) ? max(st_palette, 0) : 0) : 0; + gif_palette = ((cv_screenshot_colorprofile.value +#ifdef HWRENDER + && (rendermode == render_soft) +#endif + ) ? &pLocalPalette[palnum*256] + : &pMasterPalette[palnum*256]); +} + +// +// GIF_palwrite +// writes the gif palette. +// used both for the header and the local color table. +// +static UINT8 *GIF_palwrite(UINT8 *p) +{ + INT32 i; + RGBA_t *pal = gif_palette; + for (i = 0; i < 256; i++) + { + WRITEUINT8(p, pal[i].s.red); + WRITEUINT8(p, pal[i].s.green); + WRITEUINT8(p, pal[i].s.blue); + } + return p; +} + // // GIF_headwrite // writes the gif header to the currently open output file. @@ -402,8 +440,10 @@ static void GIF_headwrite(void) { UINT8 *gifhead = Z_Malloc(800, PU_STATIC, NULL); UINT8 *p = gifhead; - INT32 i; + UINT8 *last_p; UINT16 rwidth, rheight; + size_t totalbytes; + INT32 i; if (!gif_out) return; @@ -423,30 +463,37 @@ static void GIF_headwrite(void) rwidth = vid.width; rheight = vid.height; } + + last_p = p; WRITEUINT16(p, rwidth); WRITEUINT16(p, rheight); // colors, aspect, etc - WRITEUINT8(p, 0xF7); + WRITEUINT8(p, (gif_localcolortable ? 0xF0 : 0xF7)); // (0xF7 = 1111 0111) WRITEUINT8(p, 0x00); WRITEUINT8(p, 0x00); + // Lactozilla: should be 800 without a local color table + totalbytes = sizeof(gifhead_base) + sizeof(gifhead_nsid) + (p - last_p); + // write color table + if (!gif_localcolortable) { - RGBA_t *pal = gif_palette; - for (i = 0; i < 256; i++) - { - WRITEUINT8(p, pal[i].s.red); - WRITEUINT8(p, pal[i].s.green); - WRITEUINT8(p, pal[i].s.blue); - } + p = GIF_palwrite(p); + totalbytes += (256 * 3); + } + else + { + // write a dummy palette + for (i = 0; i < 6; i++, totalbytes++) + WRITEUINT8(p, 0); } // write extension block WRITEMEM(p, gifhead_nsid, sizeof(gifhead_nsid)); // write to file and be done with it! - fwrite(gifhead, 1, 800, gif_out); + fwrite(gifhead, 1, totalbytes, gif_out); Z_Free(gifhead); } @@ -566,7 +613,15 @@ static void GIF_framewrite(void) WRITEUINT16(p, (UINT16)(blity / scrbuf_downscaleamt)); WRITEUINT16(p, (UINT16)(blitw / scrbuf_downscaleamt)); WRITEUINT16(p, (UINT16)(blith / scrbuf_downscaleamt)); - WRITEUINT8(p, 0); // no local table of colors + + if (!gif_localcolortable) + WRITEUINT8(p, 0); // no local table of colors + else + { + WRITEUINT8(p, 0x87); // (0x87 = 1000 0111) + GIF_setpalette(); + p = GIF_palwrite(p); + } scrbuf_pos = movie_screen + blitx + (blity * vid.width); scrbuf_writeend = scrbuf_pos + (blitw - 1) + ((blith - 1) * vid.width); @@ -638,15 +693,9 @@ INT32 GIF_open(const char *filename) gif_optimize = (!!cv_gif_optimize.value); gif_downscale = (!!cv_gif_downscale.value); - - // GIF color table - // In hardware mode, uses the master palette - gif_palette = ((cv_screenshot_colorprofile.value -#ifdef HWRENDER - && (rendermode == render_soft) -#endif - ) ? pLocalPalette - : pMasterPalette); + gif_localcolortable = (!!cv_gif_localcolortable.value); + if (!gif_localcolortable) + GIF_setpalette(); GIF_headwrite(); gif_frames = 0; diff --git a/src/m_anigif.h b/src/m_anigif.h index 9bdf2cc7f..9eb6faa75 100644 --- a/src/m_anigif.h +++ b/src/m_anigif.h @@ -27,6 +27,6 @@ void GIF_frame(void); INT32 GIF_close(void); #endif -extern consvar_t cv_gif_optimize, cv_gif_downscale; +extern consvar_t cv_gif_optimize, cv_gif_downscale, cv_gif_localcolortable; #endif From 99c755c186705f5161cc6d13b9fbe74753239f5a Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 29 Jan 2020 13:52:02 -0300 Subject: [PATCH 2/6] Update the Screenshot Options menu --- src/m_menu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index f8c14dd69..52889c630 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1443,6 +1443,7 @@ static menuitem_t OP_ScreenshotOptionsMenu[] = {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 95}, {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 100}, + {IT_STRING|IT_CVAR, NULL, "Local Color Table", &cv_gif_localcolortable, 105}, {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 95}, {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 100}, @@ -1457,9 +1458,9 @@ enum op_movie_folder = 11, op_screenshot_capture = 12, op_screenshot_gif_start = 13, - op_screenshot_gif_end = 14, - op_screenshot_apng_start = 15, - op_screenshot_apng_end = 18, + op_screenshot_gif_end = 15, + op_screenshot_apng_start = 16, + op_screenshot_apng_end = 19, }; static menuitem_t OP_EraseDataMenu[] = From 999e72ab325301d248837f5337eb8f90143231ef Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 29 Jan 2020 13:56:39 -0300 Subject: [PATCH 3/6] Uh --- src/m_anigif.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/m_anigif.c b/src/m_anigif.c index bd90f6675..82e118527 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -434,7 +434,6 @@ static UINT8 *GIF_palwrite(UINT8 *p) // // GIF_headwrite // writes the gif header to the currently open output file. -// NOTE that this code does not accomodate for palette changes. // static void GIF_headwrite(void) { From 85211dcc09c922e0d42b4eeea387dcecc8e989ae Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Wed, 29 Jan 2020 17:31:27 -0300 Subject: [PATCH 4/6] Only write a Local Color Table if the frame's palette differs from the header's palette --- src/m_anigif.c | 73 +++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/src/m_anigif.c b/src/m_anigif.c index 82e118527..f917a7b26 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -35,8 +35,12 @@ consvar_t cv_gif_localcolortable = {"gif_localcolortable", "On", CV_SAVE, CV_On #ifdef HAVE_ANIGIF static boolean gif_optimize = false; // So nobody can do something dumb static boolean gif_downscale = false; // like changing cvars mid output + +// Palette handling static boolean gif_localcolortable = false; -static RGBA_t *gif_palette = NULL; +static boolean gif_colorprofile = false; +static RGBA_t *gif_headerpalette = NULL; +static RGBA_t *gif_framepalette = NULL; static FILE *gif_out = NULL; static INT32 gif_frames = 0; @@ -398,14 +402,13 @@ const UINT8 gifhead_nsid[19] = {0x21,0xFF,0x0B, // extension block + size // -// GIF_setpalette -// determine the gif palette. +// GIF_getpalette +// determine the palette for the current frame. // -static void GIF_setpalette(void) +static RGBA_t *GIF_getpalette(size_t palnum) { // In hardware mode, uses the master palette - size_t palnum = (rendermode == render_soft) ? ((gif_localcolortable) ? max(st_palette, 0) : 0) : 0; - gif_palette = ((cv_screenshot_colorprofile.value + return ((gif_colorprofile #ifdef HWRENDER && (rendermode == render_soft) #endif @@ -416,12 +419,11 @@ static void GIF_setpalette(void) // // GIF_palwrite // writes the gif palette. -// used both for the header and the local color table. +// used both for the header and local color tables. // -static UINT8 *GIF_palwrite(UINT8 *p) +static UINT8 *GIF_palwrite(UINT8 *p, RGBA_t *pal) { INT32 i; - RGBA_t *pal = gif_palette; for (i = 0; i < 256; i++) { WRITEUINT8(p, pal[i].s.red); @@ -439,10 +441,7 @@ static void GIF_headwrite(void) { UINT8 *gifhead = Z_Malloc(800, PU_STATIC, NULL); UINT8 *p = gifhead; - UINT8 *last_p; UINT16 rwidth, rheight; - size_t totalbytes; - INT32 i; if (!gif_out) return; @@ -463,36 +462,22 @@ static void GIF_headwrite(void) rheight = vid.height; } - last_p = p; WRITEUINT16(p, rwidth); WRITEUINT16(p, rheight); // colors, aspect, etc - WRITEUINT8(p, (gif_localcolortable ? 0xF0 : 0xF7)); // (0xF7 = 1111 0111) + WRITEUINT8(p, 0xF7); // (0xF7 = 1111 0111) WRITEUINT8(p, 0x00); WRITEUINT8(p, 0x00); - // Lactozilla: should be 800 without a local color table - totalbytes = sizeof(gifhead_base) + sizeof(gifhead_nsid) + (p - last_p); - // write color table - if (!gif_localcolortable) - { - p = GIF_palwrite(p); - totalbytes += (256 * 3); - } - else - { - // write a dummy palette - for (i = 0; i < 6; i++, totalbytes++) - WRITEUINT8(p, 0); - } + p = GIF_palwrite(p, gif_headerpalette); // write extension block WRITEMEM(p, gifhead_nsid, sizeof(gifhead_nsid)); // write to file and be done with it! - fwrite(gifhead, 1, totalbytes, gif_out); + fwrite(gifhead, 1, 800, gif_out); Z_Free(gifhead); } @@ -514,7 +499,7 @@ static void hwrconvert(void) INT32 x, y; size_t i = 0; - InitColorLUT(gif_palette); + InitColorLUT(gif_framepalette); for (y = 0; y < vid.height; y++) { @@ -540,6 +525,7 @@ static void GIF_framewrite(void) UINT8 *p; UINT8 *movie_screen = screens[2]; INT32 blitx, blity, blitw, blith; + boolean palchanged; if (!gifframe_data) gifframe_data = Z_Malloc(gifframe_size, PU_STATIC, NULL); @@ -548,8 +534,18 @@ static void GIF_framewrite(void) if (!gif_out) return; + // Lactozilla: Compare the header's palette with the current frame's palette and see if it changed. + if (gif_localcolortable) + { + gif_framepalette = GIF_getpalette((rendermode == render_soft) ? ((gif_localcolortable) ? max(st_palette, 0) : 0) : 0); + palchanged = memcmp(gif_headerpalette, gif_framepalette, sizeof(RGBA_t) * 256); + } + else + palchanged = false; + // Compare image data (for optimizing GIF) - if (gif_optimize && gif_frames > 0) + // If the palette has changed, the entire frame is considered to be different. + if (gif_optimize && gif_frames > 0 && (!palchanged)) { // before blit movie_screen points to last frame, cur_screen points to this frame UINT8 *cur_screen = screens[0]; @@ -617,9 +613,14 @@ static void GIF_framewrite(void) WRITEUINT8(p, 0); // no local table of colors else { - WRITEUINT8(p, 0x87); // (0x87 = 1000 0111) - GIF_setpalette(); - p = GIF_palwrite(p); + if (palchanged) + { + // The palettes are different, so write the Local Color Table! + WRITEUINT8(p, 0x87); // (0x87 = 1000 0111) + p = GIF_palwrite(p, gif_framepalette); + } + else + WRITEUINT8(p, 0); // They are equal, no Local Color Table needed. } scrbuf_pos = movie_screen + blitx + (blity * vid.width); @@ -693,8 +694,8 @@ INT32 GIF_open(const char *filename) gif_optimize = (!!cv_gif_optimize.value); gif_downscale = (!!cv_gif_downscale.value); gif_localcolortable = (!!cv_gif_localcolortable.value); - if (!gif_localcolortable) - GIF_setpalette(); + gif_colorprofile = (!!cv_screenshot_colorprofile.value); + gif_headerpalette = GIF_getpalette(0); GIF_headwrite(); gif_frames = 0; From af66a2e5fabe616142c84fab0d35bbab40d9451c Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 3 Feb 2020 02:12:55 -0300 Subject: [PATCH 5/6] Restore some functionality that went missing --- src/m_menu.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index d4ac61eb0..507d768cc 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -320,6 +320,7 @@ menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef; menu_t OP_ServerOptionsDef; menu_t OP_MonitorToggleDef; static void M_ScreenshotOptions(INT32 choice); +static void M_SetupScreenshotMenu(void); static void M_EraseData(INT32 choice); static void M_Addons(INT32 choice); @@ -358,7 +359,6 @@ static void M_DrawMonitorToggles(void); static void M_OGL_DrawFogMenu(void); #endif #ifndef NONET -static void M_DrawScreenshotMenu(void); static void M_DrawConnectMenu(void); static void M_DrawMPMainMenu(void); static void M_DrawRoomMenu(void); @@ -1454,6 +1454,7 @@ static menuitem_t OP_ScreenshotOptionsMenu[] = enum { op_screenshot_colorprofile = 1, + op_screenshot_storagelocation = 3, op_screenshot_folder = 4, op_movie_folder = 11, op_screenshot_capture = 12, @@ -3673,6 +3674,9 @@ void M_Ticker(void) if (--vidm_testingmode == 0) setmodeneeded = vidm_previousmode + 1; } + + if (currentMenu == &OP_ScreenshotOptionsDef) + M_SetupScreenshotMenu(); } // @@ -11090,9 +11094,27 @@ static void M_ScreenshotOptions(INT32 choice) Screenshot_option_Onchange(); Moviemode_mode_Onchange(); + M_SetupScreenshotMenu(); M_SetupNextMenu(&OP_ScreenshotOptionsDef); } +static void M_SetupScreenshotMenu(void) +{ + menuitem_t *item = &OP_ScreenshotOptionsMenu[op_screenshot_colorprofile]; + +#ifdef HWRENDER + // Hide some options based on render mode + if (rendermode == render_opengl) + { + item->status = IT_GRAYEDOUT; + if ((currentMenu == &OP_ScreenshotOptionsDef) && (itemOn == op_screenshot_colorprofile)) // Can't select that + itemOn = op_screenshot_storagelocation; + } + else +#endif + item->status = (IT_STRING | IT_CVAR); +} + // ============= // JOYSTICK MENU // ============= @@ -11953,6 +11975,15 @@ static void M_HandleVideoMode(INT32 ch) static void M_DrawScreenshotMenu(void) { M_DrawGenericScrollMenu(); +#ifdef HWRENDER + if ((rendermode == render_opengl) && (itemOn < 7)) // where it starts to go offscreen; change this number if you change the layout of the screenshot menu + { + INT32 y = currentMenu->y+currentMenu->menuitems[op_screenshot_colorprofile].alphaKey*2; + if (itemOn == 6) + y -= 10; + V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, y, V_REDMAP, "Yes"); + } +#endif } // =============== From d1e8744583b9a868665b4b3a5e4803a29829f7a0 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Mon, 3 Feb 2020 02:24:22 -0300 Subject: [PATCH 6/6] What --- src/m_anigif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_anigif.c b/src/m_anigif.c index 5394f569a..faa8f29e1 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -537,7 +537,7 @@ static void GIF_framewrite(void) // Lactozilla: Compare the header's palette with the current frame's palette and see if it changed. if (gif_localcolortable) { - gif_framepalette = GIF_getpalette(gif_localcolortable ? max(st_palette, 0) : 0); + gif_framepalette = GIF_getpalette(max(st_palette, 0)); palchanged = memcmp(gif_headerpalette, gif_framepalette, sizeof(RGBA_t) * 256); } else