From 073b0e88a192adebbb479ee2456beb089d8b5de7 Mon Sep 17 00:00:00 2001 From: DRC Date: Wed, 8 Nov 2017 21:01:57 -0600 Subject: [PATCH 01/12] djpeg -crop: Exit gracefully with non-PPM formats ... and document that only PPM/PGM output images are supported with the -crop option for the moment. I investigated the possibility of supporting -crop with -bmp, but even after resetting the buffer dimensions, I still kept getting virtual array access errors. It seems that doing this the "right way" would require creating a re-initialization function for each image format's destination manager. I'm disinclined to do that right now, given that this feature was Google's baby (developed as a prerequisite for including libjpeg-turbo in Android), and the -crop option in djpeg is intended only as an example of how to use the partial image decompression API. Real-world applications would need to handle this in their own destination managers. It would probably be possible to make this work with Targa by employing a similar hack to the one we used with PPM, but Targa isn't popular enough to bother. Fixes #185 --- ChangeLog.md | 4 ++++ djpeg.1 | 5 +++-- djpeg.c | 5 ++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 1f9473f2..8ecd04fb 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,6 +10,10 @@ image planes and allocates memory for the image planes. 2. Fixed an issue whereby the Java version of TJUnitTest would fail when testing BufferedImage encoding/decoding on big endian systems. +3. djpeg will now exit gracefully if an output image format other than PPM/PGM +is selected along with the `-crop` option. That option does not currently work +with other output image formats. + 1.5.2 ===== diff --git a/djpeg.1 b/djpeg.1 index b1e7f76e..b509af51 100644 --- a/djpeg.1 +++ b/djpeg.1 @@ -1,4 +1,4 @@ -.TH DJPEG 1 "18 March 2017" +.TH DJPEG 1 "8 November 2017" .SH NAME djpeg \- decompress a JPEG file to an image file .SH SYNOPSIS @@ -204,7 +204,8 @@ Decompress only a rectangular subregion of the image, starting at point X,Y with width W and height H. If necessary, X will be shifted left to the nearest iMCU boundary, and the width will be increased accordingly. Note that if decompression scaling is being used, then X, Y, W, and H are relative to the -scaled image dimensions. +scaled image dimensions. Currently this option only works with the +PBMPLUS (PPM/PGM) output format. .TP .B \-verbose Enable debug printout. More diff --git a/djpeg.c b/djpeg.c index 54cd525e..42a7f120 100644 --- a/djpeg.c +++ b/djpeg.c @@ -5,7 +5,7 @@ * Copyright (C) 1991-1997, Thomas G. Lane. * Modified 2013 by Guido Vollbeding. * libjpeg-turbo Modifications: - * Copyright (C) 2010-2011, 2013-2016, D. R. Commander. + * Copyright (C) 2010-2011, 2013-2017, D. R. Commander. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -173,6 +173,7 @@ usage (void) fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0 and Y1 (inclusive)\n"); fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of the image\n"); + fprintf(stderr, " [requires PBMPLUS (PPM/PGM) output format]\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, " -version Print version information and exit\n"); exit(EXIT_FAILURE); @@ -713,6 +714,8 @@ main (int argc, char **argv) } jpeg_crop_scanline(&cinfo, &crop_x, &crop_width); + if (requested_fmt != FMT_PPM) + ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); ((ppm_dest_ptr) dest_mgr)->buffer_width = cinfo.output_width * cinfo.out_color_components * sizeof(JSAMPLE); From 94e152b186c068e2571e98d207d1677c9fb2121c Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 13 Nov 2017 08:15:50 -0600 Subject: [PATCH 02/12] TurboJPEG C: Code formatting tweaks --- turbojpeg.c | 36 ++++++++++++------------------------ turbojpeg.h | 1 - 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/turbojpeg.c b/turbojpeg.c index c9bc6197..a8935995 100644 --- a/turbojpeg.c +++ b/turbojpeg.c @@ -790,8 +790,7 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, const unsigned char *srcBuf, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } cinfo->image_width=width; @@ -907,8 +906,7 @@ DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } cinfo->image_width=width; @@ -990,8 +988,7 @@ DLLEXPORT int DLLCALL tjEncodeYUVPlanes(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } for(row=0; rowmax_v_samp_factor) @@ -1108,8 +1105,7 @@ DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } cinfo->image_width=width; @@ -1171,8 +1167,7 @@ DLLEXPORT int DLLCALL tjCompressFromYUVPlanes(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } for(row=0; row<(int)cinfo->image_height; @@ -1404,8 +1399,7 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); @@ -1456,8 +1450,7 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } for(i=0; i<(int)dinfo->output_height; i++) { @@ -1589,8 +1582,7 @@ DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } if(pixelFormat==TJPF_CMYK) @@ -1684,8 +1676,7 @@ DLLEXPORT int DLLCALL tjDecodeYUVPlanes(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } for(row=0; rowmax_v_samp_factor) @@ -1789,8 +1780,7 @@ DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } if(!this->headerRead) @@ -1871,8 +1861,7 @@ DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } if(flags&TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling=FALSE; @@ -2060,8 +2049,7 @@ DLLEXPORT int DLLCALL tjTransform(tjhandle handle, if(setjmp(this->jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. */ - retval=-1; - goto bailout; + retval=-1; goto bailout; } jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize); diff --git a/turbojpeg.h b/turbojpeg.h index f60caf8a..410e98a8 100644 --- a/turbojpeg.h +++ b/turbojpeg.h @@ -275,7 +275,6 @@ static const int tjGreenOffset[TJ_NUMPF] = {1, 1, 1, 1, 2, 2, 0, 1, 1, 2, 2, -1} * then the blue component will be pixel[tjBlueOffset[TJ_BGRX]]. */ static const int tjBlueOffset[TJ_NUMPF] = {2, 0, 2, 0, 1, 3, 0, 2, 0, 1, 3, -1}; - /** * Pixel size (in bytes) for a given pixel format. */ From f3ad13e3d8d77eda682131d49004ff1fb1ebeeae Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 13 Nov 2017 16:00:35 -0600 Subject: [PATCH 03/12] TJBench/TJUnitTest: Don't ignore mistyped args --- ChangeLog.md | 4 +++ java/TJBench.java | 61 +++++++++++++++++++-------------------- java/TJUnitTest.java | 10 +++---- tjbench.c | 68 ++++++++++++++++++++++---------------------- tjunittest.c | 9 +++--- 5 files changed, 76 insertions(+), 76 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 8ecd04fb..10738b41 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -14,6 +14,10 @@ testing BufferedImage encoding/decoding on big endian systems. is selected along with the `-crop` option. That option does not currently work with other output image formats. +4. TJBench (both C and Java versions) will now display usage information if any +command-line argument is unrecognized. This prevents the program from silently +ignoring typos. + 1.5.2 ===== diff --git a/java/TJBench.java b/java/TJBench.java index 5185d658..ddc414c1 100644 --- a/java/TJBench.java +++ b/java/TJBench.java @@ -721,37 +721,37 @@ class TJBench { if (argv[i].equalsIgnoreCase("-tile")) { doTile = true; xformOpt |= TJTransform.OPT_CROP; } - if (argv[i].equalsIgnoreCase("-fastupsample")) { + else if (argv[i].equalsIgnoreCase("-fastupsample")) { System.out.println("Using fast upsampling code\n"); flags |= TJ.FLAG_FASTUPSAMPLE; } - if (argv[i].equalsIgnoreCase("-fastdct")) { + else if (argv[i].equalsIgnoreCase("-fastdct")) { System.out.println("Using fastest DCT/IDCT algorithm\n"); flags |= TJ.FLAG_FASTDCT; } - if (argv[i].equalsIgnoreCase("-accuratedct")) { + else if (argv[i].equalsIgnoreCase("-accuratedct")) { System.out.println("Using most accurate DCT/IDCT algorithm\n"); flags |= TJ.FLAG_ACCURATEDCT; } - if (argv[i].equalsIgnoreCase("-rgb")) + else if (argv[i].equalsIgnoreCase("-rgb")) pf = TJ.PF_RGB; - if (argv[i].equalsIgnoreCase("-rgbx")) + else if (argv[i].equalsIgnoreCase("-rgbx")) pf = TJ.PF_RGBX; - if (argv[i].equalsIgnoreCase("-bgr")) + else if (argv[i].equalsIgnoreCase("-bgr")) pf = TJ.PF_BGR; - if (argv[i].equalsIgnoreCase("-bgrx")) + else if (argv[i].equalsIgnoreCase("-bgrx")) pf = TJ.PF_BGRX; - if (argv[i].equalsIgnoreCase("-xbgr")) + else if (argv[i].equalsIgnoreCase("-xbgr")) pf = TJ.PF_XBGR; - if (argv[i].equalsIgnoreCase("-xrgb")) + else if (argv[i].equalsIgnoreCase("-xrgb")) pf = TJ.PF_XRGB; - if (argv[i].equalsIgnoreCase("-bottomup")) + else if (argv[i].equalsIgnoreCase("-bottomup")) flags |= TJ.FLAG_BOTTOMUP; - if (argv[i].equalsIgnoreCase("-quiet")) + else if (argv[i].equalsIgnoreCase("-quiet")) quiet = 1; - if (argv[i].equalsIgnoreCase("-qq")) + else if (argv[i].equalsIgnoreCase("-qq")) quiet = 2; - if (argv[i].equalsIgnoreCase("-scale") && i < argv.length - 1) { + else if (argv[i].equalsIgnoreCase("-scale") && i < argv.length - 1) { int temp1 = 0, temp2 = 0; boolean match = false, scanned = true; Scanner scanner = new Scanner(argv[++i]).useDelimiter("/"); @@ -774,25 +774,25 @@ class TJBench { } else usage(); } - if (argv[i].equalsIgnoreCase("-hflip")) + else if (argv[i].equalsIgnoreCase("-hflip")) xformOp = TJTransform.OP_HFLIP; - if (argv[i].equalsIgnoreCase("-vflip")) + else if (argv[i].equalsIgnoreCase("-vflip")) xformOp = TJTransform.OP_VFLIP; - if (argv[i].equalsIgnoreCase("-transpose")) + else if (argv[i].equalsIgnoreCase("-transpose")) xformOp = TJTransform.OP_TRANSPOSE; - if (argv[i].equalsIgnoreCase("-transverse")) + else if (argv[i].equalsIgnoreCase("-transverse")) xformOp = TJTransform.OP_TRANSVERSE; - if (argv[i].equalsIgnoreCase("-rot90")) + else if (argv[i].equalsIgnoreCase("-rot90")) xformOp = TJTransform.OP_ROT90; - if (argv[i].equalsIgnoreCase("-rot180")) + else if (argv[i].equalsIgnoreCase("-rot180")) xformOp = TJTransform.OP_ROT180; - if (argv[i].equalsIgnoreCase("-rot270")) + else if (argv[i].equalsIgnoreCase("-rot270")) xformOp = TJTransform.OP_ROT270; - if (argv[i].equalsIgnoreCase("-grayscale")) + else if (argv[i].equalsIgnoreCase("-grayscale")) xformOpt |= TJTransform.OPT_GRAY; - if (argv[i].equalsIgnoreCase("-nooutput")) + else if (argv[i].equalsIgnoreCase("-nooutput")) xformOpt |= TJTransform.OPT_NOOUTPUT; - if (argv[i].equalsIgnoreCase("-benchtime") && i < argv.length - 1) { + else if (argv[i].equalsIgnoreCase("-benchtime") && i < argv.length - 1) { double temp = -1; try { temp = Double.parseDouble(argv[++i]); @@ -802,11 +802,11 @@ class TJBench { else usage(); } - if (argv[i].equalsIgnoreCase("-yuv")) { + else if (argv[i].equalsIgnoreCase("-yuv")) { System.out.println("Testing YUV planar encoding/decoding\n"); doYUV = true; } - if (argv[i].equalsIgnoreCase("-yuvpad") && i < argv.length - 1) { + else if (argv[i].equalsIgnoreCase("-yuvpad") && i < argv.length - 1) { int temp = 0; try { temp = Integer.parseInt(argv[++i]); @@ -814,7 +814,7 @@ class TJBench { if (temp >= 1) yuvpad = temp; } - if (argv[i].equalsIgnoreCase("-subsamp") && i < argv.length - 1) { + else if (argv[i].equalsIgnoreCase("-subsamp") && i < argv.length - 1) { i++; if (argv[i].toUpperCase().startsWith("G")) subsamp = TJ.SAMP_GRAY; @@ -829,11 +829,11 @@ class TJBench { else if (argv[i].equals("411")) subsamp = TJ.SAMP_411; } - if (argv[i].equalsIgnoreCase("-componly")) + else if (argv[i].equalsIgnoreCase("-componly")) compOnly = true; - if (argv[i].equalsIgnoreCase("-nowrite")) + else if (argv[i].equalsIgnoreCase("-nowrite")) write = false; - if (argv[i].equalsIgnoreCase("-warmup") && i < argv.length - 1) { + else if (argv[i].equalsIgnoreCase("-warmup") && i < argv.length - 1) { double temp = -1; try { temp = Double.parseDouble(argv[++i]); @@ -844,8 +844,7 @@ class TJBench { } else usage(); } - if (argv[i].equalsIgnoreCase("-?")) - usage(); + else usage(); } } diff --git a/java/TJUnitTest.java b/java/TJUnitTest.java index 24be8ebf..47ff7bba 100644 --- a/java/TJUnitTest.java +++ b/java/TJUnitTest.java @@ -902,15 +902,13 @@ public class TJUnitTest { for (int i = 0; i < argv.length; i++) { if (argv[i].equalsIgnoreCase("-yuv")) doYUV = true; - if (argv[i].equalsIgnoreCase("-noyuvpad")) + else if (argv[i].equalsIgnoreCase("-noyuvpad")) pad = 1; - if (argv[i].substring(0, 1).equalsIgnoreCase("-h") || - argv[i].equalsIgnoreCase("-?")) - usage(); - if (argv[i].equalsIgnoreCase("-bi")) { + else if (argv[i].equalsIgnoreCase("-bi")) { bi = true; testName = "javabitest"; - } + } else + usage(); } if (doYUV) _4byteFormats[4] = -1; diff --git a/tjbench.c b/tjbench.c index 21b297c6..dfe66019 100644 --- a/tjbench.c +++ b/tjbench.c @@ -835,32 +835,32 @@ int main(int argc, char *argv[]) { dotile=1; xformopt|=TJXOPT_CROP; } - if(!strcasecmp(argv[i], "-fastupsample")) + else if(!strcasecmp(argv[i], "-fastupsample")) { printf("Using fast upsampling code\n\n"); flags|=TJFLAG_FASTUPSAMPLE; } - if(!strcasecmp(argv[i], "-fastdct")) + else if(!strcasecmp(argv[i], "-fastdct")) { printf("Using fastest DCT/IDCT algorithm\n\n"); flags|=TJFLAG_FASTDCT; } - if(!strcasecmp(argv[i], "-accuratedct")) + else if(!strcasecmp(argv[i], "-accuratedct")) { printf("Using most accurate DCT/IDCT algorithm\n\n"); flags|=TJFLAG_ACCURATEDCT; } - if(!strcasecmp(argv[i], "-rgb")) pf=TJPF_RGB; - if(!strcasecmp(argv[i], "-rgbx")) pf=TJPF_RGBX; - if(!strcasecmp(argv[i], "-bgr")) pf=TJPF_BGR; - if(!strcasecmp(argv[i], "-bgrx")) pf=TJPF_BGRX; - if(!strcasecmp(argv[i], "-xbgr")) pf=TJPF_XBGR; - if(!strcasecmp(argv[i], "-xrgb")) pf=TJPF_XRGB; - if(!strcasecmp(argv[i], "-cmyk")) pf=TJPF_CMYK; - if(!strcasecmp(argv[i], "-bottomup")) flags|=TJFLAG_BOTTOMUP; - if(!strcasecmp(argv[i], "-quiet")) quiet=1; - if(!strcasecmp(argv[i], "-qq")) quiet=2; - if(!strcasecmp(argv[i], "-scale") && i0.0) benchtime=temp; else usage(argv[0]); } - if(!strcasecmp(argv[i], "-warmup") && i=0.0) warmup=temp; else usage(argv[0]); printf("Warmup time = %.1f seconds\n\n", warmup); } - if(!strcmp(argv[i], "-?")) usage(argv[0]); - if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREALLOC); - if(!strcasecmp(argv[i], "-bmp")) ext="bmp"; - if(!strcasecmp(argv[i], "-yuv")) + else if(!strcasecmp(argv[i], "-alloc")) flags&=(~TJFLAG_NOREALLOC); + else if(!strcasecmp(argv[i], "-bmp")) ext="bmp"; + else if(!strcasecmp(argv[i], "-yuv")) { printf("Testing YUV planar encoding/decoding\n\n"); doyuv=1; } - if(!strcasecmp(argv[i], "-yuvpad") && i=1) yuvpad=temp; } - if(!strcasecmp(argv[i], "-subsamp") && i Date: Mon, 13 Nov 2017 21:01:53 -0600 Subject: [PATCH 04/12] Further partial image decompression fixes - Referring to 073b0e88a192adebbb479ee2456beb089d8b5de7 and #185, the reason why BMP and RLE didn't (and won't) work with partial image decompression is that the output engines for both formats maintain a whole-image buffer, which is used to reverse the order of scanlines. However, it was straightforward to add -crop support for GIF and Targa, which is useful for testing partial image decompression along with color quantization. - Such testing reproduced a bug reported by Mozilla (refer to PR #182) whereby jpeg_skip_scanlines() would segfault if color quantization was enabled. To fix this issue, read_and_discard_scanlines() now sets up a dummy quantize function in the same manner that it sets up a dummy color conversion function. Closes #182 --- ChangeLog.md | 13 ++++++++++--- cdjpeg.h | 12 ++++++++++-- djpeg.1 | 4 ++-- djpeg.c | 10 ++++------ jdapistd.c | 18 +++++++++++++++++- wrbmp.c | 3 ++- wrgif.c | 13 ++++++++++++- wrppm.c | 38 +++++++++++++++++++++++++++++++++----- wrppm.h | 26 -------------------------- wrrle.c | 5 +++-- wrtarga.c | 20 +++++++++++++++++--- 11 files changed, 110 insertions(+), 52 deletions(-) delete mode 100644 wrppm.h diff --git a/ChangeLog.md b/ChangeLog.md index 10738b41..61bd7296 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,9 +10,16 @@ image planes and allocates memory for the image planes. 2. Fixed an issue whereby the Java version of TJUnitTest would fail when testing BufferedImage encoding/decoding on big endian systems. -3. djpeg will now exit gracefully if an output image format other than PPM/PGM -is selected along with the `-crop` option. That option does not currently work -with other output image formats. +3. Fixed a segfault in djpeg that would occur if an output format other than +PPM/PGM was selected along with the `-crop` option. The `-crop` option now +works with the GIF and Targa formats as well (unfortunately, it cannot be made +to work with the BMP and RLE formats due to the fact that those output engines +write scanlines in bottom-up order.) djpeg will now exit gracefully if an +output format other than PPM/PGM, GIF, or Targa is selected along with the +`-crop` option. + +4. Fixed an issue whereby `jpeg_skip_scanlines()` would segfault if color +quantization was enabled. 4. TJBench (both C and Java versions) will now display usage information if any command-line argument is unrecognized. This prevents the program from silently diff --git a/cdjpeg.h b/cdjpeg.h index a65310e7..bb49fbfa 100644 --- a/cdjpeg.h +++ b/cdjpeg.h @@ -3,8 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1997, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code relevant - * to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2017, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -54,6 +54,14 @@ struct djpeg_dest_struct { JDIMENSION rows_supplied); /* Finish up at the end of the image. */ void (*finish_output) (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo); + /* Re-calculate buffer dimensions based on output dimensions (for use with + partial image decompression.) If this is NULL, then the output format + does not support partial image decompression (BMP and RLE, in particular, + cannot support partial decompression because they use an inversion buffer + to write the image in bottom-up order.) */ + void (*calc_buffer_dimensions) (j_decompress_ptr cinfo, + djpeg_dest_ptr dinfo); + /* Target file spec; filled in by djpeg.c after object is created. */ FILE *output_file; diff --git a/djpeg.1 b/djpeg.1 index b509af51..0a89927e 100644 --- a/djpeg.1 +++ b/djpeg.1 @@ -1,4 +1,4 @@ -.TH DJPEG 1 "8 November 2017" +.TH DJPEG 1 "13 November 2017" .SH NAME djpeg \- decompress a JPEG file to an image file .SH SYNOPSIS @@ -205,7 +205,7 @@ with width W and height H. If necessary, X will be shifted left to the nearest iMCU boundary, and the width will be increased accordingly. Note that if decompression scaling is being used, then X, Y, W, and H are relative to the scaled image dimensions. Currently this option only works with the -PBMPLUS (PPM/PGM) output format. +PBMPLUS (PPM/PGM), GIF, and Targa output formats. .TP .B \-verbose Enable debug printout. More diff --git a/djpeg.c b/djpeg.c index 42a7f120..96db4015 100644 --- a/djpeg.c +++ b/djpeg.c @@ -31,7 +31,6 @@ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "jversion.h" /* for version message */ #include "jconfigint.h" -#include "wrppm.h" #include /* to declare isprint() */ @@ -173,7 +172,7 @@ usage (void) fprintf(stderr, " -skip Y0,Y1 Decompress all rows except those between Y0 and Y1 (inclusive)\n"); fprintf(stderr, " -crop WxH+X+Y Decompress only a rectangular subregion of the image\n"); - fprintf(stderr, " [requires PBMPLUS (PPM/PGM) output format]\n"); + fprintf(stderr, " [requires PBMPLUS (PPM/PGM), GIF, or Targa output format]\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, " -version Print version information and exit\n"); exit(EXIT_FAILURE); @@ -714,11 +713,10 @@ main (int argc, char **argv) } jpeg_crop_scanline(&cinfo, &crop_x, &crop_width); - if (requested_fmt != FMT_PPM) + if (dest_mgr->calc_buffer_dimensions) + (*dest_mgr->calc_buffer_dimensions) (&cinfo, dest_mgr); + else ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); - ((ppm_dest_ptr) dest_mgr)->buffer_width = cinfo.output_width * - cinfo.out_color_components * - sizeof(JSAMPLE); /* Write output file header. This is a hack to ensure that the destination * manager creates an output image of the proper size. diff --git a/jdapistd.c b/jdapistd.c index 37afc844..6755dbb0 100644 --- a/jdapistd.c +++ b/jdapistd.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2010, 2015-2016, D. R. Commander. + * Copyright (C) 2010, 2015-2017, D. R. Commander. * Copyright (C) 2015, Google, Inc. * For conditions of distribution and use, see the accompanying README.ijg * file. @@ -293,6 +293,14 @@ noop_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, } +/* Dummy quantize function used by jpeg_skip_scanlines() */ +LOCAL(void) +noop_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) +{ +} + + /* * In some cases, it is best to call jpeg_read_scanlines() and discard the * output, rather than skipping the scanlines, because this allows us to @@ -308,14 +316,22 @@ read_and_discard_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) void (*color_convert) (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows); + void (*color_quantize) (j_decompress_ptr cinfo, JSAMPARRAY input_buf, + JSAMPARRAY output_buf, int num_rows) = NULL; color_convert = cinfo->cconvert->color_convert; cinfo->cconvert->color_convert = noop_convert; + if (cinfo->cquantize && cinfo->cquantize->color_quantize) { + color_quantize = cinfo->cquantize->color_quantize; + cinfo->cquantize->color_quantize = noop_quantize; + } for (n = 0; n < num_lines; n++) jpeg_read_scanlines(cinfo, NULL, 1); cinfo->cconvert->color_convert = color_convert; + if (color_quantize) + cinfo->cquantize->color_quantize = color_quantize; } diff --git a/wrbmp.c b/wrbmp.c index 50e469c9..94f52cac 100644 --- a/wrbmp.c +++ b/wrbmp.c @@ -5,7 +5,7 @@ * Copyright (C) 1994-1996, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright (C) 2013, Linaro Limited. - * Copyright (C) 2014-2015, D. R. Commander. + * Copyright (C) 2014-2015, 2017, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -437,6 +437,7 @@ jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2) sizeof(bmp_dest_struct)); dest->pub.start_output = start_output_bmp; dest->pub.finish_output = finish_output_bmp; + dest->pub.calc_buffer_dimensions = NULL; dest->is_os2 = is_os2; if (cinfo->out_color_space == JCS_GRAYSCALE) { diff --git a/wrgif.c b/wrgif.c index cc06f1d5..8d2050f1 100644 --- a/wrgif.c +++ b/wrgif.c @@ -4,7 +4,7 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1997, Thomas G. Lane. * libjpeg-turbo Modifications: - * Copyright (C) 2015, D. R. Commander. + * Copyright (C) 2015, 2017, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -355,6 +355,16 @@ finish_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) } +/* + * Re-calculate buffer dimensions based on output dimensions. + */ + +METHODDEF(void) +calc_buffer_dimensions_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ +} + + /* * The module selection routine for GIF format output. */ @@ -372,6 +382,7 @@ jinit_write_gif (j_decompress_ptr cinfo) dest->pub.start_output = start_output_gif; dest->pub.put_pixel_rows = put_pixel_rows; dest->pub.finish_output = finish_output_gif; + dest->pub.calc_buffer_dimensions = calc_buffer_dimensions_gif; if (cinfo->out_color_space != JCS_GRAYSCALE && cinfo->out_color_space != JCS_RGB) diff --git a/wrppm.c b/wrppm.c index 40fbf1fc..91cb10b3 100644 --- a/wrppm.c +++ b/wrppm.c @@ -4,8 +4,8 @@ * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. * Modified 2009 by Guido Vollbeding. - * It was modified by The libjpeg-turbo Project to include only code and - * information relevant to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2017, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -20,7 +20,6 @@ */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ -#include "wrppm.h" #ifdef PPM_SUPPORTED @@ -63,6 +62,21 @@ */ +/* Private version of data destination object */ + +typedef struct { + struct djpeg_dest_struct pub; /* public fields */ + + /* Usually these two pointers point to the same place: */ + char *iobuffer; /* fwrite's I/O buffer */ + JSAMPROW pixrow; /* decompressor output buffer */ + size_t buffer_width; /* width of I/O buffer */ + JDIMENSION samples_per_row; /* JSAMPLEs per output row */ +} ppm_dest_struct; + +typedef ppm_dest_struct *ppm_dest_ptr; + + /* * Write some pixel data. * In this module rows_supplied will always be 1. @@ -196,6 +210,20 @@ finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) } +/* + * Re-calculate buffer dimensions based on output dimensions. + */ + +METHODDEF(void) +calc_buffer_dimensions_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; + + dest->samples_per_row = cinfo->output_width * cinfo->out_color_components; + dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * sizeof(char)); +} + + /* * The module selection routine for PPM format output. */ @@ -211,13 +239,13 @@ jinit_write_ppm (j_decompress_ptr cinfo) sizeof(ppm_dest_struct)); dest->pub.start_output = start_output_ppm; dest->pub.finish_output = finish_output_ppm; + dest->pub.calc_buffer_dimensions = calc_buffer_dimensions_ppm; /* Calculate output image dimensions so we can allocate space */ jpeg_calc_output_dimensions(cinfo); /* Create physical I/O buffer */ - dest->samples_per_row = cinfo->output_width * cinfo->out_color_components; - dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * sizeof(char)); + dest->pub.calc_buffer_dimensions (cinfo, (djpeg_dest_ptr) dest); dest->iobuffer = (char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width); diff --git a/wrppm.h b/wrppm.h deleted file mode 100644 index aa6c5626..00000000 --- a/wrppm.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * wrppm.h - * - * This file was part of the Independent JPEG Group's software: - * Copyright (C) 1994, Thomas G. Lane. - * For conditions of distribution and use, see the accompanying README.ijg - * file. - */ - -#ifdef PPM_SUPPORTED - -/* Private version of data destination object */ - -typedef struct { - struct djpeg_dest_struct pub; /* public fields */ - - /* Usually these two pointers point to the same place: */ - char *iobuffer; /* fwrite's I/O buffer */ - JSAMPROW pixrow; /* decompressor output buffer */ - size_t buffer_width; /* width of I/O buffer */ - JDIMENSION samples_per_row; /* JSAMPLEs per output row */ -} ppm_dest_struct; - -typedef ppm_dest_struct *ppm_dest_ptr; - -#endif diff --git a/wrrle.c b/wrrle.c index cc95b413..880fadf9 100644 --- a/wrrle.c +++ b/wrrle.c @@ -3,8 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code and - * information relevant to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2017, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -286,6 +286,7 @@ jinit_write_rle (j_decompress_ptr cinfo) sizeof(rle_dest_struct)); dest->pub.start_output = start_output_rle; dest->pub.finish_output = finish_output_rle; + dest->pub.calc_buffer_dimensions = NULL; /* Calculate output image dimensions so we can allocate space */ jpeg_calc_output_dimensions(cinfo); diff --git a/wrtarga.c b/wrtarga.c index c02b3321..4db9313f 100644 --- a/wrtarga.c +++ b/wrtarga.c @@ -3,8 +3,8 @@ * * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. - * It was modified by The libjpeg-turbo Project to include only code and - * information relevant to libjpeg-turbo. + * libjpeg-turbo Modifications: + * Copyright (C) 2017, D. R. Commander. * For conditions of distribution and use, see the accompanying README.ijg * file. * @@ -211,6 +211,19 @@ finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) } +/* + * Re-calculate buffer dimensions based on output dimensions. + */ + +METHODDEF(void) +calc_buffer_dimensions_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) +{ + tga_dest_ptr dest = (tga_dest_ptr) dinfo; + + dest->buffer_width = cinfo->output_width * cinfo->output_components; +} + + /* * The module selection routine for Targa format output. */ @@ -226,12 +239,13 @@ jinit_write_targa (j_decompress_ptr cinfo) sizeof(tga_dest_struct)); dest->pub.start_output = start_output_tga; dest->pub.finish_output = finish_output_tga; + dest->pub.calc_buffer_dimensions = calc_buffer_dimensions_tga; /* Calculate output image dimensions so we can allocate space */ jpeg_calc_output_dimensions(cinfo); /* Create I/O buffer. */ - dest->buffer_width = cinfo->output_width * cinfo->output_components; + dest->pub.calc_buffer_dimensions (cinfo, (djpeg_dest_ptr) dest); dest->iobuffer = (char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) (dest->buffer_width * sizeof(char))); From f008876cc1c6f8c0a0ecc67d53b86285357b79d6 Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 13 Nov 2017 21:24:05 -0600 Subject: [PATCH 05/12] Build: Fix `make dist` Broken by previous commit --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index eb099ea5..2769b782 100644 --- a/Makefile.am +++ b/Makefile.am @@ -173,7 +173,7 @@ dist_example_DATA = example.c EXTRA_DIST = win release $(DOCS) testimages CMakeLists.txt \ sharedlib/CMakeLists.txt cmakescripts libjpeg.map.in doc doxygen.config \ doxygen-extra.css jccolext.c jdcolext.c jdcol565.c jdmrgext.c jdmrg565.c \ - jstdhuff.c jdcoefct.h jdmainct.h jdmaster.h jdsample.h wrppm.h \ + jstdhuff.c jdcoefct.h jdmainct.h jdmaster.h jdsample.h \ md5/CMakeLists.txt dist-hook: From 907dd683a4baeacd130f38aff3ff8f94010ee93f Mon Sep 17 00:00:00 2001 From: DRC Date: Mon, 13 Nov 2017 21:46:07 -0600 Subject: [PATCH 06/12] ChangeLog.md: buglet --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 61bd7296..e6565cd1 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -21,7 +21,7 @@ output format other than PPM/PGM, GIF, or Targa is selected along with the 4. Fixed an issue whereby `jpeg_skip_scanlines()` would segfault if color quantization was enabled. -4. TJBench (both C and Java versions) will now display usage information if any +5. TJBench (both C and Java versions) will now display usage information if any command-line argument is unrecognized. This prevents the program from silently ignoring typos. From 5fce2e942136cb70e5a30ff15a2d58b07947aa84 Mon Sep 17 00:00:00 2001 From: DRC Date: Tue, 14 Nov 2017 15:30:06 -0600 Subject: [PATCH 07/12] tjbench.exe: Fix decompression access violation The program crashed when a JPEG image was passed on the command line, because we were mixing our metaphors vis-a-vis malloc()/free() and tjAlloc()/tjFree() (malloc()/free() uses the tjbench.exe heap, whereas tjAlloc()/tjFree() uses the turbojpeg.dll heap.) --- ChangeLog.md | 3 +++ tjbench.c | 13 ++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index e6565cd1..7aa507e7 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -25,6 +25,9 @@ quantization was enabled. command-line argument is unrecognized. This prevents the program from silently ignoring typos. +6. Fixed an access violation in tjbench.exe (Windows) that occurred when the +program was used to decompress an existing JPEG image. + 1.5.2 ===== diff --git a/tjbench.c b/tjbench.c index dfe66019..76b61cdf 100644 --- a/tjbench.c +++ b/tjbench.c @@ -502,7 +502,7 @@ int decompTest(char *filename) char *temp=NULL, tempstr[80], tempstr2[80]; int row, col, i, iter, tilew, tileh, ntilesw=1, ntilesh=1, retval=0; double start, elapsed; - int ps=tjPixelSize[pf], tile; + int ps=tjPixelSize[pf], tile, decompsrc=0; if((file=fopen(filename, "rb"))==NULL) _throwunix("opening file"); @@ -682,18 +682,17 @@ int decompTest(char *filename) else { if(quiet==1) printf("N/A N/A "); - jpegsize[0]=srcsize; - free(jpegbuf[0]); - jpegbuf[0]=srcbuf; - srcbuf=NULL; + tjFree(jpegbuf[0]); + jpegbuf[0]=NULL; + decompsrc=1; } if(w==tilew) _tilew=_w; if(h==tileh) _tileh=_h; if(!(xformopt&TJXOPT_NOOUTPUT)) { - if(decomp(NULL, jpegbuf, jpegsize, NULL, _w, _h, _subsamp, 0, - filename, _tilew, _tileh)==-1) + if(decomp(NULL, decompsrc? &srcbuf:jpegbuf, decompsrc? &srcsize:jpegsize, + NULL, _w, _h, _subsamp, 0, filename, _tilew, _tileh)==-1) goto bailout; } else if(quiet==1) printf("N/A\n"); From 5abf2536f6f80a6b826788294669926b82ca870b Mon Sep 17 00:00:00 2001 From: DRC Date: Tue, 14 Nov 2017 16:12:13 -0600 Subject: [PATCH 08/12] Doc tweak: TJFLAG_ACCURATEDCT is the first flag --- doc/html/group___turbo_j_p_e_g.html | 22 +++++++++++----------- turbojpeg.h | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/doc/html/group___turbo_j_p_e_g.html b/doc/html/group___turbo_j_p_e_g.html index 8d7626db..89780d49 100644 --- a/doc/html/group___turbo_j_p_e_g.html +++ b/doc/html/group___turbo_j_p_e_g.html @@ -1014,7 +1014,7 @@ If you choose option 1, *jpegSize should be set to the size of your jpegSizepointer 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. jpegSubsampthe level of chrominance subsampling to be used when generating the JPEG image (see Chrominance subsampling options.) jpegQualthe image quality of the generated JPEG image (1 = worst, 100 = best) - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -1111,7 +1111,7 @@ If you choose option 1, *jpegSize should be set to the size of your 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. jpegSizepointer 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. jpegQualthe image quality of the generated JPEG image (1 = worst, 100 = best) - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -1208,7 +1208,7 @@ If you choose option 1, *jpegSize should be set to the size of your 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. jpegSizepointer 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. jpegQualthe image quality of the generated JPEG image (1 = worst, 100 = best) - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -1301,7 +1301,7 @@ If you choose option 1, *jpegSize should be set to the size of your pitchbytes per line in the destination image. Normally, this should be width * tjPixelSize[pixelFormat] if the destination image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the destination image should be padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use the pitch parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat]. heightheight (in pixels) of the source and destination images pixelFormatpixel format of the destination image (see Pixel formats.) - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -1394,7 +1394,7 @@ If you choose option 1, *jpegSize should be set to the size of your pitchbytes per line in the destination image. Normally, this should be width * tjPixelSize[pixelFormat] if the destination image is unpadded, or TJPAD(width * tjPixelSize[pixelFormat]) if each line of the destination image should be padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. You can also be clever and use the pitch parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to width * tjPixelSize[pixelFormat]. heightheight (in pixels) of the source and destination images pixelFormatpixel format of the destination image (see Pixel formats.) - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -1479,7 +1479,7 @@ If you choose option 1, *jpegSize should be set to the size of your pitchbytes per line in the destination image. Normally, this is scaledWidth * tjPixelSize[pixelFormat] if the decompressed image is unpadded, else TJPAD(scaledWidth * tjPixelSize[pixelFormat]) if each line of the decompressed image is padded to the nearest 32-bit boundary, as is the case for Windows bitmaps. (NOTE: scaledWidth can be determined by calling TJSCALED() with the JPEG image width and one of the scaling factors returned by tjGetScalingFactors().) You can also be clever and use the pitch parameter to skip lines, etc. Setting this parameter to 0 is the equivalent of setting it to scaledWidth * tjPixelSize[pixelFormat]. heightdesired height (in pixels) of the destination image. If this is different than the height of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired height. If height is set to 0, then only the width will be considered when determining the scaled image size. pixelFormatpixel format of the destination image (see Pixel formats.) - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -1629,7 +1629,7 @@ If you choose option 1, *jpegSize should be set to the size of your widthdesired width (in pixels) of the YUV image. If this is different than the width of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired width. If width is set to 0, then only the height will be considered when determining the scaled image size. If the scaled width is not an even multiple of the MCU block width (see tjMCUWidth), then an intermediate buffer copy will be performed within TurboJPEG. padthe width of each line in each plane of the YUV image will be padded to the nearest multiple of this number of bytes (must be a power of 2.) To generate images suitable for X Video, pad should be set to 4. heightdesired height (in pixels) of the YUV image. If this is different than the height of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired height. If height is set to 0, then only the width will be considered when determining the scaled image size. If the scaled height is not an even multiple of the MCU block height (see tjMCUHeight), then an intermediate buffer copy will be performed within TurboJPEG. - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -1708,7 +1708,7 @@ If you choose option 1, *jpegSize should be set to the size of your widthdesired width (in pixels) of the YUV image. If this is different than the width of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired width. If width is set to 0, then only the height will be considered when determining the scaled image size. If the scaled width is not an even multiple of the MCU block width (see tjMCUWidth), then an intermediate buffer copy will be performed within TurboJPEG. stridesan array of integers, each specifying the number of bytes per line in the corresponding plane of the output image. Setting the stride for any plane to 0 is the same as setting it to the scaled plane width (see YUV Image Format Notes.) If strides is NULL, then the strides for all planes will be set to their respective scaled plane widths. You can adjust the strides in order to add an arbitrary amount of line padding to each plane or to decompress the JPEG image into a subregion of a larger YUV planar image. heightdesired height (in pixels) of the YUV image. If this is different than the height of the JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG decompressor to generate the largest possible image that will fit within the desired height. If height is set to 0, then only the width will be considered when determining the scaled image size. If the scaled height is not an even multiple of the MCU block height (see tjMCUHeight), then an intermediate buffer copy will be performed within TurboJPEG. - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -1826,7 +1826,7 @@ If you choose option 1, *jpegSize should be set to the size of your dstBufpointer to an image buffer that will receive the YUV image. Use tjBufSizeYUV2() to determine the appropriate size for this buffer based on the image width, height, padding, and level of chrominance subsampling. The Y, U (Cb), and V (Cr) image planes will be stored sequentially in the buffer (refer to YUV Image Format Notes.) padthe width of each line in each plane of the YUV image will be padded to the nearest multiple of this number of bytes (must be a power of 2.) To generate images suitable for X Video, pad should be set to 4. subsampthe level of chrominance subsampling to be used when generating the YUV image (see Chrominance subsampling options.) To generate images suitable for X Video, subsamp should be set to TJSAMP_420. This produces an image compatible with the I420 (AKA "YUV420P") format. - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -1919,7 +1919,7 @@ If you choose option 1, *jpegSize should be set to the size of your dstPlanesan array of pointers to Y, U (Cb), and V (Cr) image planes (or just a Y plane, if generating a grayscale image) that will receive the encoded image. These planes can be contiguous or non-contiguous in memory. Use tjPlaneSizeYUV() to determine the appropriate size for each plane based on the image width, height, strides, and level of chrominance subsampling. Refer to YUV Image Format Notes for more details. stridesan array of integers, each specifying the number of bytes per line in the corresponding plane of the output image. Setting the stride for any plane to 0 is the same as setting it to the plane width (see YUV Image Format Notes.) If strides is NULL, then the strides for all planes will be set to their respective plane widths. You can adjust the strides in order to add an arbitrary amount of line padding to each plane or to encode an RGB or grayscale image into a subregion of a larger YUV planar image. subsampthe level of chrominance subsampling to be used when generating the YUV image (see Chrominance subsampling options.) To generate images suitable for X Video, subsamp should be set to TJSAMP_420. This produces an image compatible with the I420 (AKA "YUV420P") format. - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags @@ -2275,7 +2275,7 @@ If you choose option 1, *jpegSize should be set to the size of your If you choose option 1, dstSizes[i] should be set to the size of your pre-allocated buffer. In any case, unless you have set TJFLAG_NOREALLOC, you should always check dstBufs[i] upon return from this function, as it may have changed. dstSizespointer to an array of n unsigned long variables that will receive the actual sizes (in bytes) of each transformed JPEG image. If dstBufs[i] points to a pre-allocated buffer, then dstSizes[i] should be set to the size of the buffer. Upon return, dstSizes[i] will contain the size of the JPEG image (in bytes.) transformspointer to an array of n tjtransform structures, each of which specifies the transform parameters and/or cropping region for the corresponding transformed output image. - flagsthe bitwise OR of one or more of the flags + flagsthe bitwise OR of one or more of the flags diff --git a/turbojpeg.h b/turbojpeg.h index 410e98a8..307dc6f0 100644 --- a/turbojpeg.h +++ b/turbojpeg.h @@ -666,7 +666,7 @@ DLLEXPORT tjhandle DLLCALL tjInitCompress(void); * @param jpegQual the image quality of the generated JPEG image (1 = worst, * 100 = best) * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -730,7 +730,7 @@ DLLEXPORT int DLLCALL tjCompress2(tjhandle handle, const unsigned char *srcBuf, * @param jpegQual the image quality of the generated JPEG image (1 = worst, * 100 = best) * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -800,7 +800,7 @@ DLLEXPORT int DLLCALL tjCompressFromYUV(tjhandle handle, * @param jpegQual the image quality of the generated JPEG image (1 = worst, * 100 = best) * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -960,7 +960,7 @@ DLLEXPORT int tjPlaneHeight(int componentID, int height, int subsamp); * Video, subsamp should be set to @ref TJSAMP_420. This produces an * image compatible with the I420 (AKA "YUV420P") format. * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -1018,7 +1018,7 @@ DLLEXPORT int DLLCALL tjEncodeYUV3(tjhandle handle, * Video, subsamp should be set to @ref TJSAMP_420. This produces an * image compatible with the I420 (AKA "YUV420P") format. * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -1125,7 +1125,7 @@ DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors); * @param pixelFormat pixel format of the destination image (see @ref * TJPF "Pixel formats".) * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -1175,7 +1175,7 @@ DLLEXPORT int DLLCALL tjDecompress2(tjhandle handle, * block height (see #tjMCUHeight), then an intermediate buffer copy will be * performed within TurboJPEG. * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -1231,7 +1231,7 @@ DLLEXPORT int DLLCALL tjDecompressToYUV2(tjhandle handle, * block height (see #tjMCUHeight), then an intermediate buffer copy will be * performed within TurboJPEG. * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -1283,7 +1283,7 @@ DLLEXPORT int DLLCALL tjDecompressToYUVPlanes(tjhandle handle, * @param pixelFormat pixel format of the destination image (see @ref TJPF * "Pixel formats".) * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -1340,7 +1340,7 @@ DLLEXPORT int DLLCALL tjDecodeYUV(tjhandle handle, const unsigned char *srcBuf, * @param pixelFormat pixel format of the destination image (see @ref TJPF * "Pixel formats".) * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) @@ -1414,7 +1414,7 @@ DLLEXPORT tjhandle DLLCALL tjInitTransform(void); * which specifies the transform parameters and/or cropping region for the * corresponding transformed output image. * - * @param flags the bitwise OR of one or more of the @ref TJFLAG_BOTTOMUP + * @param flags the bitwise OR of one or more of the @ref TJFLAG_ACCURATEDCT * "flags" * * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr().) From 468f2fed2794c0b5fd9d3fe997e524916efa79df Mon Sep 17 00:00:00 2001 From: DRC Date: Wed, 15 Nov 2017 19:33:06 -0600 Subject: [PATCH 09/12] TJExample.java: Don't ignore mistyped args --- java/TJExample.java | 209 ++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 104 deletions(-) diff --git a/java/TJExample.java b/java/TJExample.java index da098078..97d3d758 100644 --- a/java/TJExample.java +++ b/java/TJExample.java @@ -1,5 +1,6 @@ /* - * Copyright (C)2011-2012, 2014-2015 D. R. Commander. All Rights Reserved. + * Copyright (C)2011-2012, 2014-2015, 2017 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: @@ -117,114 +118,114 @@ public class TJExample implements TJCustomFilter { int outSubsamp = -1, outQual = 95; boolean display = false; - if (argv.length > 1) { - for (int i = 1; i < argv.length; i++) { - if (argv[i].length() < 2) - continue; - if (argv[i].length() > 2 && - argv[i].substring(0, 3).equalsIgnoreCase("-sc")) { - int match = 0; - if (i < argv.length - 1) { - String[] scaleArg = argv[++i].split("/"); - if (scaleArg.length == 2) { - TJScalingFactor tempsf = - new TJScalingFactor(Integer.parseInt(scaleArg[0]), - Integer.parseInt(scaleArg[1])); - for (int j = 0; j < sf.length; j++) { - if (tempsf.equals(sf[j])) { - scaleFactor = sf[j]; - match = 1; - break; - } + if (argv[1].substring(0, 2).equalsIgnoreCase("-d")) + display = true; + + for (int i = 2; i < argv.length; i++) { + if (argv[i].length() < 2) + continue; + else if (argv[i].length() > 2 && + argv[i].substring(0, 3).equalsIgnoreCase("-sc")) { + int match = 0; + if (i < argv.length - 1) { + String[] scaleArg = argv[++i].split("/"); + if (scaleArg.length == 2) { + TJScalingFactor tempsf = + new TJScalingFactor(Integer.parseInt(scaleArg[0]), + Integer.parseInt(scaleArg[1])); + for (int j = 0; j < sf.length; j++) { + if (tempsf.equals(sf[j])) { + scaleFactor = sf[j]; + match = 1; + break; } } } - if (match != 1) usage(); - } - if (argv[i].equalsIgnoreCase("-h") || argv[i].equalsIgnoreCase("-?")) - usage(); - if (argv[i].length() > 2 && - argv[i].substring(0, 3).equalsIgnoreCase("-sa")) { - if (i < argv.length - 1) { - i++; - if (argv[i].substring(0, 1).equalsIgnoreCase("g")) - outSubsamp = TJ.SAMP_GRAY; - else if (argv[i].equals("444")) - outSubsamp = TJ.SAMP_444; - else if (argv[i].equals("422")) - outSubsamp = TJ.SAMP_422; - else if (argv[i].equals("420")) - outSubsamp = TJ.SAMP_420; - else - usage(); - } else - usage(); - } - if (argv[i].substring(0, 2).equalsIgnoreCase("-q")) { - if (i < argv.length - 1) { - int qual = Integer.parseInt(argv[++i]); - if (qual >= 1 && qual <= 100) - outQual = qual; - else - usage(); - } else - usage(); - } - if (argv[i].substring(0, 2).equalsIgnoreCase("-g")) - xform.options |= TJTransform.OPT_GRAY; - if (argv[i].equalsIgnoreCase("-hflip")) - xform.op = TJTransform.OP_HFLIP; - if (argv[i].equalsIgnoreCase("-vflip")) - xform.op = TJTransform.OP_VFLIP; - if (argv[i].equalsIgnoreCase("-transpose")) - xform.op = TJTransform.OP_TRANSPOSE; - if (argv[i].equalsIgnoreCase("-transverse")) - xform.op = TJTransform.OP_TRANSVERSE; - if (argv[i].equalsIgnoreCase("-rot90")) - xform.op = TJTransform.OP_ROT90; - if (argv[i].equalsIgnoreCase("-rot180")) - xform.op = TJTransform.OP_ROT180; - if (argv[i].equalsIgnoreCase("-rot270")) - xform.op = TJTransform.OP_ROT270; - if (argv[i].equalsIgnoreCase("-custom")) - xform.cf = new TJExample(); - else if (argv[i].length() > 2 && - argv[i].substring(0, 2).equalsIgnoreCase("-c")) { - if (i >= argv.length - 1) - usage(); - String[] cropArg = argv[++i].split(","); - if (cropArg.length != 3) - usage(); - String[] dimArg = cropArg[2].split("[xX]"); - if (dimArg.length != 2) - usage(); - int tempx = Integer.parseInt(cropArg[0]); - int tempy = Integer.parseInt(cropArg[1]); - int tempw = Integer.parseInt(dimArg[0]); - int temph = Integer.parseInt(dimArg[1]); - if (tempx < 0 || tempy < 0 || tempw < 0 || temph < 0) - usage(); - xform.x = tempx; - xform.y = tempy; - xform.width = tempw; - xform.height = temph; - xform.options |= TJTransform.OPT_CROP; - } - if (argv[i].substring(0, 2).equalsIgnoreCase("-d")) - display = true; - if (argv[i].equalsIgnoreCase("-fastupsample")) { - System.out.println("Using fast upsampling code"); - flags |= TJ.FLAG_FASTUPSAMPLE; - } - if (argv[i].equalsIgnoreCase("-fastdct")) { - System.out.println("Using fastest DCT/IDCT algorithm"); - flags |= TJ.FLAG_FASTDCT; - } - if (argv[i].equalsIgnoreCase("-accuratedct")) { - System.out.println("Using most accurate DCT/IDCT algorithm"); - flags |= TJ.FLAG_ACCURATEDCT; } + if (match != 1) usage(); } + else if (argv[i].length() > 2 && + argv[i].substring(0, 3).equalsIgnoreCase("-sa")) { + if (i < argv.length - 1) { + i++; + if (argv[i].substring(0, 1).equalsIgnoreCase("g")) + outSubsamp = TJ.SAMP_GRAY; + else if (argv[i].equals("444")) + outSubsamp = TJ.SAMP_444; + else if (argv[i].equals("422")) + outSubsamp = TJ.SAMP_422; + else if (argv[i].equals("420")) + outSubsamp = TJ.SAMP_420; + else + usage(); + } else + usage(); + } + else if (argv[i].substring(0, 2).equalsIgnoreCase("-q")) { + if (i < argv.length - 1) { + int qual = Integer.parseInt(argv[++i]); + if (qual >= 1 && qual <= 100) + outQual = qual; + else + usage(); + } else + usage(); + } + else if (argv[i].substring(0, 2).equalsIgnoreCase("-g")) + xform.options |= TJTransform.OPT_GRAY; + else if (argv[i].equalsIgnoreCase("-hflip")) + xform.op = TJTransform.OP_HFLIP; + else if (argv[i].equalsIgnoreCase("-vflip")) + xform.op = TJTransform.OP_VFLIP; + else if (argv[i].equalsIgnoreCase("-transpose")) + xform.op = TJTransform.OP_TRANSPOSE; + else if (argv[i].equalsIgnoreCase("-transverse")) + xform.op = TJTransform.OP_TRANSVERSE; + else if (argv[i].equalsIgnoreCase("-rot90")) + xform.op = TJTransform.OP_ROT90; + else if (argv[i].equalsIgnoreCase("-rot180")) + xform.op = TJTransform.OP_ROT180; + else if (argv[i].equalsIgnoreCase("-rot270")) + xform.op = TJTransform.OP_ROT270; + else if (argv[i].equalsIgnoreCase("-custom")) + xform.cf = new TJExample(); + else if (argv[i].length() > 2 && + argv[i].substring(0, 2).equalsIgnoreCase("-c")) { + if (i >= argv.length - 1) + usage(); + String[] cropArg = argv[++i].split(","); + if (cropArg.length != 3) + usage(); + String[] dimArg = cropArg[2].split("[xX]"); + if (dimArg.length != 2) + usage(); + int tempx = Integer.parseInt(cropArg[0]); + int tempy = Integer.parseInt(cropArg[1]); + int tempw = Integer.parseInt(dimArg[0]); + int temph = Integer.parseInt(dimArg[1]); + if (tempx < 0 || tempy < 0 || tempw < 0 || temph < 0) + usage(); + xform.x = tempx; + xform.y = tempy; + xform.width = tempw; + xform.height = temph; + xform.options |= TJTransform.OPT_CROP; + } + else if (argv[i].substring(0, 2).equalsIgnoreCase("-d")) + display = true; + else if (argv[i].equalsIgnoreCase("-fastupsample")) { + System.out.println("Using fast upsampling code"); + flags |= TJ.FLAG_FASTUPSAMPLE; + } + else if (argv[i].equalsIgnoreCase("-fastdct")) { + System.out.println("Using fastest DCT/IDCT algorithm"); + flags |= TJ.FLAG_FASTDCT; + } + else if (argv[i].equalsIgnoreCase("-accuratedct")) { + System.out.println("Using most accurate DCT/IDCT algorithm"); + flags |= TJ.FLAG_ACCURATEDCT; + } + else usage(); } String[] inFileTokens = argv[0].split("\\."); if (inFileTokens.length > 1) From 78e97e38cbf9f136e483bfcc406a166d23b9c5f5 Mon Sep 17 00:00:00 2001 From: DRC Date: Wed, 15 Nov 2017 19:39:45 -0600 Subject: [PATCH 10/12] Uniquify tjbenchtest log file names based on args + clean up log files when 'make testclean' is invoked + fix 'tjbenchtest -yuv -alloc' + fix tjexampletest so that it creates images under /tmp + clean up tjexampletest --- Makefile.am | 2 ++ tjbenchtest.in | 19 ++++++++++------- tjbenchtest.java.in | 4 ++-- tjexampletest.in | 52 ++++++++++++++++++++++----------------------- 4 files changed, 41 insertions(+), 36 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2769b782..8043f096 100644 --- a/Makefile.am +++ b/Makefile.am @@ -697,6 +697,8 @@ testclean: rm -f *_411_*.ppm rm -f *_411_*.jpg rm -f *_411.yuv + rm -f tjbenchtest*.log + rm -f tjexampletest*.log tjtest: diff --git a/tjbenchtest.in b/tjbenchtest.in index ef11b246..22e15db7 100755 --- a/tjbenchtest.in +++ b/tjbenchtest.in @@ -36,10 +36,9 @@ if [ -d $OUTDIR ]; then fi mkdir -p $OUTDIR -exec >$EXEDIR/tjbenchtest.log - -if [ $# -gt 0 ]; then - if [ "$1" = "-yuv" ]; then +while [ $# -gt 0 ]; do + case "$1" in + -yuv) NSARG=-nosmooth YUVARG=-yuv @@ -60,12 +59,16 @@ if [ $# -gt 0 ]; then # phenomenon is not yet fully understood but is also believed to be some sort # of round-off error.) IMAGES="vgl_6548_0026a.${EXT}" - fi - if [ "$1" = "-alloc" ]; then + ;; + -alloc) ALLOCARG=-alloc ALLOC=1 - fi -fi + ;; + esac + shift +done + +exec >$EXEDIR/tjbenchtest$YUVARG$ALLOCARG.log # Standard tests for image in $IMAGES; do diff --git a/tjbenchtest.java.in b/tjbenchtest.java.in index acdabd08..0fd2896f 100755 --- a/tjbenchtest.java.in +++ b/tjbenchtest.java.in @@ -33,8 +33,6 @@ if [ -d $OUTDIR ]; then fi mkdir -p $OUTDIR -exec >$EXEDIR/tjbenchtest-java.log - if [ $# -gt 0 ]; then if [ "$1" = "-yuv" ]; then NSARG=-nosmooth @@ -60,6 +58,8 @@ if [ $# -gt 0 ]; then fi fi +exec >$EXEDIR/tjbenchtest-java$YUVARG.log + # Standard tests for image in $IMAGES; do diff --git a/tjexampletest.in b/tjexampletest.in index 40b342ed..4cb9e9d9 100755 --- a/tjexampletest.in +++ b/tjexampletest.in @@ -21,7 +21,7 @@ runme() IMAGES="vgl_5674_0098.bmp vgl_6434_0018a.bmp vgl_6548_0026a.bmp nightshot_iso_100.bmp" IMGDIR=@srcdir@/testimages -OUTDIR=__tjexampletest_output +OUTDIR=`mktemp -d /tmp/__tjexampletest_output.XXXXXX` EXEDIR=. JAVA="@JAVA@ -cp java/turbojpeg.jar -Djava.library.path=.libs" @@ -36,23 +36,23 @@ for image in $IMAGES; do cp $IMGDIR/$image $OUTDIR basename=`basename $image .bmp` - $EXEDIR/cjpeg -quality 95 -dct fast -grayscale $IMGDIR/${basename}.bmp >$OUTDIR/${basename}_GRAY_fast_cjpeg.jpg - $EXEDIR/cjpeg -quality 95 -dct fast -sample 2x2 $IMGDIR/${basename}.bmp >$OUTDIR/${basename}_420_fast_cjpeg.jpg - $EXEDIR/cjpeg -quality 95 -dct fast -sample 2x1 $IMGDIR/${basename}.bmp >$OUTDIR/${basename}_422_fast_cjpeg.jpg - $EXEDIR/cjpeg -quality 95 -dct fast -sample 1x1 $IMGDIR/${basename}.bmp >$OUTDIR/${basename}_444_fast_cjpeg.jpg - $EXEDIR/cjpeg -quality 95 -dct int -grayscale $IMGDIR/${basename}.bmp >$OUTDIR/${basename}_GRAY_accurate_cjpeg.jpg - $EXEDIR/cjpeg -quality 95 -dct int -sample 2x2 $IMGDIR/${basename}.bmp >$OUTDIR/${basename}_420_accurate_cjpeg.jpg - $EXEDIR/cjpeg -quality 95 -dct int -sample 2x1 $IMGDIR/${basename}.bmp >$OUTDIR/${basename}_422_accurate_cjpeg.jpg - $EXEDIR/cjpeg -quality 95 -dct int -sample 1x1 $IMGDIR/${basename}.bmp >$OUTDIR/${basename}_444_accurate_cjpeg.jpg + runme $EXEDIR/cjpeg -quality 95 -dct fast -grayscale -outfile $OUTDIR/${basename}_GRAY_fast_cjpeg.jpg $IMGDIR/${basename}.bmp + runme $EXEDIR/cjpeg -quality 95 -dct fast -sample 2x2 -outfile $OUTDIR/${basename}_420_fast_cjpeg.jpg $IMGDIR/${basename}.bmp + runme $EXEDIR/cjpeg -quality 95 -dct fast -sample 2x1 -outfile $OUTDIR/${basename}_422_fast_cjpeg.jpg $IMGDIR/${basename}.bmp + runme $EXEDIR/cjpeg -quality 95 -dct fast -sample 1x1 -outfile $OUTDIR/${basename}_444_fast_cjpeg.jpg $IMGDIR/${basename}.bmp + runme $EXEDIR/cjpeg -quality 95 -dct int -grayscale -outfile $OUTDIR/${basename}_GRAY_accurate_cjpeg.jpg $IMGDIR/${basename}.bmp + runme $EXEDIR/cjpeg -quality 95 -dct int -sample 2x2 -outfile $OUTDIR/${basename}_420_accurate_cjpeg.jpg $IMGDIR/${basename}.bmp + runme $EXEDIR/cjpeg -quality 95 -dct int -sample 2x1 -outfile $OUTDIR/${basename}_422_accurate_cjpeg.jpg $IMGDIR/${basename}.bmp + runme $EXEDIR/cjpeg -quality 95 -dct int -sample 1x1 -outfile $OUTDIR/${basename}_444_accurate_cjpeg.jpg $IMGDIR/${basename}.bmp for samp in GRAY 420 422 444; do - $EXEDIR/djpeg -rgb -bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg >$OUTDIR/${basename}_${samp}_default_djpeg.bmp - $EXEDIR/djpeg -dct fast -rgb -bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg >$OUTDIR/${basename}_${samp}_fast_djpeg.bmp - $EXEDIR/djpeg -dct int -rgb -bmp $OUTDIR/${basename}_${samp}_accurate_cjpeg.jpg >$OUTDIR/${basename}_${samp}_accurate_djpeg.bmp + runme $EXEDIR/djpeg -rgb -bmp -outfile $OUTDIR/${basename}_${samp}_default_djpeg.bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg + runme $EXEDIR/djpeg -dct fast -rgb -bmp -outfile $OUTDIR/${basename}_${samp}_fast_djpeg.bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg + runme $EXEDIR/djpeg -dct int -rgb -bmp -outfile $OUTDIR/${basename}_${samp}_accurate_djpeg.bmp $OUTDIR/${basename}_${samp}_accurate_cjpeg.jpg done for samp in 420 422; do - $EXEDIR/djpeg -nosmooth -bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg >$OUTDIR/${basename}_${samp}_default_nosmooth_djpeg.bmp - $EXEDIR/djpeg -dct fast -nosmooth -bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg >$OUTDIR/${basename}_${samp}_fast_nosmooth_djpeg.bmp - $EXEDIR/djpeg -dct int -nosmooth -bmp $OUTDIR/${basename}_${samp}_accurate_cjpeg.jpg >$OUTDIR/${basename}_${samp}_accurate_nosmooth_djpeg.bmp + runme $EXEDIR/djpeg -nosmooth -bmp -outfile $OUTDIR/${basename}_${samp}_default_nosmooth_djpeg.bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg + runme $EXEDIR/djpeg -dct fast -nosmooth -bmp -outfile $OUTDIR/${basename}_${samp}_fast_nosmooth_djpeg.bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg + runme $EXEDIR/djpeg -dct int -nosmooth -bmp -outfile $OUTDIR/${basename}_${samp}_accurate_nosmooth_djpeg.bmp $OUTDIR/${basename}_${samp}_accurate_cjpeg.jpg done # Compression @@ -87,7 +87,7 @@ for image in $IMAGES; do for scale in 2_1 15_8 7_4 13_8 3_2 11_8 5_4 9_8 7_8 3_4 5_8 1_2 3_8 1_4 1_8; do scalearg=`echo $scale | sed s@_@/@g` for samp in GRAY 420 422 444; do - $EXEDIR/djpeg -rgb -bmp -scale ${scalearg} $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg >$OUTDIR/${basename}_${samp}_${scale}_djpeg.bmp + runme $EXEDIR/djpeg -rgb -bmp -scale ${scalearg} -outfile $OUTDIR/${basename}_${samp}_${scale}_djpeg.bmp $OUTDIR/${basename}_${samp}_fast_cjpeg.jpg runme $JAVA TJExample $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${scale}.bmp -scale ${scalearg} runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${scale}.bmp $OUTDIR/${basename}_${samp}_${scale}_djpeg.bmp rm $OUTDIR/${basename}_${samp}_${scale}.bmp @@ -96,25 +96,25 @@ for image in $IMAGES; do # Transforms for samp in GRAY 420 422 444; do - $EXEDIR/jpegtran -crop 70x60+16+16 -flip horizontal -trim $OUTDIR/${basename}_${samp}_fast.jpg >$OUTDIR/${basename}_${samp}_hflip_jpegtran.jpg - $EXEDIR/jpegtran -crop 70x60+16+16 -flip vertical -trim $OUTDIR/${basename}_${samp}_fast.jpg >$OUTDIR/${basename}_${samp}_vflip_jpegtran.jpg - $EXEDIR/jpegtran -crop 70x60+16+16 -transpose -trim $OUTDIR/${basename}_${samp}_fast.jpg >$OUTDIR/${basename}_${samp}_transpose_jpegtran.jpg - $EXEDIR/jpegtran -crop 70x60+16+16 -transverse -trim $OUTDIR/${basename}_${samp}_fast.jpg >$OUTDIR/${basename}_${samp}_transverse_jpegtran.jpg - $EXEDIR/jpegtran -crop 70x60+16+16 -rotate 90 -trim $OUTDIR/${basename}_${samp}_fast.jpg >$OUTDIR/${basename}_${samp}_rot90_jpegtran.jpg - $EXEDIR/jpegtran -crop 70x60+16+16 -rotate 180 -trim $OUTDIR/${basename}_${samp}_fast.jpg >$OUTDIR/${basename}_${samp}_rot180_jpegtran.jpg - $EXEDIR/jpegtran -crop 70x60+16+16 -rotate 270 -trim $OUTDIR/${basename}_${samp}_fast.jpg >$OUTDIR/${basename}_${samp}_rot270_jpegtran.jpg + runme $EXEDIR/jpegtran -crop 70x60+16+16 -flip horizontal -trim -outfile $OUTDIR/${basename}_${samp}_hflip_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg + runme $EXEDIR/jpegtran -crop 70x60+16+16 -flip vertical -trim -outfile $OUTDIR/${basename}_${samp}_vflip_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg + runme $EXEDIR/jpegtran -crop 70x60+16+16 -transpose -trim -outfile $OUTDIR/${basename}_${samp}_transpose_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg + runme $EXEDIR/jpegtran -crop 70x60+16+16 -transverse -trim -outfile $OUTDIR/${basename}_${samp}_transverse_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg + runme $EXEDIR/jpegtran -crop 70x60+16+16 -rotate 90 -trim -outfile $OUTDIR/${basename}_${samp}_rot90_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg + runme $EXEDIR/jpegtran -crop 70x60+16+16 -rotate 180 -trim -outfile $OUTDIR/${basename}_${samp}_rot180_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg + runme $EXEDIR/jpegtran -crop 70x60+16+16 -rotate 270 -trim -outfile $OUTDIR/${basename}_${samp}_rot270_jpegtran.jpg $OUTDIR/${basename}_${samp}_fast.jpg done for xform in hflip vflip transpose transverse rot90 rot180 rot270; do for samp in GRAY 420 422 444; do runme $JAVA TJExample $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}.jpg -$xform -crop 16,16,70x60 runme cmp $OUTDIR/${basename}_${samp}_${xform}.jpg $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg - $EXEDIR/djpeg -rgb -bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg >$OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp + runme $EXEDIR/djpeg -rgb -bmp -outfile $OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg runme $JAVA TJExample $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}.bmp -$xform -crop 16,16,70x60 runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${xform}.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp rm $OUTDIR/${basename}_${samp}_${xform}.bmp done for samp in 420 422; do - $EXEDIR/djpeg -nosmooth -rgb -bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg >$OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp + runme $EXEDIR/djpeg -nosmooth -rgb -bmp -outfile $OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg runme $JAVA TJExample $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}.bmp -$xform -crop 16,16,70x60 -fastupsample runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${xform}.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.bmp rm $OUTDIR/${basename}_${samp}_${xform}.bmp @@ -137,7 +137,7 @@ for image in $IMAGES; do for samp in GRAY 444 422 420; do for scale in 2_1 15_8 7_4 13_8 3_2 11_8 5_4 9_8 7_8 3_4 5_8 1_2 3_8 1_4 1_8; do scalearg=`echo $scale | sed s@_@/@g` - $EXEDIR/djpeg -rgb -bmp -scale ${scalearg} $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg >$OUTDIR/${basename}_${samp}_${xform}_${scale}_jpegtran.bmp + runme $EXEDIR/djpeg -rgb -bmp -scale ${scalearg} -outfile $OUTDIR/${basename}_${samp}_${xform}_${scale}_jpegtran.bmp $OUTDIR/${basename}_${samp}_${xform}_jpegtran.jpg runme $JAVA TJExample $OUTDIR/${basename}_${samp}_fast.jpg $OUTDIR/${basename}_${samp}_${xform}_${scale}.bmp -$xform -scale ${scalearg} -crop 16,16,70x60 runme cmp -i 54:54 $OUTDIR/${basename}_${samp}_${xform}_${scale}.bmp $OUTDIR/${basename}_${samp}_${xform}_${scale}_jpegtran.bmp rm $OUTDIR/${basename}_${samp}_${xform}_${scale}.bmp From 9d9d8fe658b21e57db783cf30f00cf8baa9c9d27 Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 17 Nov 2017 18:15:42 -0600 Subject: [PATCH 11/12] Code formatting tweaks --- jcdctmgr.c | 2 +- jcstest.c | 4 ++-- jdatadst-tj.c | 2 +- jdcolor.c | 2 +- jdmerge.c | 2 +- wrbmp.c | 6 +++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/jcdctmgr.c b/jcdctmgr.c index aef8517f..6e3b19bc 100644 --- a/jcdctmgr.c +++ b/jcdctmgr.c @@ -216,7 +216,7 @@ compute_reciprocal (UINT16 divisor, DCTELEM *dtbl) #endif dtbl[DCTSIZE2 * 3] = (DCTELEM) r - sizeof(DCTELEM)*8; /* shift */ - if(r <= 16) return 0; + if (r <= 16) return 0; else return 1; } diff --git a/jcstest.c b/jcstest.c index 358ed251..11883b59 100644 --- a/jcstest.c +++ b/jcstest.c @@ -77,7 +77,7 @@ int main(void) jerr.pub.error_exit = my_error_exit; jerr.pub.output_message = my_output_message; - if(setjmp(jerr.jb)) { + if (setjmp(jerr.jb)) { /* this will execute if libjpeg has an error */ jcs_valid = 0; goto done; @@ -104,7 +104,7 @@ int main(void) printf(" Not present at compile time\n"); #endif - if(setjmp(jerr.jb)) { + if (setjmp(jerr.jb)) { /* this will execute if libjpeg has an error */ jcs_alpha_valid = 0; goto done2; diff --git a/jdatadst-tj.c b/jdatadst-tj.c index c6144ecb..a2219dff 100644 --- a/jdatadst-tj.c +++ b/jdatadst-tj.c @@ -130,7 +130,7 @@ term_mem_destination (j_compress_ptr cinfo) { my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; - if(dest->alloc) *dest->outbuffer = dest->buffer; + if (dest->alloc) *dest->outbuffer = dest->buffer; *dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer); } diff --git a/jdcolor.c b/jdcolor.c index ab8fa249..05cbf4df 100644 --- a/jdcolor.c +++ b/jdcolor.c @@ -616,7 +616,7 @@ static const JLONG dither_matrix[4] = { static INLINE boolean is_big_endian(void) { int test_value = 1; - if(*(char *)&test_value != 1) + if (*(char *)&test_value != 1) return TRUE; return FALSE; } diff --git a/jdmerge.c b/jdmerge.c index 6276dd09..ca6f16c2 100644 --- a/jdmerge.c +++ b/jdmerge.c @@ -503,7 +503,7 @@ static const JLONG dither_matrix[4] = { static INLINE boolean is_big_endian(void) { int test_value = 1; - if(*(char *)&test_value != 1) + if (*(char *)&test_value != 1) return TRUE; return FALSE; } diff --git a/wrbmp.c b/wrbmp.c index 94f52cac..728bbadd 100644 --- a/wrbmp.c +++ b/wrbmp.c @@ -70,7 +70,7 @@ LOCAL(void) write_colormap static INLINE boolean is_big_endian(void) { int test_value = 1; - if(*(char *)&test_value != 1) + if (*(char *)&test_value != 1) return TRUE; return FALSE; } @@ -104,7 +104,7 @@ put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, inptr = dest->pub.buffer[0]; outptr = image_ptr[0]; - if(cinfo->out_color_space == JCS_RGB565) { + if (cinfo->out_color_space == JCS_RGB565) { boolean big_endian = is_big_endian(); unsigned short *inptr2 = (unsigned short *)inptr; for (col = cinfo->output_width; col > 0; col--) { @@ -447,7 +447,7 @@ jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2) dest->pub.put_pixel_rows = put_gray_rows; else dest->pub.put_pixel_rows = put_pixel_rows; - } else if(cinfo->out_color_space == JCS_RGB565 ) { + } else if (cinfo->out_color_space == JCS_RGB565) { dest->pub.put_pixel_rows = put_pixel_rows; } else { ERREXIT(cinfo, JERR_BMP_COLORSPACE); From 19b393b62422c97d97de4a5f2943d2cf4dc44120 Mon Sep 17 00:00:00 2001 From: DRC Date: Fri, 17 Nov 2017 18:45:08 -0600 Subject: [PATCH 12/12] TJExample: Fix array index OOB w/ 4:1:1 JPEG input --- ChangeLog.md | 4 ++++ java/TJExample.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 7aa507e7..d6299f11 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -28,6 +28,10 @@ ignoring typos. 6. Fixed an access violation in tjbench.exe (Windows) that occurred when the program was used to decompress an existing JPEG image. +7. Fixed an ArrayIndexOutOfBoundsException in the TJExample Java program that +occurred when attempting to decompress a JPEG image that had been compressed +with 4:1:1 chrominance subsampling. + 1.5.2 ===== diff --git a/java/TJExample.java b/java/TJExample.java index 97d3d758..835a5b97 100644 --- a/java/TJExample.java +++ b/java/TJExample.java @@ -95,7 +95,7 @@ public class TJExample implements TJCustomFilter { } private static final String[] sampName = { - "4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0" + "4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0", "4:1:1" }; public static void main(String[] argv) {