Emulate colorspace extensions if they are not present in the libjpeg API. This allows the TurboJPEG wrapper to be used with libjpeg rather than libjpeg-turbo. Not useful within the context of our project, but other projects prefer to include the TurboJPEG wrapper in-tree, and this allows them to be linked against either libjpeg-turbo or libjpeg.
This commit is contained in:
233
turbojpeg.c
233
turbojpeg.c
@@ -172,12 +172,17 @@ static int setCompDefaults(struct jpeg_compress_struct *cinfo,
|
|||||||
cinfo->in_color_space=JCS_EXT_XBGR; break;
|
cinfo->in_color_space=JCS_EXT_XBGR; break;
|
||||||
#else
|
#else
|
||||||
case TJPF_RGB:
|
case TJPF_RGB:
|
||||||
if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
|
case TJPF_BGR:
|
||||||
{
|
case TJPF_RGBX:
|
||||||
cinfo->in_color_space=JCS_RGB; break;
|
case TJPF_BGRX:
|
||||||
}
|
case TJPF_XRGB:
|
||||||
default:
|
case TJPF_XBGR:
|
||||||
_throw("Unsupported pixel format");
|
case TJPF_RGBA:
|
||||||
|
case TJPF_BGRA:
|
||||||
|
case TJPF_ARGB:
|
||||||
|
case TJPF_ABGR:
|
||||||
|
cinfo->in_color_space=JCS_RGB; pixelFormat=TJPF_RGB;
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,9 +206,6 @@ static int setCompDefaults(struct jpeg_compress_struct *cinfo,
|
|||||||
cinfo->comp_info[1].v_samp_factor=1;
|
cinfo->comp_info[1].v_samp_factor=1;
|
||||||
cinfo->comp_info[2].v_samp_factor=1;
|
cinfo->comp_info[2].v_samp_factor=1;
|
||||||
|
|
||||||
#if JCS_EXTENSIONS!=1
|
|
||||||
bailout:
|
|
||||||
#endif
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,10 +243,16 @@ static int setDecompDefaults(struct jpeg_decompress_struct *dinfo,
|
|||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
case TJPF_RGB:
|
case TJPF_RGB:
|
||||||
if(RGB_RED==0 && RGB_GREEN==1 && RGB_BLUE==2 && RGB_PIXELSIZE==3)
|
case TJPF_BGR:
|
||||||
{
|
case TJPF_RGBX:
|
||||||
|
case TJPF_BGRX:
|
||||||
|
case TJPF_XRGB:
|
||||||
|
case TJPF_XBGR:
|
||||||
|
case TJPF_RGBA:
|
||||||
|
case TJPF_BGRA:
|
||||||
|
case TJPF_ARGB:
|
||||||
|
case TJPF_ABGR:
|
||||||
dinfo->out_color_space=JCS_RGB; break;
|
dinfo->out_color_space=JCS_RGB; break;
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
_throw("Unsupported pixel format");
|
_throw("Unsupported pixel format");
|
||||||
@@ -283,6 +291,149 @@ static int getSubsamp(j_decompress_ptr dinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
|
||||||
|
/* Conversion functions to emulate the colorspace extensions. This allows the
|
||||||
|
TurboJPEG wrapper to be used with libjpeg */
|
||||||
|
|
||||||
|
#define TORGB(PS, ROFFSET, GOFFSET, BOFFSET) { \
|
||||||
|
int rowPad=pitch-width*PS; \
|
||||||
|
while(height--) \
|
||||||
|
{ \
|
||||||
|
unsigned char *endOfRow=src+width*PS; \
|
||||||
|
while(src<endOfRow) \
|
||||||
|
{ \
|
||||||
|
dst[RGB_RED]=src[ROFFSET]; \
|
||||||
|
dst[RGB_GREEN]=src[GOFFSET]; \
|
||||||
|
dst[RGB_BLUE]=src[BOFFSET]; \
|
||||||
|
dst+=RGB_PIXELSIZE; src+=PS; \
|
||||||
|
} \
|
||||||
|
src+=rowPad; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char *toRGB(unsigned char *src, int width, int pitch,
|
||||||
|
int height, int pixelFormat, unsigned char *dst)
|
||||||
|
{
|
||||||
|
unsigned char *retval=src;
|
||||||
|
switch(pixelFormat)
|
||||||
|
{
|
||||||
|
case TJPF_RGB:
|
||||||
|
#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
|
||||||
|
retval=dst; TORGB(3, 0, 1, 2);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_BGR:
|
||||||
|
#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
|
||||||
|
retval=dst; TORGB(3, 2, 1, 0);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_RGBX:
|
||||||
|
case TJPF_RGBA:
|
||||||
|
#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
|
||||||
|
retval=dst; TORGB(4, 0, 1, 2);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_BGRX:
|
||||||
|
case TJPF_BGRA:
|
||||||
|
#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
|
||||||
|
retval=dst; TORGB(4, 2, 1, 0);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_XRGB:
|
||||||
|
case TJPF_ARGB:
|
||||||
|
#if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
|
||||||
|
retval=dst; TORGB(4, 1, 2, 3);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_XBGR:
|
||||||
|
case TJPF_ABGR:
|
||||||
|
#if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
|
||||||
|
retval=dst; TORGB(4, 3, 2, 1);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FROMRGB(PS, ROFFSET, GOFFSET, BOFFSET, SETALPHA) { \
|
||||||
|
int rowPad=pitch-width*PS; \
|
||||||
|
while(height--) \
|
||||||
|
{ \
|
||||||
|
unsigned char *endOfRow=dst+width*PS; \
|
||||||
|
while(dst<endOfRow) \
|
||||||
|
{ \
|
||||||
|
dst[ROFFSET]=src[RGB_RED]; \
|
||||||
|
dst[GOFFSET]=src[RGB_GREEN]; \
|
||||||
|
dst[BOFFSET]=src[RGB_BLUE]; \
|
||||||
|
SETALPHA \
|
||||||
|
dst+=PS; src+=RGB_PIXELSIZE; \
|
||||||
|
} \
|
||||||
|
dst+=rowPad; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fromRGB(unsigned char *src, unsigned char *dst, int width,
|
||||||
|
int pitch, int height, int pixelFormat)
|
||||||
|
{
|
||||||
|
switch(pixelFormat)
|
||||||
|
{
|
||||||
|
case TJPF_RGB:
|
||||||
|
#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=3
|
||||||
|
FROMRGB(3, 0, 1, 2,);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_BGR:
|
||||||
|
#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=3
|
||||||
|
FROMRGB(3, 2, 1, 0,);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_RGBX:
|
||||||
|
#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
|
||||||
|
FROMRGB(4, 0, 1, 2,);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_RGBA:
|
||||||
|
#if RGB_RED!=0 || RGB_GREEN!=1 || RGB_BLUE!=2 || RGB_PIXELSIZE!=4
|
||||||
|
FROMRGB(4, 0, 1, 2, dst[3]=0xFF;);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_BGRX:
|
||||||
|
#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
|
||||||
|
FROMRGB(4, 2, 1, 0,);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_BGRA:
|
||||||
|
#if RGB_RED!=2 || RGB_GREEN!=1 || RGB_BLUE!=0 || RGB_PIXELSIZE!=4
|
||||||
|
FROMRGB(4, 2, 1, 0, dst[3]=0xFF;); return;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_XRGB:
|
||||||
|
#if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
|
||||||
|
FROMRGB(4, 1, 2, 3,); return;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_ARGB:
|
||||||
|
#if RGB_RED!=1 || RGB_GREEN!=2 || RGB_BLUE!=3 || RGB_PIXELSIZE!=4
|
||||||
|
FROMRGB(4, 1, 2, 3, dst[0]=0xFF;); return;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_XBGR:
|
||||||
|
#if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
|
||||||
|
FROMRGB(4, 3, 2, 1,); return;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case TJPF_ABGR:
|
||||||
|
#if RGB_RED!=3 || RGB_GREEN!=2 || RGB_BLUE!=1 || RGB_PIXELSIZE!=4
|
||||||
|
FROMRGB(4, 3, 2, 1, dst[0]=0xFF;); return;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* General API functions */
|
/* General API functions */
|
||||||
|
|
||||||
DLLEXPORT char* DLLCALL tjGetErrorStr(void)
|
DLLEXPORT char* DLLCALL tjGetErrorStr(void)
|
||||||
@@ -423,6 +574,9 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
|
|||||||
unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
|
unsigned long *jpegSize, int jpegSubsamp, int jpegQual, int flags)
|
||||||
{
|
{
|
||||||
int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
|
int i, retval=0, alloc=1; JSAMPROW *row_pointer=NULL;
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
unsigned char *rgbBuf=NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
getinstance(handle)
|
getinstance(handle)
|
||||||
if((this->init&COMPRESS)==0)
|
if((this->init&COMPRESS)==0)
|
||||||
@@ -442,6 +596,16 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
|
|||||||
|
|
||||||
if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
|
if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
|
||||||
|
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
if(pixelFormat!=TJPF_GRAY)
|
||||||
|
{
|
||||||
|
rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
|
||||||
|
if(!rgbBuf) _throw("tjCompress2(): Memory allocation failure");
|
||||||
|
srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
|
||||||
|
pitch=width*RGB_PIXELSIZE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
cinfo->image_width=width;
|
cinfo->image_width=width;
|
||||||
cinfo->image_height=height;
|
cinfo->image_height=height;
|
||||||
|
|
||||||
@@ -474,6 +638,9 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
|
|||||||
|
|
||||||
bailout:
|
bailout:
|
||||||
if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
|
if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
if(rgbBuf && rgbBuf!=srcBuf) free(rgbBuf);
|
||||||
|
#endif
|
||||||
if(row_pointer) free(row_pointer);
|
if(row_pointer) free(row_pointer);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -512,6 +679,9 @@ DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
|
|||||||
JSAMPLE *ptr=dstBuf;
|
JSAMPLE *ptr=dstBuf;
|
||||||
unsigned long yuvsize=0;
|
unsigned long yuvsize=0;
|
||||||
jpeg_component_info *compptr;
|
jpeg_component_info *compptr;
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
unsigned char *rgbBuf=NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
getinstance(handle);
|
getinstance(handle);
|
||||||
if((this->init&COMPRESS)==0)
|
if((this->init&COMPRESS)==0)
|
||||||
@@ -537,6 +707,16 @@ DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
|
|||||||
|
|
||||||
if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
|
if(pitch==0) pitch=width*tjPixelSize[pixelFormat];
|
||||||
|
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
if(pixelFormat!=TJPF_GRAY)
|
||||||
|
{
|
||||||
|
rgbBuf=(unsigned char *)malloc(width*height*RGB_PIXELSIZE);
|
||||||
|
if(!rgbBuf) _throw("tjEncodeYUV2(): Memory allocation failure");
|
||||||
|
srcBuf=toRGB(srcBuf, width, pitch, height, pixelFormat, rgbBuf);
|
||||||
|
pitch=width*RGB_PIXELSIZE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
cinfo->image_width=width;
|
cinfo->image_width=width;
|
||||||
cinfo->image_height=height;
|
cinfo->image_height=height;
|
||||||
|
|
||||||
@@ -619,6 +799,9 @@ DLLEXPORT int DLLCALL tjEncodeYUV2(tjhandle handle, unsigned char *srcBuf,
|
|||||||
|
|
||||||
bailout:
|
bailout:
|
||||||
if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
|
if(cinfo->global_state>CSTATE_START) jpeg_abort_compress(cinfo);
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
if(rgbBuf && rgbBuf!=srcBuf) free(rgbBuf);
|
||||||
|
#endif
|
||||||
if(row_pointer) free(row_pointer);
|
if(row_pointer) free(row_pointer);
|
||||||
for(i=0; i<MAX_COMPONENTS; i++)
|
for(i=0; i<MAX_COMPONENTS; i++)
|
||||||
{
|
{
|
||||||
@@ -746,6 +929,10 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
|
|||||||
{
|
{
|
||||||
int i, retval=0; JSAMPROW *row_pointer=NULL;
|
int i, retval=0; JSAMPROW *row_pointer=NULL;
|
||||||
int jpegwidth, jpegheight, scaledw, scaledh;
|
int jpegwidth, jpegheight, scaledw, scaledh;
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
unsigned char *rgbBuf=NULL;
|
||||||
|
unsigned char *_dstBuf=NULL; int _pitch=0;
|
||||||
|
#endif
|
||||||
|
|
||||||
getinstance(handle);
|
getinstance(handle);
|
||||||
if((this->init&DECOMPRESS)==0)
|
if((this->init&DECOMPRESS)==0)
|
||||||
@@ -793,6 +980,21 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
|
|||||||
|
|
||||||
jpeg_start_decompress(dinfo);
|
jpeg_start_decompress(dinfo);
|
||||||
if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
|
if(pitch==0) pitch=dinfo->output_width*tjPixelSize[pixelFormat];
|
||||||
|
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
if(pixelFormat!=TJPF_GRAY &&
|
||||||
|
(RGB_RED!=tjRedOffset[pixelFormat] ||
|
||||||
|
RGB_GREEN!=tjGreenOffset[pixelFormat] ||
|
||||||
|
RGB_BLUE!=tjBlueOffset[pixelFormat] ||
|
||||||
|
RGB_PIXELSIZE!=tjPixelSize[pixelFormat]))
|
||||||
|
{
|
||||||
|
rgbBuf=(unsigned char *)malloc(width*height*3);
|
||||||
|
if(!rgbBuf) _throw("tjDecompress2(): Memory allocation failure");
|
||||||
|
_pitch=pitch; pitch=width*3;
|
||||||
|
_dstBuf=dstBuf; dstBuf=rgbBuf;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
|
if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
|
||||||
*dinfo->output_height))==NULL)
|
*dinfo->output_height))==NULL)
|
||||||
_throw("tjDecompress2(): Memory allocation failure");
|
_throw("tjDecompress2(): Memory allocation failure");
|
||||||
@@ -809,8 +1011,15 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, unsigned char *jpegBuf,
|
|||||||
}
|
}
|
||||||
jpeg_finish_decompress(dinfo);
|
jpeg_finish_decompress(dinfo);
|
||||||
|
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
fromRGB(rgbBuf, _dstBuf, width, _pitch, height, pixelFormat);
|
||||||
|
#endif
|
||||||
|
|
||||||
bailout:
|
bailout:
|
||||||
if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
|
if(dinfo->global_state>DSTATE_START) jpeg_abort_decompress(dinfo);
|
||||||
|
#ifndef JCS_EXTENSIONS
|
||||||
|
if(rgbBuf && rgbBuf!=dstBuf) free(rgbBuf);
|
||||||
|
#endif
|
||||||
if(row_pointer) free(row_pointer);
|
if(row_pointer) free(row_pointer);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user