Destroyed screenshot_tool (markdown)

omar 2022-05-16 17:37:35 +02:00
parent 65cc82929e
commit 55e3511ff7

@ -1,286 +0,0 @@
## Screenshot tool
Simple tool to help creating screenshot of ImGui windows (requires OpenGL + stb_image_write.h)
![Screenshot tool](https://cloud.githubusercontent.com/assets/8225057/9546820/d0934d32-4d8d-11e5-8b3e-a8b852361bcb.PNG)
It can also create big screenshot of a large window by stitching multiple shots together.
### Source (V2)
```
// ImGui Screenshot Maker (OpenGL only)
#define _CRT_SECURE_NO_WARNINGS
#include "imgui.h"
#define IMGUI_DEFINE_MATH_OPERATORS
#include "imgui_internal.h"
#include <examples/libs/glfw/include/GLFW/glfw3.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
// Helper class for simple bitmap manipulation (not particularly efficient!)
struct ImageBuf
{
typedef unsigned int u32;
int Width, Height;
u32* Data;
ImageBuf() { Width = Height = 0; Data = NULL; }
~ImageBuf() { Clear(); }
void Clear() { if (Data) free(Data); Data = NULL; }
void CreateEmpty(int w, int h)
{
Clear();
Width = w;
Height = h;
Data = (u32*)malloc(Width * Height * 4);
memset(Data, 0, Width * Height * 4);
}
void CreateFromCaptureGL(int x, int y, int w, int h)
{
Clear();
Width = w;
Height = h;
Data = (u32*)malloc(Width * Height * 4);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, Data);
RemoveAlpha();
}
void SaveFile(const char* filename)
{
stbi_write_png(filename, Width, Height, 4, Data, Width * 4);
}
void RemoveAlpha()
{
u32* p = Data;
int n = Width * Height;
while (n-- > 0)
{
*p |= 0xFF000000;
p++;
}
}
void BlitTo(ImageBuf* dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
{
ImageBuf* src = this;
IM_ASSERT(dst != src);
IM_ASSERT(dst != NULL);
IM_ASSERT(src_x >= 0 && src_y >= 0);
IM_ASSERT(src_x + w <= src->Width);
IM_ASSERT(src_y + h <= src->Height);
IM_ASSERT(dst_x >= 0 && dst_y >= 0);
IM_ASSERT(dst_x + w <= dst->Width);
IM_ASSERT(dst_y + h <= dst->Height);
for (int y = 0; y < h; y++)
memcpy(dst->Data + dst_x + (dst_y + y) * dst->Width, src->Data + src_x + (src_y + y) * src->Width, w * 4);
}
void FlipVertical()
{
int comp = 4;
int stride = Width * comp;
unsigned char* line_tmp = new unsigned char[stride];
unsigned char* line_a = (unsigned char*)Data;
unsigned char* line_b = (unsigned char*)Data + (stride * (Height - 1));
while (line_a < line_b)
{
memcpy(line_tmp, line_a, stride);
memcpy(line_a, line_b, stride);
memcpy(line_b, line_tmp, stride);
line_a += stride;
line_b -= stride;
}
delete[] line_tmp;
}
u32* GetPtr(int x, int y)
{
return &Data[x + y * Width];
}
u32 GetPixel(int x, int y) const
{
return Data[x + y * Width];
}
};
struct ScreenshotMaker
{
ImGuiStorage Storage;
float BorderSize;
bool LargePictureMode;
ImRect VisibleRect;
bool CaptureActive;
int CaptureFrame;
ImRect CaptureRect;
int CaptureLargeOffY;
ImGuiWindow* CaptureWindow;
ImageBuf Output;
ScreenshotMaker()
{
BorderSize = 16.0f;
LargePictureMode = false;
CaptureActive = false;
CaptureFrame = 0;
CaptureLargeOffY = 0;
CaptureWindow = NULL;
}
void CaptureStart(ImGuiWindow* window)
{
CaptureActive = true;
CaptureFrame = 0;
Output.Clear();
CaptureWindow = window;
if (!CaptureWindow)
LargePictureMode = false;
if (LargePictureMode)
{
ImGui::SetWindowSize(CaptureWindow->Name, ImVec2(CaptureWindow->SizeFull.x, CaptureWindow->SizeContents.y));
Output.CreateEmpty((int)(CaptureWindow->Size.x + BorderSize * 2), (int)(CaptureWindow->Size.y + BorderSize * 2));
}
else
{
// Capture immediately
ImGuiIO& io = ImGui::GetIO();
Output.CreateFromCaptureGL((int)CaptureRect.Min.x, (int)io.DisplaySize.y - (int)CaptureRect.Max.y, (int)CaptureRect.GetWidth(), (int)CaptureRect.GetHeight());
Output.FlipVertical();
CaptureEnd();
return;
}
}
void CaptureUpdate()
{
if (!LargePictureMode)
return;
int TIME_STEP = 15;
IM_ASSERT(TIME_STEP > 5);
int chunk_no = CaptureFrame / TIME_STEP;
int chunk_w = (int)CaptureRect.GetWidth();
int chunk_h = (int)CaptureRect.GetHeight();
if ((CaptureFrame % TIME_STEP) == 2)
{
// Move window
ImVec2 p = CaptureRect.Min + ImVec2(BorderSize, BorderSize);
p.y -= chunk_no * CaptureRect.GetHeight();
ImGui::SetWindowPos(CaptureWindow->Name, p);
}
if ((CaptureFrame % TIME_STEP) == 4)
{
// Capture, stitch into output
ImGuiIO& io = ImGui::GetIO();
ImageBuf img;
img.CreateFromCaptureGL((int)CaptureRect.Min.x, (int)io.DisplaySize.y - (int)CaptureRect.Max.y, chunk_w, chunk_h);
img.FlipVertical();
int chunk_y = chunk_no * chunk_h;
img.BlitTo(&Output, 0, 0, 0, chunk_y, chunk_w, ImMin(chunk_h, Output.Height - chunk_y));
char buf[128];
sprintf(buf, "out%03d.png", chunk_no);
//img.SaveFile(buf);
if (CaptureWindow->Pos.y + CaptureWindow->SizeFull.y < CaptureRect.Max.y)
CaptureEnd();
}
CaptureFrame++;
}
void CaptureEnd()
{
if (Output.Data)
Output.SaveFile("out.png");
CaptureActive = false;
}
void Draw(bool* p_open = NULL)
{
if (!ImGui::Begin("Screenshot Maker", p_open))
{
ImGui::End();
return;
}
ImGuiContext& g = *GImGui;
ImGuiIO& io = ImGui::GetIO();
bool capture = ImGui::Button("ALT+C: Capture");
if (CaptureActive)
{
ImGui::SameLine();
ImGui::Text("Capturing...");
}
ImGui::SliderFloat("Border", &BorderSize, 0.0f, 32.0f, "%.0f");
ImGui::Checkbox("Large Window Capture Mode (1 window)", &LargePictureMode);
ImGui::Separator();
ImVector<ImGuiWindow*> windows_selected;
VisibleRect = ImRect(ImVec2(0,0), io.DisplaySize);
ImRect capture_rect;
ImGui::Text("Windows:");
for (int i = 0; i < g.Windows.size(); i++)
{
ImGuiWindow* window = g.Windows[i];
if (!window->Active && !window->WasActive)
continue;
if (window->Flags & ImGuiWindowFlags_Popup)
{
CaptureRect.Add(window->Rect());
continue;
}
if (window->Flags & ImGuiWindowFlags_ChildWindow)
continue;
ImGui::PushID(window);
bool* p_selected = (bool*)Storage.GetIntRef(window->RootWindow->ID, 0);
ImGui::Checkbox("##checkbox", p_selected);
ImGui::SameLine();
ImGui::TextUnformatted(window->Name);
if (*p_selected)
{
capture_rect.Add(window->Rect());
windows_selected.push_back(window);
}
ImGui::SameLine(160);
ImGui::PushItemWidth(120);
ImGui::DragFloat2("Pos", &window->PosFloat.x, 0.05f, 0.0f, 0.0f, "%.0f");
ImGui::SameLine();
ImGui::DragFloat2("Size", &window->SizeFull.x, 0.05f, 0.0f, 0.0f, "%.0f");
ImGui::PopItemWidth();
ImGui::PopID();
}
capture_rect.Expand(BorderSize);
capture_rect.Clip(VisibleRect);
if (!CaptureActive)
CaptureRect = capture_rect;
char buf[128];
sprintf(buf, "%.0f x %.0f", CaptureRect.GetWidth(), capture_rect.GetHeight());
g.OverlayDrawList.AddText(ImGui::GetWindowFont(), ImGui::GetWindowFontSize(), ImVec2(1,1), IM_COL32_WHITE, buf);
g.OverlayDrawList.AddRect(CaptureRect.Min-ImVec2(1,1), CaptureRect.Max+ImVec2(1,1), IM_COL32_WHITE);
capture |= io.KeyAlt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C));
if (capture)
CaptureStart(windows_selected.empty() ? NULL : windows_selected[0]);
if (CaptureActive)
CaptureUpdate();
ImGui::End();
}
};
```