зеркало из https://github.com/mozilla/mozjpeg.git
Replace the TJ_YUV flag with two new API functions, and add TJBUFSIZEYUV() from trunk
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/branches/1.1.x@440 632fc199-4ca6-4c93-a231-07263d6284db
This commit is contained in:
Родитель
5cb1b68d39
Коммит
eeab6957dd
61
jpegut.c
61
jpegut.c
|
@ -225,8 +225,7 @@ int checkbuf(unsigned char *buf, int w, int h, int ps, int subsamp, int flags)
|
|||
|
||||
#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
|
||||
|
||||
int checkbufyuv(unsigned char *buf, unsigned long size, int w, int h,
|
||||
int subsamp)
|
||||
int checkbufyuv(unsigned char *buf, int w, int h, int subsamp)
|
||||
{
|
||||
int i, j;
|
||||
int hsf=_hsf[subsamp], vsf=_vsf[subsamp];
|
||||
|
@ -234,13 +233,6 @@ int checkbufyuv(unsigned char *buf, unsigned long size, int w, int h,
|
|||
int cw=pw/hsf, ch=ph/vsf;
|
||||
int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
|
||||
int retval=1;
|
||||
unsigned long correctsize=ypitch*ph + (subsamp==TJ_GRAYSCALE? 0:uvpitch*ch*2);
|
||||
|
||||
if(size!=correctsize)
|
||||
{
|
||||
printf("\nIncorrect size %lu. Should be %lu\n", size, correctsize);
|
||||
retval=0; goto bailout;
|
||||
}
|
||||
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
|
@ -349,8 +341,6 @@ void gentestjpeg(tjhandle hnd, unsigned char *jpegbuf, unsigned long *size,
|
|||
char tempstr[1024]; unsigned char *bmpbuf=NULL;
|
||||
const char *pixformat; double t;
|
||||
|
||||
if(yuv==YUVENCODE) flags|=TJ_YUV;
|
||||
|
||||
if(flags&TJ_BGR)
|
||||
{
|
||||
if(ps==3) pixformat="BGR";
|
||||
|
@ -374,10 +364,20 @@ void gentestjpeg(tjhandle hnd, unsigned char *jpegbuf, unsigned long *size,
|
|||
printf("ERROR: Could not allocate buffer\n"); bailout();
|
||||
}
|
||||
initbuf(bmpbuf, w, h, ps, flags);
|
||||
memset(jpegbuf, 0, TJBUFSIZE(w, h));
|
||||
memset(jpegbuf, 0,
|
||||
yuv==YUVENCODE? TJBUFSIZEYUV(w, h, subsamp):TJBUFSIZE(w, h));
|
||||
|
||||
t=rrtime();
|
||||
_catch(tjCompress(hnd, bmpbuf, w, 0, h, ps, jpegbuf, size, subsamp, qual, flags));
|
||||
if(yuv==YUVENCODE)
|
||||
{
|
||||
_catch(tjEncodeYUV(hnd, bmpbuf, w, 0, h, ps, jpegbuf, subsamp, flags));
|
||||
*size=TJBUFSIZEYUV(w, h, subsamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
_catch(tjCompress(hnd, bmpbuf, w, 0, h, ps, jpegbuf, size, subsamp, qual,
|
||||
flags));
|
||||
}
|
||||
t=rrtime()-t;
|
||||
|
||||
if(yuv==YUVENCODE)
|
||||
|
@ -389,7 +389,7 @@ void gentestjpeg(tjhandle hnd, unsigned char *jpegbuf, unsigned long *size,
|
|||
writejpeg(jpegbuf, *size, tempstr);
|
||||
if(yuv==YUVENCODE)
|
||||
{
|
||||
if(checkbufyuv(jpegbuf, *size, w, h, subsamp)) printf("Passed.");
|
||||
if(checkbufyuv(jpegbuf, w, h, subsamp)) printf("Passed.");
|
||||
else {printf("FAILED!"); exitstatus=-1;}
|
||||
}
|
||||
else printf("Done.");
|
||||
|
@ -405,13 +405,8 @@ void gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
|
|||
unsigned char *bmpbuf=NULL;
|
||||
const char *pixformat; int _w=0, _h=0; double t;
|
||||
unsigned long size=0;
|
||||
int hsf=_hsf[subsamp], vsf=_vsf[subsamp];
|
||||
int pw=PAD(w, hsf), ph=PAD(h, vsf);
|
||||
int cw=pw/hsf, ch=ph/vsf;
|
||||
int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
|
||||
|
||||
if(yuv==YUVDECODE) flags|=TJ_YUV;
|
||||
else if(yuv==YUVENCODE) return;
|
||||
if(yuv==YUVENCODE) return;
|
||||
|
||||
if(flags&TJ_BGR)
|
||||
{
|
||||
|
@ -436,24 +431,29 @@ void gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
|
|||
printf("Incorrect JPEG header\n"); bailout();
|
||||
}
|
||||
|
||||
if(yuv==YUVDECODE)
|
||||
size=ypitch*ph + (subsamp==TJ_GRAYSCALE? 0:uvpitch*ch*2);
|
||||
else
|
||||
size=w*h*ps;
|
||||
if((bmpbuf=(unsigned char *)malloc(size+1))==NULL)
|
||||
if(yuv==YUVDECODE) size=TJBUFSIZEYUV(w, h, subsamp);
|
||||
else size=w*h*ps+1;
|
||||
if((bmpbuf=(unsigned char *)malloc(size))==NULL)
|
||||
{
|
||||
printf("ERROR: Could not allocate buffer\n"); bailout();
|
||||
}
|
||||
memset(bmpbuf, 0, size+1);
|
||||
memset(bmpbuf, 0, size);
|
||||
|
||||
t=rrtime();
|
||||
_catch(tjDecompress(hnd, jpegbuf, jpegsize, bmpbuf, w, w*ps, h, ps, flags));
|
||||
if(yuv==YUVDECODE)
|
||||
{
|
||||
_catch(tjDecompressToYUV(hnd, jpegbuf, jpegsize, bmpbuf, flags));
|
||||
}
|
||||
else
|
||||
{
|
||||
_catch(tjDecompress(hnd, jpegbuf, jpegsize, bmpbuf, w, w*ps, h, ps,
|
||||
flags));
|
||||
}
|
||||
t=rrtime()-t;
|
||||
|
||||
if(yuv==YUVDECODE)
|
||||
{
|
||||
if(checkbufyuv(bmpbuf, size, pw, ph, subsamp))
|
||||
printf("Passed.");
|
||||
if(checkbufyuv(bmpbuf, w, h, subsamp)) printf("Passed.");
|
||||
else {printf("FAILED!"); exitstatus=-1;}
|
||||
}
|
||||
else
|
||||
|
@ -476,7 +476,8 @@ void dotest(int w, int h, int ps, int subsamp, char *basefilename)
|
|||
tjhandle hnd=NULL, dhnd=NULL; unsigned char *jpegbuf=NULL;
|
||||
unsigned long size;
|
||||
|
||||
if((jpegbuf=(unsigned char *)malloc(TJBUFSIZE(w, h))) == NULL)
|
||||
size=(yuv==YUVENCODE? TJBUFSIZEYUV(w, h, subsamp):TJBUFSIZE(w, h));
|
||||
if((jpegbuf=(unsigned char *)malloc(size)) == NULL)
|
||||
{
|
||||
puts("ERROR: Could not allocate buffer."); bailout();
|
||||
}
|
||||
|
|
73
jpgtest.c
73
jpgtest.c
|
@ -43,8 +43,6 @@ const int _bindex[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3};
|
|||
const char *_pfname[]={"RGB", "RGBX", "BGR", "BGRX", "XBGR", "XRGB"};
|
||||
const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY"};
|
||||
const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY"};
|
||||
const int _hsf[NUMSUBOPT]={1, 2, 2, 1};
|
||||
const int _vsf[NUMSUBOPT]={1, 1, 2, 1};
|
||||
|
||||
void printsigfig(double val, int figs)
|
||||
{
|
||||
|
@ -78,16 +76,12 @@ void dotest(unsigned char *srcbuf, int w, int h, int pf, int bu,
|
|||
|(fastupsample?TJ_FASTUPSAMPLE:0);
|
||||
int ps=_ps[pf], tilen;
|
||||
int pitch=w*ps, yuvsize;
|
||||
int hsf=_hsf[jpegsub], vsf=_vsf[jpegsub];
|
||||
int pw=PAD(w, hsf), ph=PAD(h, vsf);
|
||||
int cw=pw/hsf, ch=ph/vsf;
|
||||
int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
|
||||
|
||||
flags |= _flags[pf];
|
||||
if(bu) flags |= TJ_BOTTOMUP;
|
||||
if(yuv==YUVENCODE) flags |= TJ_YUV;
|
||||
|
||||
yuvsize=ypitch*ph + (jpegsub==TJ_GRAYSCALE? 0:uvpitch*ch*2);
|
||||
yuvsize=TJBUFSIZEYUV(w, h, jpegsub);
|
||||
if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*h))) == NULL)
|
||||
_throwunix("allocating image buffer");
|
||||
|
||||
|
@ -125,7 +119,14 @@ void dotest(unsigned char *srcbuf, int w, int h, int pf, int bu,
|
|||
for(i=0; i<h; i++) memcpy(&rgbbuf[pitch*i], &srcbuf[w*ps*i], w*ps);
|
||||
if((hnd=tjInitCompress())==NULL)
|
||||
_throwtj("executing tjInitCompress()");
|
||||
if(tjCompress(hnd, rgbbuf, tilesizex, pitch, tilesizey, ps,
|
||||
if(yuv==YUVENCODE)
|
||||
{
|
||||
if(tjEncodeYUV(hnd, rgbbuf, tilesizex, pitch, tilesizey, ps,
|
||||
jpegbuf[0], jpegsub, flags)==-1)
|
||||
_throwtj("executing tjEncodeYUV()");
|
||||
comptilesize[0]=TJBUFSIZEYUV(tilesizex, tilesizey, jpegsub);
|
||||
}
|
||||
else if(tjCompress(hnd, rgbbuf, tilesizex, pitch, tilesizey, ps,
|
||||
jpegbuf[0], &comptilesize[0], jpegsub, qual, flags)==-1)
|
||||
_throwtj("executing tjCompress()");
|
||||
ITER=0;
|
||||
|
@ -138,7 +139,14 @@ void dotest(unsigned char *srcbuf, int w, int h, int pf, int bu,
|
|||
for(j=0; j<w; j+=tilesizex)
|
||||
{
|
||||
int tempw=min(tilesizex, w-j), temph=min(tilesizey, h-i);
|
||||
if(tjCompress(hnd, &rgbbuf[pitch*i+j*ps], tempw, pitch,
|
||||
if(yuv==YUVENCODE)
|
||||
{
|
||||
if(tjEncodeYUV(hnd, &rgbbuf[pitch*i+j*ps], tempw, pitch,
|
||||
temph, ps, jpegbuf[tilen], jpegsub, flags)==-1)
|
||||
_throwtj("executing tjEncodeYUV()");
|
||||
comptilesize[tilen]=TJBUFSIZEYUV(tempw, temph, jpegsub);
|
||||
}
|
||||
else if(tjCompress(hnd, &rgbbuf[pitch*i+j*ps], tempw, pitch,
|
||||
temph, ps, jpegbuf[tilen], &comptilesize[tilen], jpegsub, qual,
|
||||
flags)==-1)
|
||||
_throwtj("executing tjCompress()");
|
||||
|
@ -194,11 +202,15 @@ void dotest(unsigned char *srcbuf, int w, int h, int pf, int bu,
|
|||
}
|
||||
|
||||
// Decompression test
|
||||
if(yuv==YUVDECODE) flags |= TJ_YUV;
|
||||
memset(rgbbuf, 127, max(yuvsize, pitch*h)); // Grey image means decompressor did nothing
|
||||
if((hnd=tjInitDecompress())==NULL)
|
||||
_throwtj("executing tjInitDecompress()");
|
||||
if(tjDecompress(hnd, jpegbuf[0], jpgbufsize, rgbbuf, tilesizex, pitch,
|
||||
if(yuv==YUVDECODE)
|
||||
{
|
||||
if(tjDecompressToYUV(hnd, jpegbuf[0], jpgbufsize, rgbbuf, flags)==-1)
|
||||
_throwtj("executing tjDecompressToYUV()");
|
||||
}
|
||||
else if(tjDecompress(hnd, jpegbuf[0], jpgbufsize, rgbbuf, tilesizex, pitch,
|
||||
tilesizey, ps, flags)==-1)
|
||||
_throwtj("executing tjDecompress()");
|
||||
ITER=0;
|
||||
|
@ -211,7 +223,13 @@ void dotest(unsigned char *srcbuf, int w, int h, int pf, int bu,
|
|||
for(j=0; j<w; j+=tilesizex)
|
||||
{
|
||||
int tempw=min(tilesizex, w-j), temph=min(tilesizey, h-i);
|
||||
if(tjDecompress(hnd, jpegbuf[tilen], comptilesize[tilen],
|
||||
if(yuv==YUVDECODE)
|
||||
{
|
||||
if(tjDecompressToYUV(hnd, jpegbuf[tilen], comptilesize[tilen],
|
||||
&rgbbuf[pitch*i+ps*j], flags)==-1)
|
||||
_throwtj("executing tjDecompressToYUV()");
|
||||
}
|
||||
else if(tjDecompress(hnd, jpegbuf[tilen], comptilesize[tilen],
|
||||
&rgbbuf[pitch*i+ps*j], tempw, pitch, temph, ps, flags)==-1)
|
||||
_throwtj("executing tjDecompress()");
|
||||
tilen++;
|
||||
|
@ -321,11 +339,10 @@ void dodecomptest(char *filename, int pf, int bu, int useppm,
|
|||
|(fastupsample?TJ_FASTUPSAMPLE:0);
|
||||
int ps=_ps[pf], pitch, jpegsub=-1;
|
||||
char *temp=NULL;
|
||||
int hsf, vsf, pw, ph, cw, ch, ypitch, uvpitch, yuvsize;
|
||||
int yuvsize, bufsize;
|
||||
|
||||
flags |= _flags[pf];
|
||||
if(bu) flags |= TJ_BOTTOMUP;
|
||||
if(yuv==YUVDECODE) flags |= TJ_YUV;
|
||||
|
||||
if((file=fopen(filename, "rb"))==NULL)
|
||||
_throwunix("opening file");
|
||||
|
@ -346,11 +363,7 @@ void dodecomptest(char *filename, int pf, int bu, int useppm,
|
|||
if(tjDecompressHeader2(hnd, jpegbuf, jpgbufsize, &w, &h, &jpegsub)==-1)
|
||||
_throwtj("executing tjDecompressHeader2()");
|
||||
|
||||
hsf=_hsf[jpegsub], vsf=_vsf[jpegsub];
|
||||
pw=PAD(w, hsf), ph=PAD(h, vsf);
|
||||
cw=pw/hsf, ch=ph/vsf;
|
||||
ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
|
||||
yuvsize=ypitch*ph + (jpegsub==TJ_GRAYSCALE? 0:uvpitch*ch*2);
|
||||
yuvsize=TJBUFSIZEYUV(w, h, jpegsub);
|
||||
|
||||
pitch=w*ps;
|
||||
|
||||
|
@ -362,7 +375,8 @@ void dodecomptest(char *filename, int pf, int bu, int useppm,
|
|||
printf("%s\t%s\t%-4d %-4d\t", _pfname[pf], bu?"BU":"TD", w, h);
|
||||
}
|
||||
|
||||
if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*h)))==NULL)
|
||||
bufsize=(yuv==YUVDECODE? yuvsize:pitch*h);
|
||||
if((rgbbuf=(unsigned char *)malloc(bufsize))==NULL)
|
||||
_throwunix("allocating image buffer");
|
||||
|
||||
if(!quiet)
|
||||
|
@ -375,15 +389,26 @@ void dodecomptest(char *filename, int pf, int bu, int useppm,
|
|||
printf("\nImage size: %d x %d\n", w, h);
|
||||
}
|
||||
|
||||
memset(rgbbuf, 127, max(yuvsize, pitch*h)); // Grey image means decompressor did nothing
|
||||
if(tjDecompress(hnd, jpegbuf, jpgbufsize, rgbbuf, w, pitch, h, ps, flags)==-1)
|
||||
memset(rgbbuf, 127, bufsize); // Grey image means decompressor did nothing
|
||||
if(yuv==YUVDECODE)
|
||||
{
|
||||
if(tjDecompressToYUV(hnd, jpegbuf, jpgbufsize, rgbbuf, flags)==-1)
|
||||
_throwtj("executing tjDecompressToYUV()");
|
||||
}
|
||||
else if(tjDecompress(hnd, jpegbuf, jpgbufsize, rgbbuf, w, pitch, h, ps,
|
||||
flags)==-1)
|
||||
_throwtj("executing tjDecompress()");
|
||||
ITER=0;
|
||||
start=rrtime();
|
||||
do
|
||||
{
|
||||
if(tjDecompress(hnd, jpegbuf, jpgbufsize, rgbbuf, w, pitch, h, ps, flags)
|
||||
==-1)
|
||||
if(yuv==YUVDECODE)
|
||||
{
|
||||
if(tjDecompressToYUV(hnd, jpegbuf, jpgbufsize, rgbbuf, flags)==-1)
|
||||
_throwtj("executing tjDecompressToYUV()");
|
||||
}
|
||||
else if(tjDecompress(hnd, jpegbuf, jpgbufsize, rgbbuf, w, pitch, h, ps,
|
||||
flags)==-1)
|
||||
_throwtj("executing tjDecompress()");
|
||||
ITER++;
|
||||
} while((elapsed=rrtime()-start)<5.);
|
||||
|
|
|
@ -16,5 +16,8 @@ TURBOJPEG_1.0
|
|||
TURBOJPEG_1.1
|
||||
{
|
||||
global:
|
||||
TJBUFSIZEYUV;
|
||||
tjDecompressHeader2;
|
||||
tjDecompressToYUV;
|
||||
tjEncodeYUV;
|
||||
} TURBOJPEG_1.0;
|
||||
|
|
146
turbojpeg.h
146
turbojpeg.h
|
@ -54,26 +54,7 @@ enum {TJ_444=0, TJ_422, TJ_420, TJ_GRAYSCALE};
|
|||
/* Use fast, inaccurate 4:2:2 and 4:2:0 YUV upsampling routines
|
||||
(libjpeg and libjpeg-turbo versions only) */
|
||||
#define TJ_YUV 512
|
||||
/* If passed to tjCompress(), this causes TurboJPEG to use the accelerated
|
||||
color conversion routines in the underlying codec to produce a planar
|
||||
YUV image that is suitable for X Video. Specifically, if the chrominance
|
||||
components are subsampled along the horizontal dimension, then the width
|
||||
of the luminance plane is padded to 2 in the output image (same goes for
|
||||
the height of the luminance plane, if the chrominance components are
|
||||
subsampled along the vertical dimension.) Also, each line of each plane
|
||||
in the output image is padded to 4 bytes. Although this will work with
|
||||
any subsampling option, it is really only useful in combination with
|
||||
TJ_420, which produces an image compatible with the I420 (AKA "YUV420P")
|
||||
format.
|
||||
|
||||
If passed to tjDecompress(), this tells TurboJPEG to perform JPEG
|
||||
decompression but to leave out the color conversion step, so a planar YUV
|
||||
image is generated instead of an RGB image. The padding of the planes in
|
||||
this image is the same as in the above case. Note that, if the width or
|
||||
height of the output image is not a multiple of 8 (or a multiple of 16
|
||||
along any dimension in which chrominance subsampling is used), then an
|
||||
intermediate buffer copy will be performed within TurboJPEG.
|
||||
*/
|
||||
/* Nothing to see here. Pay no attention to the man behind the curtain. */
|
||||
|
||||
typedef void* tjhandle;
|
||||
|
||||
|
@ -96,7 +77,8 @@ extern "C" {
|
|||
and returns a handle to the instance. Most applications will only
|
||||
need to call this once at the beginning of the program or once for each
|
||||
concurrent thread. Don't try to create a new instance every time you
|
||||
compress an image, because this will cause performance to suffer.
|
||||
compress an image, because this may cause performance to suffer in some
|
||||
TurboJPEG implementations.
|
||||
|
||||
RETURNS: NULL on error
|
||||
*/
|
||||
|
@ -113,7 +95,7 @@ DLLEXPORT tjhandle DLLCALL tjInitCompress(void);
|
|||
tjInitCompress()
|
||||
[INPUT] srcbuf = pointer to user-allocated image buffer containing RGB or
|
||||
grayscale pixels to be compressed
|
||||
[INPUT] width = width (in pixels) of the source image
|
||||
[INPUT] width = width (in pixels) of the source image
|
||||
[INPUT] pitch = bytes per line of the source image (width*pixelsize if the
|
||||
bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap
|
||||
is padded to the nearest 32-bit boundary, such as is the case for Windows
|
||||
|
@ -128,12 +110,12 @@ DLLEXPORT tjhandle DLLCALL tjInitCompress(void);
|
|||
the appropriate size for this buffer based on the image width and height.
|
||||
[OUTPUT] size = pointer to unsigned long which receives the size (in bytes)
|
||||
of the compressed image
|
||||
[INPUT] jpegsubsamp = Specifies either 4:2:0, 4:2:2, or 4:4:4 subsampling.
|
||||
When the image is converted from the RGB to YCbCr colorspace as part of
|
||||
the JPEG compression process, every other Cb and Cr (chrominance) pixel
|
||||
can be discarded to produce a smaller image with little perceptible loss
|
||||
of image clarity (the human eye is more sensitive to small changes in
|
||||
brightness than small changes in color.)
|
||||
[INPUT] jpegsubsamp = Specifies either 4:2:0, 4:2:2, 4:4:4, or grayscale
|
||||
subsampling. When the image is converted from the RGB to YCbCr colorspace
|
||||
as part of the JPEG compression process, every other Cb and Cr
|
||||
(chrominance) pixel can be discarded to produce a smaller image with
|
||||
little perceptible loss of image clarity (the human eye is more sensitive
|
||||
to small changes in brightness than small changes in color.)
|
||||
|
||||
TJ_420: 4:2:0 subsampling. Discards every other Cb, Cr pixel in both
|
||||
horizontal and vertical directions
|
||||
|
@ -153,8 +135,77 @@ DLLEXPORT int DLLCALL tjCompress(tjhandle j,
|
|||
unsigned char *dstbuf, unsigned long *size,
|
||||
int jpegsubsamp, int jpegqual, int flags);
|
||||
|
||||
|
||||
/*
|
||||
unsigned long TJBUFSIZE(int width, int height)
|
||||
|
||||
Convenience function which returns the maximum size of the buffer required to
|
||||
hold a JPEG image with the given width and height
|
||||
|
||||
RETURNS: -1 if arguments are out of bounds
|
||||
*/
|
||||
DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height);
|
||||
|
||||
|
||||
/*
|
||||
unsigned long TJBUFSIZEYUV(int width, int height, int subsamp)
|
||||
|
||||
Convenience function which returns the size of the buffer required to
|
||||
hold a YUV planar image with the given width, height, and level of
|
||||
chrominance subsampling
|
||||
|
||||
RETURNS: -1 if arguments are out of bounds
|
||||
*/
|
||||
DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
|
||||
int subsamp);
|
||||
|
||||
|
||||
/*
|
||||
int tjEncodeYUV(tjhandle j,
|
||||
unsigned char *srcbuf, int width, int pitch, int height, int pixelsize,
|
||||
unsigned char *dstbuf, int subsamp, int flags)
|
||||
|
||||
This function uses the accelerated color conversion routines in TurboJPEG's
|
||||
underlying codec to produce a planar YUV image that is suitable for X Video.
|
||||
Specifically, if the chrominance components are subsampled along the
|
||||
horizontal dimension, then the width of the luminance plane is padded to 2 in
|
||||
the output image (same goes for the height of the luminance plane, if the
|
||||
chrominance components are subsampled along the vertical dimension.) Also,
|
||||
each line of each plane in the output image is padded to 4 bytes. Although
|
||||
this will work with any subsampling option, it is really only useful in
|
||||
combination with TJ_420, which produces an image compatible with the I420
|
||||
(AKA "YUV420P") format.
|
||||
|
||||
[INPUT] j = instance handle previously returned from a call to
|
||||
tjInitCompress()
|
||||
[INPUT] srcbuf = pointer to user-allocated image buffer containing RGB or
|
||||
grayscale pixels to be encoded
|
||||
[INPUT] width = width (in pixels) of the source image
|
||||
[INPUT] pitch = bytes per line of the source image (width*pixelsize if the
|
||||
bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap
|
||||
is padded to the nearest 32-bit boundary, such as is the case for Windows
|
||||
bitmaps. You can also be clever and use this parameter to skip lines,
|
||||
etc. Setting this parameter to 0 is the equivalent of setting it to
|
||||
width*pixelsize.
|
||||
[INPUT] height = height (in pixels) of the source image
|
||||
[INPUT] pixelsize = size (in bytes) of each pixel in the source image
|
||||
RGBX/BGRX/XRGB/XBGR: 4, RGB/BGR: 3, Grayscale: 1
|
||||
[INPUT] dstbuf = pointer to user-allocated image buffer which will receive
|
||||
the YUV image. Use the TJBUFSIZEYUV(width, height, subsamp) function to
|
||||
determine the appropriate size for this buffer based on the image width,
|
||||
height, and level of subsampling.
|
||||
[INPUT] subsamp = Specifies either 4:2:0, 4:2:2, 4:4:4, or grayscale
|
||||
subsampling (see description under tjCompress())
|
||||
[INPUT] flags = the bitwise OR of one or more of the flags described in the
|
||||
"Flags" section above
|
||||
|
||||
RETURNS: 0 on success, -1 on error
|
||||
*/
|
||||
DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle j,
|
||||
unsigned char *srcbuf, int width, int pitch, int height, int pixelsize,
|
||||
unsigned char *dstbuf, int subsamp, int flags);
|
||||
|
||||
|
||||
/*
|
||||
tjhandle tjInitDecompress(void)
|
||||
|
||||
|
@ -162,7 +213,8 @@ DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height);
|
|||
structures, and returns a handle to the instance. Most applications will
|
||||
only need to call this once at the beginning of the program or once for each
|
||||
concurrent thread. Don't try to create a new instance every time you
|
||||
decompress an image, because this will cause performance to suffer.
|
||||
decompress an image, because this may cause performance to suffer in some
|
||||
TurboJPEG implementations.
|
||||
|
||||
RETURNS: NULL on error
|
||||
*/
|
||||
|
@ -176,8 +228,7 @@ DLLEXPORT tjhandle DLLCALL tjInitDecompress(void);
|
|||
|
||||
[INPUT] j = instance handle previously returned from a call to
|
||||
tjInitDecompress()
|
||||
[INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image
|
||||
to decompress
|
||||
[INPUT] srcbuf = pointer to a user-allocated buffer containing a JPEG image
|
||||
[INPUT] size = size of the JPEG image buffer (in bytes)
|
||||
[OUTPUT] width = width (in pixels) of the JPEG image
|
||||
[OUTPUT] height = height (in pixels) of the JPEG image
|
||||
|
@ -213,7 +264,7 @@ DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j,
|
|||
the bitmap image. This buffer should normally be pitch*height
|
||||
bytes in size, although this pointer may also be used to decompress into
|
||||
a specific region of a larger buffer.
|
||||
[INPUT] width = width (in pixels) of the destination image
|
||||
[INPUT] width = width (in pixels) of the destination image
|
||||
[INPUT] pitch = bytes per line of the destination image (width*pixelsize if
|
||||
the bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the
|
||||
bitmap is padded to the nearest 32-bit boundary, such as is the case for
|
||||
|
@ -234,6 +285,37 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle j,
|
|||
int flags);
|
||||
|
||||
|
||||
/*
|
||||
int tjDecompressToYUV(tjhandle j,
|
||||
unsigned char *srcbuf, unsigned long size,
|
||||
unsigned char *dstbuf, int flags)
|
||||
|
||||
This function performs JPEG decompression but leaves out the color conversion
|
||||
step, so a planar YUV image is generated instead of an RGB image. The
|
||||
padding of the planes in this image is the same as in tjEncodeYUV().
|
||||
Note that, if the width or height of the output image is not a multiple of 8
|
||||
(or a multiple of 16 along any dimension in which chrominance subsampling is
|
||||
used), then an intermediate buffer copy will be performed within TurboJPEG.
|
||||
|
||||
[INPUT] j = instance handle previously returned from a call to
|
||||
tjInitDecompress()
|
||||
[INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image
|
||||
to decompress
|
||||
[INPUT] size = size of the JPEG image buffer (in bytes)
|
||||
[INPUT] dstbuf = pointer to user-allocated image buffer which will receive
|
||||
the YUV image. Use the TJBUFSIZEYUV(width, height, subsamp) function to
|
||||
determine the appropriate size for this buffer based on the image width,
|
||||
height, and level of subsampling.
|
||||
[INPUT] flags = the bitwise OR of one or more of the flags described in the
|
||||
"Flags" section above.
|
||||
|
||||
RETURNS: 0 on success, -1 on error
|
||||
*/
|
||||
DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle j,
|
||||
unsigned char *srcbuf, unsigned long size,
|
||||
unsigned char *dstbuf, int flags);
|
||||
|
||||
|
||||
/*
|
||||
int tjDestroy(tjhandle h)
|
||||
|
||||
|
|
58
turbojpegl.c
58
turbojpegl.c
|
@ -112,12 +112,40 @@ DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
|
|||
return (tjhandle)j;
|
||||
}
|
||||
|
||||
|
||||
DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
|
||||
{
|
||||
// This allows enough room in case the image doesn't compress
|
||||
return ((width+15)&(~15)) * ((height+15)&(~15)) * 6 + 2048;
|
||||
unsigned long retval=0;
|
||||
if(width<1 || height<1)
|
||||
_throw("Invalid argument in TJBUFSIZE()");
|
||||
|
||||
// This allows for rare corner cases in which a JPEG image can actually be
|
||||
// larger than the uncompressed input (we wouldn't mention it if it hadn't
|
||||
// happened before.)
|
||||
retval=((width+15)&(~15)) * ((height+15)&(~15)) * 6 + 2048;
|
||||
|
||||
bailout:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
|
||||
int subsamp)
|
||||
{
|
||||
unsigned long retval=0;
|
||||
int pw, ph, cw, ch;
|
||||
if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
|
||||
_throw("Invalid argument in TJBUFSIZEYUV()");
|
||||
pw=PAD(width, hsampfactor[subsamp]);
|
||||
ph=PAD(height, vsampfactor[subsamp]);
|
||||
cw=pw/hsampfactor[subsamp]; ch=ph/vsampfactor[subsamp];
|
||||
retval=PAD(pw, 4)*ph + (subsamp==TJ_GRAYSCALE? 0:PAD(cw, 4)*ch*2);
|
||||
|
||||
bailout:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
DLLEXPORT int DLLCALL tjCompress(tjhandle h,
|
||||
unsigned char *srcbuf, int width, int pitch, int height, int ps,
|
||||
unsigned char *dstbuf, unsigned long *size,
|
||||
|
@ -308,6 +336,16 @@ DLLEXPORT int DLLCALL tjCompress(tjhandle h,
|
|||
}
|
||||
|
||||
|
||||
DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle h,
|
||||
unsigned char *srcbuf, int width, int pitch, int height, int ps,
|
||||
unsigned char *dstbuf, int subsamp, int flags)
|
||||
{
|
||||
unsigned long size;
|
||||
return tjCompress(h, srcbuf, width, pitch, height, ps, dstbuf, &size,
|
||||
subsamp, 0, flags|TJ_YUV);
|
||||
}
|
||||
|
||||
|
||||
// DEC
|
||||
|
||||
static boolean fill_input_buffer (struct jpeg_decompress_struct *dinfo)
|
||||
|
@ -471,10 +509,10 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
|
|||
int ih;
|
||||
iw[i]=compptr->width_in_blocks*DCTSIZE;
|
||||
ih=compptr->height_in_blocks*DCTSIZE;
|
||||
cw[i]=PAD(width, dinfo->max_h_samp_factor)*compptr->h_samp_factor
|
||||
/dinfo->max_h_samp_factor;
|
||||
ch[i]=PAD(height, dinfo->max_v_samp_factor)*compptr->v_samp_factor
|
||||
/dinfo->max_v_samp_factor;
|
||||
cw[i]=PAD(dinfo->image_width, dinfo->max_h_samp_factor)
|
||||
*compptr->h_samp_factor/dinfo->max_h_samp_factor;
|
||||
ch[i]=PAD(dinfo->image_height, dinfo->max_v_samp_factor)
|
||||
*compptr->v_samp_factor/dinfo->max_v_samp_factor;
|
||||
if(iw[i]!=cw[i] || ih!=ch[i]) usetmpbuf=1;
|
||||
th[i]=compptr->v_samp_factor*DCTSIZE;
|
||||
tmpbufsize+=iw[i]*th[i];
|
||||
|
@ -589,6 +627,14 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
|
|||
}
|
||||
|
||||
|
||||
DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle h,
|
||||
unsigned char *srcbuf, unsigned long size,
|
||||
unsigned char *dstbuf, int flags)
|
||||
{
|
||||
return tjDecompress(h, srcbuf, size, dstbuf, 1, 0, 1, 3, flags|TJ_YUV);
|
||||
}
|
||||
|
||||
|
||||
// General
|
||||
|
||||
DLLEXPORT char* DLLCALL tjGetErrorStr(void)
|
||||
|
|
Загрузка…
Ссылка в новой задаче