GUAC-236: Do not use features specific to libjpeg-turbo. Ensure compatibility with libjpeg.
This commit is contained in:
parent
a1822c5a2c
commit
fd430e8b69
@ -32,6 +32,58 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Translates libjpeg's 24-bit RGB format into Cairo's 32-bit ARGB32 / RGB24
|
||||
* format. The red, green, and blue components from the libjpeg pixel are
|
||||
* copied verbatim, while the extra high byte used within Cairo is set to 0xFF.
|
||||
*
|
||||
* @param src
|
||||
* A pointer to the first byte of the 24-bit RGB pixel within a libjpeg
|
||||
* scanline buffer.
|
||||
*
|
||||
* @return
|
||||
* A 32-bit Cairo ARGB32 / RGB24 pixel value equivalent to the libjpeg
|
||||
* pixel at the given pointer.
|
||||
*/
|
||||
static uint32_t guacenc_jpeg_translate_rgb(const unsigned char* src) {
|
||||
|
||||
/* Pull components from source */
|
||||
int r = *(src++);
|
||||
int g = *(src++);
|
||||
int b = *(src++);
|
||||
|
||||
/* Translate to 32-bit integer compatible with Cairo */
|
||||
return 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the data from a libjpeg scanline buffer into a row of image data
|
||||
* within a Cairo surface, translating each pixel as necessary.
|
||||
*
|
||||
* @param dst
|
||||
* The destination buffer into which the scanline should be copied.
|
||||
*
|
||||
* @param src
|
||||
* The libjpeg scanline buffer that should be copied into the
|
||||
* destination buffer.
|
||||
*
|
||||
* @param width
|
||||
* The number of pixels available within both the scanline buffer and the
|
||||
* destination buffer.
|
||||
*/
|
||||
static void guacenc_jpeg_copy_scanline(unsigned char* dst,
|
||||
const unsigned char* src, int width) {
|
||||
|
||||
uint32_t* current = (uint32_t*) dst;
|
||||
|
||||
/* Copy all pixels from source to destination, translating for Cairo */
|
||||
for (; width > 0; width--, src += 3) {
|
||||
*(current++) = guacenc_jpeg_translate_rgb(src);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cairo_surface_t* guacenc_jpeg_decoder(unsigned char* data, int length) {
|
||||
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
@ -52,13 +104,16 @@ cairo_surface_t* guacenc_jpeg_decoder(unsigned char* data, int length) {
|
||||
}
|
||||
|
||||
/* Begin decompression */
|
||||
cinfo.out_color_space = JCS_EXT_BGRX;
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
/* Pull JPEG dimensions from decompressor */
|
||||
int width = cinfo.output_width;
|
||||
int height = cinfo.output_height;
|
||||
|
||||
/* Allocate sufficient buffer space for one JPEG scanline */
|
||||
unsigned char* jpeg_scanline = malloc(width * 3);
|
||||
|
||||
/* Create blank Cairo surface (no transparency in JPEG) */
|
||||
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
|
||||
width, height);
|
||||
@ -69,11 +124,22 @@ cairo_surface_t* guacenc_jpeg_decoder(unsigned char* data, int length) {
|
||||
|
||||
/* Read JPEG into surface */
|
||||
while (cinfo.output_scanline < height) {
|
||||
unsigned char* buffers[1] = { row };
|
||||
|
||||
/* Read single scanline */
|
||||
unsigned char* buffers[1] = { jpeg_scanline };
|
||||
jpeg_read_scanlines(&cinfo, buffers, 1);
|
||||
|
||||
/* Copy scanline to Cairo surface */
|
||||
guacenc_jpeg_copy_scanline(row, jpeg_scanline, width);
|
||||
|
||||
/* Advance to next row of Cairo surface */
|
||||
row += stride;
|
||||
|
||||
}
|
||||
|
||||
/* Scanline buffer is no longer needed */
|
||||
free(jpeg_scanline);
|
||||
|
||||
/* End decompression */
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user