diff --git a/ChangeLog.txt b/ChangeLog.txt
index 6f39b0a2..c31a0075 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -106,6 +106,15 @@ test program specifically designed to make the bug occur (by injecting random
high-frequency YUV data into the compressor), it was reproducible only once in
about every 25 million iterations.
+[16] Fixed an oversight in the TurboJPEG C wrapper: if any of the JPEG
+compression functions was called repeatedly with the same
+automatically-allocated destination buffer, then TurboJPEG would erroneously
+assume that the jpegSize parameter was equal to the size of the buffer, when in
+fact that parameter was probably equal to the size of the most recently
+compressed JPEG image. If the size of the previous JPEG image was not as large
+as the current JPEG image, then TurboJPEG would unnecessarily reallocate the
+destination buffer.
+
1.3.1
=====
diff --git a/doc/html/group___turbo_j_p_e_g.html b/doc/html/group___turbo_j_p_e_g.html
index c7b19bf4..7188c7d6 100644
--- a/doc/html/group___turbo_j_p_e_g.html
+++ b/doc/html/group___turbo_j_p_e_g.html
@@ -1011,7 +1011,7 @@ Variables
pre-allocate the buffer to a "worst case" size determined by calling tjBufSize(). This should ensure that the buffer never has to be re-allocated (setting TJFLAG_NOREALLOC guarantees this.)
If you choose option 1, *jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed.
- | jpegSize | pointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.) |
+ | jpegSize | pointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.) If *jpegBuf points to a JPEG image buffer that is being reused from a previous call to one of the JPEG compression functions, then *jpegSize is ignored. |
| jpegSubsamp | the level of chrominance subsampling to be used when generating the JPEG image (see Chrominance subsampling options.) |
| jpegQual | the image quality of the generated JPEG image (1 = worst, 100 = best) |
| flags | the bitwise OR of one or more of the flags |
@@ -1109,7 +1109,7 @@ If you choose option 1, *jpegSize should be set to the size of your
pre-allocate the buffer to a "worst case" size determined by calling tjBufSize(). This should ensure that the buffer never has to be re-allocated (setting TJFLAG_NOREALLOC guarantees this.)
If you choose option 1, *jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed.
- | jpegSize | pointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.) |
+ | jpegSize | pointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.) If *jpegBuf points to a JPEG image buffer that is being reused from a previous call to one of the JPEG compression functions, then *jpegSize is ignored. |
| jpegQual | the image quality of the generated JPEG image (1 = worst, 100 = best) |
| flags | the bitwise OR of one or more of the flags |
@@ -1206,7 +1206,7 @@ If you choose option 1, *jpegSize should be set to the size of your
pre-allocate the buffer to a "worst case" size determined by calling tjBufSize(). This should ensure that the buffer never has to be re-allocated (setting TJFLAG_NOREALLOC guarantees this.)
If you choose option 1, *jpegSize should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check *jpegBuf upon return from this function, as it may have changed.
- | jpegSize | pointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.) |
+ | jpegSize | pointer to an unsigned long variable that holds the size of the JPEG image buffer. If *jpegBuf points to a pre-allocated buffer, then *jpegSize should be set to the size of the buffer. Upon return, *jpegSize will contain the size of the JPEG image (in bytes.) If *jpegBuf points to a JPEG image buffer that is being reused from a previous call to one of the JPEG compression functions, then *jpegSize is ignored. |
| jpegQual | the image quality of the generated JPEG image (1 = worst, 100 = best) |
| flags | the bitwise OR of one or more of the flags |
diff --git a/jdatadst-tj.c b/jdatadst-tj.c
index bc4a35dd..8289d3a4 100644
--- a/jdatadst-tj.c
+++ b/jdatadst-tj.c
@@ -5,7 +5,7 @@
* Copyright (C) 1994-1996, Thomas G. Lane.
* Modified 2009-2012 by Guido Vollbeding.
* libjpeg-turbo Modifications:
- * Copyright (C) 2011, D. R. Commander.
+ * Copyright (C) 2011, 2014 D. R. Commander.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains compression data destination routines for the case of
@@ -150,6 +150,7 @@ jpeg_mem_dest_tj (j_compress_ptr cinfo,
unsigned char ** outbuffer, unsigned long * outsize,
boolean alloc)
{
+ boolean reused = FALSE;
my_mem_dest_ptr dest;
if (outbuffer == NULL || outsize == NULL) /* sanity check */
@@ -164,12 +165,16 @@ jpeg_mem_dest_tj (j_compress_ptr cinfo,
sizeof(my_mem_destination_mgr));
dest = (my_mem_dest_ptr) cinfo->dest;
dest->newbuffer = NULL;
+ dest->outbuffer = NULL;
}
dest = (my_mem_dest_ptr) cinfo->dest;
dest->pub.init_destination = init_mem_destination;
dest->pub.empty_output_buffer = empty_mem_output_buffer;
dest->pub.term_destination = term_mem_destination;
+ if (dest->outbuffer && *(dest->outbuffer) == *outbuffer &&
+ *outbuffer != NULL && alloc)
+ reused = TRUE;
dest->outbuffer = outbuffer;
dest->outsize = outsize;
dest->alloc = alloc;
@@ -186,5 +191,7 @@ jpeg_mem_dest_tj (j_compress_ptr cinfo,
}
dest->pub.next_output_byte = dest->buffer = *outbuffer;
- dest->pub.free_in_buffer = dest->bufsize = *outsize;
+ if (!reused)
+ dest->bufsize = *outsize;
+ dest->pub.free_in_buffer = dest->bufsize;
}
diff --git a/tjunittest.c b/tjunittest.c
index dc84bbaa..9ac6626c 100644
--- a/tjunittest.c
+++ b/tjunittest.c
@@ -638,7 +638,10 @@ void bufSizeTest(void)
&dstSize, subsamp, 100, alloc? 0:TJFLAG_NOREALLOC));
}
free(srcBuf); srcBuf=NULL;
- tjFree(dstBuf); dstBuf=NULL;
+ if(!alloc)
+ {
+ tjFree(dstBuf); dstBuf=NULL;
+ }
if((srcBuf=(unsigned char *)malloc(h*w*4))==NULL)
_throw("Memory allocation failure");
@@ -667,7 +670,10 @@ void bufSizeTest(void)
&dstSize, subsamp, 100, alloc? 0:TJFLAG_NOREALLOC));
}
free(srcBuf); srcBuf=NULL;
- tjFree(dstBuf); dstBuf=NULL;
+ if(!alloc)
+ {
+ tjFree(dstBuf); dstBuf=NULL;
+ }
}
}
}
diff --git a/turbojpeg.h b/turbojpeg.h
index 2505100c..1ada65a2 100644
--- a/turbojpeg.h
+++ b/turbojpeg.h
@@ -656,7 +656,9 @@ DLLEXPORT tjhandle DLLCALL tjInitCompress(void);
* the JPEG image buffer. If *jpegBuf points to a pre-allocated
* buffer, then *jpegSize should be set to the size of the buffer.
* Upon return, *jpegSize will contain the size of the JPEG image (in
- * bytes.)
+ * bytes.) If *jpegBuf points to a JPEG image buffer that is being
+ * reused from a previous call to one of the JPEG compression functions, then
+ * *jpegSize is ignored.
*
* @param jpegSubsamp the level of chrominance subsampling to be used when
* generating the JPEG image (see @ref TJSAMP
@@ -722,7 +724,9 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, unsigned char *srcBuf,
* the JPEG image buffer. If *jpegBuf points to a pre-allocated
* buffer, then *jpegSize should be set to the size of the buffer.
* Upon return, *jpegSize will contain the size of the JPEG image (in
- * bytes.)
+ * bytes.) If *jpegBuf points to a JPEG image buffer that is being
+ * reused from a previous call to one of the JPEG compression functions, then
+ * *jpegSize is ignored.
*
* @param jpegQual the image quality of the generated JPEG image (1 = worst,
* 100 = best)
@@ -790,7 +794,9 @@ DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, unsigned char *srcBuf,
* the JPEG image buffer. If *jpegBuf points to a pre-allocated
* buffer, then *jpegSize should be set to the size of the buffer.
* Upon return, *jpegSize will contain the size of the JPEG image (in
- * bytes.)
+ * bytes.) If *jpegBuf points to a JPEG image buffer that is being
+ * reused from a previous call to one of the JPEG compression functions, then
+ * *jpegSize is ignored.
*
* @param jpegQual the image quality of the generated JPEG image (1 = worst,
* 100 = best)