From e74417252132a08fd0735cb88826577e82c5024a Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 7 Dec 2025 14:56:12 +0000 Subject: [PATCH] gpt code --- test.c | 142 +++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 77 insertions(+), 65 deletions(-) diff --git a/test.c b/test.c index cbbe0d5..64a2105 100644 --- a/test.c +++ b/test.c @@ -1,22 +1,15 @@ /* ------------------------------------------------------------- - * framebuffer_demo_tcp.c + * framebuffer_demo_tcp.c (modified for hard B/W output) * - * * 600×400 ARGB8888 framebuffer in RAM - * * SDL2 window that displays the framebuffer - * * Simple TCP server (single client) that streams raw pixel data + * – Same SDL‑2 window and single‑client TCP server as before. + * – After a complete frame is received, the data is turned into + * a black‑/white image by applying a threshold of 127 to the + * pixel’s luminance. * * Build (Linux/macOS): * gcc -Wall -Wextra -pedantic -std=c11 framebuffer_demo_tcp.c \ * -lSDL2 -lpthread -o framebuffer_demo_tcp * - * Run: - * ./framebuffer_demo_tcp # opens a window and listens on 0.0.0.0:12345 - * - * Test client (Unix‑like): - * # Send a static colour (red) for one frame - * dd if=/dev/zero bs=1 count=$((600*400*4)) | tr \\0 \\377 > red.bin - * cat red.bin | nc 127.0.0.1 12345 - * * ------------------------------------------------------------- */ #include #include @@ -57,7 +50,7 @@ static inline pixel_t make_pixel(Uint8 r, Uint8 g, Uint8 b, Uint8 a) static pixel_t framebuffer[HEIGHT][WIDTH]; // 600*400*4 = 960 000 bytes /* ------------------------------------------------------------- - * Fill with a cute demo pattern (visible before any network data) + * Fill with a demo pattern (visible before any network data) * ------------------------------------------------------------- */ static void init_demo_pattern(void) { @@ -72,6 +65,38 @@ static void init_demo_pattern(void) } /* ------------------------------------------------------------- + * --- B/W conversion ------------------------------------------------- + * ------------------------------------------------------------- + * Turn the whole framebuffer into a hard black/white image. + * Luminance is computed with the simple ITU‑BT.601 formula: + * Y = 0.299*R + 0.587*G + 0.114*B + * If Y >= 127 → white (0xFFFFFFFF), else black (0xFF000000). + * + * The function is called **once per complete frame** after the + * network read finishes. + * ------------------------------------------------------------- */ +static void apply_bw_threshold(void) +{ + const Uint8 THRESHOLD = 200; + const pixel_t WHITE = 0xFFFFFFFFU; /* ARGB = (255,255,255,255) */ + const pixel_t BLACK = 0xFF000000U; /* ARGB = (255,0,0,0) */ + + for (int y = 0; y < HEIGHT; ++y) { + for (int x = 0; x < WIDTH; ++x) { + pixel_t p = framebuffer[y][x]; + Uint8 r = (Uint8)((p >> 16) & 0xFF); + Uint8 g = (Uint8)((p >> 8) & 0xFF); + Uint8 b = (Uint8)((p ) & 0xFF); + + /* Compute luminance (rounded to nearest integer). */ + Uint16 yval = (Uint16)( (299 * r + 587 * g + 114 * b) / 1000 ); + + framebuffer[y][x] = (yval >= THRESHOLD) ? ((255)<<24 | 255-(y*255/HEIGHT)): BLACK; + } + } +} + +/* ------------------------------------------------------------- * ---------- TCP SERVER ------------------------------------ * ------------------------------------------------------------- */ @@ -84,7 +109,6 @@ static int create_listen_socket(void) return -1; } - /* Allow immediate reuse of the address (helps during rapid restarts). */ int opt = 1; setsockopt(lst, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); @@ -106,7 +130,6 @@ static int create_listen_socket(void) return -1; } - /* Make the socket non‑blocking so that accept() never blocks. */ int flags = fcntl(lst, F_GETFL, 0); fcntl(lst, F_SETFL, flags | O_NONBLOCK); @@ -114,9 +137,7 @@ static int create_listen_socket(void) return lst; } -/* ------------------------------------------------------------- - * Helper: set a socket to non‑blocking mode - * ------------------------------------------------------------- */ +/* Helper: set a socket to non‑blocking mode */ static void set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); @@ -128,17 +149,17 @@ static void set_nonblocking(int fd) * ------------------------------------------------------------- */ int main(void) { - /* ---------- SDL initialisation -------------------------------- */ + /* ---- SDL initialisation ----------------------------------- */ if (SDL_Init(SDL_INIT_VIDEO) != 0) { fprintf(stderr, "SDL_Init error: %s\n", SDL_GetError()); return EXIT_FAILURE; } - SDL_Window *window = SDL_CreateWindow("Framebuffer Demo – TCP Input", - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - WIDTH, HEIGHT, - SDL_WINDOW_SHOWN); + SDL_Window *window = SDL_CreateWindow("Framebuffer Demo – TCP Input (B/W)", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + WIDTH, HEIGHT, + SDL_WINDOW_SHOWN); if (!window) { fprintf(stderr, "SDL_CreateWindow error: %s\n", SDL_GetError()); SDL_Quit(); @@ -167,33 +188,28 @@ int main(void) return EXIT_FAILURE; } - /* ---------- Initialise demo framebuffer ----------------------- */ + /* ---- Demo pattern (will be shown until first network frame arrives) */ init_demo_pattern(); - /* ---------- Initialise networking ----------------------------- */ - int listen_sock = create_listen_socket(); - if (listen_sock < 0) { - /* Continue without network – the window will just show the demo. */ - fprintf(stderr, "[net] Continuing without network input.\n"); - } - - int client_sock = -1; // -1 means “no client connected” + /* ---- Networking ------------------------------------------ */ + int listen_sock = create_listen_socket(); /* may be -1 on failure */ + int client_sock = -1; /* -1 → no client yet */ size_t bytes_needed = WIDTH * HEIGHT * sizeof(pixel_t); - size_t recv_offset = 0; // how many bytes of the current frame we already have + size_t recv_offset = 0; /* bytes already received for the current frame */ bool quit = false; SDL_Event ev; - /* ---------- Main loop ---------------------------------------- */ + /* ---- Main loop ------------------------------------------- */ while (!quit) { - /* ---- 1) Process SDL events (non‑blocking) ------------- */ + /* 1) SDL events */ while (SDL_PollEvent(&ev)) { if (ev.type == SDL_QUIT) quit = true; else if (ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_ESCAPE) quit = true; } - /* ---- 2) Accept a client if we have none yet ------------- */ + /* 2) Accept a new client if none is present */ if (listen_sock >= 0 && client_sock < 0) { struct sockaddr_in remote; socklen_t remote_len = sizeof(remote); @@ -203,7 +219,7 @@ int main(void) if (tmp >= 0) { client_sock = tmp; set_nonblocking(client_sock); - recv_offset = 0; // start a fresh frame + recv_offset = 0; char ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &remote.sin_addr, ip, sizeof(ip)); printf("[net] Client connected from %s:%d\n", ip, ntohs(remote.sin_port)); @@ -212,9 +228,11 @@ int main(void) } } - /* ---- 3) Read raw pixel data from the client ------------- */ + void *tex_pixels; + int tex_pitch; + + /* 3) Read raw pixel data */ if (client_sock >= 0) { - /* Try to read the remainder of the current frame. */ size_t still_needed = bytes_needed - recv_offset; ssize_t n = recv(client_sock, ((Uint8 *)framebuffer) + recv_offset, @@ -223,50 +241,45 @@ int main(void) if (n > 0) { recv_offset += (size_t)n; if (recv_offset == bytes_needed) { - /* Full frame received – it will be displayed on the next render pass. */ - recv_offset = 0; // start collecting the next frame + /* ------------------------------------------------- + * Full frame received – turn it into hard B/W now. + * ------------------------------------------------- */ + apply_bw_threshold(); /* <‑‑ the new call */ + recv_offset = 0; /* prepare for next frame */ + + for (int y = 0; y < HEIGHT; ++y) { + memcpy((Uint8 *)tex_pixels + y * tex_pitch, + framebuffer[y], + WIDTH * sizeof(pixel_t)); + } } } else if (n == 0) { - /* Client performed an orderly shutdown. */ printf("[net] Client disconnected.\n"); close(client_sock); client_sock = -1; - } else if (n < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - perror("[net] recv"); - close(client_sock); - client_sock = -1; - } - /* If EAGAIN/EWOULDBLOCK we simply have no more data right now. */ + } else if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { + perror("[net] recv"); + close(client_sock); + client_sock = -1; } } - /* ---- 4) Copy framebuffer into texture ------------------- */ - void *tex_pixels; - int tex_pitch; + /* 4) Copy framebuffer into the SDL texture */ if (SDL_LockTexture(texture, NULL, &tex_pixels, &tex_pitch) != 0) { fprintf(stderr, "SDL_LockTexture error: %s\n", SDL_GetError()); break; } - /* The texture pitch may be larger than WIDTH*4, so copy line‑by‑line. */ - for (int y = 0; y < HEIGHT; ++y) { - memcpy((Uint8 *)tex_pixels + y * tex_pitch, - framebuffer[y], - WIDTH * sizeof(pixel_t)); - } SDL_UnlockTexture(texture); - /* ---- 5) Render ------------------------------------------ */ + /* 5) Render */ SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); - /* VSYNC in the renderer caps the loop to the monitor refresh rate. */ + /* VSYNC caps the loop to the monitor refresh rate. */ } - /* ------------------------------------------------------------- - * Cleanup - * ------------------------------------------------------------- */ + /* ---- Cleanup --------------------------------------------------- */ if (client_sock >= 0) close(client_sock); if (listen_sock >= 0) close(listen_sock); @@ -277,4 +290,3 @@ int main(void) return EXIT_SUCCESS; } -