add screenshot function #1
1 changed files with 112 additions and 0 deletions
112
screenshot.c
Normal file
112
screenshot.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright © 2025 Hashirama Senju
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t* pixels; // Raw RGB bytes (PPM P6 format)
|
||||
int width;
|
||||
int height;
|
||||
size_t size; // Total buffer size (header + pixels)
|
||||
} PPMBuffer;
|
||||
|
||||
// Interactive region selection and capture
|
||||
PPMBuffer capture_ppm_region() {
|
||||
PPMBuffer buf = {0};
|
||||
Display* disp = XOpenDisplay(NULL);
|
||||
if (!disp) return buf;
|
||||
|
||||
// Region selection logic
|
||||
Window root = DefaultRootWindow(disp);
|
||||
Cursor cursor = XCreateFontCursor(disp, XC_crosshair);
|
||||
XGrabPointer(disp, root, False, ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
|
||||
GrabModeAsync, GrabModeAsync, root, cursor, CurrentTime);
|
||||
|
||||
XEvent ev;
|
||||
int start_x = 0, start_y = 0, end_x = 0, end_y = 0;
|
||||
int selecting = 0;
|
||||
|
||||
while (1) {
|
||||
XNextEvent(disp, &ev);
|
||||
if (ev.type == ButtonPress) {
|
||||
start_x = ev.xbutton.x;
|
||||
start_y = ev.xbutton.y;
|
||||
selecting = 1;
|
||||
} else if (ev.type == MotionNotify && selecting) {
|
||||
end_x = ev.xmotion.x;
|
||||
end_y = ev.xmotion.y;
|
||||
} else if (ev.type == ButtonRelease) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XUngrabPointer(disp, CurrentTime);
|
||||
XFreeCursor(disp, cursor);
|
||||
|
||||
// Calculate region bounds
|
||||
int x = start_x < end_x ? start_x : end_x;
|
||||
int y = start_y < end_y ? start_y : end_y;
|
||||
int width = abs(end_x - start_x);
|
||||
int height = abs(end_y - start_y);
|
||||
|
||||
// Capture pixels
|
||||
XImage* ximg = XGetImage(disp, root, x, y, width, height, AllPlanes, ZPixmap);
|
||||
if (!ximg) {
|
||||
XCloseDisplay(disp);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Create PPM buffer
|
||||
const char header[64];
|
||||
int header_len = snprintf((char*)header, sizeof(header),
|
||||
"P6\n%d %d\n255\n", width, height);
|
||||
|
||||
buf.width = width;
|
||||
buf.height = height;
|
||||
buf.size = header_len + (width * height * 3);
|
||||
buf.pixels = malloc(buf.size);
|
||||
|
||||
// Copy header
|
||||
memcpy(buf.pixels, header, header_len);
|
||||
|
||||
// Convert XImage to RGB24
|
||||
uint8_t* pixel_ptr = buf.pixels + header_len;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
unsigned long pixel = XGetPixel(ximg, x, y);
|
||||
*pixel_ptr++ = (pixel >> 16) & 0xFF; // R
|
||||
*pixel_ptr++ = (pixel >> 8) & 0xFF; // G
|
||||
*pixel_ptr++ = pixel & 0xFF; // B
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
XDestroyImage(ximg);
|
||||
XCloseDisplay(disp);
|
||||
return buf;
|
||||
}
|
||||
|
||||
int main() {
|
||||
PPMBuffer ppm = capture_ppm_region();
|
||||
|
||||
if (ppm.pixels) {
|
||||
// Example: Write to file (could pass to another function)
|
||||
FILE* fp = fopen("screenshot.ppm", "wb");
|
||||
fwrite(ppm.pixels, 1, ppm.size, fp);
|
||||
fclose(fp);
|
||||
|
||||
// To simulate stbi_load_from_memory usage:
|
||||
// uint8_t* rgb = ppm.pixels + snprintf(...);
|
||||
// int w = ppm.width, h = ppm.height;
|
||||
// Your processing here...
|
||||
|
||||
free(ppm.pixels);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue