add screenshot function #1

Merged
hashirama merged 4 commits from screenshot into rewrite/cpp 2025-04-08 01:07:03 +00:00

112
screenshot.c Normal file
View 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;
}