From 0e9e8d345088e7220cb289746003e819eb2927ff Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 7 Dec 2025 14:58:32 +0000 Subject: [PATCH] further gpt "improvements" --- test.c | 179 ++++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 104 insertions(+), 75 deletions(-) diff --git a/test.c b/test.c index 64a2105..8b65778 100644 --- a/test.c +++ b/test.c @@ -1,14 +1,21 @@ /* ------------------------------------------------------------- - * framebuffer_demo_tcp.c (modified for hard B/W output) + * waveform_tcp.c * - * – 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. + * * 600×400 ARGB8888 frame is streamed over a single‑client TCP socket. + * * The received frame is transformed so that the resulting bitmap + * can be displayed on a video waveform monitor and will look like + * the original picture. * - * Build (Linux/macOS): - * gcc -Wall -Wextra -pedantic -std=c11 framebuffer_demo_tcp.c \ - * -lSDL2 -lpthread -o framebuffer_demo_tcp + * Build (Linux/macOS): + * gcc -Wall -Wextra -pedantic -std=c11 waveform_tcp.c \ + * -lSDL2 -lpthread -o waveform_tcp + * + * Run: + * ./waveform_tcp # opens a window and listens on 0.0.0.0:12345 + * + * Test client (Unix‑like, sends one frame of solid gray): + * dd if=/dev/zero bs=1 count=$((600*400*4)) | tr \\0 \\377 > gray.bin + * cat gray.bin | nc 127.0.0.1 12345 * * ------------------------------------------------------------- */ #include @@ -22,21 +29,20 @@ #include #include #include -#include // select() #include /* ------------------------------------------------------------- * Configuration * ------------------------------------------------------------- */ -#define WIDTH 600 -#define HEIGHT 400 +#define WIDTH 800 +#define HEIGHT 600 #define LISTEN_PORT 12345 // change if you like #define BACKLOG 1 // only one pending connection /* ------------------------------------------------------------- - * Simple pixel format helpers + * Simple pixel helpers (ARGB8888 – 0xAARRGGBB in memory) * ------------------------------------------------------------- */ -typedef Uint32 pixel_t; // 0xAARRGGBB in memory (little‑endian) +typedef Uint32 pixel_t; static inline pixel_t make_pixel(Uint8 r, Uint8 g, Uint8 b, Uint8 a) { @@ -45,53 +51,74 @@ static inline pixel_t make_pixel(Uint8 r, Uint8 g, Uint8 b, Uint8 a) #define MAKE_OPAQUE_PIXEL(r,g,b) make_pixel((r),(g),(b),0xFF) /* ------------------------------------------------------------- - * Global framebuffer (contiguous block) + * Global buffers * ------------------------------------------------------------- */ -static pixel_t framebuffer[HEIGHT][WIDTH]; // 600*400*4 = 960 000 bytes +/* 1. The raw frame received from the network */ +static pixel_t net_frame[HEIGHT][WIDTH]; + +/* 2. The image that we actually draw (after the waveform conversion) */ +static pixel_t draw_buf[HEIGHT][WIDTH]; /* ------------------------------------------------------------- - * Fill with a demo pattern (visible before any network data) + * Demo pattern – what we see until the first network frame arrives * ------------------------------------------------------------- */ static void init_demo_pattern(void) { for (int y = 0; y < HEIGHT; ++y) { for (int x = 0; x < WIDTH; ++x) { - Uint8 r = (Uint8)((x * 255) / (WIDTH - 1)); - Uint8 g = (Uint8)((y * 255) / (HEIGHT - 1)); - Uint8 b = 0x80; - framebuffer[y][x] = MAKE_OPAQUE_PIXEL(r, g, b); + Uint8 r = (HEIGHT-y)*255/HEIGHT;//(Uint8)((x * 255) / (WIDTH - 1)); + Uint8 g = (HEIGHT-y)*255/HEIGHT;//(Uint8)((y * 255) / (HEIGHT - 1)); + Uint8 b = (HEIGHT-y)*255/HEIGHT;//0x80; + draw_buf[y][x] = MAKE_OPAQUE_PIXEL(r, g, b); } } } /* ------------------------------------------------------------- - * --- 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. + * Luminance conversion – ITU‑BT.601 (Y = 0.299R + 0.587G + 0.114B) * ------------------------------------------------------------- */ -static void apply_bw_threshold(void) +static inline Uint8 rgb_to_luma(Uint8 r, Uint8 g, Uint8 b) { - const Uint8 THRESHOLD = 200; - const pixel_t WHITE = 0xFFFFFFFFU; /* ARGB = (255,255,255,255) */ - const pixel_t BLACK = 0xFF000000U; /* ARGB = (255,0,0,0) */ + /* weighted sum, integer arithmetic, rounded */ + return (Uint8)((299 * r + 587 * g + 114 * b) / 1000); +} - for (int y = 0; y < HEIGHT; ++y) { - for (int x = 0; x < WIDTH; ++x) { - pixel_t p = framebuffer[y][x]; +/* ------------------------------------------------------------- + * Transform the raw ARGB frame into a waveform‑ready image. + * + * * dest is the global draw_buf + * * every source pixel (sx, sy) becomes a white dot at + * dx = sx + * dy = round( luma * (HEIGHT‑1) / 255 ) + * + * The whole destination buffer is cleared to black first. + * ------------------------------------------------------------- */ +static void convert_to_waveform(void) +{ + const pixel_t WHITE = 0xFFFFFFFFU; /* ARGB = opaque white */ + const pixel_t BLACK = 0xFF000000U; /* opaque black (background) */ + + /* 1. clear destination */ + for (int y = 0; y < HEIGHT; ++y) + memset(draw_buf[y], 0, WIDTH * sizeof(pixel_t)); + for (int y = 0; y < HEIGHT; ++y) + for (int x = 0; x < WIDTH; ++x) + draw_buf[y][x] = BLACK; + + /* 2. plot points */ + for (int sy = 0; sy < HEIGHT; ++sy) { + for (int sx = 0; sx < WIDTH; ++sx) { + pixel_t p = net_frame[sy][sx]; Uint8 r = (Uint8)((p >> 16) & 0xFF); Uint8 g = (Uint8)((p >> 8) & 0xFF); - Uint8 b = (Uint8)((p ) & 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; + Uint8 luma = rgb_to_luma(r, g, b); /* 0‑255 */ + if(luma >= 150) + draw_buf[sy][sx] = 0xff<<24 | (255-sy/2) << 16 | (255-sy/2) << 8 | (255-sy/2); /* overwrite – white dot */ + else + draw_buf[sy][sx] = 0xff<<24; + //draw_buf[sy][sx] = (255-sy/2)<<24 | 0xFFFFFFU; } } } @@ -130,6 +157,7 @@ static int create_listen_socket(void) return -1; } + /* make non‑blocking */ int flags = fcntl(lst, F_GETFL, 0); fcntl(lst, F_SETFL, flags | O_NONBLOCK); @@ -137,7 +165,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); @@ -145,21 +173,21 @@ static void set_nonblocking(int fd) } /* ------------------------------------------------------------- - * Main entry point + * MAIN * ------------------------------------------------------------- */ 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 (B/W)", - SDL_WINDOWPOS_CENTERED, - SDL_WINDOWPOS_CENTERED, - WIDTH, HEIGHT, - SDL_WINDOW_SHOWN); + SDL_Window *window = SDL_CreateWindow("Waveform‑ready demo (TCP input)", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + WIDTH, HEIGHT, + SDL_WINDOW_SHOWN); if (!window) { fprintf(stderr, "SDL_CreateWindow error: %s\n", SDL_GetError()); SDL_Quit(); @@ -188,19 +216,20 @@ int main(void) return EXIT_FAILURE; } - /* ---- Demo pattern (will be shown until first network frame arrives) */ + /* ---------- Demo pattern (until first network frame) ---------- */ init_demo_pattern(); - /* ---- Networking ------------------------------------------ */ + /* ---------- 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; /* bytes already received for the current frame */ + + const size_t FRAME_BYTES = WIDTH * HEIGHT * sizeof(pixel_t); + size_t recv_offset = 0; /* bytes already received */ bool quit = false; SDL_Event ev; - /* ---- Main loop ------------------------------------------- */ + /* ---------- Main loop --------------------------------------- */ while (!quit) { /* 1) SDL events */ while (SDL_PollEvent(&ev)) { @@ -222,36 +251,26 @@ int main(void) 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)); + printf("[net] Client connected from %s:%d\n", ip, + ntohs(remote.sin_port)); } else if (errno != EAGAIN && errno != EWOULDBLOCK) { perror("[net] accept"); } } - void *tex_pixels; - int tex_pitch; - - /* 3) Read raw pixel data */ + /* 3) Read raw pixel data from the client */ if (client_sock >= 0) { - size_t still_needed = bytes_needed - recv_offset; + size_t still_needed = FRAME_BYTES - recv_offset; ssize_t n = recv(client_sock, - ((Uint8 *)framebuffer) + recv_offset, + ((Uint8 *)net_frame) + recv_offset, still_needed, 0); if (n > 0) { recv_offset += (size_t)n; - if (recv_offset == bytes_needed) { - /* ------------------------------------------------- - * 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)); - } + if (recv_offset == FRAME_BYTES) { + /* Full frame received – convert to waveform image */ + convert_to_waveform(); + recv_offset = 0; /* ready for the next frame */ } } else if (n == 0) { printf("[net] Client disconnected.\n"); @@ -264,12 +283,19 @@ int main(void) } } - /* 4) Copy framebuffer into the SDL texture */ + /* 4) Copy the (possibly transformed) draw buffer into the texture */ + void *tex_pixels; + int tex_pitch; if (SDL_LockTexture(texture, NULL, &tex_pixels, &tex_pitch) != 0) { fprintf(stderr, "SDL_LockTexture error: %s\n", SDL_GetError()); break; } + for (int y = 0; y < HEIGHT; ++y) { + memcpy((Uint8 *)tex_pixels + y * tex_pitch, + draw_buf[y], + WIDTH * sizeof(pixel_t)); + } SDL_UnlockTexture(texture); /* 5) Render */ @@ -279,7 +305,9 @@ int main(void) /* 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); @@ -290,3 +318,4 @@ int main(void) return EXIT_SUCCESS; } +