diff --git a/ChangeLog.txt b/ChangeLog.txt index 80253b52..2ca98395 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -56,6 +56,10 @@ omitted at compile time". [4] Fixed a couple of issues whereby malformed JPEG images would cause libjpeg-turbo to use uninitialized memory during decompression. +[5] Fixed an error ("Buffer passed to JPEG library is too small") that occurred +when calling the TurboJPEG YUV encoding function with a very small (< 5x5) +source image, and added a unit test to check for this error. + 1.3.0 ===== diff --git a/java/TJUnitTest.java b/java/TJUnitTest.java index 4d57f127..a6ee73eb 100644 --- a/java/TJUnitTest.java +++ b/java/TJUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C)2011-2013 D. R. Commander. All Rights Reserved. + * Copyright (C)2011-2014 D. R. Commander. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -945,7 +945,7 @@ public class TJUnitTest { private static void bufSizeTest() throws Exception { int w, h, i, subsamp; - byte[] srcBuf, jpegBuf; + byte[] srcBuf, dstBuf; TJCompressor tjc = null; Random r = new Random(); @@ -959,22 +959,35 @@ public class TJUnitTest { if (h % 100 == 0) System.out.format("%04d x %04d\b\b\b\b\b\b\b\b\b\b\b", w, h); srcBuf = new byte[w * h * 4]; - jpegBuf = new byte[TJ.bufSize(w, h, subsamp)]; + if (yuv == YUVENCODE) + dstBuf = new byte[TJ.bufSizeYUV(w, pad, h, subsamp)]; + else + dstBuf = new byte[TJ.bufSize(w, h, subsamp)]; for (i = 0; i < w * h * 4; i++) { srcBuf[i] = (byte)(r.nextInt(2) * 255); } tjc.setSourceImage(srcBuf, w, 0, h, TJ.PF_BGRX); tjc.setSubsamp(subsamp); tjc.setJPEGQuality(100); - tjc.compress(jpegBuf, 0); + tjc.setYUVPad(pad); + if (yuv == YUVENCODE) + tjc.encodeYUV(dstBuf, 0); + else + tjc.compress(dstBuf, 0); srcBuf = new byte[h * w * 4]; - jpegBuf = new byte[TJ.bufSize(h, w, subsamp)]; + if (yuv == YUVENCODE) + dstBuf = new byte[TJ.bufSizeYUV(h, pad, w, subsamp)]; + else + dstBuf = new byte[TJ.bufSize(h, w, subsamp)]; for (i = 0; i < h * w * 4; i++) { srcBuf[i] = (byte)(r.nextInt(2) * 255); } tjc.setSourceImage(srcBuf, h, 0, w, TJ.PF_BGRX); - tjc.compress(jpegBuf, 0); + if (yuv == YUVENCODE) + tjc.encodeYUV(dstBuf, 0); + else + tjc.compress(dstBuf, 0); } } } @@ -1033,9 +1046,10 @@ public class TJUnitTest { _4byteFormats[4] = -1; doTest(35, 39, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_GRAY, testName); - if (!doyuv && !bi) + if (!bi) bufSizeTest(); if (doyuv && !bi) { + System.out.print("\n--------------------\n\n"); yuv = YUVDECODE; doTest(48, 48, onlyRGB, TJ.SAMP_444, "javatest_yuv0"); doTest(35, 39, onlyRGB, TJ.SAMP_444, "javatest_yuv1"); diff --git a/tjunittest.c b/tjunittest.c index 519686fc..8204153d 100644 --- a/tjunittest.c +++ b/tjunittest.c @@ -1,5 +1,5 @@ /* - * Copyright (C)2009-2013 D. R. Commander. All Rights Reserved. + * Copyright (C)2009-2014 D. R. Commander. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -667,9 +667,9 @@ void doTest(int w, int h, const int *formats, int nformats, int subsamp, void bufSizeTest(void) { int w, h, i, subsamp; - unsigned char *srcBuf=NULL, *jpegBuf=NULL; + unsigned char *srcBuf=NULL, *dstBuf=NULL; tjhandle handle=NULL; - unsigned long jpegSize=0; + unsigned long dstSize=0; if((handle=tjInitCompress())==NULL) _throwtj(); @@ -684,12 +684,12 @@ void bufSizeTest(void) if(h%100==0) printf("%.4d x %.4d\b\b\b\b\b\b\b\b\b\b\b", w, h); if((srcBuf=(unsigned char *)malloc(w*h*4))==NULL) _throw("Memory allocation failure"); - if(!alloc) + if(!alloc || yuv==YUVENCODE) { - if((jpegBuf=(unsigned char *)tjAlloc(tjBufSize(w, h, subsamp))) - ==NULL) + if(yuv==YUVENCODE) dstSize=tjBufSizeYUV2(w, pad, h, subsamp); + else dstSize=tjBufSize(w, h, subsamp); + if((dstBuf=(unsigned char *)tjAlloc(dstSize))==NULL) _throw("Memory allocation failure"); - jpegSize=tjBufSize(w, h, subsamp); } for(i=0; iglobal_state!=CSTATE_START) + _throw("tjEncodeYUV3(): libjpeg API is in the wrong state"); + (*cinfo->err->reset_error_mgr)((j_common_ptr)cinfo); + (*cinfo->dest->init_destination)(cinfo); + jinit_c_master_control(cinfo, FALSE); + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE); + (*cinfo->mem->realize_virt_arrays)((j_common_ptr)cinfo); + pw=PAD(width, cinfo->max_h_samp_factor); ph=PAD(height, cinfo->max_v_samp_factor);