]> granicus.if.org Git - libjpeg-turbo/commitdiff
Replace the TJ_YUV flag with two new API functions
authorDRC <dcommander@users.sourceforge.net>
Fri, 25 Feb 2011 02:08:23 +0000 (02:08 +0000)
committerDRC <dcommander@users.sourceforge.net>
Fri, 25 Feb 2011 02:08:23 +0000 (02:08 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@448 632fc199-4ca6-4c93-a231-07263d6284db

jpegut.c
jpgtest.c
turbojpeg-mapfile
turbojpeg-mapfile.jni
turbojpeg.h
turbojpegl.c

index c974129e796a4d27126e92d9888f8af385f5592d..995d54424c5aa9126bced8ca2b3e8605de4aff93 100644 (file)
--- a/jpegut.c
+++ b/jpegut.c
@@ -229,8 +229,7 @@ int checkbuf(unsigned char *buf, int w, int h, int ps, int subsamp,
 
 #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];
@@ -238,13 +237,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++)
        {
@@ -353,8 +345,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";
@@ -378,11 +368,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)
@@ -394,7 +393,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.");
@@ -414,8 +413,7 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
        int temp1, temp2;
        unsigned long size=0;
 
-       if(yuv==YUVDECODE) flags|=TJ_YUV;
-       else if(yuv==YUVENCODE) return;
+       if(yuv==YUVENCODE) return;
 
        if(flags&TJ_BGR)
        {
@@ -452,25 +450,29 @@ void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
                printf("Scaled size mismatch\n");  bailout();
        }
 
-       if(yuv==YUVDECODE)
-               size=TJBUFSIZEYUV(w, h, subsamp);
-       else
-               size=scaledw*scaledh*ps;
-       if((bmpbuf=(unsigned char *)malloc(size+1))==NULL)
+       if(yuv==YUVDECODE) size=TJBUFSIZEYUV(w, h, subsamp);
+       else size=scaledw*scaledh*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, scaledw, 0, scaledh, ps,
-               flags));
+       if(yuv==YUVDECODE)
+       {
+               _catch(tjDecompressToYUV(hnd, jpegbuf, jpegsize, bmpbuf, flags));
+       }
+       else
+       {
+               _catch(tjDecompress(hnd, jpegbuf, jpegsize, bmpbuf, scaledw, 0, scaledh, ps,
+                       flags));
+       }
        t=rrtime()-t;
 
        if(yuv==YUVDECODE)
        {
-               if(checkbufyuv(bmpbuf, size, w, h, subsamp))
-                       printf("Passed.");
+               if(checkbufyuv(bmpbuf, w, h, subsamp)) printf("Passed.");
                else {printf("FAILED!");  exitstatus=-1;}
        }
        else
@@ -510,7 +512,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();
        }
index 1e79c306529e399d31eb8d2216cb44e168e8f29e..1af91c7680f029eafa20975c8ea76946e26f2fa2 100644 (file)
--- a/jpgtest.c
+++ b/jpgtest.c
@@ -44,8 +44,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,13 +76,9 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
        int i, j, ITER, rgbbufalloc=0;
        double start, elapsed;
        int ps=_ps[pf];
-       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);
-       int yuvsize=ypitch*ph + (jpegsub==TJ_GRAYSCALE? 0:uvpitch*ch*2);
-       int scaledw=(flags&TJ_YUV)? w : (w+scalefactor-1)/scalefactor;
-       int scaledh=(flags&TJ_YUV)? h : (h+scalefactor-1)/scalefactor;
+       int yuvsize=TJBUFSIZEYUV(w, h, jpegsub), bufsize;
+       int scaledw=(yuv==YUVDECODE)? w : (w+scalefactor-1)/scalefactor;
+       int scaledh=(yuv==YUVDECODE)? h : (h+scalefactor-1)/scalefactor;
        int pitch=scaledw*ps;
 
        if(qual>0)
@@ -95,21 +89,26 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
 
        flags |= _flags[pf];
        if(bu) flags |= TJ_BOTTOMUP;
-       if(yuv==YUVDECODE) flags |= TJ_YUV;
        if((hnd=tjInitDecompress())==NULL)
                _throwtj("executing tjInitDecompress()");
 
        if(rgbbuf==NULL)
        {
-               if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*scaledh))) == NULL)
+               bufsize=(yuv==YUVDECODE? yuvsize:pitch*h);
+               if((rgbbuf=(unsigned char *)malloc(bufsize)) == NULL)
                        _throwunix("allocating image buffer");
                rgbbufalloc=1;
        }
        // Grey image means decompressor did nothing
