diff options
author | Michael Johnson <ahze@FreeBSD.org> | 2007-03-08 14:20:03 +0000 |
---|---|---|
committer | Michael Johnson <ahze@FreeBSD.org> | 2007-03-08 14:20:03 +0000 |
commit | d2deeabc7ae3cf8adb075c50e490495b79d38aa2 (patch) | |
tree | 31da7da5903555d44578baa47b9bfe7c5c595baf /graphics | |
parent | c9fc7fc6e19501939e87f9acac7614817e386781 (diff) | |
download | ports-d2deeabc7ae3cf8adb075c50e490495b79d38aa2.tar.gz ports-d2deeabc7ae3cf8adb075c50e490495b79d38aa2.zip |
Notes
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/Makefile | 2 | ||||
-rw-r--r-- | graphics/gstreamer-plugins-jpeg-mmx80/Makefile | 18 | ||||
-rw-r--r-- | graphics/jpeg-mmx/Makefile | 72 | ||||
-rw-r--r-- | graphics/jpeg-mmx/distinfo | 3 | ||||
-rw-r--r-- | graphics/jpeg-mmx/files/patch-configure | 21 | ||||
-rw-r--r-- | graphics/jpeg-mmx/files/patch-djpeg.c | 20 | ||||
-rw-r--r-- | graphics/jpeg-mmx/files/patch-jerror.h | 30 | ||||
-rw-r--r-- | graphics/jpeg-mmx/files/patch-jpegtran.c | 400 | ||||
-rw-r--r-- | graphics/jpeg-mmx/files/patch-rdjpgcom.c | 218 | ||||
-rw-r--r-- | graphics/jpeg-mmx/files/patch-transupp.c | 1895 | ||||
-rw-r--r-- | graphics/jpeg-mmx/files/patch-transupp.h | 197 | ||||
-rw-r--r-- | graphics/jpeg-mmx/pkg-descr | 7 | ||||
-rw-r--r-- | graphics/lphoto/Makefile | 16 |
13 files changed, 1 insertions, 2898 deletions
diff --git a/graphics/Makefile b/graphics/Makefile index e1cb796461e8..8b89a0ef0b16 100644 --- a/graphics/Makefile +++ b/graphics/Makefile @@ -238,7 +238,6 @@ SUBDIR += gstreamer-plugins-gdkpixbuf80 SUBDIR += gstreamer-plugins-hermes80 SUBDIR += gstreamer-plugins-jpeg - SUBDIR += gstreamer-plugins-jpeg-mmx80 SUBDIR += gstreamer-plugins-jpeg80 SUBDIR += gstreamer-plugins-libcaca SUBDIR += gstreamer-plugins-libcaca80 @@ -299,7 +298,6 @@ SUBDIR += jp2a SUBDIR += jpatch SUBDIR += jpeg - SUBDIR += jpeg-mmx SUBDIR += jpeg2pdf SUBDIR += jpeg2ps-a4 SUBDIR += jpeg2ps-letter diff --git a/graphics/gstreamer-plugins-jpeg-mmx80/Makefile b/graphics/gstreamer-plugins-jpeg-mmx80/Makefile deleted file mode 100644 index cdfcde2b1b84..000000000000 --- a/graphics/gstreamer-plugins-jpeg-mmx80/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# New ports collection makefile for: gstreamer-plugins-jpeg-mmx -# Date created: 1 Nov 2004 -# Whom: Michael Johnson <ahze@FreeBSD.org> -# -# $FreeBSD$ -# $MCom: ports/graphics/gstreamer-plugins-jpeg-mmx80/Makefile,v 1.2 2006/02/24 18:50:33 marcus Exp $ -# - -PORTREVISION= 2 -CATEGORIES= graphics - -COMMENT= Gstreamer jpeg encoder/decoder plugin with mmx optimalizations - -GST_PLUGIN= jpeg-mmx - -MASTERDIR= ${.CURDIR}/../../multimedia/gstreamer-plugins80 - -.include "${MASTERDIR}/Makefile" diff --git a/graphics/jpeg-mmx/Makefile b/graphics/jpeg-mmx/Makefile deleted file mode 100644 index cecee582d488..000000000000 --- a/graphics/jpeg-mmx/Makefile +++ /dev/null @@ -1,72 +0,0 @@ -# New ports collection makefile for: jpeg -# Date created: 6 November 1994 -# Whom: smace -# -# $FreeBSD$ -# - -PORTNAME= jpeg-mmx -PORTVERSION= 0.1.6 -CATEGORIES= graphics -MASTER_SITES= ${MASTER_SITE_SOURCEFORGE} -MASTER_SITE_SUBDIR= mjpeg - -MAINTAINER= multimedia@FreeBSD.org -COMMENT= IJG's jpeg compression utilities with MMX optimization - -BUILD_DEPENDS= nasm:${PORTSDIR}/devel/nasm -RUN_DEPENDS= cjpeg:${PORTSDIR}/graphics/jpeg - -ONLY_FOR_ARCHS= i386 - -DEPRECATED= This port has outlived its usefulness -EXPIRATION_DATE=2007-02-28 - -WRKSRC= ${WRKDIR}/jpeg-mmx -USE_AUTOTOOLS= libtool:15 -USE_GMAKE= yes -INSTALLS_SHLIB= yes -CONFIGURE_ARGS= --enable-shared --enable-static -USE_GCC= 3.4+ - -JPEG_EXT= -mmx -INCDIR= include/${PORTNAME} - -BIN_FILES= cjpeg djpeg jpegtran -INC_FILES= jconfig.h jerror.h jinclude.h jmorecfg.h jpegint.h jpeglib.h -LIB_FILES= libjpeg-mmx.a libjpeg-mmx.so libjpeg-mmx.so.62 - -PORTDOCS= README coderules.doc filelist.doc install.doc jconfig.doc \ - libjpeg.doc structure.doc usage.doc wizard.doc -PLIST_DIRS= include/jpeg-mmx -PLIST_FILES= ${BIN_FILES:S|^|bin/|:S|$|${JPEG_EXT}|} \ - ${INC_FILES:S|^|${INCDIR}/|} \ - ${LIB_FILES:S|^|lib/|} - -# define J_MAXMEM like "make J_MAXMEM=32" to limit max processing memory to 32Mb -.if defined(J_MAXMEM) -CONFIGURE_ARGS+= --enable-maxmem=${J_MAXMEM} -.endif - -post-patch: - @${REINPLACE_CMD} -e 's|./libtool|${LIBTOOL} --tag=CXX|' \ - ${WRKSRC}/configure - -do-install: -.for f in ${BIN_FILES} - @${INSTALL_PROGRAM} ${WRKSRC}/.libs/${f} ${PREFIX}/bin/${f}${JPEG_EXT} -.endfor - @${MKDIR} ${PREFIX}/${INCDIR} -.for f in ${INC_FILES} - @${INSTALL_DATA} ${WRKSRC}/${f} ${PREFIX}/${INCDIR} -.endfor -.for f in ${LIB_FILES} - @${INSTALL_DATA} ${WRKSRC}/.libs/${f} ${PREFIX}/lib/ -.endfor -.if !defined(NOPORTDOCS) - @${MKDIR} ${DOCSDIR} - @${INSTALL_DATA} ${WRKSRC}/README ${DOCSDIR} - @${INSTALL_DATA} ${WRKSRC}/*.doc ${DOCSDIR} -.endif - -.include <bsd.port.mk> diff --git a/graphics/jpeg-mmx/distinfo b/graphics/jpeg-mmx/distinfo deleted file mode 100644 index 3423005287ac..000000000000 --- a/graphics/jpeg-mmx/distinfo +++ /dev/null @@ -1,3 +0,0 @@ -MD5 (jpeg-mmx-0.1.6.tar.gz) = 9156c429bd8c4dea65c877c50ed89e15 -SHA256 (jpeg-mmx-0.1.6.tar.gz) = 196d71593f7dc06adc047297c614b40060c7083d2ab692c5c9ad7ddd2970bf44 -SIZE (jpeg-mmx-0.1.6.tar.gz) = 597439 diff --git a/graphics/jpeg-mmx/files/patch-configure b/graphics/jpeg-mmx/files/patch-configure deleted file mode 100644 index 69f94b1585a0..000000000000 --- a/graphics/jpeg-mmx/files/patch-configure +++ /dev/null @@ -1,21 +0,0 @@ ---- configure.orig Tue Feb 3 16:49:23 2004 -+++ configure Fri Jul 30 04:20:34 2004 -@@ -1530,7 +1530,7 @@ - if test "x$LTSHARED" != xno -o "x$LTSTATIC" != xno; then - USELIBTOOL="yes" - LIBTOOL="./libtool" -- O="lo" -+ O="o" - A="la" - LN='$(LIBTOOL) --mode=link $(CC)' - INSTALL_LIB='$(LIBTOOL) --mode=install ${INSTALL}' -@@ -1559,7 +1559,8 @@ - if test "x$LTSTATIC" = xno; then - disable_static="--disable-static" - fi -- $srcdir/ltconfig $disable_shared $disable_static $srcdir/ltmain.sh -+ pic_flag="-fPIC" -+ $ac_aux_dir/ltconfig $disable_shared $disable_static $ac_aux_dir/ltmain.sh - fi - - # Select memory manager depending on user input. diff --git a/graphics/jpeg-mmx/files/patch-djpeg.c b/graphics/jpeg-mmx/files/patch-djpeg.c deleted file mode 100644 index 224fefe2e850..000000000000 --- a/graphics/jpeg-mmx/files/patch-djpeg.c +++ /dev/null @@ -1,20 +0,0 @@ ---- djpeg.c.orig Sat Oct 11 18:29:07 1997 -+++ djpeg.c Mon Apr 24 16:04:13 2000 -@@ -26,6 +26,7 @@ - #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ - #include "jversion.h" /* for version message */ - -+#include <locale.h> /* to declare setlocal() */ - #include <ctype.h> /* to declare isprint() */ - - #ifdef USE_CCOMMAND /* command-line reader for Macintosh */ -@@ -385,6 +386,9 @@ - cinfo->unread_marker - JPEG_APP0, (long) length); - } - -+ if (traceit) { -+ setlocale(LC_ALL, ""); -+ } - while (--length >= 0) { - ch = jpeg_getc(cinfo); - if (traceit) { diff --git a/graphics/jpeg-mmx/files/patch-jerror.h b/graphics/jpeg-mmx/files/patch-jerror.h deleted file mode 100644 index ae1d6434ce24..000000000000 --- a/graphics/jpeg-mmx/files/patch-jerror.h +++ /dev/null @@ -1,30 +0,0 @@ ---- jerror.h.orig Sat Oct 18 14:59:10 1997 -+++ jerror.h Fri Jun 4 15:20:23 2004 -@@ -45,8 +45,11 @@ - JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") - JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") - JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") -+JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") - JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") - JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") -+JMESSAGE(JERR_BAD_DROP_SAMPLING, -+ "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") - JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") - JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") - JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") -@@ -226,6 +229,15 @@ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (cinfo)->err->msg_parm.i[3] = (p4), \ -+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -+#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ -+ ((cinfo)->err->msg_code = (code), \ -+ (cinfo)->err->msg_parm.i[0] = (p1), \ -+ (cinfo)->err->msg_parm.i[1] = (p2), \ -+ (cinfo)->err->msg_parm.i[2] = (p3), \ -+ (cinfo)->err->msg_parm.i[3] = (p4), \ -+ (cinfo)->err->msg_parm.i[4] = (p5), \ -+ (cinfo)->err->msg_parm.i[5] = (p6), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) - #define ERREXITS(cinfo,code,str) \ - ((cinfo)->err->msg_code = (code), \ diff --git a/graphics/jpeg-mmx/files/patch-jpegtran.c b/graphics/jpeg-mmx/files/patch-jpegtran.c deleted file mode 100644 index 34e4539d7a94..000000000000 --- a/graphics/jpeg-mmx/files/patch-jpegtran.c +++ /dev/null @@ -1,400 +0,0 @@ ---- jpegtran.c.orig Wed Jul 23 22:37:26 1997 -+++ jpegtran.c Fri Jun 4 14:47:24 2004 -@@ -1,7 +1,7 @@ - /* - * jpegtran.c - * -- * Copyright (C) 1995-1997, Thomas G. Lane. -+ * Copyright (C) 1995-2001, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * -@@ -37,6 +37,7 @@ - - static const char * progname; /* program name for error messages */ - static char * outfilename; /* for -outfile switch */ -+static char * dropfilename; /* for -drop switch */ - static JCOPY_OPTION copyoption; /* -copy switch */ - static jpeg_transform_info transformoption; /* image transformation options */ - -@@ -56,6 +57,7 @@ - fprintf(stderr, " -copy none Copy no extra markers from source file\n"); - fprintf(stderr, " -copy comments Copy only comment markers (default)\n"); - fprintf(stderr, " -copy all Copy all extra markers\n"); -+ fprintf(stderr, " -copy exif Copy EXIF marker and omit JFIF if EXIF\n"); - #ifdef ENTROPY_OPT_SUPPORTED - fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); - #endif -@@ -64,12 +66,16 @@ - #endif - #if TRANSFORMS_SUPPORTED - fprintf(stderr, "Switches for modifying the image:\n"); -+ fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular subarea\n"); -+ fprintf(stderr, " -drop +X+Y filename Drop another image\n"); - fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n"); - fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n"); -+ fprintf(stderr, " -perfect Fail if there is non-transformable edge blocks\n"); - fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n"); - fprintf(stderr, " -transpose Transpose image\n"); - fprintf(stderr, " -transverse Transverse transpose image\n"); -- fprintf(stderr, " -trim Drop non-transformable edge blocks\n"); -+ fprintf(stderr, " -trim Drop non-transformable edge blocks or\n"); -+ fprintf(stderr, " with -drop: Requantize drop file to source file\n"); - #endif /* TRANSFORMS_SUPPORTED */ - fprintf(stderr, "Switches for advanced users:\n"); - fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); -@@ -109,6 +115,50 @@ - #endif - } - -+LOCAL(void) -+handle_exif (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JCOPY_OPTION *copyoption) -+/* Adjust the marker writing options to create an EXIF file, instead of JFIF, -+ * if so requested or an EXIF file is detected as input. Must be called after -+ * jpeg_copy_critical_parameters() as that sets the defaults. */ -+{ -+ jpeg_saved_marker_ptr cur_marker, prev_marker; -+ -+ /* Look for an exif marker */ -+ prev_marker = NULL; -+ cur_marker = srcinfo->marker_list; -+ while (cur_marker != NULL) { -+ if (cur_marker->marker == JPEG_APP0+1 && -+ cur_marker->data_length >= 6 && -+ GETJOCTET(cur_marker->data[0]) == 0x45 && -+ GETJOCTET(cur_marker->data[1]) == 0x78 && -+ GETJOCTET(cur_marker->data[2]) == 0x69 && -+ GETJOCTET(cur_marker->data[3]) == 0x66 && -+ GETJOCTET(cur_marker->data[4]) == 0 && -+ GETJOCTET(cur_marker->data[5]) == 0) -+ break; /* found an EXIF marker */ -+ prev_marker = cur_marker; -+ cur_marker = cur_marker->next; -+ } -+ /* If we've found an EXIF marker but not JFIF this is an EXIF file. Unless -+ * explicitely requested, make sure we keep the EXIF marker and do not -+ * emit a JFIF marker (which would come before). EXIF requires that the -+ * first marker be EXIF. */ -+ if (cur_marker != NULL && -+ ((*copyoption != JCOPYOPT_NONE && !srcinfo->saw_JFIF_marker) || -+ (*copyoption == JCOPYOPT_EXIF))) { -+ dstinfo->write_JFIF_header = FALSE; -+ if (*copyoption == JCOPYOPT_COMMENTS) -+ *copyoption = JCOPYOPT_EXIF; -+ } -+ /* If making an EXIF file, make sure that EXIF is first marker */ -+ if (cur_marker != NULL && prev_marker != NULL && -+ *copyoption == JCOPYOPT_EXIF) { -+ prev_marker->next = cur_marker->next; -+ cur_marker->next = srcinfo->marker_list; -+ srcinfo->marker_list = cur_marker; -+ } -+} - - LOCAL(int) - parse_switches (j_compress_ptr cinfo, int argc, char **argv, -@@ -130,10 +180,13 @@ - /* Set up default JPEG parameters. */ - simple_progressive = FALSE; - outfilename = NULL; -+ dropfilename = NULL; - copyoption = JCOPYOPT_DEFAULT; - transformoption.transform = JXFORM_NONE; - transformoption.trim = FALSE; -+ transformoption.perfect = FALSE; - transformoption.force_grayscale = FALSE; -+ transformoption.crop = FALSE; - cinfo->err->trace_level = 0; - - /* Scan command line options, adjust parameters */ -@@ -160,7 +213,7 @@ - exit(EXIT_FAILURE); - #endif - -- } else if (keymatch(arg, "copy", 1)) { -+ } else if (keymatch(arg, "copy", 2)) { - /* Select which extra markers to copy. */ - if (++argn >= argc) /* advance to next argument */ - usage(); -@@ -170,9 +223,47 @@ - copyoption = JCOPYOPT_COMMENTS; - } else if (keymatch(argv[argn], "all", 1)) { - copyoption = JCOPYOPT_ALL; -+ } else if (keymatch(argv[argn], "exif", 1)) { -+ copyoption = JCOPYOPT_EXIF; - } else - usage(); - -+ } else if (keymatch(arg, "crop", 2)) { -+ /* Perform lossless cropping. */ -+#if TRANSFORMS_SUPPORTED -+ if (++argn >= argc) /* advance to next argument */ -+ usage(); -+ if (transformoption.crop /* reject multiple crop/drop requests */ || -+ ! jtransform_parse_crop_spec(&transformoption, argv[argn])) { -+ fprintf(stderr, "%s: bogus -crop argument '%s'\n", -+ progname, argv[argn]); -+ exit(EXIT_FAILURE); -+ } -+#else -+ select_transform(JXFORM_NONE); /* force an error */ -+#endif -+ -+ } else if (keymatch(arg, "drop", 2)) { -+#if TRANSFORMS_SUPPORTED -+ if (++argn >= argc) /* advance to next argument */ -+ usage(); -+ if (transformoption.crop /* reject multiple crop/drop requests */ || -+ ! jtransform_parse_crop_spec(&transformoption, argv[argn]) || -+ transformoption.crop_width_set != JCROP_UNSET || -+ transformoption.crop_height_set != JCROP_UNSET) { -+ fprintf(stderr, "%s: bogus -drop argument '%s'\n", -+ progname, argv[argn]); -+ exit(EXIT_FAILURE); -+ } -+ if (++argn >= argc) /* advance to next argument */ -+ usage(); -+ dropfilename = argv[argn]; -+ select_transform(JXFORM_DROP); -+#else -+ select_transform(JXFORM_NONE); /* force an error */ -+#endif -+ -+ - } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { - /* Enable debug printouts. */ - /* On first -d, print version identification */ -@@ -181,6 +272,7 @@ - if (! printed_version) { - fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n", - JVERSION, JCOPYRIGHT); -+ fprintf(stderr, "EXIF support v 0.1 added 29-Sep-2003\n"); - printed_version = TRUE; - } - cinfo->err->trace_level++; -@@ -233,7 +325,12 @@ - usage(); - outfilename = argv[argn]; /* save it away for later use */ - -- } else if (keymatch(arg, "progressive", 1)) { -+ } else if (keymatch(arg, "perfect", 2)) { -+ /* Fail if there is any partial edge MCUs that the transform can't -+ * handle. */ -+ transformoption.perfect = TRUE; -+ -+ } else if (keymatch(arg, "progressive", 2)) { - /* Select simple progressive mode. */ - #ifdef C_PROGRESSIVE_SUPPORTED - simple_progressive = TRUE; -@@ -334,16 +431,24 @@ - main (int argc, char **argv) - { - struct jpeg_decompress_struct srcinfo; -+ struct jpeg_error_mgr jsrcerr; -+#if TRANSFORMS_SUPPORTED -+ struct jpeg_decompress_struct dropinfo; -+ struct jpeg_error_mgr jdroperr; -+ FILE * drop_file; -+#endif - struct jpeg_compress_struct dstinfo; -- struct jpeg_error_mgr jsrcerr, jdsterr; -+ struct jpeg_error_mgr jdsterr; - #ifdef PROGRESS_REPORT - struct cdjpeg_progress_mgr progress; - #endif - jvirt_barray_ptr * src_coef_arrays; - jvirt_barray_ptr * dst_coef_arrays; - int file_index; -- FILE * input_file; -- FILE * output_file; -+ /* We assume all-in-memory processing and can therefore use only a -+ * single file pointer for sequential input and output operation. -+ */ -+ FILE * fp; - - /* On Mac, fetch a command line. */ - #ifdef USE_CCOMMAND -@@ -406,32 +511,36 @@ - - /* Open the input file. */ - if (file_index < argc) { -- if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { -- fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); -+ if ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) { -+ fprintf(stderr, "%s: can't open %s for reading\n", progname, argv[file_index]); - exit(EXIT_FAILURE); - } - } else { - /* default input file is stdin */ -- input_file = read_stdin(); -+ fp = read_stdin(); - } -- -- /* Open the output file. */ -- if (outfilename != NULL) { -- if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { -- fprintf(stderr, "%s: can't open %s\n", progname, outfilename); -+#if TRANSFORMS_SUPPORTED -+ /* Open the drop file. */ -+ if (dropfilename != NULL) { -+ if ((drop_file = fopen(dropfilename, READ_BINARY)) == NULL) { -+ fprintf(stderr, "%s: can't open %s for reading\n", progname, dropfilename); - exit(EXIT_FAILURE); - } -+ dropinfo.err = jpeg_std_error(&jdroperr); -+ jpeg_create_decompress(&dropinfo); -+ jpeg_stdio_src(&dropinfo, drop_file); - } else { -- /* default output file is stdout */ -- output_file = write_stdout(); -+ drop_file = NULL; - } -+#endif -+ - - #ifdef PROGRESS_REPORT - start_progress_monitor((j_common_ptr) &dstinfo, &progress); - #endif - - /* Specify data source for decompression */ -- jpeg_stdio_src(&srcinfo, input_file); -+ jpeg_stdio_src(&srcinfo, fp); - - /* Enable saving of extra markers that we want to copy */ - jcopy_markers_setup(&srcinfo, copyoption); -@@ -439,19 +548,46 @@ - /* Read file header */ - (void) jpeg_read_header(&srcinfo, TRUE); - -+#if TRANSFORMS_SUPPORTED -+ if (dropfilename != NULL) { -+ (void) jpeg_read_header(&dropinfo, TRUE); -+ transformoption.crop_width = dropinfo.image_width; -+ transformoption.crop_width_set = JCROP_POS; -+ transformoption.crop_height = dropinfo.image_height; -+ transformoption.crop_height_set = JCROP_POS; -+ transformoption.drop_ptr = &dropinfo; -+ } -+#endif -+ - /* Any space needed by a transform option must be requested before - * jpeg_read_coefficients so that memory allocation will be done right. - */ - #if TRANSFORMS_SUPPORTED -+ /* Fails right away if -perfect is given and transformation is not perfect. -+ */ -+ if (transformoption.perfect && -+ !jtransform_perfect_transform(srcinfo.image_width, srcinfo.image_height, -+ srcinfo.max_h_samp_factor * DCTSIZE, srcinfo.max_v_samp_factor * DCTSIZE, -+ transformoption.transform)) { -+ fprintf(stderr, "%s: transformation is not perfect\n", progname); -+ exit(EXIT_FAILURE); -+ } - jtransform_request_workspace(&srcinfo, &transformoption); - #endif - - /* Read source file as DCT coefficients */ - src_coef_arrays = jpeg_read_coefficients(&srcinfo); - -+#if TRANSFORMS_SUPPORTED -+ if (dropfilename != NULL) { -+ transformoption.drop_coef_arrays = jpeg_read_coefficients(&dropinfo); -+ } -+#endif -+ - /* Initialize destination compression parameters from source values */ - jpeg_copy_critical_parameters(&srcinfo, &dstinfo); - -+ - /* Adjust destination parameters if required by transform options; - * also find out which set of coefficient arrays will hold the output. - */ -@@ -463,11 +599,36 @@ - dst_coef_arrays = src_coef_arrays; - #endif - -+ /* Close input file, if we opened it. -+ * Note: we assume that jpeg_read_coefficients consumed all input -+ * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will -+ * only consume more while (! cinfo->inputctl->eoi_reached). -+ * We cannot call jpeg_finish_decompress here since we still need the -+ * virtual arrays allocated from the source object for processing. -+ */ -+ if (fp != stdin) -+ fclose(fp); -+ -+ /* Open the output file. */ -+ if (outfilename != NULL) { -+ if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) { -+ fprintf(stderr, "%s: can't open %s for writing\n", progname, outfilename); -+ exit(EXIT_FAILURE); -+ } -+ } else { -+ /* default output file is stdout */ -+ fp = write_stdout(); -+ } -+ - /* Adjust default compression parameters by re-parsing the options */ -+ /* Save value of copyoption */ - file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE); - -+ /* If we want EXIF, make sure we do not write incompatible markers */ -+ handle_exif(&srcinfo,&dstinfo,©option); -+ - /* Specify data destination for compression */ -- jpeg_stdio_dest(&dstinfo, output_file); -+ jpeg_stdio_dest(&dstinfo, fp); - - /* Start compressor (note no image data is actually written here) */ - jpeg_write_coefficients(&dstinfo, dst_coef_arrays); -@@ -477,28 +638,41 @@ - - /* Execute image transformation, if any */ - #if TRANSFORMS_SUPPORTED -- jtransform_execute_transformation(&srcinfo, &dstinfo, -- src_coef_arrays, -- &transformoption); -+ jtransform_execute_transform(&srcinfo, &dstinfo, -+ src_coef_arrays, -+ &transformoption); - #endif - - /* Finish compression and release memory */ - jpeg_finish_compress(&dstinfo); - jpeg_destroy_compress(&dstinfo); -+#if TRANSFORMS_SUPPORTED -+ if (dropfilename != NULL) { -+ (void) jpeg_finish_decompress(&dropinfo); -+ jpeg_destroy_decompress(&dropinfo); -+ } -+#endif - (void) jpeg_finish_decompress(&srcinfo); - jpeg_destroy_decompress(&srcinfo); - -- /* Close files, if we opened them */ -- if (input_file != stdin) -- fclose(input_file); -- if (output_file != stdout) -- fclose(output_file); -+ /* Close output file, if we opened it */ -+ if (fp != stdout) -+ fclose(fp); -+#if TRANSFORMS_SUPPORTED -+ if (drop_file != NULL) -+ fclose(drop_file); -+#endif - - #ifdef PROGRESS_REPORT - end_progress_monitor((j_common_ptr) &dstinfo); - #endif - - /* All done. */ -+#if TRANSFORMS_SUPPORTED -+ if (dropfilename != NULL) -+ exit(jsrcerr.num_warnings + jdroperr.num_warnings + jdsterr.num_warnings ? -+ EXIT_WARNING : EXIT_SUCCESS); -+#endif - exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS); - return 0; /* suppress no-return-value warnings */ - } diff --git a/graphics/jpeg-mmx/files/patch-rdjpgcom.c b/graphics/jpeg-mmx/files/patch-rdjpgcom.c deleted file mode 100644 index db6bd23c249f..000000000000 --- a/graphics/jpeg-mmx/files/patch-rdjpgcom.c +++ /dev/null @@ -1,218 +0,0 @@ ---- rdjpgcom.c.orig Sun Oct 12 00:41:04 1997 -+++ rdjpgcom.c Thu Mar 18 06:37:23 2004 -@@ -14,6 +14,7 @@ - #define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ - #include "jinclude.h" /* get auto-config symbols, <stdio.h> */ - -+#include <locale.h> /* to declare setlocale() */ - #include <ctype.h> /* to declare isupper(), tolower() */ - #ifdef USE_SETMODE - #include <fcntl.h> /* to declare setmode()'s parameter macros */ -@@ -120,6 +121,7 @@ - #define M_EOI 0xD9 /* End Of Image (end of datastream) */ - #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ - #define M_APP0 0xE0 /* Application-specific marker, type N */ -+#define M_APP1 0xE1 /* Typically EXIF marker */ - #define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */ - #define M_COM 0xFE /* COMment */ - -@@ -210,6 +212,175 @@ - } - } - -+/* -+ * Helper routine to skip the given number of bytes. -+ */ -+ -+static void -+skip_n (unsigned int length) -+{ -+ while (length > 0) { -+ (void) read_1_byte(); -+ length--; -+ } -+} -+ -+/* -+ * Parses an APP1 marker looking for EXIF data. If EXIF, the orientation is -+ * reported to stdout. -+ */ -+ -+static void -+process_APP1 (void) -+{ -+ unsigned int length, i; -+ int is_motorola; /* byte order indicator */ -+ unsigned int offset, number_of_tags, tagnum; -+ int orientation; -+ char *ostr; -+ /* This 64K buffer would probably be best if allocated dynamically, but it's -+ * the only one on this program so it's really not that -+ * important. Allocating on the stack is not an option, as 64K might be too -+ * big for some (crippled) platforms. */ -+ static unsigned char exif_data[65536L]; -+ -+ /* Get the marker parameter length count */ -+ length = read_2_bytes(); -+ /* Length includes itself, so must be at least 2 */ -+ if (length < 2) -+ ERREXIT("Erroneous JPEG marker length"); -+ length -= 2; -+ -+ /* We only care if APP1 is really an EXIF marker. Minimum length is 6 for -+ * signature plus 12 for an IFD. */ -+ if (length < 18) { -+ skip_n(length); -+ return; -+ } -+ -+ /* Check for actual EXIF marker */ -+ for (i=0; i < 6; i++) -+ exif_data[i] = (unsigned char) read_1_byte(); -+ length -= 6; -+ if (exif_data[0] != 0x45 || -+ exif_data[1] != 0x78 || -+ exif_data[2] != 0x69 || -+ exif_data[3] != 0x66 || -+ exif_data[4] != 0 || -+ exif_data[5] != 0) { -+ skip_n(length); -+ return; -+ } -+ -+ /* Read all EXIF body */ -+ for (i=0; i < length; i++) -+ exif_data[i] = (unsigned char) read_1_byte(); -+ -+ /* Discover byte order */ -+ if (exif_data[0] == 0x49 && exif_data[1] == 0x49) -+ is_motorola = 0; -+ else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D) -+ is_motorola = 1; -+ else -+ return; -+ -+ /* Check Tag Mark */ -+ if (is_motorola) { -+ if (exif_data[2] != 0) return; -+ if (exif_data[3] != 0x2A) return; -+ } else { -+ if (exif_data[3] != 0) return; -+ if (exif_data[2] != 0x2A) return; -+ } -+ -+ /* Get first IFD offset (offset to IFD0) */ -+ if (is_motorola) { -+ if (exif_data[4] != 0) return; -+ if (exif_data[5] != 0) return; -+ offset = exif_data[6]; -+ offset <<= 8; -+ offset += exif_data[7]; -+ } else { -+ if (exif_data[7] != 0) return; -+ if (exif_data[6] != 0) return; -+ offset = exif_data[5]; -+ offset <<= 8; -+ offset += exif_data[4]; -+ } -+ if (offset > length - 2) return; /* check end of data segment */ -+ -+ /* Get the number of directory entries contained in this IFD */ -+ if (is_motorola) { -+ number_of_tags = exif_data[offset]; -+ number_of_tags <<= 8; -+ number_of_tags += exif_data[offset+1]; -+ } else { -+ number_of_tags = exif_data[offset+1]; -+ number_of_tags <<= 8; -+ number_of_tags += exif_data[offset]; -+ } -+ if (number_of_tags == 0) return; -+ offset += 2; -+ -+ /* Search for Orientation Tag in IFD0 */ -+ for (;;) { -+ if (offset > length - 12) return; /* check end of data segment */ -+ /* Get Tag number */ -+ if (is_motorola) { -+ tagnum = exif_data[offset]; -+ tagnum <<= 8; -+ tagnum += exif_data[offset+1]; -+ } else { -+ tagnum = exif_data[offset+1]; -+ tagnum <<= 8; -+ tagnum += exif_data[offset]; -+ } -+ if (tagnum == 0x0112) break; /* found Orientation Tag */ -+ if (--number_of_tags == 0) return; -+ offset += 12; -+ } -+ -+ /* Get the Orientation value */ -+ if (is_motorola) { -+ if (exif_data[offset+8] != 0) return; -+ orientation = exif_data[offset+9]; -+ } else { -+ if (exif_data[offset+9] != 0) return; -+ orientation = exif_data[offset+8]; -+ } -+ if (orientation == 0 || orientation > 8) return; -+ -+ /* Print the orientation (position of the 0th row - 0th column) */ -+ switch (orientation) { -+ case 1: -+ ostr = "top-left"; -+ break; -+ case 2: -+ ostr = "top-right"; -+ break; -+ case 3: -+ ostr = "bottom-right"; -+ break; -+ case 4: -+ ostr = "bottom-left"; -+ break; -+ case 5: -+ ostr = "left-top"; -+ break; -+ case 6: -+ ostr = "right-top"; -+ break; -+ case 7: -+ ostr = "right-bottom"; -+ break; -+ case 8: -+ ostr = "left-bottom"; -+ break; -+ default: -+ return; -+ } -+ printf("EXIF orientation: %s\n",ostr); -+} - - /* - * Process a COM marker. -@@ -231,6 +402,7 @@ - ERREXIT("Erroneous JPEG marker length"); - length -= 2; - -+ setlocale(LC_ALL, ""); - while (length > 0) { - ch = read_1_byte(); - /* Emit the character in a readable form. -@@ -363,6 +535,15 @@ - - case M_COM: - process_COM(); -+ break; -+ -+ case M_APP1: -+ /* APP1 is usually the EXIF marker used by digital cameras, attempt to -+ * process it to give some useful info. */ -+ if (verbose) { -+ process_APP1(); -+ } else -+ skip_variable(); - break; - - case M_APP12: diff --git a/graphics/jpeg-mmx/files/patch-transupp.c b/graphics/jpeg-mmx/files/patch-transupp.c deleted file mode 100644 index 55b039b96fc5..000000000000 --- a/graphics/jpeg-mmx/files/patch-transupp.c +++ /dev/null @@ -1,1895 +0,0 @@ ---- transupp.c.orig Sat Aug 9 20:15:26 1997 -+++ transupp.c Fri Jun 4 15:25:29 2004 -@@ -1,7 +1,7 @@ - /* - * transupp.c - * -- * Copyright (C) 1997, Thomas G. Lane. -+ * Copyright (C) 1997-2001, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * -@@ -20,6 +20,7 @@ - #include "jinclude.h" - #include "jpeglib.h" - #include "transupp.h" /* My own external interface */ -+#include <ctype.h> /* to declare isdigit() */ - - - #if TRANSFORMS_SUPPORTED -@@ -28,7 +29,8 @@ - * Lossless image transformation routines. These routines work on DCT - * coefficient arrays and thus do not require any lossy decompression - * or recompression of the image. -- * Thanks to Guido Vollbeding for the initial design and code of this feature. -+ * Thanks to Guido Vollbeding for the initial design and code of this feature, -+ * and to Ben Jackson for introducing the cropping feature. - * - * Horizontal flipping is done in-place, using a single top-to-bottom - * pass through the virtual source array. It will thus be much the -@@ -42,6 +44,13 @@ - * arrays for most of the transforms. That could result in much thrashing - * if the image is larger than main memory. - * -+ * If cropping or trimming is involved, the destination arrays may be smaller -+ * than the source arrays. Note it is not possible to do horizontal flip -+ * in-place when a nonzero Y crop offset is specified, since we'd have to move -+ * data from one block row to another but the virtual array manager doesn't -+ * guarantee we can touch more than one row at a time. So in that case, -+ * we have to use a separate destination array. -+ * - * Some notes about the operating environment of the individual transform - * routines: - * 1. Both the source and destination virtual arrays are allocated from the -@@ -54,20 +63,366 @@ - * and we may as well take that as the effective iMCU size. - * 4. When "trim" is in effect, the destination's dimensions will be the - * trimmed values but the source's will be untrimmed. -- * 5. All the routines assume that the source and destination buffers are -+ * 5. When "crop" is in effect, the destination's dimensions will be the -+ * cropped values but the source's will be uncropped. Each transform -+ * routine is responsible for picking up source data starting at the -+ * correct X and Y offset for the crop region. (The X and Y offsets -+ * passed to the transform routines are measured in iMCU blocks of the -+ * destination.) -+ * 6. All the routines assume that the source and destination buffers are - * padded out to a full iMCU boundary. This is true, although for the - * source buffer it is an undocumented property of jdcoefct.c. -- * Notes 2,3,4 boil down to this: generally we should use the destination's -- * dimensions and ignore the source's. - */ - - -+/* Drop code may be used with or without virtual memory adaptation code. -+ * This code has some dependencies on internal library behavior, so you -+ * may choose to disable it. For example, it doesn't make a difference -+ * if you only use jmemnobs anyway. -+ */ -+#ifndef DROP_REQUEST_FROM_SRC -+#define DROP_REQUEST_FROM_SRC 1 /* 0 disables adaptation */ -+#endif -+ -+ -+#if DROP_REQUEST_FROM_SRC -+/* Force jpeg_read_coefficients to request -+ * the virtual coefficient arrays from -+ * the source decompression object. -+ */ -+METHODDEF(jvirt_barray_ptr) -+drop_request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, -+ JDIMENSION blocksperrow, JDIMENSION numrows, -+ JDIMENSION maxaccess) -+{ -+ j_decompress_ptr srcinfo = (j_decompress_ptr) cinfo->client_data; -+ -+ return (*srcinfo->mem->request_virt_barray) -+ ((j_common_ptr) srcinfo, pool_id, pre_zero, -+ blocksperrow, numrows, maxaccess); -+} -+ -+ -+/* Force jpeg_read_coefficients to return -+ * after requesting and before accessing -+ * the virtual coefficient arrays. -+ */ -+METHODDEF(int) -+drop_consume_input (j_decompress_ptr cinfo) -+{ -+ return JPEG_SUSPENDED; -+} -+ -+ -+METHODDEF(void) -+drop_start_input_pass (j_decompress_ptr cinfo) -+{ -+ cinfo->inputctl->consume_input = drop_consume_input; -+} -+ -+ - LOCAL(void) --do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -- jvirt_barray_ptr *src_coef_arrays) --/* Horizontal flip; done in-place, so no separate dest array is required */ -+drop_request_from_src (j_decompress_ptr dropinfo, j_decompress_ptr srcinfo) -+{ -+ void *save_client_data; -+ JMETHOD(jvirt_barray_ptr, save_request_virt_barray, -+ (j_common_ptr cinfo, int pool_id, boolean pre_zero, -+ JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION maxaccess)); -+ JMETHOD(void, save_start_input_pass, (j_decompress_ptr cinfo)); -+ -+ /* Set custom method pointers, save original pointers */ -+ save_client_data = dropinfo->client_data; -+ dropinfo->client_data = (void *) srcinfo; -+ save_request_virt_barray = dropinfo->mem->request_virt_barray; -+ dropinfo->mem->request_virt_barray = drop_request_virt_barray; -+ save_start_input_pass = dropinfo->inputctl->start_input_pass; -+ dropinfo->inputctl->start_input_pass = drop_start_input_pass; -+ -+ /* Execute only initialization part. -+ * Requested coefficient arrays will be realized later by the srcinfo object. -+ * Next call to the same function will then do the actual data reading. -+ * NB: since we request the coefficient arrays from another object, -+ * the inherent realization call is effectively a no-op. -+ */ -+ (void) jpeg_read_coefficients(dropinfo); -+ -+ /* Reset method pointers */ -+ dropinfo->client_data = save_client_data; -+ dropinfo->mem->request_virt_barray = save_request_virt_barray; -+ dropinfo->inputctl->start_input_pass = save_start_input_pass; -+ /* Do input initialization for first scan now, -+ * which also resets the consume_input method. -+ */ -+ (*save_start_input_pass)(dropinfo); -+} -+#endif /* DROP_REQUEST_FROM_SRC */ -+ -+ -+LOCAL(void) -+dequant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr, -+ jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1) -+{ -+ JDIMENSION blk_x, blk_y; -+ int offset_y, k; -+ JQUANT_TBL *qtblptr; -+ JBLOCKARRAY buffer; -+ JBLOCKROW block; -+ JCOEFPTR ptr; -+ -+ qtblptr = compptr->quant_table; -+ for (blk_y = 0; blk_y < compptr->height_in_blocks; -+ blk_y += compptr->v_samp_factor) { -+ buffer = (*cinfo->mem->access_virt_barray) -+ ((j_common_ptr) cinfo, coef_array, blk_y, -+ (JDIMENSION) compptr->v_samp_factor, TRUE); -+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -+ block = buffer[offset_y]; -+ for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { -+ ptr = block[blk_x]; -+ for (k = 0; k < DCTSIZE2; k++) -+ if (qtblptr->quantval[k] != qtblptr1->quantval[k]) -+ ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k]; -+ } -+ } -+ } -+} -+ -+ -+LOCAL(void) -+requant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr, -+ jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1) -+{ -+ JDIMENSION blk_x, blk_y; -+ int offset_y, k; -+ JQUANT_TBL *qtblptr; -+ JBLOCKARRAY buffer; -+ JBLOCKROW block; -+ JCOEFPTR ptr; -+ JCOEF temp, qval; -+ -+ qtblptr = compptr->quant_table; -+ for (blk_y = 0; blk_y < compptr->height_in_blocks; -+ blk_y += compptr->v_samp_factor) { -+ buffer = (*cinfo->mem->access_virt_barray) -+ ((j_common_ptr) cinfo, coef_array, blk_y, -+ (JDIMENSION) compptr->v_samp_factor, TRUE); -+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -+ block = buffer[offset_y]; -+ for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { -+ ptr = block[blk_x]; -+ for (k = 0; k < DCTSIZE2; k++) { -+ temp = qtblptr->quantval[k]; -+ qval = qtblptr1->quantval[k]; -+ if (temp != qval) { -+ temp *= ptr[k]; -+ /* The following quantization code is a copy from jcdctmgr.c */ -+#ifdef FAST_DIVIDE -+#define DIVIDE_BY(a,b) a /= b -+#else -+#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 -+#endif -+ if (temp < 0) { -+ temp = -temp; -+ temp += qval>>1; /* for rounding */ -+ DIVIDE_BY(temp, qval); -+ temp = -temp; -+ } else { -+ temp += qval>>1; /* for rounding */ -+ DIVIDE_BY(temp, qval); -+ } -+ ptr[k] = temp; -+ } -+ } -+ } -+ } -+ } -+} -+ -+ -+/* Calculate largest common denominator with Euklid's algorithm. -+ */ -+LOCAL(JCOEF) -+largest_common_denominator(JCOEF a, JCOEF b) -+{ -+ JCOEF c; -+ -+ do { -+ c = a % b; -+ a = b; -+ b = c; -+ } while (c); -+ -+ return a; -+} -+ -+ -+LOCAL(void) -+adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays, -+ j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays, -+ boolean trim, j_compress_ptr dstinfo) -+{ -+ jpeg_component_info *compptr1, *compptr2; -+ JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3; -+ int ci, k; -+ -+ for (ci = 0; ci < dstinfo->num_components && -+ ci < dropinfo->num_components; ci++) { -+ compptr1 = srcinfo->comp_info + ci; -+ compptr2 = dropinfo->comp_info + ci; -+ qtblptr1 = compptr1->quant_table; -+ qtblptr2 = compptr2->quant_table; -+ for (k = 0; k < DCTSIZE2; k++) { -+ if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) { -+ if (trim) -+ requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1); -+ else { -+ qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no]; -+ for (k = 0; k < DCTSIZE2; k++) -+ if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) -+ qtblptr3->quantval[k] = largest_common_denominator -+ (qtblptr1->quantval[k], qtblptr2->quantval[k]); -+ dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3); -+ dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3); -+ } -+ break; -+ } -+ } -+ } -+} -+ -+ -+LOCAL(void) -+do_drop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, -+ jvirt_barray_ptr *src_coef_arrays, -+ j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays, -+ JDIMENSION drop_width, JDIMENSION drop_height) -+/* Drop. If the dropinfo component number is smaller than the destination's, -+ * we fill in the remaining components with zero. This provides the feature -+ * of dropping grayscale into (arbitrarily sampled) color images. -+ */ -+{ -+ JDIMENSION comp_width, comp_height; -+ JDIMENSION blk_y, x_drop_blocks, y_drop_blocks; -+ int ci, offset_y; -+ JBLOCKARRAY src_buffer, dst_buffer; -+ jpeg_component_info *compptr; -+ -+ for (ci = 0; ci < dstinfo->num_components; ci++) { -+ compptr = dstinfo->comp_info + ci; -+ comp_width = drop_width * compptr->h_samp_factor; -+ comp_height = drop_height * compptr->v_samp_factor; -+ x_drop_blocks = x_crop_offset * compptr->h_samp_factor; -+ y_drop_blocks = y_crop_offset * compptr->v_samp_factor; -+ for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) { -+ dst_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks, -+ (JDIMENSION) compptr->v_samp_factor, TRUE); -+ if (ci < dropinfo->num_components) { -+ src_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, drop_coef_arrays[ci], blk_y, -+ (JDIMENSION) compptr->v_samp_factor, FALSE); -+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -+ jcopy_block_row(src_buffer[offset_y], -+ dst_buffer[offset_y] + x_drop_blocks, -+ comp_width); -+ } -+ } else { -+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -+ jzero_far(dst_buffer[offset_y] + x_drop_blocks, -+ comp_width * SIZEOF(JBLOCK)); -+ } -+ } -+ } -+ } -+} -+ -+ -+LOCAL(void) -+do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, -+ jvirt_barray_ptr *src_coef_arrays, -+ jvirt_barray_ptr *dst_coef_arrays) -+/* Crop. This is only used when no rotate/flip is requested with the crop. -+ * Extension: If the destination size is larger than the source, we fill in -+ * the extra area with zero (neutral gray). Note we also have to zero partial -+ * iMCUs at the right and bottom edge of the source image area in this case. -+ */ -+{ -+ JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height; -+ JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; -+ int ci, offset_y; -+ JBLOCKARRAY src_buffer, dst_buffer; -+ jpeg_component_info *compptr; -+ -+ MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); -+ MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); -+ -+ for (ci = 0; ci < dstinfo->num_components; ci++) { -+ compptr = dstinfo->comp_info + ci; -+ comp_width = MCU_cols * compptr->h_samp_factor; -+ comp_height = MCU_rows * compptr->v_samp_factor; -+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor; -+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; -+ dst_blk_y += compptr->v_samp_factor) { -+ dst_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, -+ (JDIMENSION) compptr->v_samp_factor, TRUE); -+ if (dstinfo->image_height > srcinfo->image_height) { -+ if (dst_blk_y < y_crop_blocks || -+ dst_blk_y >= comp_height + y_crop_blocks) { -+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -+ jzero_far(dst_buffer[offset_y], -+ compptr->width_in_blocks * SIZEOF(JBLOCK)); -+ } -+ continue; -+ } -+ src_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ dst_blk_y - y_crop_blocks, -+ (JDIMENSION) compptr->v_samp_factor, FALSE); -+ } else { -+ src_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ dst_blk_y + y_crop_blocks, -+ (JDIMENSION) compptr->v_samp_factor, FALSE); -+ } -+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -+ if (dstinfo->image_width > srcinfo->image_width) { -+ if (x_crop_blocks > 0) { -+ jzero_far(dst_buffer[offset_y], -+ x_crop_blocks * SIZEOF(JBLOCK)); -+ } -+ jcopy_block_row(src_buffer[offset_y], -+ dst_buffer[offset_y] + x_crop_blocks, -+ comp_width); -+ if (compptr->width_in_blocks > comp_width + x_crop_blocks) { -+ jzero_far(dst_buffer[offset_y] + -+ comp_width + x_crop_blocks, -+ (compptr->width_in_blocks - -+ comp_width - x_crop_blocks) * SIZEOF(JBLOCK)); -+ } -+ } else { -+ jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, -+ dst_buffer[offset_y], -+ compptr->width_in_blocks); -+ } -+ } -+ } -+ } -+} -+ -+ -+LOCAL(void) -+do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, -+ jvirt_barray_ptr *src_coef_arrays) -+/* Horizontal flip; done in-place, so no separate dest array is required. -+ * NB: this only works when y_crop_offset is zero. -+ */ - { -- JDIMENSION MCU_cols, comp_width, blk_x, blk_y; -+ JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks; - int ci, k, offset_y; - JBLOCKARRAY buffer; - JCOEFPTR ptr1, ptr2; -@@ -79,17 +434,19 @@ - * mirroring by changing the signs of odd-numbered columns. - * Partial iMCUs at the right edge are left untouched. - */ -- MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); -+ MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); - - for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_width = MCU_cols * compptr->h_samp_factor; -+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor; - for (blk_y = 0; blk_y < compptr->height_in_blocks; - blk_y += compptr->v_samp_factor) { - buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, - (JDIMENSION) compptr->v_samp_factor, TRUE); - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -+ /* Do the mirroring */ - for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { - ptr1 = buffer[offset_y][blk_x]; - ptr2 = buffer[offset_y][comp_width - blk_x - 1]; -@@ -105,6 +462,79 @@ - *ptr2++ = -temp1; - } - } -+ if (x_crop_blocks > 0) { -+ /* Now left-justify the portion of the data to be kept. -+ * We can't use a single jcopy_block_row() call because that routine -+ * depends on memcpy(), whose behavior is unspecified for overlapping -+ * source and destination areas. Sigh. -+ */ -+ for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { -+ jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks, -+ buffer[offset_y] + blk_x, -+ (JDIMENSION) 1); -+ } -+ } -+ } -+ } -+ } -+} -+ -+ -+LOCAL(void) -+do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, -+ jvirt_barray_ptr *src_coef_arrays, -+ jvirt_barray_ptr *dst_coef_arrays) -+/* Horizontal flip in general cropping case */ -+{ -+ JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; -+ JDIMENSION x_crop_blocks, y_crop_blocks; -+ int ci, k, offset_y; -+ JBLOCKARRAY src_buffer, dst_buffer; -+ JBLOCKROW src_row_ptr, dst_row_ptr; -+ JCOEFPTR src_ptr, dst_ptr; -+ jpeg_component_info *compptr; -+ -+ /* Here we must output into a separate array because we can't touch -+ * different rows of a single virtual array simultaneously. Otherwise, -+ * this is essentially the same as the routine above. -+ */ -+ MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); -+ -+ for (ci = 0; ci < dstinfo->num_components; ci++) { -+ compptr = dstinfo->comp_info + ci; -+ comp_width = MCU_cols * compptr->h_samp_factor; -+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor; -+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; -+ dst_blk_y += compptr->v_samp_factor) { -+ dst_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, -+ (JDIMENSION) compptr->v_samp_factor, TRUE); -+ src_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ dst_blk_y + y_crop_blocks, -+ (JDIMENSION) compptr->v_samp_factor, FALSE); -+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -+ dst_row_ptr = dst_buffer[offset_y]; -+ src_row_ptr = src_buffer[offset_y]; -+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { -+ if (x_crop_blocks + dst_blk_x < comp_width) { -+ /* Do the mirrorable blocks */ -+ dst_ptr = dst_row_ptr[dst_blk_x]; -+ src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; -+ /* this unrolled loop doesn't need to know which row it's on... */ -+ for (k = 0; k < DCTSIZE2; k += 2) { -+ *dst_ptr++ = *src_ptr++; /* copy even column */ -+ *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */ -+ } -+ } else { -+ /* Copy last partial block(s) verbatim */ -+ jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, -+ dst_row_ptr + dst_blk_x, -+ (JDIMENSION) 1); -+ } -+ } - } - } - } -@@ -113,11 +543,13 @@ - - LOCAL(void) - do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) - /* Vertical flip */ - { - JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; -+ JDIMENSION x_crop_blocks, y_crop_blocks; - int ci, i, j, offset_y; - JBLOCKARRAY src_buffer, dst_buffer; - JBLOCKROW src_row_ptr, dst_row_ptr; -@@ -131,33 +563,38 @@ - * of odd-numbered rows. - * Partial iMCUs at the bottom edge are copied verbatim. - */ -- MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); -+ MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); - - for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_height = MCU_rows * compptr->v_samp_factor; -+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; - dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, - (JDIMENSION) compptr->v_samp_factor, TRUE); -- if (dst_blk_y < comp_height) { -+ if (y_crop_blocks + dst_blk_y < comp_height) { - /* Row is within the mirrorable area. */ - src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], -- comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, -+ comp_height - y_crop_blocks - dst_blk_y - -+ (JDIMENSION) compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } else { - /* Bottom-edge blocks will be copied verbatim. */ - src_buffer = (*srcinfo->mem->access_virt_barray) -- ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ dst_blk_y + y_crop_blocks, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -- if (dst_blk_y < comp_height) { -+ if (y_crop_blocks + dst_blk_y < comp_height) { - /* Row is within the mirrorable area. */ - dst_row_ptr = dst_buffer[offset_y]; - src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; -+ src_row_ptr += x_crop_blocks; - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; -@@ -173,7 +610,8 @@ - } - } else { - /* Just copy row verbatim. */ -- jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y], -+ jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, -+ dst_buffer[offset_y], - compptr->width_in_blocks); - } - } -@@ -184,11 +622,12 @@ - - LOCAL(void) - do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) - /* Transpose source into destination */ - { -- JDIMENSION dst_blk_x, dst_blk_y; -+ JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks; - int ci, i, j, offset_x, offset_y; - JBLOCKARRAY src_buffer, dst_buffer; - JCOEFPTR src_ptr, dst_ptr; -@@ -201,6 +640,8 @@ - */ - for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; -+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; - dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) -@@ -210,11 +651,12 @@ - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x += compptr->h_samp_factor) { - src_buffer = (*srcinfo->mem->access_virt_barray) -- ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ dst_blk_x + x_crop_blocks, - (JDIMENSION) compptr->h_samp_factor, FALSE); - for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { -- src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks]; - for (i = 0; i < DCTSIZE; i++) - for (j = 0; j < DCTSIZE; j++) - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; -@@ -228,6 +670,7 @@ - - LOCAL(void) - do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) - /* 90 degree rotation is equivalent to -@@ -237,6 +680,7 @@ - */ - { - JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; -+ JDIMENSION x_crop_blocks, y_crop_blocks; - int ci, i, j, offset_x, offset_y; - JBLOCKARRAY src_buffer, dst_buffer; - JCOEFPTR src_ptr, dst_ptr; -@@ -246,11 +690,13 @@ - * at the (output) right edge properly. They just get transposed and - * not mirrored. - */ -- MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); -+ MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE); - - for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_width = MCU_cols * compptr->h_samp_factor; -+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; - dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) -@@ -259,15 +705,26 @@ - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x += compptr->h_samp_factor) { -- src_buffer = (*srcinfo->mem->access_virt_barray) -- ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, -- (JDIMENSION) compptr->h_samp_factor, FALSE); -+ if (x_crop_blocks + dst_blk_x < comp_width) { -+ /* Block is within the mirrorable area. */ -+ src_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ comp_width - x_crop_blocks - dst_blk_x - -+ (JDIMENSION) compptr->h_samp_factor, -+ (JDIMENSION) compptr->h_samp_factor, FALSE); -+ } else { -+ /* Edge blocks are transposed but not mirrored. */ -+ src_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ dst_blk_x + x_crop_blocks, -+ (JDIMENSION) compptr->h_samp_factor, FALSE); -+ } - for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { -- src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; -- if (dst_blk_x < comp_width) { -+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -+ if (x_crop_blocks + dst_blk_x < comp_width) { - /* Block is within the mirrorable area. */ -- dst_ptr = dst_buffer[offset_y] -- [comp_width - dst_blk_x - offset_x - 1]; -+ src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] -+ [dst_blk_y + offset_y + y_crop_blocks]; - for (i = 0; i < DCTSIZE; i++) { - for (j = 0; j < DCTSIZE; j++) - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; -@@ -277,7 +734,8 @@ - } - } else { - /* Edge blocks are transposed but not mirrored. */ -- dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -+ src_ptr = src_buffer[offset_x] -+ [dst_blk_y + offset_y + y_crop_blocks]; - for (i = 0; i < DCTSIZE; i++) - for (j = 0; j < DCTSIZE; j++) - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; -@@ -292,6 +750,7 @@ - - LOCAL(void) - do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) - /* 270 degree rotation is equivalent to -@@ -301,6 +760,7 @@ - */ - { - JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; -+ JDIMENSION x_crop_blocks, y_crop_blocks; - int ci, i, j, offset_x, offset_y; - JBLOCKARRAY src_buffer, dst_buffer; - JCOEFPTR src_ptr, dst_ptr; -@@ -310,11 +770,13 @@ - * at the (output) bottom edge properly. They just get transposed and - * not mirrored. - */ -- MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); -+ MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE); - - for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_height = MCU_rows * compptr->v_samp_factor; -+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; - dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) -@@ -324,14 +786,15 @@ - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x += compptr->h_samp_factor) { - src_buffer = (*srcinfo->mem->access_virt_barray) -- ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ dst_blk_x + x_crop_blocks, - (JDIMENSION) compptr->h_samp_factor, FALSE); - for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -- if (dst_blk_y < comp_height) { -+ if (y_crop_blocks + dst_blk_y < comp_height) { - /* Block is within the mirrorable area. */ - src_ptr = src_buffer[offset_x] -- [comp_height - dst_blk_y - offset_y - 1]; -+ [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; - for (i = 0; i < DCTSIZE; i++) { - for (j = 0; j < DCTSIZE; j++) { - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; -@@ -341,7 +804,8 @@ - } - } else { - /* Edge blocks are transposed but not mirrored. */ -- src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; -+ src_ptr = src_buffer[offset_x] -+ [dst_blk_y + offset_y + y_crop_blocks]; - for (i = 0; i < DCTSIZE; i++) - for (j = 0; j < DCTSIZE; j++) - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; -@@ -356,6 +820,7 @@ - - LOCAL(void) - do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) - /* 180 degree rotation is equivalent to -@@ -365,89 +830,93 @@ - */ - { - JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; -+ JDIMENSION x_crop_blocks, y_crop_blocks; - int ci, i, j, offset_y; - JBLOCKARRAY src_buffer, dst_buffer; - JBLOCKROW src_row_ptr, dst_row_ptr; - JCOEFPTR src_ptr, dst_ptr; - jpeg_component_info *compptr; - -- MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); -- MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); -+ MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); -+ MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); - - for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_width = MCU_cols * compptr->h_samp_factor; - comp_height = MCU_rows * compptr->v_samp_factor; -+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; - dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, - (JDIMENSION) compptr->v_samp_factor, TRUE); -- if (dst_blk_y < comp_height) { -+ if (y_crop_blocks + dst_blk_y < comp_height) { - /* Row is within the vertically mirrorable area. */ - src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], -- comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, -+ comp_height - y_crop_blocks - dst_blk_y - -+ (JDIMENSION) compptr->v_samp_factor, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } else { - /* Bottom-edge rows are only mirrored horizontally. */ - src_buffer = (*srcinfo->mem->access_virt_barray) -- ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ dst_blk_y + y_crop_blocks, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { -- if (dst_blk_y < comp_height) { -+ dst_row_ptr = dst_buffer[offset_y]; -+ if (y_crop_blocks + dst_blk_y < comp_height) { - /* Row is within the mirrorable area. */ -- dst_row_ptr = dst_buffer[offset_y]; - src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; -- /* Process the blocks that can be mirrored both ways. */ -- for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { -+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { - dst_ptr = dst_row_ptr[dst_blk_x]; -- src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; -- for (i = 0; i < DCTSIZE; i += 2) { -- /* For even row, negate every odd column. */ -- for (j = 0; j < DCTSIZE; j += 2) { -- *dst_ptr++ = *src_ptr++; -- *dst_ptr++ = - *src_ptr++; -+ if (x_crop_blocks + dst_blk_x < comp_width) { -+ /* Process the blocks that can be mirrored both ways. */ -+ src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; -+ for (i = 0; i < DCTSIZE; i += 2) { -+ /* For even row, negate every odd column. */ -+ for (j = 0; j < DCTSIZE; j += 2) { -+ *dst_ptr++ = *src_ptr++; -+ *dst_ptr++ = - *src_ptr++; -+ } -+ /* For odd row, negate every even column. */ -+ for (j = 0; j < DCTSIZE; j += 2) { -+ *dst_ptr++ = - *src_ptr++; -+ *dst_ptr++ = *src_ptr++; -+ } - } -- /* For odd row, negate every even column. */ -- for (j = 0; j < DCTSIZE; j += 2) { -- *dst_ptr++ = - *src_ptr++; -- *dst_ptr++ = *src_ptr++; -+ } else { -+ /* Any remaining right-edge blocks are only mirrored vertically. */ -+ src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x]; -+ for (i = 0; i < DCTSIZE; i += 2) { -+ for (j = 0; j < DCTSIZE; j++) -+ *dst_ptr++ = *src_ptr++; -+ for (j = 0; j < DCTSIZE; j++) -+ *dst_ptr++ = - *src_ptr++; - } - } - } -- /* Any remaining right-edge blocks are only mirrored vertically. */ -- for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { -- dst_ptr = dst_row_ptr[dst_blk_x]; -- src_ptr = src_row_ptr[dst_blk_x]; -- for (i = 0; i < DCTSIZE; i += 2) { -- for (j = 0; j < DCTSIZE; j++) -- *dst_ptr++ = *src_ptr++; -- for (j = 0; j < DCTSIZE; j++) -- *dst_ptr++ = - *src_ptr++; -- } -- } - } else { - /* Remaining rows are just mirrored horizontally. */ -- dst_row_ptr = dst_buffer[offset_y]; - src_row_ptr = src_buffer[offset_y]; -- /* Process the blocks that can be mirrored. */ -- for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) { -- dst_ptr = dst_row_ptr[dst_blk_x]; -- src_ptr = src_row_ptr[comp_width - dst_blk_x - 1]; -- for (i = 0; i < DCTSIZE2; i += 2) { -- *dst_ptr++ = *src_ptr++; -- *dst_ptr++ = - *src_ptr++; -+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { -+ if (x_crop_blocks + dst_blk_x < comp_width) { -+ /* Process the blocks that can be mirrored. */ -+ dst_ptr = dst_row_ptr[dst_blk_x]; -+ src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1]; -+ for (i = 0; i < DCTSIZE2; i += 2) { -+ *dst_ptr++ = *src_ptr++; -+ *dst_ptr++ = - *src_ptr++; -+ } -+ } else { -+ /* Any remaining right-edge blocks are only copied. */ -+ jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks, -+ dst_row_ptr + dst_blk_x, -+ (JDIMENSION) 1); - } - } -- /* Any remaining right-edge blocks are only copied. */ -- for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { -- dst_ptr = dst_row_ptr[dst_blk_x]; -- src_ptr = src_row_ptr[dst_blk_x]; -- for (i = 0; i < DCTSIZE2; i++) -- *dst_ptr++ = *src_ptr++; -- } - } - } - } -@@ -457,6 +926,7 @@ - - LOCAL(void) - do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, -+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, - jvirt_barray_ptr *src_coef_arrays, - jvirt_barray_ptr *dst_coef_arrays) - /* Transverse transpose is equivalent to -@@ -470,18 +940,21 @@ - */ - { - JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y; -+ JDIMENSION x_crop_blocks, y_crop_blocks; - int ci, i, j, offset_x, offset_y; - JBLOCKARRAY src_buffer, dst_buffer; - JCOEFPTR src_ptr, dst_ptr; - jpeg_component_info *compptr; - -- MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); -- MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); -+ MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE); -+ MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE); - - for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_width = MCU_cols * compptr->h_samp_factor; - comp_height = MCU_rows * compptr->v_samp_factor; -+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor; -+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor; - for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; - dst_blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) -@@ -490,17 +963,26 @@ - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; - dst_blk_x += compptr->h_samp_factor) { -- src_buffer = (*srcinfo->mem->access_virt_barray) -- ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, -- (JDIMENSION) compptr->h_samp_factor, FALSE); -+ if (x_crop_blocks + dst_blk_x < comp_width) { -+ /* Block is within the mirrorable area. */ -+ src_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ comp_width - x_crop_blocks - dst_blk_x - -+ (JDIMENSION) compptr->h_samp_factor, -+ (JDIMENSION) compptr->h_samp_factor, FALSE); -+ } else { -+ src_buffer = (*srcinfo->mem->access_virt_barray) -+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], -+ dst_blk_x + x_crop_blocks, -+ (JDIMENSION) compptr->h_samp_factor, FALSE); -+ } - for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { -- if (dst_blk_y < comp_height) { -- src_ptr = src_buffer[offset_x] -- [comp_height - dst_blk_y - offset_y - 1]; -- if (dst_blk_x < comp_width) { -+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -+ if (y_crop_blocks + dst_blk_y < comp_height) { -+ if (x_crop_blocks + dst_blk_x < comp_width) { - /* Block is within the mirrorable area. */ -- dst_ptr = dst_buffer[offset_y] -- [comp_width - dst_blk_x - offset_x - 1]; -+ src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] -+ [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; - for (i = 0; i < DCTSIZE; i++) { - for (j = 0; j < DCTSIZE; j++) { - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; -@@ -516,7 +998,8 @@ - } - } else { - /* Right-edge blocks are mirrored in y only */ -- dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -+ src_ptr = src_buffer[offset_x] -+ [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1]; - for (i = 0; i < DCTSIZE; i++) { - for (j = 0; j < DCTSIZE; j++) { - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; -@@ -526,11 +1009,10 @@ - } - } - } else { -- src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; -- if (dst_blk_x < comp_width) { -+ if (x_crop_blocks + dst_blk_x < comp_width) { - /* Bottom-edge blocks are mirrored in x only */ -- dst_ptr = dst_buffer[offset_y] -- [comp_width - dst_blk_x - offset_x - 1]; -+ src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1] -+ [dst_blk_y + offset_y + y_crop_blocks]; - for (i = 0; i < DCTSIZE; i++) { - for (j = 0; j < DCTSIZE; j++) - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; -@@ -540,7 +1022,8 @@ - } - } else { - /* At lower right corner, just transpose, no mirroring */ -- dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; -+ src_ptr = src_buffer[offset_x] -+ [dst_blk_y + offset_y + y_crop_blocks]; - for (i = 0; i < DCTSIZE; i++) - for (j = 0; j < DCTSIZE; j++) - dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; -@@ -554,8 +1037,116 @@ - } - - -+/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec. -+ * Returns TRUE if valid integer found, FALSE if not. -+ * *strptr is advanced over the digit string, and *result is set to its value. -+ */ -+ -+LOCAL(boolean) -+jt_read_integer (const char ** strptr, JDIMENSION * result) -+{ -+ const char * ptr = *strptr; -+ JDIMENSION val = 0; -+ -+ for (; isdigit(*ptr); ptr++) { -+ val = val * 10 + (JDIMENSION) (*ptr - '0'); -+ } -+ *result = val; -+ if (ptr == *strptr) -+ return FALSE; /* oops, no digits */ -+ *strptr = ptr; -+ return TRUE; -+} -+ -+ -+/* Parse a crop specification (written in X11 geometry style). -+ * The routine returns TRUE if the spec string is valid, FALSE if not. -+ * -+ * The crop spec string should have the format -+ * <width>x<height>{+-}<xoffset>{+-}<yoffset> -+ * where width, height, xoffset, and yoffset are unsigned integers. -+ * Each of the elements can be omitted to indicate a default value. -+ * (A weakness of this style is that it is not possible to omit xoffset -+ * while specifying yoffset, since they look alike.) -+ * -+ * This code is loosely based on XParseGeometry from the X11 distribution. -+ */ -+ -+GLOBAL(boolean) -+jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec) -+{ -+ info->crop = FALSE; -+ info->crop_width_set = JCROP_UNSET; -+ info->crop_height_set = JCROP_UNSET; -+ info->crop_xoffset_set = JCROP_UNSET; -+ info->crop_yoffset_set = JCROP_UNSET; -+ -+ if (isdigit(*spec)) { -+ /* fetch width */ -+ if (! jt_read_integer(&spec, &info->crop_width)) -+ return FALSE; -+ info->crop_width_set = JCROP_POS; -+ } -+ if (*spec == 'x' || *spec == 'X') { -+ /* fetch height */ -+ spec++; -+ if (! jt_read_integer(&spec, &info->crop_height)) -+ return FALSE; -+ info->crop_height_set = JCROP_POS; -+ } -+ if (*spec == '+' || *spec == '-') { -+ /* fetch xoffset */ -+ info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; -+ spec++; -+ if (! jt_read_integer(&spec, &info->crop_xoffset)) -+ return FALSE; -+ } -+ if (*spec == '+' || *spec == '-') { -+ /* fetch yoffset */ -+ info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; -+ spec++; -+ if (! jt_read_integer(&spec, &info->crop_yoffset)) -+ return FALSE; -+ } -+ /* We had better have gotten to the end of the string. */ -+ if (*spec != '\0') -+ return FALSE; -+ info->crop = TRUE; -+ return TRUE; -+} -+ -+ -+/* Trim off any partial iMCUs on the indicated destination edge */ -+ -+LOCAL(void) -+trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width) -+{ -+ JDIMENSION MCU_cols; -+ -+ MCU_cols = info->output_width / (info->max_h_samp_factor * DCTSIZE); -+ if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == -+ full_width / (info->max_h_samp_factor * DCTSIZE)) -+ info->output_width = MCU_cols * (info->max_h_samp_factor * DCTSIZE); -+} -+ -+LOCAL(void) -+trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) -+{ -+ JDIMENSION MCU_rows; -+ -+ MCU_rows = info->output_height / (info->max_v_samp_factor * DCTSIZE); -+ if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == -+ full_height / (info->max_v_samp_factor * DCTSIZE)) -+ info->output_height = MCU_rows * (info->max_v_samp_factor * DCTSIZE); -+} -+ -+ - /* Request any required workspace. - * -+ * This routine figures out the size that the output image will be -+ * (which implies that all the transform parameters must be set before -+ * it is called). -+ * - * We allocate the workspace virtual arrays from the source decompression - * object, so that all the arrays (both the original data and the workspace) - * will be taken into account while making memory management decisions. -@@ -569,9 +1160,13 @@ - jpeg_transform_info *info) - { - jvirt_barray_ptr *coef_arrays = NULL; -+ boolean need_workspace, transpose_it; - jpeg_component_info *compptr; -- int ci; -+ JDIMENSION xoffset, yoffset, dtemp, width_in_iMCUs, height_in_iMCUs; -+ JDIMENSION width_in_blocks, height_in_blocks; -+ int itemp, ci, h_samp_factor, v_samp_factor; - -+ /* Determine number of components in output image */ - if (info->force_grayscale && - srcinfo->jpeg_color_space == JCS_YCbCr && - srcinfo->num_components == 3) { -@@ -581,55 +1176,267 @@ - /* Process all the components */ - info->num_components = srcinfo->num_components; - } -+ /* If there is only one output component, force the iMCU size to be 1; -+ * else use the source iMCU size. (This allows us to do the right thing -+ * when reducing color to grayscale, and also provides a handy way of -+ * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) -+ */ - - switch (info->transform) { -+ case JXFORM_TRANSPOSE: -+ case JXFORM_TRANSVERSE: -+ case JXFORM_ROT_90: -+ case JXFORM_ROT_270: -+ info->output_width = srcinfo->image_height; -+ info->output_height = srcinfo->image_width; -+ if (info->num_components == 1) { -+ info->max_h_samp_factor = 1; -+ info->max_v_samp_factor = 1; -+ } else { -+ info->max_h_samp_factor = srcinfo->max_v_samp_factor; -+ info->max_v_samp_factor = srcinfo->max_h_samp_factor; -+ } -+ break; -+ default: -+ info->output_width = srcinfo->image_width; -+ info->output_height = srcinfo->image_height; -+ if (info->num_components == 1) { -+ info->max_h_samp_factor = 1; -+ info->max_v_samp_factor = 1; -+ } else { -+ info->max_h_samp_factor = srcinfo->max_h_samp_factor; -+ info->max_v_samp_factor = srcinfo->max_v_samp_factor; -+ } -+ break; -+ } -+ -+ /* If cropping has been requested, compute the crop area's position and -+ * dimensions, ensuring that its upper left corner falls at an iMCU boundary. -+ */ -+ if (info->crop) { -+ /* Insert default values for unset crop parameters */ -+ if (info->crop_xoffset_set == JCROP_UNSET) -+ info->crop_xoffset = 0; /* default to +0 */ -+ if (info->crop_yoffset_set == JCROP_UNSET) -+ info->crop_yoffset = 0; /* default to +0 */ -+ if (info->crop_width_set == JCROP_UNSET) { -+ if (info->crop_xoffset >= info->output_width) -+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); -+ info->crop_width = info->output_width - info->crop_xoffset; -+ } else { -+ /* Check for crop extension */ -+ if (info->crop_width > info->output_width) { -+ /* Crop extension does not work when transforming! */ -+ if (info->transform != JXFORM_NONE || -+ info->crop_xoffset >= info->crop_width || -+ info->crop_xoffset > info->crop_width - info->output_width) -+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); -+ } else { -+ if (info->crop_xoffset >= info->output_width || -+ info->crop_width <= 0 || -+ info->crop_xoffset > info->output_width - info->crop_width) -+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); -+ } -+ } -+ if (info->crop_height_set == JCROP_UNSET) { -+ if (info->crop_yoffset >= info->output_height) -+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); -+ info->crop_height = info->output_height - info->crop_yoffset; -+ } else { -+ /* Check for crop extension */ -+ if (info->crop_height > info->output_height) { -+ /* Crop extension does not work when transforming! */ -+ if (info->transform != JXFORM_NONE || -+ info->crop_yoffset >= info->crop_height || -+ info->crop_yoffset > info->crop_height - info->output_height) -+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); -+ } else { -+ if (info->crop_yoffset >= info->output_height || -+ info->crop_height <= 0 || -+ info->crop_yoffset > info->output_height - info->crop_height) -+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); -+ } -+ } -+ /* Convert negative crop offsets into regular offsets */ -+ if (info->crop_xoffset_set == JCROP_NEG) { -+ if (info->crop_width > info->output_width) -+ xoffset = info->crop_width - info->output_width - info->crop_xoffset; -+ else -+ xoffset = info->output_width - info->crop_width - info->crop_xoffset; -+ } else -+ xoffset = info->crop_xoffset; -+ if (info->crop_yoffset_set == JCROP_NEG) { -+ if (info->crop_height > info->output_height) -+ yoffset = info->crop_height - info->output_height - info->crop_yoffset; -+ else -+ yoffset = info->output_height - info->crop_height - info->crop_yoffset; -+ } else -+ yoffset = info->crop_yoffset; -+ /* Now adjust so that upper left corner falls at an iMCU boundary */ -+ if (info->transform == JXFORM_DROP) { -+ /* Ensure the effective drop region will not exceed the requested */ -+ itemp = info->max_h_samp_factor * DCTSIZE; -+ dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp); -+ xoffset += dtemp; -+ if (info->crop_width > dtemp) -+ info->drop_width = (info->crop_width - dtemp) / itemp; -+ else -+ info->drop_width = 0; -+ itemp = info->max_v_samp_factor * DCTSIZE; -+ dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp); -+ yoffset += dtemp; -+ if (info->crop_height > dtemp) -+ info->drop_height = (info->crop_height - dtemp) / itemp; -+ else -+ info->drop_height = 0; -+ /* Check if sampling factors match for dropping */ -+ if (info->drop_width != 0 && info->drop_height != 0) -+ for (ci = 0; ci < info->num_components && -+ ci < info->drop_ptr->num_components; ci++) { -+ if (info->drop_ptr->comp_info[ci].h_samp_factor * -+ srcinfo->max_h_samp_factor != -+ srcinfo->comp_info[ci].h_samp_factor * -+ info->drop_ptr->max_h_samp_factor) -+ ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci, -+ info->drop_ptr->comp_info[ci].h_samp_factor, -+ info->drop_ptr->max_h_samp_factor, -+ srcinfo->comp_info[ci].h_samp_factor, -+ srcinfo->max_h_samp_factor, 'h'); -+ if (info->drop_ptr->comp_info[ci].v_samp_factor * -+ srcinfo->max_v_samp_factor != -+ srcinfo->comp_info[ci].v_samp_factor * -+ info->drop_ptr->max_v_samp_factor) -+ ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci, -+ info->drop_ptr->comp_info[ci].v_samp_factor, -+ info->drop_ptr->max_v_samp_factor, -+ srcinfo->comp_info[ci].v_samp_factor, -+ srcinfo->max_v_samp_factor, 'v'); -+ } -+ } else { -+ /* Ensure the effective crop region will cover the requested */ -+ if (info->crop_width > info->output_width) -+ info->output_width = info->crop_width; -+ else -+ info->output_width = -+ info->crop_width + (xoffset % (info->max_h_samp_factor * DCTSIZE)); -+ if (info->crop_height > info->output_height) -+ info->output_height = info->crop_height; -+ else -+ info->output_height = -+ info->crop_height + (yoffset % (info->max_v_samp_factor * DCTSIZE)); -+ } -+ /* Save x/y offsets measured in iMCUs */ -+ info->x_crop_offset = xoffset / (info->max_h_samp_factor * DCTSIZE); -+ info->y_crop_offset = yoffset / (info->max_v_samp_factor * DCTSIZE); -+ } else { -+ info->x_crop_offset = 0; -+ info->y_crop_offset = 0; -+ } -+ -+ /* Figure out whether we need workspace arrays, -+ * and if so whether they are transposed relative to the source. -+ */ -+ need_workspace = FALSE; -+ transpose_it = FALSE; -+ switch (info->transform) { - case JXFORM_NONE: -+ if (info->x_crop_offset != 0 || info->y_crop_offset != 0 || -+ info->output_width > srcinfo->image_width || -+ info->output_height > srcinfo->image_height) -+ need_workspace = TRUE; -+ /* No workspace needed if neither cropping nor transforming */ -+ break; - case JXFORM_FLIP_H: -- /* Don't need a workspace array */ -+ if (info->trim) -+ trim_right_edge(info, srcinfo->image_width); -+ if (info->y_crop_offset != 0) -+ need_workspace = TRUE; -+ /* do_flip_h_no_crop doesn't need a workspace array */ - break; - case JXFORM_FLIP_V: -- case JXFORM_ROT_180: -- /* Need workspace arrays having same dimensions as source image. -- * Note that we allocate arrays padded out to the next iMCU boundary, -- * so that transform routines need not worry about missing edge blocks. -- */ -- coef_arrays = (jvirt_barray_ptr *) -- (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, -- SIZEOF(jvirt_barray_ptr) * info->num_components); -- for (ci = 0; ci < info->num_components; ci++) { -- compptr = srcinfo->comp_info + ci; -- coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) -- ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, -- (JDIMENSION) jround_up((long) compptr->width_in_blocks, -- (long) compptr->h_samp_factor), -- (JDIMENSION) jround_up((long) compptr->height_in_blocks, -- (long) compptr->v_samp_factor), -- (JDIMENSION) compptr->v_samp_factor); -- } -+ if (info->trim) -+ trim_bottom_edge(info, srcinfo->image_height); -+ /* Need workspace arrays having same dimensions as source image. */ -+ need_workspace = TRUE; - break; - case JXFORM_TRANSPOSE: -+ /* transpose does NOT have to trim anything */ -+ /* Need workspace arrays having transposed dimensions. */ -+ need_workspace = TRUE; -+ transpose_it = TRUE; -+ break; - case JXFORM_TRANSVERSE: -+ if (info->trim) { -+ trim_right_edge(info, srcinfo->image_height); -+ trim_bottom_edge(info, srcinfo->image_width); -+ } -+ /* Need workspace arrays having transposed dimensions. */ -+ need_workspace = TRUE; -+ transpose_it = TRUE; -+ break; - case JXFORM_ROT_90: -+ if (info->trim) -+ trim_right_edge(info, srcinfo->image_height); -+ /* Need workspace arrays having transposed dimensions. */ -+ need_workspace = TRUE; -+ transpose_it = TRUE; -+ break; -+ case JXFORM_ROT_180: -+ if (info->trim) { -+ trim_right_edge(info, srcinfo->image_width); -+ trim_bottom_edge(info, srcinfo->image_height); -+ } -+ /* Need workspace arrays having same dimensions as source image. */ -+ need_workspace = TRUE; -+ break; - case JXFORM_ROT_270: -- /* Need workspace arrays having transposed dimensions. -- * Note that we allocate arrays padded out to the next iMCU boundary, -- * so that transform routines need not worry about missing edge blocks. -- */ -+ if (info->trim) -+ trim_bottom_edge(info, srcinfo->image_width); -+ /* Need workspace arrays having transposed dimensions. */ -+ need_workspace = TRUE; -+ transpose_it = TRUE; -+ break; -+ case JXFORM_DROP: -+#if DROP_REQUEST_FROM_SRC -+ drop_request_from_src(info->drop_ptr, srcinfo); -+#endif -+ break; -+ } -+ -+ /* Allocate workspace if needed. -+ * Note that we allocate arrays padded out to the next iMCU boundary, -+ * so that transform routines need not worry about missing edge blocks. -+ */ -+ if (need_workspace) { - coef_arrays = (jvirt_barray_ptr *) - (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, -- SIZEOF(jvirt_barray_ptr) * info->num_components); -+ SIZEOF(jvirt_barray_ptr) * info->num_components); -+ width_in_iMCUs = (JDIMENSION) -+ jdiv_round_up((long) info->output_width, -+ (long) (info->max_h_samp_factor * DCTSIZE)); -+ height_in_iMCUs = (JDIMENSION) -+ jdiv_round_up((long) info->output_height, -+ (long) (info->max_v_samp_factor * DCTSIZE)); - for (ci = 0; ci < info->num_components; ci++) { - compptr = srcinfo->comp_info + ci; -+ if (info->num_components == 1) { -+ /* we're going to force samp factors to 1x1 in this case */ -+ h_samp_factor = v_samp_factor = 1; -+ } else if (transpose_it) { -+ h_samp_factor = compptr->v_samp_factor; -+ v_samp_factor = compptr->h_samp_factor; -+ } else { -+ h_samp_factor = compptr->h_samp_factor; -+ v_samp_factor = compptr->v_samp_factor; -+ } -+ width_in_blocks = width_in_iMCUs * h_samp_factor; -+ height_in_blocks = height_in_iMCUs * v_samp_factor; - coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) - ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, -- (JDIMENSION) jround_up((long) compptr->height_in_blocks, -- (long) compptr->v_samp_factor), -- (JDIMENSION) jround_up((long) compptr->width_in_blocks, -- (long) compptr->h_samp_factor), -- (JDIMENSION) compptr->h_samp_factor); -+ width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); - } -- break; - } -+ - info->workspace_coef_arrays = coef_arrays; - } - -@@ -642,14 +1449,8 @@ - int tblno, i, j, ci, itemp; - jpeg_component_info *compptr; - JQUANT_TBL *qtblptr; -- JDIMENSION dtemp; - UINT16 qtemp; - -- /* Transpose basic image dimensions */ -- dtemp = dstinfo->image_width; -- dstinfo->image_width = dstinfo->image_height; -- dstinfo->image_height = dtemp; -- - /* Transpose sampling factors */ - for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; -@@ -674,46 +1475,159 @@ - } - - --/* Trim off any partial iMCUs on the indicated destination edge */ -+/* Adjust Exif image parameters. -+ * -+ * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. -+ */ - - LOCAL(void) --trim_right_edge (j_compress_ptr dstinfo) -+adjust_exif_parameters (JOCTET FAR * data, unsigned int length, -+ JDIMENSION new_width, JDIMENSION new_height) - { -- int ci, max_h_samp_factor; -- JDIMENSION MCU_cols; -+ boolean is_motorola; /* Flag for byte order */ -+ unsigned int number_of_tags, tagnum; -+ unsigned int firstoffset, offset; -+ JDIMENSION new_value; -+ -+ if (length < 12) return; /* Length of an IFD entry */ -+ -+ /* Discover byte order */ -+ if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) -+ is_motorola = FALSE; -+ else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D) -+ is_motorola = TRUE; -+ else -+ return; -+ -+ /* Check Tag Mark */ -+ if (is_motorola) { -+ if (GETJOCTET(data[2]) != 0) return; -+ if (GETJOCTET(data[3]) != 0x2A) return; -+ } else { -+ if (GETJOCTET(data[3]) != 0) return; -+ if (GETJOCTET(data[2]) != 0x2A) return; -+ } - -- /* We have to compute max_h_samp_factor ourselves, -- * because it hasn't been set yet in the destination -- * (and we don't want to use the source's value). -- */ -- max_h_samp_factor = 1; -- for (ci = 0; ci < dstinfo->num_components; ci++) { -- int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor; -- max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor); -+ /* Get first IFD offset (offset to IFD0) */ -+ if (is_motorola) { -+ if (GETJOCTET(data[4]) != 0) return; -+ if (GETJOCTET(data[5]) != 0) return; -+ firstoffset = GETJOCTET(data[6]); -+ firstoffset <<= 8; -+ firstoffset += GETJOCTET(data[7]); -+ } else { -+ if (GETJOCTET(data[7]) != 0) return; -+ if (GETJOCTET(data[6]) != 0) return; -+ firstoffset = GETJOCTET(data[5]); -+ firstoffset <<= 8; -+ firstoffset += GETJOCTET(data[4]); - } -- MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE); -- if (MCU_cols > 0) /* can't trim to 0 pixels */ -- dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE); --} -+ if (firstoffset > length - 2) return; /* check end of data segment */ - --LOCAL(void) --trim_bottom_edge (j_compress_ptr dstinfo) --{ -- int ci, max_v_samp_factor; -- JDIMENSION MCU_rows; -+ /* Get the number of directory entries contained in this IFD */ -+ if (is_motorola) { -+ number_of_tags = GETJOCTET(data[firstoffset]); -+ number_of_tags <<= 8; -+ number_of_tags += GETJOCTET(data[firstoffset+1]); -+ } else { -+ number_of_tags = GETJOCTET(data[firstoffset+1]); -+ number_of_tags <<= 8; -+ number_of_tags += GETJOCTET(data[firstoffset]); -+ } -+ if (number_of_tags == 0) return; -+ firstoffset += 2; -+ -+ /* Search for ExifSubIFD offset Tag in IFD0 */ -+ for (;;) { -+ if (firstoffset > length - 12) return; /* check end of data segment */ -+ /* Get Tag number */ -+ if (is_motorola) { -+ tagnum = GETJOCTET(data[firstoffset]); -+ tagnum <<= 8; -+ tagnum += GETJOCTET(data[firstoffset+1]); -+ } else { -+ tagnum = GETJOCTET(data[firstoffset+1]); -+ tagnum <<= 8; -+ tagnum += GETJOCTET(data[firstoffset]); -+ } -+ if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */ -+ if (--number_of_tags == 0) return; -+ firstoffset += 12; -+ } -+ -+ /* Get the ExifSubIFD offset */ -+ if (is_motorola) { -+ if (GETJOCTET(data[firstoffset+8]) != 0) return; -+ if (GETJOCTET(data[firstoffset+9]) != 0) return; -+ offset = GETJOCTET(data[firstoffset+10]); -+ offset <<= 8; -+ offset += GETJOCTET(data[firstoffset+11]); -+ } else { -+ if (GETJOCTET(data[firstoffset+11]) != 0) return; -+ if (GETJOCTET(data[firstoffset+10]) != 0) return; -+ offset = GETJOCTET(data[firstoffset+9]); -+ offset <<= 8; -+ offset += GETJOCTET(data[firstoffset+8]); -+ } -+ if (offset > length - 2) return; /* check end of data segment */ - -- /* We have to compute max_v_samp_factor ourselves, -- * because it hasn't been set yet in the destination -- * (and we don't want to use the source's value). -- */ -- max_v_samp_factor = 1; -- for (ci = 0; ci < dstinfo->num_components; ci++) { -- int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor; -- max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor); -- } -- MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE); -- if (MCU_rows > 0) /* can't trim to 0 pixels */ -- dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE); -+ /* Get the number of directory entries contained in this SubIFD */ -+ if (is_motorola) { -+ number_of_tags = GETJOCTET(data[offset]); -+ number_of_tags <<= 8; -+ number_of_tags += GETJOCTET(data[offset+1]); -+ } else { -+ number_of_tags = GETJOCTET(data[offset+1]); -+ number_of_tags <<= 8; -+ number_of_tags += GETJOCTET(data[offset]); -+ } -+ if (number_of_tags < 2) return; -+ offset += 2; -+ -+ /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */ -+ do { -+ if (offset > length - 12) return; /* check end of data segment */ -+ /* Get Tag number */ -+ if (is_motorola) { -+ tagnum = GETJOCTET(data[offset]); -+ tagnum <<= 8; -+ tagnum += GETJOCTET(data[offset+1]); -+ } else { -+ tagnum = GETJOCTET(data[offset+1]); -+ tagnum <<= 8; -+ tagnum += GETJOCTET(data[offset]); -+ } -+ if (tagnum == 0xA002 || tagnum == 0xA003) { -+ if (tagnum == 0xA002) -+ new_value = new_width; /* ExifImageWidth Tag */ -+ else -+ new_value = new_height; /* ExifImageHeight Tag */ -+ if (is_motorola) { -+ data[offset+2] = 0; /* Format = unsigned long (4 octets) */ -+ data[offset+3] = 4; -+ data[offset+4] = 0; /* Number Of Components = 1 */ -+ data[offset+5] = 0; -+ data[offset+6] = 0; -+ data[offset+7] = 1; -+ data[offset+8] = 0; -+ data[offset+9] = 0; -+ data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF); -+ data[offset+11] = (JOCTET)(new_value & 0xFF); -+ } else { -+ data[offset+2] = 4; /* Format = unsigned long (4 octets) */ -+ data[offset+3] = 0; -+ data[offset+4] = 1; /* Number Of Components = 1 */ -+ data[offset+5] = 0; -+ data[offset+6] = 0; -+ data[offset+7] = 0; -+ data[offset+8] = (JOCTET)(new_value & 0xFF); -+ data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF); -+ data[offset+10] = 0; -+ data[offset+11] = 0; -+ } -+ } -+ offset += 12; -+ } while (--number_of_tags); - } - - -@@ -736,18 +1650,22 @@ - { - /* If force-to-grayscale is requested, adjust destination parameters */ - if (info->force_grayscale) { -- /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed -- * properly. Among other things, the target h_samp_factor & v_samp_factor -- * will get set to 1, which typically won't match the source. -- * In fact we do this even if the source is already grayscale; that -- * provides an easy way of coercing a grayscale JPEG with funny sampling -- * factors to the customary 1,1. (Some decoders fail on other factors.) -+ /* First, ensure we have YCbCr or grayscale data, and that the source's -+ * Y channel is full resolution. (No reasonable person would make Y -+ * be less than full resolution, so actually coping with that case -+ * isn't worth extra code space. But we check it to avoid crashing.) - */ -- if ((dstinfo->jpeg_color_space == JCS_YCbCr && -- dstinfo->num_components == 3) || -- (dstinfo->jpeg_color_space == JCS_GRAYSCALE && -- dstinfo->num_components == 1)) { -- /* We have to preserve the source's quantization table number. */ -+ if (((dstinfo->jpeg_color_space == JCS_YCbCr && -+ dstinfo->num_components == 3) || -+ (dstinfo->jpeg_color_space == JCS_GRAYSCALE && -+ dstinfo->num_components == 1)) && -+ srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor && -+ srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) { -+ /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed -+ * properly. Among other things, it sets the target h_samp_factor & -+ * v_samp_factor to 1, which typically won't match the source. -+ * We have to preserve the source's quantization table number, however. -+ */ - int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; - jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); - dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; -@@ -755,48 +1673,54 @@ - /* Sorry, can't do it */ - ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); - } -+ } else if (info->num_components == 1) { -+ /* For a single-component source, we force the destination sampling factors -+ * to 1x1, with or without force_grayscale. This is useful because some -+ * decoders choke on grayscale images with other sampling factors. -+ */ -+ dstinfo->comp_info[0].h_samp_factor = 1; -+ dstinfo->comp_info[0].v_samp_factor = 1; - } - -- /* Correct the destination's image dimensions etc if necessary */ -+ /* Correct the destination's image dimensions etc as necessary -+ * for crop and rotate/flip operations. -+ */ -+ dstinfo->image_width = info->output_width; -+ dstinfo->image_height = info->output_height; - switch (info->transform) { -- case JXFORM_NONE: -- /* Nothing to do */ -- break; -- case JXFORM_FLIP_H: -- if (info->trim) -- trim_right_edge(dstinfo); -- break; -- case JXFORM_FLIP_V: -- if (info->trim) -- trim_bottom_edge(dstinfo); -- break; - case JXFORM_TRANSPOSE: -- transpose_critical_parameters(dstinfo); -- /* transpose does NOT have to trim anything */ -- break; - case JXFORM_TRANSVERSE: -- transpose_critical_parameters(dstinfo); -- if (info->trim) { -- trim_right_edge(dstinfo); -- trim_bottom_edge(dstinfo); -- } -- break; - case JXFORM_ROT_90: -- transpose_critical_parameters(dstinfo); -- if (info->trim) -- trim_right_edge(dstinfo); -- break; -- case JXFORM_ROT_180: -- if (info->trim) { -- trim_right_edge(dstinfo); -- trim_bottom_edge(dstinfo); -- } -- break; - case JXFORM_ROT_270: - transpose_critical_parameters(dstinfo); -- if (info->trim) -- trim_bottom_edge(dstinfo); - break; -+ case JXFORM_DROP: -+ if (info->drop_width != 0 && info->drop_height != 0) -+ adjust_quant(srcinfo, src_coef_arrays, -+ info->drop_ptr, info->drop_coef_arrays, -+ info->trim, dstinfo); -+ break; -+ } -+ -+ /* Adjust Exif properties */ -+ if (srcinfo->marker_list != NULL && -+ srcinfo->marker_list->marker == JPEG_APP0+1 && -+ srcinfo->marker_list->data_length >= 6 && -+ GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 && -+ GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 && -+ GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 && -+ GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 && -+ GETJOCTET(srcinfo->marker_list->data[4]) == 0 && -+ GETJOCTET(srcinfo->marker_list->data[5]) == 0) { -+ /* Suppress output of JFIF marker */ -+ dstinfo->write_JFIF_header = FALSE; -+ /* Adjust Exif image parameters */ -+ if (dstinfo->image_width != srcinfo->image_width || -+ dstinfo->image_height != srcinfo->image_height) -+ /* Align data segment to start of TIFF structure for parsing */ -+ adjust_exif_parameters(srcinfo->marker_list->data + 6, -+ srcinfo->marker_list->data_length - 6, -+ dstinfo->image_width, dstinfo->image_height); - } - - /* Return the appropriate output data set */ -@@ -816,38 +1740,114 @@ - */ - - GLOBAL(void) --jtransform_execute_transformation (j_decompress_ptr srcinfo, -- j_compress_ptr dstinfo, -- jvirt_barray_ptr *src_coef_arrays, -- jpeg_transform_info *info) -+jtransform_execute_transform (j_decompress_ptr srcinfo, -+ j_compress_ptr dstinfo, -+ jvirt_barray_ptr *src_coef_arrays, -+ jpeg_transform_info *info) - { - jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays; - -+ /* Note: conditions tested here should match those in switch statement -+ * in jtransform_request_workspace() -+ */ - switch (info->transform) { - case JXFORM_NONE: -+ if (info->x_crop_offset != 0 || info->y_crop_offset != 0 || -+ info->output_width > srcinfo->image_width || -+ info->output_height > srcinfo->image_height) -+ do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, -+ src_coef_arrays, dst_coef_arrays); - break; - case JXFORM_FLIP_H: -- do_flip_h(srcinfo, dstinfo, src_coef_arrays); -+ if (info->y_crop_offset != 0) -+ do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, -+ src_coef_arrays, dst_coef_arrays); -+ else -+ do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset, -+ src_coef_arrays); - break; - case JXFORM_FLIP_V: -- do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); -+ do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, -+ src_coef_arrays, dst_coef_arrays); - break; - case JXFORM_TRANSPOSE: -- do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); -+ do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, -+ src_coef_arrays, dst_coef_arrays); - break; - case JXFORM_TRANSVERSE: -- do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); -+ do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, -+ src_coef_arrays, dst_coef_arrays); - break; - case JXFORM_ROT_90: -- do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); -+ do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, -+ src_coef_arrays, dst_coef_arrays); - break; - case JXFORM_ROT_180: -- do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); -+ do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, -+ src_coef_arrays, dst_coef_arrays); -+ break; -+ case JXFORM_ROT_270: -+ do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, -+ src_coef_arrays, dst_coef_arrays); - break; -+ case JXFORM_DROP: -+ if (info->drop_width != 0 && info->drop_height != 0) -+ do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, -+ src_coef_arrays, info->drop_ptr, info->drop_coef_arrays, -+ info->drop_width, info->drop_height); -+ break; -+ } -+} -+ -+/* jtransform_perfect_transform -+ * -+ * Determine whether lossless transformation is perfectly -+ * possible for a specified image and transformation. -+ * -+ * Inputs: -+ * image_width, image_height: source image dimensions. -+ * MCU_width, MCU_height: pixel dimensions of MCU. -+ * transform: transformation identifier. -+ * Parameter sources from initialized jpeg_struct -+ * (after reading source header): -+ * image_width = cinfo.image_width -+ * image_height = cinfo.image_height -+ * MCU_width = cinfo.max_h_samp_factor * DCTSIZE -+ * MCU_height = cinfo.max_v_samp_factor * DCTSIZE -+ * Result: -+ * TRUE = perfect transformation possible -+ * FALSE = perfect transformation not possible -+ * (may use custom action then) -+ */ -+ -+GLOBAL(boolean) -+jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, -+ int MCU_width, int MCU_height, -+ JXFORM_CODE transform) -+{ -+ boolean result = TRUE; /* initialize TRUE */ -+ -+ switch (transform) { -+ case JXFORM_FLIP_H: - case JXFORM_ROT_270: -- do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays); -+ if (image_width % (JDIMENSION) MCU_width) -+ result = FALSE; -+ break; -+ case JXFORM_FLIP_V: -+ case JXFORM_ROT_90: -+ if (image_height % (JDIMENSION) MCU_height) -+ result = FALSE; -+ break; -+ case JXFORM_TRANSVERSE: -+ case JXFORM_ROT_180: -+ if (image_width % (JDIMENSION) MCU_width) -+ result = FALSE; -+ if (image_height % (JDIMENSION) MCU_height) -+ result = FALSE; - break; - } -+ -+ return result; - } - - #endif /* TRANSFORMS_SUPPORTED */ diff --git a/graphics/jpeg-mmx/files/patch-transupp.h b/graphics/jpeg-mmx/files/patch-transupp.h deleted file mode 100644 index c8e1941f3fc4..000000000000 --- a/graphics/jpeg-mmx/files/patch-transupp.h +++ /dev/null @@ -1,197 +0,0 @@ ---- transupp.h.orig Wed Jul 23 22:39:12 1997 -+++ transupp.h Fri Jun 4 15:07:31 2004 -@@ -1,7 +1,7 @@ - /* - * transupp.h - * -- * Copyright (C) 1997, Thomas G. Lane. -+ * Copyright (C) 1997-2001, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * -@@ -22,32 +22,6 @@ - #define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ - #endif - --/* Short forms of external names for systems with brain-damaged linkers. */ -- --#ifdef NEED_SHORT_EXTERNAL_NAMES --#define jtransform_request_workspace jTrRequest --#define jtransform_adjust_parameters jTrAdjust --#define jtransform_execute_transformation jTrExec --#define jcopy_markers_setup jCMrkSetup --#define jcopy_markers_execute jCMrkExec --#endif /* NEED_SHORT_EXTERNAL_NAMES */ -- -- --/* -- * Codes for supported types of image transformations. -- */ -- --typedef enum { -- JXFORM_NONE, /* no transformation */ -- JXFORM_FLIP_H, /* horizontal flip */ -- JXFORM_FLIP_V, /* vertical flip */ -- JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ -- JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ -- JXFORM_ROT_90, /* 90-degree clockwise rotation */ -- JXFORM_ROT_180, /* 180-degree rotation */ -- JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ --} JXFORM_CODE; -- - /* - * Although rotating and flipping data expressed as DCT coefficients is not - * hard, there is an asymmetry in the JPEG format specification for images -@@ -75,6 +49,19 @@ - * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim - * followed by -rot 180 -trim trims both edges.) - * -+ * We also offer a lossless-crop option, which discards data outside a given -+ * image region but losslessly preserves what is inside. Like the rotate and -+ * flip transforms, lossless crop is restricted by the JPEG format: the upper -+ * left corner of the selected region must fall on an iMCU boundary. If this -+ * does not hold for the given crop parameters, we silently move the upper left -+ * corner up and/or left to make it so, simultaneously increasing the region -+ * dimensions to keep the lower right crop corner unchanged. (Thus, the -+ * output image covers at least the requested region, but may cover more.) -+ * -+ * If both crop and a rotate/flip transform are requested, the crop is applied -+ * last --- that is, the crop region is specified in terms of the destination -+ * image. -+ * - * We also offer a "force to grayscale" option, which simply discards the - * chrominance channels of a YCbCr image. This is lossless in the sense that - * the luminance channel is preserved exactly. It's not the same kind of -@@ -83,20 +70,96 @@ - * be aware of the option to know how many components to work on. - */ - -+ -+/* Short forms of external names for systems with brain-damaged linkers. */ -+ -+#ifdef NEED_SHORT_EXTERNAL_NAMES -+#define jtransform_parse_crop_spec jTrParCrop -+#define jtransform_request_workspace jTrRequest -+#define jtransform_adjust_parameters jTrAdjust -+#define jtransform_execute_transform jTrExec -+#define jtransform_perfect_transform jTrPerfect -+#define jcopy_markers_setup jCMrkSetup -+#define jcopy_markers_execute jCMrkExec -+#endif /* NEED_SHORT_EXTERNAL_NAMES */ -+ -+ -+/* -+ * Codes for supported types of image transformations. -+ */ -+ -+typedef enum { -+ JXFORM_NONE, /* no transformation */ -+ JXFORM_FLIP_H, /* horizontal flip */ -+ JXFORM_FLIP_V, /* vertical flip */ -+ JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ -+ JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ -+ JXFORM_ROT_90, /* 90-degree clockwise rotation */ -+ JXFORM_ROT_180, /* 180-degree rotation */ -+ JXFORM_ROT_270, /* 270-degree clockwise (or 90 ccw) */ -+ JXFORM_DROP /* drop */ -+} JXFORM_CODE; -+ -+/* -+ * Codes for crop parameters, which can individually be unspecified, -+ * positive, or negative. (Negative width or height makes no sense, though.) -+ */ -+ -+typedef enum { -+ JCROP_UNSET, -+ JCROP_POS, -+ JCROP_NEG -+} JCROP_CODE; -+ -+/* -+ * Transform parameters struct. -+ * NB: application must not change any elements of this struct after -+ * calling jtransform_request_workspace. -+ */ -+ - typedef struct { - /* Options: set by caller */ - JXFORM_CODE transform; /* image transform operator */ -+ boolean perfect; /* if TRUE, fail if partial MCUs are requested */ - boolean trim; /* if TRUE, trim partial MCUs as needed */ - boolean force_grayscale; /* if TRUE, convert color image to grayscale */ -+ boolean crop; /* if TRUE, crop source image */ -+ -+ /* Crop parameters: application need not set these unless crop is TRUE. -+ * These can be filled in by jtransform_parse_crop_spec(). -+ */ -+ JDIMENSION crop_width; /* Width of selected region */ -+ JCROP_CODE crop_width_set; -+ JDIMENSION crop_height; /* Height of selected region */ -+ JCROP_CODE crop_height_set; -+ JDIMENSION crop_xoffset; /* X offset of selected region */ -+ JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */ -+ JDIMENSION crop_yoffset; /* Y offset of selected region */ -+ JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */ -+ -+ /* Drop parameters: set by caller for drop request */ -+ j_decompress_ptr drop_ptr; -+ jvirt_barray_ptr * drop_coef_arrays; - - /* Internal workspace: caller should not touch these */ - int num_components; /* # of components in workspace */ - jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ -+ JDIMENSION output_width; /* cropped destination dimensions */ -+ JDIMENSION output_height; -+ JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */ -+ JDIMENSION y_crop_offset; -+ JDIMENSION drop_width; /* drop dimensions measured in iMCUs */ -+ JDIMENSION drop_height; -+ int max_h_samp_factor; /* destination iMCU size */ -+ int max_v_samp_factor; - } jpeg_transform_info; - - - #if TRANSFORMS_SUPPORTED - -+/* Parse a crop specification (written in X11 geometry style) */ -+EXTERN(boolean) jtransform_parse_crop_spec -+ JPP((jpeg_transform_info *info, const char *spec)); - /* Request any required workspace */ - EXTERN(void) jtransform_request_workspace - JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); -@@ -106,10 +169,24 @@ - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); - /* Execute the actual transformation, if any */ --EXTERN(void) jtransform_execute_transformation -+EXTERN(void) jtransform_execute_transform - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); -+/* Determine whether lossless transformation is perfectly -+ * possible for a specified image and transformation. -+ */ -+EXTERN(boolean) jtransform_perfect_transform -+ JPP((JDIMENSION image_width, JDIMENSION image_height, -+ int MCU_width, int MCU_height, -+ JXFORM_CODE transform)); -+ -+/* jtransform_execute_transform used to be called -+ * jtransform_execute_transformation, but some compilers complain about -+ * routine names that long. This macro is here to avoid breaking any -+ * old source code that uses the original name... -+ */ -+#define jtransform_execute_transformation jtransform_execute_transform - - #endif /* TRANSFORMS_SUPPORTED */ - -@@ -121,7 +198,8 @@ - typedef enum { - JCOPYOPT_NONE, /* copy no optional markers */ - JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ -- JCOPYOPT_ALL /* copy all optional markers */ -+ JCOPYOPT_ALL, /* copy all optional markers */ -+ JCOPYOPT_EXIF /* copy Exif APP1 marker */ - } JCOPY_OPTION; - - #define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ diff --git a/graphics/jpeg-mmx/pkg-descr b/graphics/jpeg-mmx/pkg-descr deleted file mode 100644 index 4844e3b215bb..000000000000 --- a/graphics/jpeg-mmx/pkg-descr +++ /dev/null @@ -1,7 +0,0 @@ -IJG's jpeg compression utilities and libraries with MMX optimization - -This is NOT a drop in replacement to graphics/jpeg - -See graphics/jpeg/pkg-descr for more information - -WWW: http://mjpeg.sf.net/ diff --git a/graphics/lphoto/Makefile b/graphics/lphoto/Makefile index 5abc1f4c6475..31bcb6fe6310 100644 --- a/graphics/lphoto/Makefile +++ b/graphics/lphoto/Makefile @@ -7,7 +7,7 @@ PORTNAME= lphoto PORTVERSION= 2.0.42 -PORTREVISION= 2 +PORTREVISION= 3 CATEGORIES= graphics MASTER_SITES= http://software.linspire.com/emptypool/lindowsos/pool/main/l/lphoto/ DISTNAME= ${PORTNAME}_${PORTVERSION}-0.0.0.45.lindows0.1 @@ -31,20 +31,6 @@ WRKSRC= ${WRKDIR}/${PORTNAME}-${PORTVERSION} .include <bsd.port.pre.mk> -.if ${ARCH}=="i386" -.if ${MACHINE_CPU:Mmmx} && !defined(WITHOUT_JPEGMMX) -RUN_DEPENDS+= jpegtran-mmx:${PORTSDIR}/graphics/jpeg-mmx - -pre_everything:: - @${ECHO_MSG} "===> Define WITHOUT_JPEGMMX to disable jpeg-mmx support" - @${ECHO_MSG} "===>" - -post-patch: - @${REINPLACE_CMD} -e 's|jpegtran|jpegtran-mmx|' \ - ${WRKSRC}/Lphoto/photolibrary.py -.endif -.endif - do-install: @cd ${WRKSRC} && ${PYTHON_CMD} install.py -d ${PREFIX}/${PYTHON_SITELIBDIR:S/${PYTHONBASE}//} -b ${PREFIX}/bin |