Skip to content

Commit 01eeef5

Browse files
committed
fix screenshots
1 parent 6cda689 commit 01eeef5

File tree

3 files changed

+45
-34
lines changed

3 files changed

+45
-34
lines changed

Source/Managers/FrameMan.cpp

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
using namespace RTE;
3434

3535
void BitmapDeleter::operator()(BITMAP* bitmap) const { destroy_bitmap(bitmap); }
36+
void SurfaceDeleter::operator()(SDL_Surface* surface) const { SDL_FreeSurface(surface); }
3637

3738
const std::array<std::function<void(int r, int g, int b, int a)>, DrawBlendMode::BlendModeCount> FrameMan::c_BlenderSetterFunctions = {
3839
nullptr, // NoBlend obviously has no blender, but we want to keep the indices matching with the enum.
@@ -183,7 +184,9 @@ int FrameMan::CreateBackBuffers() {
183184
m_PlayerScreen = m_BackBuffer;
184185
}
185186

186-
m_ScreenDumpBuffer = std::unique_ptr<BITMAP, BitmapDeleter>(create_bitmap_ex(24, m_BackBuffer32->w, m_BackBuffer32->h));
187+
m_ScreenDumpBuffer = std::unique_ptr<SDL_Surface, SurfaceDeleter>(
188+
SDL_CreateRGBSurfaceWithFormat(0, m_BackBuffer8->w, m_BackBuffer8->h, 24, SDL_PIXELFORMAT_RGB24)
189+
);
187190

188191
return 0;
189192
}
@@ -519,6 +522,7 @@ int FrameMan::SaveBitmap(SaveBitmapMode modeToSave, const std::string& nameBase,
519522
if (nameBase.empty() || nameBase.size() <= 0) {
520523
return -1;
521524
}
525+
set_palette(m_DefaultPalette);
522526

523527
// TODO: Remove this once GCC13 is released and switched to. std::format and std::chrono::time_zone are not part of latest libstdc++.
524528
#if defined(__GNUC__) && __GNUC__ < 13
@@ -530,7 +534,7 @@ int FrameMan::SaveBitmap(SaveBitmapMode modeToSave, const std::string& nameBase,
530534

531535
std::array<char, 128> fullFileNameBuffer = {};
532536
// We can't get sub-second precision from timeBuffer so we'll append absolute time to not overwrite the same file when dumping multiple times per second.
533-
std::snprintf(fullFileNameBuffer.data(), sizeof(fullFileNameBuffer), "%s/%s_%s.%zi.png", System::GetScreenshotDirectory().c_str(), nameBase.c_str(), formattedTimeAndDate.data(), g_TimerMan.GetAbsoluteTime());
537+
std::snprintf(fullFileNameBuffer.data(), sizeof(fullFileNameBuffer), "%s/%s_%s.%lli.png", System::GetScreenshotDirectory().c_str(), nameBase.c_str(), formattedTimeAndDate.data(), g_TimerMan.GetAbsoluteTime());
534538

535539
std::string fullFileName(fullFileNameBuffer.data());
536540
#else
@@ -547,23 +551,21 @@ int FrameMan::SaveBitmap(SaveBitmapMode modeToSave, const std::string& nameBase,
547551
}
548552
break;
549553
case ScreenDump:
550-
if (m_BackBuffer32 && m_ScreenDumpBuffer) {
554+
if (m_ScreenDumpBuffer) {
551555
SaveScreenToBitmap();
552556

553557
// Make a copy of the buffer because it may be overwritten mid thread and everything will be on fire.
554-
BITMAP* outputBitmap = create_bitmap_ex(bitmap_color_depth(m_ScreenDumpBuffer.get()), m_ScreenDumpBuffer->w, m_ScreenDumpBuffer->h);
555-
stretch_blit(m_ScreenDumpBuffer.get(), outputBitmap, 0, 0, m_ScreenDumpBuffer->w, m_ScreenDumpBuffer->h, 0, 0, outputBitmap->w, outputBitmap->h);
556-
557-
auto saveScreenDump = [fullFileName](BITMAP* bitmapToSaveCopy) {
558+
SDL_Surface* saveSurface = SDL_ConvertSurfaceFormat(m_ScreenDumpBuffer.get(), m_ScreenDumpBuffer->format->format, 0);
559+
auto saveScreenDump = [fullFileName](SDL_Surface* bitmapToSaveCopy) {
558560
// nullptr for the PALETTE parameter here because we're saving a 24bpp file and it's irrelevant.
559-
if (save_png(fullFileName.c_str(), bitmapToSaveCopy, nullptr) == 0) {
561+
if (IMG_SavePNG(bitmapToSaveCopy, fullFileName.c_str()) == 0) {
560562
g_ConsoleMan.PrintString("SYSTEM: Screen was dumped to: " + fullFileName);
561563
} else {
562564
g_ConsoleMan.PrintString("ERROR: Unable to save bitmap to: " + fullFileName);
563565
}
564-
destroy_bitmap(bitmapToSaveCopy);
566+
//SDL_FreeSurface(bitmapToSaveCopy);
565567
};
566-
std::thread saveThread(saveScreenDump, outputBitmap);
568+
std::thread saveThread(saveScreenDump, saveSurface);
567569
saveThread.detach();
568570

569571
saveSuccess = true;
@@ -591,12 +593,21 @@ int FrameMan::SaveBitmap(SaveBitmapMode modeToSave, const std::string& nameBase,
591593

592594
BITMAP* depthConvertBitmap = create_bitmap_ex(24, m_WorldDumpBuffer->w, m_WorldDumpBuffer->h);
593595
blit(m_WorldDumpBuffer.get(), depthConvertBitmap, 0, 0, 0, 0, m_WorldDumpBuffer->w, m_WorldDumpBuffer->h);
594-
595-
if (save_png(fullFileName.c_str(), depthConvertBitmap, nullptr) == 0) {
596+
SDL_Surface* saveSurface = SDL_CreateRGBSurfaceWithFormatFrom(
597+
depthConvertBitmap->dat,
598+
depthConvertBitmap->w,
599+
depthConvertBitmap->h,
600+
24,
601+
3,
602+
SDL_PIXELFORMAT_RGB24
603+
);
604+
605+
if (IMG_SavePNG(saveSurface, fullFileName.c_str()) == 0) {
596606
g_ConsoleMan.PrintString("SYSTEM: World was dumped to: " + fullFileName);
597607
saveSuccess = true;
598608
}
599609
destroy_bitmap(depthConvertBitmap);
610+
//SDL_FreeSurface(saveSurface);
600611
}
601612
break;
602613
default:
@@ -616,28 +627,27 @@ void FrameMan::SaveScreenToBitmap() {
616627
return;
617628
}
618629

630+
glPixelStorei(GL_PACK_ALIGNMENT, 4);
619631
GL_CHECK(glBindTexture(GL_TEXTURE_2D, g_WindowMan.GetScreenBuffer()->GetColorTexture().id));
620-
GL_CHECK(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, m_ScreenDumpBuffer->line[0]));
632+
GL_CHECK(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, m_ScreenDumpBuffer->pixels));
633+
634+
// Flip the pixels
635+
std::vector<char*> temp(m_ScreenDumpBuffer->pitch);
636+
char* pixels = reinterpret_cast<char*>(m_ScreenDumpBuffer->pixels);
637+
ssize_t pitch = m_ScreenDumpBuffer->pitch;
638+
for (ssize_t y = 0; y < m_ScreenDumpBuffer->h / 2; ++y) {
639+
std::swap_ranges(pixels + y * pitch, pixels + (y + 1) * pitch, pixels + (m_ScreenDumpBuffer->h - y - 1) * pitch);
640+
}
621641
}
622642

623643
int FrameMan::SaveIndexedPNG(const char* fileName, BITMAP* bitmapToSave) const {
624-
// nullptr for the PALETTE parameter here because the bitmap is 32bpp and whatever we index it with will end up wrong anyway.
625-
save_png(fileName, bitmapToSave, nullptr);
626-
627-
int lastColorConversionMode = get_color_conversion();
628-
set_color_conversion(COLORCONV_REDUCE_TO_256);
629-
// nullptr for the PALETTE parameter here because we don't need the bad palette from it and don't want it to overwrite anything.
630-
BITMAP* tempLoadBitmap = load_bitmap(fileName, nullptr);
631-
std::remove(fileName);
632-
633-
BITMAP* tempConvertingBitmap = create_bitmap_ex(8, bitmapToSave->w, bitmapToSave->h);
634-
blit(tempLoadBitmap, tempConvertingBitmap, 0, 0, 0, 0, tempConvertingBitmap->w, tempConvertingBitmap->h);
635-
636-
int saveResult = save_png(fileName, tempConvertingBitmap, m_Palette);
637-
638-
set_color_conversion(lastColorConversionMode);
639-
destroy_bitmap(tempLoadBitmap);
640-
destroy_bitmap(tempConvertingBitmap);
644+
set_palette(m_DefaultPalette);
645+
SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormatFrom(bitmapToSave->dat, bitmapToSave->w, bitmapToSave->h, bitmap_color_depth(bitmapToSave), bitmap_color_depth(bitmapToSave)/8, SDL_PIXELFORMAT_INDEX8);
646+
SDL_Palette* pal = ContentFile::DefaultPaletteToSDL();
647+
SDL_SetSurfacePalette(surface, pal);
648+
int saveResult = IMG_SavePNG(surface, fileName);
649+
SDL_FreePalette(pal);
650+
SDL_FreeSurface(surface);
641651

642652
return saveResult;
643653
}

Source/Managers/FrameMan.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ namespace RTE {
2121
struct BitmapDeleter {
2222
void operator()(BITMAP* bitmap) const;
2323
};
24+
struct SurfaceDeleter {
25+
void operator()(SDL_Surface* surface) const;
26+
};
2427

2528
/// The singleton manager over the composition of frames.
2629
class FrameMan : public Singleton<FrameMan> {
@@ -433,7 +436,7 @@ namespace RTE {
433436
std::shared_ptr<BITMAP> m_BackBuffer8; //!< Screen backbuffer, always 8bpp, gets copied to the 32bpp buffer for post-processing.
434437
std::unique_ptr<BITMAP, BitmapDeleter> m_BackBuffer32; //!< 32bpp backbuffer, only used for post-processing.
435438
std::unique_ptr<BITMAP, BitmapDeleter> m_OverlayBitmap32; //!< 32bpp bitmap used for overlaying (fading in/out or darkening) the screen.
436-
std::unique_ptr<BITMAP, BitmapDeleter> m_ScreenDumpBuffer; //!< Temporary buffer for making quick screencaps. This is used for color conversion between 32bpp and 24bpp so we can save the file.
439+
std::unique_ptr<SDL_Surface, SurfaceDeleter> m_ScreenDumpBuffer; //!< Temporary buffer for making quick screencaps. This is used for color conversion between 32bpp and 24bpp so we can save the file.
437440
std::unique_ptr<BITMAP, BitmapDeleter> m_WorldDumpBuffer; //!< Temporary buffer for making whole scene screencaps.
438441
std::unique_ptr<BITMAP, BitmapDeleter> m_ScenePreviewDumpGradient; //!< BITMAP for the scene preview sky gradient (easier to load from a pre-made file because it's dithered).
439442
std::unique_ptr<BITMAP, BitmapDeleter> m_ScreenDumpNamePlaceholder; //!< Dummy BITMAP for keeping naming continuity when saving ScreenDumps with multi-threading.

Source/Managers/WindowMan.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,6 @@ void WindowMan::ClearBackbuffer(bool clearFrameMan) {
685685
if (clearFrameMan) {
686686
g_FrameMan.ClearBackBuffer32();
687687
}
688-
m_ScreenBuffer->Begin(true);
689-
m_ScreenBuffer->End();
690688
GL_CHECK(glActiveTexture(GL_TEXTURE0));
691689
GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
692690
GL_CHECK(glActiveTexture(GL_TEXTURE1));
@@ -696,7 +694,7 @@ void WindowMan::ClearBackbuffer(bool clearFrameMan) {
696694

697695
void WindowMan::UploadFrame() {
698696

699-
m_ScreenBuffer->Begin(false);
697+
m_ScreenBuffer->Begin(true);
700698

701699
rlDisableDepthTest();
702700
rlDisableColorBlend();

0 commit comments

Comments
 (0)