-       memset(rgbbuf, 127, max(yuvsize, pitch*scaledh));
+       memset(rgbbuf, 127, bufsize);
 
-       if(tjDecompress(hnd, jpegbuf[0], comptilesize[0], rgbbuf, scaledw, pitch,
-               scaledh, ps, flags)==-1)
+       if(yuv==YUVDECODE)
+       {
+               if(tjDecompressToYUV(hnd, jpegbuf[0], comptilesize[0], rgbbuf, flags)==-1)
+                       _throwtj("executing tjDecompressToYUV()");
+       }
+       else if(tjDecompress(hnd, jpegbuf[0], comptilesize[0], rgbbuf, scaledw,
+               pitch, scaledh, ps, flags)==-1)
                _throwtj("executing tjDecompress()");
        ITER=0;
        start=rrtime();
@@ -121,14 +120,20 @@ int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
                        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], scaledw, pitch, scaledh, ps, flags)==-1)
                                        _throwtj("executing tjDecompress()");
                                tilen++;
                        }
                }
                ITER++;
-       }       while((elapsed=rrtime()-start)<5.);
+       }       while((elapsed=rrtime()-start)<0.05);
        if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()");
        hnd=NULL;
        if(quiet)
@@ -221,17 +226,12 @@ void dotest(unsigned char *srcbuf, int w, int h, int jpegsub, int qual,
                |(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);
-       if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*h))) == NULL)
+       if(yuv==YUVENCODE) yuvsize=TJBUFSIZEYUV(w, h, jpegsub);
+       if((rgbbuf=(unsigned char *)malloc(max(yuvsize, pitch*h+1))) == NULL)
                _throwunix("allocating image buffer");
 
        if(!quiet)
@@ -258,7 +258,9 @@ void dotest(unsigned char *srcbuf, int w, int h, int jpegsub, int qual,
                memset(jpegbuf, 0, sizeof(unsigned char *)*numtilesx*numtilesy);
                for(i=0; i<numtilesx*numtilesy; i++)
                {
-                       if((jpegbuf[i]=(unsigned char *)malloc(TJBUFSIZE(tilesizex, tilesizey))) == NULL)
+                       if((jpegbuf[i]=(unsigned char *)malloc(
+                               yuv==YUVENCODE? TJBUFSIZEYUV(tilesizex, tilesizey, jpegsub)
+                                       : TJBUFSIZE(tilesizex, tilesizey))) == NULL)
                                _throwunix("allocating image buffers");
                }
 
@@ -268,7 +270,14 @@ void dotest(unsigned char *srcbuf, int w, int h, int jpegsub, int qual,
                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;
@@ -281,7 +290,14 @@ void dotest(unsigned char *srcbuf, int w, int h, int jpegsub, int qual,
                                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()");
@@ -290,7 +306,7 @@ void dotest(unsigned char *srcbuf, int w, int h, int jpegsub, int qual,
                                }
                        }
                        ITER++;
-               } while((elapsed=rrtime()-start)<5.);
+               } while((elapsed=rrtime()-start)<0.05);
                if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()");
                hnd=NULL;
                if(quiet==1)
index eb954717adb60840f11a14f5aa8206c202e5b2b7..0fcca9790effff21d59528f03e0b9a362471c2b2 100755 (executable)
@@ -19,4 +19,6 @@ TURBOJPEG_1.1
        global:
                TJBUFSIZEYUV;
                tjDecompressHeader2;
+               tjDecompressToYUV;
+               tjEncodeYUV;
 } TURBOJPEG_1.0;
index 6459bd6f5ab98ebb799cbc64c8dcab639f63369c..eead41bbb0be7888d3315400716d9208cb0dc057 100755 (executable)
@@ -19,6 +19,8 @@ TURBOJPEG_1.1
        global:
                TJBUFSIZEYUV;
                tjDecompressHeader2;
+               tjDecompressToYUV;
+               tjEncodeYUV;
 } TURBOJPEG_1.0;
 
 TURBOJPEG_1.2
index 5fa91f587f2c8539f498c492f8ad469a4213c1ad..adefd25ffa2248b49b9766bac86765464ab385a5 100644 (file)
@@ -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
@@ -178,6 +160,52 @@ 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)
 
