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

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

index 5a864eadd088abfef6fbbf900f7209d95b9aaccb..ea58bb4960f24682dbfa9267c504431b7f7650aa 100644 (file)
--- a/jpegut.c
+++ b/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();
        }
index a2c04b027b958279a71162562ce44c7e446374f6..11d679cf3c761cfbd3b49ba51988f0a05820f3ae 100644 (file)
--- a/jpgtest.c
+++ b/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.);
index aa033c93c93a4c0e0493593390d5125c488c4104..aa0b65824164505c9b180f885ed317e8c8d53297 100755 (executable)
@@ -16,5 +16,8 @@ TURBOJPEG_1.0
 TURBOJPEG_1.1
 {
        global:
+               TJBUFSIZEYUV;
                tjDecompressHeader2;
+               tjDecompressToYUV;
+               tjEncodeYUV;
 } TURBOJPEG_1.0;
index 47e5aa6c7fe359ffe0101948430094528ce23f93..24816d7ecd1c24cb0714da6492bdfa5b1168585e 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
@@ -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)
 
index 7dd6a41a796b73343b2644be4e3a7e7d45d26089..464cf04300b2f42fba455632ca20ff859ee3b604 100644 (file)
@@ -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)