send image data to client

This commit is contained in:
ktyl 2023-02-17 22:55:31 +00:00
parent 8b62cd574d
commit d244c23e2b
3 changed files with 106 additions and 33 deletions

View File

@ -2,22 +2,62 @@
#include "rtweekend.h"
// for writing to stdout
#include <iostream>
void write_colour(std::ostream &out, colour pixel_colour, int samples_per_pixel)
{
auto r = pixel_colour.x();
auto g = pixel_colour.y();
auto b = pixel_colour.z();
// for writing to socket
#include <unistd.h>
// divide the colour total by the number of samples and gamme-correct for gamma=2.0
auto scale = 1.0 / samples_per_pixel;
void correct_gamma(colour& pixel_colour, int samples)
{
double r = pixel_colour.x();
double g = pixel_colour.y();
double b = pixel_colour.z();
// divide the colour total by the number of samples and gamma-correct for gamma=2.0
auto scale = 1.0 / samples;
r = sqrt(scale * r);
g = sqrt(scale * g);
b = sqrt(scale * b);
pixel_colour = colour(r, g, b);
}
void write_colour_to_stream(std::ostream &out, colour pixel_colour, int samples_per_pixel)
{
correct_gamma(pixel_colour, samples_per_pixel);
auto r = pixel_colour.x();
auto g = pixel_colour.y();
auto b = pixel_colour.z();
// write the translated [0,255] value of each colour component.
out << static_cast<int>(256 * clamp(r, 0.0, 0.999)) << ' '
<< static_cast<int>(256 * clamp(g, 0.0, 0.999)) << ' '
<< static_cast<int>(256 * clamp(b, 0.0, 0.999)) << '\n';
}
int format_component(double component)
{
return int(256 * clamp(component, 0.0, 0.999));
}
void write_colour_to_socket(int sockfd, colour pixel_colour, int samples_per_pixel)
{
correct_gamma(pixel_colour, samples_per_pixel);
int r = format_component(pixel_colour.x());
int g = format_component(pixel_colour.y());
int b = format_component(pixel_colour.z());
// pack values
int len = 3;
char s[len];
sprintf(s, "%c%c%c", r, g, b);
int written = write(sockfd, s, len);
if (written < 0)
{
error("ERROR writing colour to socket");
}
}

View File

@ -2,6 +2,13 @@
#include "hittable_list.h"
#include "sphere.h"
void error(const char* message)
{
perror(message);
exit(1);
}
#include "colour.h"
#include "camera.h"
#include "material.h"
@ -15,9 +22,9 @@
#include <sys/socket.h>
#include <netinet/in.h>
const double ASPECT_RATIO = 16.0 / 9.0;
const int WIDTH = 1920;
const int HEIGHT = static_cast<int>(WIDTH / ASPECT_RATIO);
const double ASPECT_RATIO = 1.0;
const unsigned int WIDTH = 256;
const unsigned int HEIGHT = static_cast<int>(WIDTH / ASPECT_RATIO);
const int SAMPLES_PER_PIXEL = 8;
const int MAX_DEPTH = 5;
@ -119,12 +126,6 @@ hittable_list random_scene()
return world;
}
void error(const char* message)
{
perror(message);
exit(1);
}
// file descriptor of the socket we're listening for connections on
//
// returns fd for the client connection
@ -162,6 +163,18 @@ int wait_for_client(int& sockfd)
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(64999); // convert number from host to network byte order
// this is a bit of developer QoL so we can iterate more quickly
// TODO: make it possible to disable this debug/release build configuration
const int enable = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
{
error("ERROR setsockopt(SO_REUSEADDR) failed");
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0)
{
error("ERROR setsockopt(SO_REUSEPORT) failed");
}
// bind the socket
if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
@ -185,6 +198,24 @@ void send_message(int sock, const char* message)
printf("SEND %s\n", message);
}
void send_image_dimensions(int sock, unsigned int width, unsigned int height)
{
// https://linux.die.net/man/3/htons
width = htonl(width);
height = htonl(height);
int written = write(sock, &width, sizeof(uint32_t));
if (written < 0)
{
error("ERROR writing width");
}
written = write(sock, &height, sizeof(uint32_t));
if (written < 0)
{
error("ERROR writing height");
}
}
int main()
{
int sockfd;
@ -192,20 +223,9 @@ int main()
printf("got a connection!\n");
// write a message to the client
send_message(newsockfd, "hi there!");
send_image_dimensions(newsockfd, WIDTH, HEIGHT);
// close client socket
close(newsockfd);
printf("closed client connection\n");
// close listening socket
close(sockfd);
// exit after all our connections are closed
exit(0);
std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n";
//std::cout << "P3\n" << WIDTH << ' ' << HEIGHT << "\n255\n";
hittable_list world = random_scene();
@ -234,10 +254,23 @@ int main()
pixel_colour += ray_colour(r, world, MAX_DEPTH);
}
write_colour(std::cout, pixel_colour, SAMPLES_PER_PIXEL);
//write_colour_to_stream(std::cout, pixel_colour, SAMPLES_PER_PIXEL);
write_colour_to_socket(newsockfd, pixel_colour, SAMPLES_PER_PIXEL);
}
}
std::cerr << "\nDone." << std::endl;
// close client socket
close(newsockfd);
printf("closed client connection\n");
// close listening socket
close(sockfd);
printf("closed listening socket\n");
printf("done!\n");
return 0;
}

View File

@ -6,8 +6,8 @@ use rti1w as a base
* [x] client establishes connection
* [x] send a message to the client
* [ ] move rendering out of main.cpp
* [ ] send rendered image data to client
* [ ] form image file on client
* [x] send rendered image data to client
* [x] form image file on client
* [ ] client sends receiving port to server
* [ ] client application sends command to send image
* [ ] server receives imaging command