@@ -185,7 +213,8 @@ DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(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
 */
@@ -281,9 +310,6 @@ DLLEXPORT int DLLCALL tjScaledSize(int input_width, int input_height,
   [INPUT] flags = the bitwise OR of one or more of the flags described in the
      "Flags" section above.
 
-  NOTE: The width, pitch, height, and pixelsize parameters are ignored if
-  decompressing to a YUV planar image.
-
   RETURNS: 0 on success, -1 on error
 */
 DLLEXPORT int DLLCALL tjDecompress(tjhandle j,
@@ -292,6 +318,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)
 
index 93f4b6a6008e46c6c6aab344c9c2a1f0e73a82ba..e621e2a3cd37343db4471eb430b79b5e771d6189 100644 (file)
@@ -112,6 +112,7 @@ DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
        return (tjhandle)j;
 }
 
+
 DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
 {
        unsigned long retval=0;
@@ -127,6 +128,7 @@ DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
        return retval;
 }
 
+
 DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
        int subsamp)
 {
@@ -143,6 +145,7 @@ DLLEXPORT unsigned long DLLCALL TJBUFSIZEYUV(int width, int height,
        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,
@@ -333,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)
@@ -512,24 +525,6 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
 
        jpeg_read_header(&j->dinfo, TRUE);
 
-       jpegwidth=j->dinfo.image_width;  jpegheight=j->dinfo.image_height;
-       if(width==0) width=jpegwidth;
-       if(height==0) height=jpegheight;
-       if(width<jpegwidth || height<jpegheight)
-       {
-               for(i=1; i<=8; i*=2)
-               {
-                       scaledw=(jpegwidth+i-1)/i;
-                       scaledh=(jpegheight+i-1)/i;
-                       if(scaledw<=width && scaledh<=height)
-                               break;
-               }
-               if(scaledw>width || scaledh>height)
-                       _throw("Could not scale down to desired image dimensions");
-               width=scaledw;  height=scaledh;
-               scale_denom=i;
-       }
-
        if(flags&TJ_YUV)
        {
                j_decompress_ptr dinfo=&j->dinfo;
@@ -549,7 +544,7 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
                        th[i]=compptr->v_samp_factor*DCTSIZE;
                        tmpbufsize+=iw[i]*th[i];
                        if((outbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*ch[i]))==NULL)
-                               _throw("Memory allocation failed in tjInitDecompress()");
+                               _throw("Memory allocation failed in tjDecompress()");
                        for(row=0; row<ch[i]; row++)
                        {
                                outbuf[i][row]=ptr;
@@ -559,13 +554,13 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
                if(usetmpbuf)
                {
                        if((_tmpbuf=(JSAMPLE *)malloc(sizeof(JSAMPLE)*tmpbufsize))==NULL)
-                               _throw("Memory allocation failed in tjInitDecompress()");
+                               _throw("Memory allocation failed in tjDecompress()");
                        ptr=_tmpbuf;
                        for(i=0; i<dinfo->num_components; i++)
                        {
                                jpeg_component_info *compptr=&dinfo->comp_info[i];
                                if((tmpbuf[i]=(JSAMPROW *)malloc(sizeof(JSAMPROW)*th[i]))==NULL)
-                                       _throw("Memory allocation failed in tjInitDecompress()");
+                                       _throw("Memory allocation failed in tjDecompress()");
                                for(row=0; row<th[i]; row++)
                                {
                                        tmpbuf[i][row]=ptr;
@@ -596,6 +591,23 @@ DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
        if(flags&TJ_YUV) j->dinfo.raw_data_out=TRUE;
        else
        {
+               jpegwidth=j->dinfo.image_width;  jpegheight=j->dinfo.image_height;
+               if(width==0) width=jpegwidth;
+               if(height==0) height=jpegheight;
+               if(width<jpegwidth || height<jpegheight)
+               {
+                       for(i=1; i<=8; i*=2)
+                       {
+                               scaledw=(jpegwidth+i-1)/i;
+                               scaledh=(jpegheight+i-1)/i;
+                               if(scaledw<=width && scaledh<=height)
+                                       break;
+                       }
+                       if(scaledw>width || scaledh>height)
+                               _throw("Could not scale down to desired image dimensions");
+                       width=scaledw;  height=scaledh;
+                       scale_denom=i;
+               }
                j->dinfo.scale_num=scale_num;
                j->dinfo.scale_denom=scale_denom;
        }
@@ -664,6 +676,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)