Destroyed screenshot_tool (markdown)
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();
|
||||
}
|
||||
};
|
||||
```
|
Loading…
Reference in New Issue
Block a user