Using libjpeg, compressing Webcam Image
by Paul Griffiths · in Torque Game Engine · 06/06/2006 (11:17 pm) · 3 replies
Does anyone have any experiance in using libjpeg? it comes with torqueSDK.
I wish to compresss a webcam image into jpg to be send from game client to game server.
I can get at the images pixels RGB values with:
After the image is converted to jpg I will then convert the binary data to hexidecimal, split it into chunks of 256 bytes and then send them to server via multiple commandToServer commands.
After the server recieves the image it will send it out to each game client to be displayed when the clients crosshair is over a player.
Any code, info, links to tutorials apreciated on converting a RGB24 bit image to jpg?
I wish to compresss a webcam image into jpg to be send from game client to game server.
I can get at the images pixels RGB values with:
for (int x = 0; x < grabImage->Width(); x++)
{
for (int y=0; y < grabImage->Height(); y++)
{
float r,g,b;
if (CVFAILED(grabImage->GetPixel(x,y,r,g,b)))
{
printf("GetPixel Error!\n");
}
else
{
// rgb pixel values is floats r,g & b
}
}
}After the image is converted to jpg I will then convert the binary data to hexidecimal, split it into chunks of 256 bytes and then send them to server via multiple commandToServer commands.
After the server recieves the image it will send it out to each game client to be displayed when the clients crosshair is over a player.
Any code, info, links to tutorials apreciated on converting a RGB24 bit image to jpg?
Torque Owner Paul Griffiths
Can anyone see what i'm doing wrong because it's just trial & error.
void VideoCaptureTexture::write_JPEG_file (char * filename, int quality) { /* This struct contains the JPEG compression parameters and pointers to * working space (which is allocated as needed by the JPEG library). * It is possible to have several such structures, representing multiple * compression/decompression processes, in existence at once. We refer * to any one struct (and its associated working data) as a "JPEG object". */ struct jpeg_compress_struct cinfo; /* This struct represents a JPEG error handler. It is declared separately * because applications often want to supply a specialized error handler * (see the second half of this file for an example). But here we just * take the easy way out and use the standard error handler, which will * print a message on stderr and call exit() if compression fails. * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ struct jpeg_error_mgr jerr; /* More stuff */ FILE * outfile; /* target file */ JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ int row_stride; /* physical row width in image buffer */ /* Step 1: allocate and initialize JPEG compression object */ /* We have to set up the error handler first, in case the initialization * step fails. (Unlikely, but it could happen if you are out of memory.) * This routine fills in the contents of struct jerr, and returns jerr's * address which we place into the link field in cinfo. */ cinfo.err = jpeg_std_error(&jerr); /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); /* Step 2: specify data destination (eg, a file) */ /* Note: steps 2 and 3 can be done in either order. */ /* Here we use the library-supplied code to send compressed data to a * stdio stream. You can also write your own code to do something else. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to write binary files. */ if ((outfile = fopen((filename + fileNumber++), "wb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); // exit(1); } jpeg_stdio_dest(&cinfo); /* Step 3: set parameters for compression */ /* First we supply a description of the input image. * Four fields of the cinfo struct must be filled in: */ cinfo.client_data = (void*)&outfile; cinfo.image_width = grabImage->Width(); /* image width and height, in pixels */ cinfo.image_height = grabImage->Height(); cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ /* Now use the library's routine to set default compression parameters. * (You must set at least cinfo.in_color_space before calling this, * since the defaults depend on the source color space.) */ jpeg_set_defaults(&cinfo); /* Now you can set any non-default parameters you wish to. * Here we just illustrate the use of quality (quantization table) scaling: */ jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); /* Step 4: Start compressor */ /* TRUE ensures that we will write a complete interchange-JPEG file. * Pass TRUE unless you are very sure of what you're doing. */ jpeg_start_compress(&cinfo, TRUE); /* Step 5: while (scan lines remain to be written) */ /* jpeg_write_scanlines(...); */ /* Here we use the library's state variable cinfo.next_scanline as the * loop counter, so that we don't have to keep track ourselves. * To keep things simple, we pass one scanline per call; you can pass * more if you wish, though. */ row_stride = grabImage->Width() * 3; /* JSAMPLEs per row in image_buffer */ const int BYTE_SIZE = (160 * 3); U8 lineBuffer[BYTE_SIZE]; for (int y = 0; y < grabImage->Height(); y++) { int j = 0; for (int x=0; x < grabImage->Width(); x++) {Con::printf("j: %d.\n", (x*3)); float r,g,b; if (CVFAILED(grabImage->GetPixel(x,y,r,g,b))) { Con::printf("GetPixel Error!\n"); } else { lineBuffer[x * 3] = r; lineBuffer[x * 3 + 1] = g; lineBuffer[x * 3 + 2] = b; } } row_pointer[0] = & lineBuffer[0]; (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); } /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); /* After finish_compress, we can close the output file. */ fclose(outfile); /* Step 7: release JPEG compression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_compress(&cinfo); /* And we're done! */ }