diff --git a/screenshot.c b/screenshot.c new file mode 100644 index 0000000..9b69e53 --- /dev/null +++ b/screenshot.c @@ -0,0 +1,112 @@ +// Copyright © 2025 Hashirama Senju + +#include +#include +#include +#include +#include +#include +#include + +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; +}