From be0a9e728f5f06aa8b4277e13e053140627e0b54 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 12 Mar 2016 19:55:17 -0800 Subject: [PATCH] GUAC-236: Implement JPEG. --- src/guacenc/jpeg.c | 57 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/guacenc/jpeg.c b/src/guacenc/jpeg.c index 706e21c7..dfed2d13 100644 --- a/src/guacenc/jpeg.c +++ b/src/guacenc/jpeg.c @@ -22,13 +22,66 @@ #include "config.h" #include "jpeg.h" +#include "log.h" + +#include +#include #include +#include #include cairo_surface_t* guacenc_jpeg_decoder(unsigned char* data, int length) { - /* STUB */ - return NULL; + + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + + /* Create decompressor with standard error handling */ + jpeg_create_decompress(&cinfo); + cinfo.err = jpeg_std_error(&jerr); + + /* Read JPEG directly from memory buffer */ + jpeg_mem_src(&cinfo, data, length); + + /* Read and validate JPEG header */ + if (!jpeg_read_header(&cinfo, TRUE)) { + guacenc_log(GUAC_LOG_WARNING, "Invalid JPEG data"); + jpeg_destroy_decompress(&cinfo); + return NULL; + } + + /* Begin decompression */ + cinfo.out_color_space = JCS_EXT_BGRX; + jpeg_start_decompress(&cinfo); + + /* Pull JPEG dimensions from decompressor */ + int width = cinfo.output_width; + int height = cinfo.output_height; + + /* Create blank Cairo surface (no transparency in JPEG) */ + cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, + width, height); + + /* Pull underlying buffer and its stride */ + int stride = cairo_image_surface_get_stride(surface); + unsigned char* row = cairo_image_surface_get_data(surface); + + /* Read JPEG into surface */ + while (cinfo.output_scanline < height) { + unsigned char* buffers[1] = { row }; + jpeg_read_scanlines(&cinfo, buffers, 1); + row += stride; + } + + /* End decompression */ + jpeg_finish_decompress(&cinfo); + + /* Free decompressor */ + jpeg_destroy_decompress(&cinfo); + + /* JPEG was read successfully */ + return surface; + }