You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1896 lines
71 KiB

  1. #! /bin/sh -e
  2. # DP: Lossless-crop patch from <http://sylvana.net/jpegcrop/croppatch.tar.gz>
  3. # DP: by <guido@jpegclub.org>.
  4. case "$1" in
  5. -patch) patch -f --no-backup-if-mismatch -p1 < $0;;
  6. -unpatch) patch -f --no-backup-if-mismatch -R -p1 < $0;;
  7. *)
  8. echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
  9. exit 1
  10. esac
  11. exit 0
  12. @DPATCH@
  13. diff -urNad /home/bill/debian/libjpeg/libjpeg6b-6b/jerror.h libjpeg6b-6b/jerror.h
  14. --- /home/bill/debian/libjpeg/libjpeg6b-6b/jerror.h 2003-09-22 18:15:48.000000000 +0200
  15. +++ libjpeg6b-6b/jerror.h 2003-09-22 18:16:12.000000000 +0200
  16. @@ -45,6 +45,7 @@
  17. JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
  18. JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
  19. JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
  20. +JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
  21. JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
  22. JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
  23. JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
  24. diff -urNad /home/bill/debian/libjpeg/libjpeg6b-6b/jpegtran.c libjpeg6b-6b/jpegtran.c
  25. --- /home/bill/debian/libjpeg/libjpeg6b-6b/jpegtran.c 2003-09-22 18:15:48.000000000 +0200
  26. +++ libjpeg6b-6b/jpegtran.c 2003-09-22 18:16:22.000000000 +0200
  27. @@ -1,7 +1,7 @@
  28. /*
  29. * jpegtran.c
  30. *
  31. - * Copyright (C) 1995-1997, Thomas G. Lane.
  32. + * Copyright (C) 1995-2001, Thomas G. Lane.
  33. * This file is part of the Independent JPEG Group's software.
  34. * For conditions of distribution and use, see the accompanying README file.
  35. *
  36. @@ -64,8 +64,10 @@
  37. #endif
  38. #if TRANSFORMS_SUPPORTED
  39. fprintf(stderr, "Switches for modifying the image:\n");
  40. + fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular subarea\n");
  41. fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n");
  42. fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n");
  43. + fprintf(stderr, " -perfect Fail if there is non-transformable edge blocks\n");
  44. fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n");
  45. fprintf(stderr, " -transpose Transpose image\n");
  46. fprintf(stderr, " -transverse Transverse transpose image\n");
  47. @@ -133,7 +135,9 @@
  48. copyoption = JCOPYOPT_DEFAULT;
  49. transformoption.transform = JXFORM_NONE;
  50. transformoption.trim = FALSE;
  51. + transformoption.perfect = FALSE;
  52. transformoption.force_grayscale = FALSE;
  53. + transformoption.crop = FALSE;
  54. cinfo->err->trace_level = 0;
  55. /* Scan command line options, adjust parameters */
  56. @@ -160,7 +164,7 @@
  57. exit(EXIT_FAILURE);
  58. #endif
  59. - } else if (keymatch(arg, "copy", 1)) {
  60. + } else if (keymatch(arg, "copy", 2)) {
  61. /* Select which extra markers to copy. */
  62. if (++argn >= argc) /* advance to next argument */
  63. usage();
  64. @@ -173,6 +177,20 @@
  65. } else
  66. usage();
  67. + } else if (keymatch(arg, "crop", 2)) {
  68. + /* Perform lossless cropping. */
  69. +#if TRANSFORMS_SUPPORTED
  70. + if (++argn >= argc) /* advance to next argument */
  71. + usage();
  72. + if (! jtransform_parse_crop_spec(&transformoption, argv[argn])) {
  73. + fprintf(stderr, "%s: bogus -crop argument '%s'\n",
  74. + progname, argv[argn]);
  75. + exit(EXIT_FAILURE);
  76. + }
  77. +#else
  78. + select_transform(JXFORM_NONE); /* force an error */
  79. +#endif
  80. +
  81. } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
  82. /* Enable debug printouts. */
  83. /* On first -d, print version identification */
  84. @@ -233,7 +251,12 @@
  85. usage();
  86. outfilename = argv[argn]; /* save it away for later use */
  87. - } else if (keymatch(arg, "progressive", 1)) {
  88. + } else if (keymatch(arg, "perfect", 2)) {
  89. + /* Fail if there is any partial edge MCUs that the transform can't
  90. + * handle. */
  91. + transformoption.perfect = TRUE;
  92. +
  93. + } else if (keymatch(arg, "progressive", 2)) {
  94. /* Select simple progressive mode. */
  95. #ifdef C_PROGRESSIVE_SUPPORTED
  96. simple_progressive = TRUE;
  97. @@ -342,8 +365,10 @@
  98. jvirt_barray_ptr * src_coef_arrays;
  99. jvirt_barray_ptr * dst_coef_arrays;
  100. int file_index;
  101. - FILE * input_file;
  102. - FILE * output_file;
  103. + /* We assume all-in-memory processing and can therefore use only a
  104. + * single file pointer for sequential input and output operation.
  105. + */
  106. + FILE * fp;
  107. /* On Mac, fetch a command line. */
  108. #ifdef USE_CCOMMAND
  109. @@ -406,24 +431,13 @@
  110. /* Open the input file. */
  111. if (file_index < argc) {
  112. - if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
  113. - fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
  114. + if ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) {
  115. + fprintf(stderr, "%s: can't open %s for reading\n", progname, argv[file_index]);
  116. exit(EXIT_FAILURE);
  117. }
  118. } else {
  119. /* default input file is stdin */
  120. - input_file = read_stdin();
  121. - }
  122. -
  123. - /* Open the output file. */
  124. - if (outfilename != NULL) {
  125. - if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
  126. - fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
  127. - exit(EXIT_FAILURE);
  128. - }
  129. - } else {
  130. - /* default output file is stdout */
  131. - output_file = write_stdout();
  132. + fp = read_stdin();
  133. }
  134. #ifdef PROGRESS_REPORT
  135. @@ -431,7 +445,7 @@
  136. #endif
  137. /* Specify data source for decompression */
  138. - jpeg_stdio_src(&srcinfo, input_file);
  139. + jpeg_stdio_src(&srcinfo, fp);
  140. /* Enable saving of extra markers that we want to copy */
  141. jcopy_markers_setup(&srcinfo, copyoption);
  142. @@ -443,6 +457,15 @@
  143. * jpeg_read_coefficients so that memory allocation will be done right.
  144. */
  145. #if TRANSFORMS_SUPPORTED
  146. + /* Fails right away if -perfect is given and transformation is not perfect.
  147. + */
  148. + if (transformoption.perfect &&
  149. + !jtransform_perfect_transform(srcinfo.image_width, srcinfo.image_height,
  150. + srcinfo.max_h_samp_factor * DCTSIZE, srcinfo.max_v_samp_factor * DCTSIZE,
  151. + transformoption.transform)) {
  152. + fprintf(stderr, "%s: transformation is not perfect\n", progname);
  153. + exit(EXIT_FAILURE);
  154. + }
  155. jtransform_request_workspace(&srcinfo, &transformoption);
  156. #endif
  157. @@ -463,11 +486,32 @@
  158. dst_coef_arrays = src_coef_arrays;
  159. #endif
  160. + /* Close input file, if we opened it.
  161. + * Note: we assume that jpeg_read_coefficients consumed all input
  162. + * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
  163. + * only consume more while (! cinfo->inputctl->eoi_reached).
  164. + * We cannot call jpeg_finish_decompress here since we still need the
  165. + * virtual arrays allocated from the source object for processing.
  166. + */
  167. + if (fp != stdin)
  168. + fclose(fp);
  169. +
  170. + /* Open the output file. */
  171. + if (outfilename != NULL) {
  172. + if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) {
  173. + fprintf(stderr, "%s: can't open %s for writing\n", progname, outfilename);
  174. + exit(EXIT_FAILURE);
  175. + }
  176. + } else {
  177. + /* default output file is stdout */
  178. + fp = write_stdout();
  179. + }
  180. +
  181. /* Adjust default compression parameters by re-parsing the options */
  182. file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
  183. /* Specify data destination for compression */
  184. - jpeg_stdio_dest(&dstinfo, output_file);
  185. + jpeg_stdio_dest(&dstinfo, fp);
  186. /* Start compressor (note no image data is actually written here) */
  187. jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
  188. @@ -488,11 +532,9 @@
  189. (void) jpeg_finish_decompress(&srcinfo);
  190. jpeg_destroy_decompress(&srcinfo);
  191. - /* Close files, if we opened them */
  192. - if (input_file != stdin)
  193. - fclose(input_file);
  194. - if (output_file != stdout)
  195. - fclose(output_file);
  196. + /* Close output file, if we opened it */
  197. + if (fp != stdout)
  198. + fclose(fp);
  199. #ifdef PROGRESS_REPORT
  200. end_progress_monitor((j_common_ptr) &dstinfo);
  201. diff -urNad /home/bill/debian/libjpeg/libjpeg6b-6b/transupp.c libjpeg6b-6b/transupp.c
  202. --- /home/bill/debian/libjpeg/libjpeg6b-6b/transupp.c 2003-09-22 18:15:49.000000000 +0200
  203. +++ libjpeg6b-6b/transupp.c 2003-09-22 18:16:28.000000000 +0200
  204. @@ -1,7 +1,7 @@
  205. /*
  206. * transupp.c
  207. *
  208. - * Copyright (C) 1997, Thomas G. Lane.
  209. + * Copyright (C) 1997-2001, Thomas G. Lane.
  210. * This file is part of the Independent JPEG Group's software.
  211. * For conditions of distribution and use, see the accompanying README file.
  212. *
  213. @@ -20,6 +20,7 @@
  214. #include "jinclude.h"
  215. #include "jpeglib.h"
  216. #include "transupp.h" /* My own external interface */
  217. +#include <ctype.h> /* to declare isdigit() */
  218. #if TRANSFORMS_SUPPORTED
  219. @@ -28,7 +29,8 @@
  220. * Lossless image transformation routines. These routines work on DCT
  221. * coefficient arrays and thus do not require any lossy decompression
  222. * or recompression of the image.
  223. - * Thanks to Guido Vollbeding for the initial design and code of this feature.
  224. + * Thanks to Guido Vollbeding for the initial design and code of this feature,
  225. + * and to Ben Jackson for introducing the cropping feature.
  226. *
  227. * Horizontal flipping is done in-place, using a single top-to-bottom
  228. * pass through the virtual source array. It will thus be much the
  229. @@ -42,6 +44,13 @@
  230. * arrays for most of the transforms. That could result in much thrashing
  231. * if the image is larger than main memory.
  232. *
  233. + * If cropping or trimming is involved, the destination arrays may be smaller
  234. + * than the source arrays. Note it is not possible to do horizontal flip
  235. + * in-place when a nonzero Y crop offset is specified, since we'd have to move
  236. + * data from one block row to another but the virtual array manager doesn't
  237. + * guarantee we can touch more than one row at a time. So in that case,
  238. + * we have to use a separate destination array.
  239. + *
  240. * Some notes about the operating environment of the individual transform
  241. * routines:
  242. * 1. Both the source and destination virtual arrays are allocated from the
  243. @@ -54,20 +63,65 @@
  244. * and we may as well take that as the effective iMCU size.
  245. * 4. When "trim" is in effect, the destination's dimensions will be the
  246. * trimmed values but the source's will be untrimmed.
  247. - * 5. All the routines assume that the source and destination buffers are
  248. + * 5. When "crop" is in effect, the destination's dimensions will be the
  249. + * cropped values but the source's will be uncropped. Each transform
  250. + * routine is responsible for picking up source data starting at the
  251. + * correct X and Y offset for the crop region. (The X and Y offsets
  252. + * passed to the transform routines are measured in iMCU blocks of the
  253. + * destination.)
  254. + * 6. All the routines assume that the source and destination buffers are
  255. * padded out to a full iMCU boundary. This is true, although for the
  256. * source buffer it is an undocumented property of jdcoefct.c.
  257. - * Notes 2,3,4 boil down to this: generally we should use the destination's
  258. - * dimensions and ignore the source's.
  259. */
  260. LOCAL(void)
  261. -do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  262. - jvirt_barray_ptr *src_coef_arrays)
  263. -/* Horizontal flip; done in-place, so no separate dest array is required */
  264. +do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  265. + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  266. + jvirt_barray_ptr *src_coef_arrays,
  267. + jvirt_barray_ptr *dst_coef_arrays)
  268. +/* Crop. This is only used when no rotate/flip is requested with the crop. */
  269. {
  270. - JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
  271. + JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
  272. + int ci, offset_y;
  273. + JBLOCKARRAY src_buffer, dst_buffer;
  274. + jpeg_component_info *compptr;
  275. +
  276. + /* We simply have to copy the right amount of data (the destination's
  277. + * image size) starting at the given X and Y offsets in the source.
  278. + */
  279. + for (ci = 0; ci < dstinfo->num_components; ci++) {
  280. + compptr = dstinfo->comp_info + ci;
  281. + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  282. + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  283. + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  284. + dst_blk_y += compptr->v_samp_factor) {
  285. + dst_buffer = (*srcinfo->mem->access_virt_barray)
  286. + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
  287. + (JDIMENSION) compptr->v_samp_factor, TRUE);
  288. + src_buffer = (*srcinfo->mem->access_virt_barray)
  289. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  290. + dst_blk_y + y_crop_blocks,
  291. + (JDIMENSION) compptr->v_samp_factor, FALSE);
  292. + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  293. + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
  294. + dst_buffer[offset_y],
  295. + compptr->width_in_blocks);
  296. + }
  297. + }
  298. + }
  299. +}
  300. +
  301. +
  302. +LOCAL(void)
  303. +do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  304. + JDIMENSION x_crop_offset,
  305. + jvirt_barray_ptr *src_coef_arrays)
  306. +/* Horizontal flip; done in-place, so no separate dest array is required.
  307. + * NB: this only works when y_crop_offset is zero.
  308. + */
  309. +{
  310. + JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
  311. int ci, k, offset_y;
  312. JBLOCKARRAY buffer;
  313. JCOEFPTR ptr1, ptr2;
  314. @@ -79,17 +133,19 @@
  315. * mirroring by changing the signs of odd-numbered columns.
  316. * Partial iMCUs at the right edge are left untouched.
  317. */
  318. - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
  319. + MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
  320. for (ci = 0; ci < dstinfo->num_components; ci++) {
  321. compptr = dstinfo->comp_info + ci;
  322. comp_width = MCU_cols * compptr->h_samp_factor;
  323. + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  324. for (blk_y = 0; blk_y < compptr->height_in_blocks;
  325. blk_y += compptr->v_samp_factor) {
  326. buffer = (*srcinfo->mem->access_virt_barray)
  327. ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
  328. (JDIMENSION) compptr->v_samp_factor, TRUE);
  329. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  330. + /* Do the mirroring */
  331. for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
  332. ptr1 = buffer[offset_y][blk_x];
  333. ptr2 = buffer[offset_y][comp_width - blk_x - 1];
  334. @@ -105,6 +161,79 @@
  335. *ptr2++ = -temp1;
  336. }
  337. }
  338. + if (x_crop_blocks > 0) {
  339. + /* Now left-justify the portion of the data to be kept.
  340. + * We can't use a single jcopy_block_row() call because that routine
  341. + * depends on memcpy(), whose behavior is unspecified for overlapping
  342. + * source and destination areas. Sigh.
  343. + */
  344. + for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
  345. + jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
  346. + buffer[offset_y] + blk_x,
  347. + (JDIMENSION) 1);
  348. + }
  349. + }
  350. + }
  351. + }
  352. + }
  353. +}
  354. +
  355. +
  356. +LOCAL(void)
  357. +do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  358. + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  359. + jvirt_barray_ptr *src_coef_arrays,
  360. + jvirt_barray_ptr *dst_coef_arrays)
  361. +/* Horizontal flip in general cropping case */
  362. +{
  363. + JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
  364. + JDIMENSION x_crop_blocks, y_crop_blocks;
  365. + int ci, k, offset_y;
  366. + JBLOCKARRAY src_buffer, dst_buffer;
  367. + JBLOCKROW src_row_ptr, dst_row_ptr;
  368. + JCOEFPTR src_ptr, dst_ptr;
  369. + jpeg_component_info *compptr;
  370. +
  371. + /* Here we must output into a separate array because we can't touch
  372. + * different rows of a single virtual array simultaneously. Otherwise,
  373. + * this is essentially the same as the routine above.
  374. + */
  375. + MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
  376. +
  377. + for (ci = 0; ci < dstinfo->num_components; ci++) {
  378. + compptr = dstinfo->comp_info + ci;
  379. + comp_width = MCU_cols * compptr->h_samp_factor;
  380. + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  381. + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  382. + for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  383. + dst_blk_y += compptr->v_samp_factor) {
  384. + dst_buffer = (*srcinfo->mem->access_virt_barray)
  385. + ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
  386. + (JDIMENSION) compptr->v_samp_factor, TRUE);
  387. + src_buffer = (*srcinfo->mem->access_virt_barray)
  388. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  389. + dst_blk_y + y_crop_blocks,
  390. + (JDIMENSION) compptr->v_samp_factor, FALSE);
  391. + for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  392. + dst_row_ptr = dst_buffer[offset_y];
  393. + src_row_ptr = src_buffer[offset_y];
  394. + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
  395. + if (x_crop_blocks + dst_blk_x < comp_width) {
  396. + /* Do the mirrorable blocks */
  397. + dst_ptr = dst_row_ptr[dst_blk_x];
  398. + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
  399. + /* this unrolled loop doesn't need to know which row it's on... */
  400. + for (k = 0; k < DCTSIZE2; k += 2) {
  401. + *dst_ptr++ = *src_ptr++; /* copy even column */
  402. + *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
  403. + }
  404. + } else {
  405. + /* Copy last partial block(s) verbatim */
  406. + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
  407. + dst_row_ptr + dst_blk_x,
  408. + (JDIMENSION) 1);
  409. + }
  410. + }
  411. }
  412. }
  413. }
  414. @@ -113,11 +242,13 @@
  415. LOCAL(void)
  416. do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  417. + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  418. jvirt_barray_ptr *src_coef_arrays,
  419. jvirt_barray_ptr *dst_coef_arrays)
  420. /* Vertical flip */
  421. {
  422. JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
  423. + JDIMENSION x_crop_blocks, y_crop_blocks;
  424. int ci, i, j, offset_y;
  425. JBLOCKARRAY src_buffer, dst_buffer;
  426. JBLOCKROW src_row_ptr, dst_row_ptr;
  427. @@ -131,33 +262,38 @@
  428. * of odd-numbered rows.
  429. * Partial iMCUs at the bottom edge are copied verbatim.
  430. */
  431. - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
  432. + MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
  433. for (ci = 0; ci < dstinfo->num_components; ci++) {
  434. compptr = dstinfo->comp_info + ci;
  435. comp_height = MCU_rows * compptr->v_samp_factor;
  436. + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  437. + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  438. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  439. dst_blk_y += compptr->v_samp_factor) {
  440. dst_buffer = (*srcinfo->mem->access_virt_barray)
  441. ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
  442. (JDIMENSION) compptr->v_samp_factor, TRUE);
  443. - if (dst_blk_y < comp_height) {
  444. + if (y_crop_blocks + dst_blk_y < comp_height) {
  445. /* Row is within the mirrorable area. */
  446. src_buffer = (*srcinfo->mem->access_virt_barray)
  447. ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  448. - comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
  449. + comp_height - y_crop_blocks - dst_blk_y -
  450. + (JDIMENSION) compptr->v_samp_factor,
  451. (JDIMENSION) compptr->v_samp_factor, FALSE);
  452. } else {
  453. /* Bottom-edge blocks will be copied verbatim. */
  454. src_buffer = (*srcinfo->mem->access_virt_barray)
  455. - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
  456. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  457. + dst_blk_y + y_crop_blocks,
  458. (JDIMENSION) compptr->v_samp_factor, FALSE);
  459. }
  460. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  461. - if (dst_blk_y < comp_height) {
  462. + if (y_crop_blocks + dst_blk_y < comp_height) {
  463. /* Row is within the mirrorable area. */
  464. dst_row_ptr = dst_buffer[offset_y];
  465. src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
  466. + src_row_ptr += x_crop_blocks;
  467. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  468. dst_blk_x++) {
  469. dst_ptr = dst_row_ptr[dst_blk_x];
  470. @@ -173,7 +309,8 @@
  471. }
  472. } else {
  473. /* Just copy row verbatim. */
  474. - jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
  475. + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
  476. + dst_buffer[offset_y],
  477. compptr->width_in_blocks);
  478. }
  479. }
  480. @@ -184,11 +321,12 @@
  481. LOCAL(void)
  482. do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  483. + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  484. jvirt_barray_ptr *src_coef_arrays,
  485. jvirt_barray_ptr *dst_coef_arrays)
  486. /* Transpose source into destination */
  487. {
  488. - JDIMENSION dst_blk_x, dst_blk_y;
  489. + JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
  490. int ci, i, j, offset_x, offset_y;
  491. JBLOCKARRAY src_buffer, dst_buffer;
  492. JCOEFPTR src_ptr, dst_ptr;
  493. @@ -201,6 +339,8 @@
  494. */
  495. for (ci = 0; ci < dstinfo->num_components; ci++) {
  496. compptr = dstinfo->comp_info + ci;
  497. + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  498. + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  499. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  500. dst_blk_y += compptr->v_samp_factor) {
  501. dst_buffer = (*srcinfo->mem->access_virt_barray)
  502. @@ -210,11 +350,12 @@
  503. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  504. dst_blk_x += compptr->h_samp_factor) {
  505. src_buffer = (*srcinfo->mem->access_virt_barray)
  506. - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
  507. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  508. + dst_blk_x + x_crop_blocks,
  509. (JDIMENSION) compptr->h_samp_factor, FALSE);
  510. for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
  511. - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
  512. dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  513. + src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
  514. for (i = 0; i < DCTSIZE; i++)
  515. for (j = 0; j < DCTSIZE; j++)
  516. dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
  517. @@ -228,6 +369,7 @@
  518. LOCAL(void)
  519. do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  520. + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  521. jvirt_barray_ptr *src_coef_arrays,
  522. jvirt_barray_ptr *dst_coef_arrays)
  523. /* 90 degree rotation is equivalent to
  524. @@ -237,6 +379,7 @@
  525. */
  526. {
  527. JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
  528. + JDIMENSION x_crop_blocks, y_crop_blocks;
  529. int ci, i, j, offset_x, offset_y;
  530. JBLOCKARRAY src_buffer, dst_buffer;
  531. JCOEFPTR src_ptr, dst_ptr;
  532. @@ -246,11 +389,13 @@
  533. * at the (output) right edge properly. They just get transposed and
  534. * not mirrored.
  535. */
  536. - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
  537. + MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE);
  538. for (ci = 0; ci < dstinfo->num_components; ci++) {
  539. compptr = dstinfo->comp_info + ci;
  540. comp_width = MCU_cols * compptr->h_samp_factor;
  541. + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  542. + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  543. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  544. dst_blk_y += compptr->v_samp_factor) {
  545. dst_buffer = (*srcinfo->mem->access_virt_barray)
  546. @@ -259,15 +404,26 @@
  547. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  548. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  549. dst_blk_x += compptr->h_samp_factor) {
  550. - src_buffer = (*srcinfo->mem->access_virt_barray)
  551. - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
  552. - (JDIMENSION) compptr->h_samp_factor, FALSE);
  553. + if (x_crop_blocks + dst_blk_x < comp_width) {
  554. + /* Block is within the mirrorable area. */
  555. + src_buffer = (*srcinfo->mem->access_virt_barray)
  556. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  557. + comp_width - x_crop_blocks - dst_blk_x -
  558. + (JDIMENSION) compptr->h_samp_factor,
  559. + (JDIMENSION) compptr->h_samp_factor, FALSE);
  560. + } else {
  561. + /* Edge blocks are transposed but not mirrored. */
  562. + src_buffer = (*srcinfo->mem->access_virt_barray)
  563. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  564. + dst_blk_x + x_crop_blocks,
  565. + (JDIMENSION) compptr->h_samp_factor, FALSE);
  566. + }
  567. for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
  568. - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
  569. - if (dst_blk_x < comp_width) {
  570. + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  571. + if (x_crop_blocks + dst_blk_x < comp_width) {
  572. /* Block is within the mirrorable area. */
  573. - dst_ptr = dst_buffer[offset_y]
  574. - [comp_width - dst_blk_x - offset_x - 1];
  575. + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
  576. + [dst_blk_y + offset_y + y_crop_blocks];
  577. for (i = 0; i < DCTSIZE; i++) {
  578. for (j = 0; j < DCTSIZE; j++)
  579. dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
  580. @@ -277,7 +433,8 @@
  581. }
  582. } else {
  583. /* Edge blocks are transposed but not mirrored. */
  584. - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  585. + src_ptr = src_buffer[offset_x]
  586. + [dst_blk_y + offset_y + y_crop_blocks];
  587. for (i = 0; i < DCTSIZE; i++)
  588. for (j = 0; j < DCTSIZE; j++)
  589. dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
  590. @@ -292,6 +449,7 @@
  591. LOCAL(void)
  592. do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  593. + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  594. jvirt_barray_ptr *src_coef_arrays,
  595. jvirt_barray_ptr *dst_coef_arrays)
  596. /* 270 degree rotation is equivalent to
  597. @@ -301,6 +459,7 @@
  598. */
  599. {
  600. JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
  601. + JDIMENSION x_crop_blocks, y_crop_blocks;
  602. int ci, i, j, offset_x, offset_y;
  603. JBLOCKARRAY src_buffer, dst_buffer;
  604. JCOEFPTR src_ptr, dst_ptr;
  605. @@ -310,11 +469,13 @@
  606. * at the (output) bottom edge properly. They just get transposed and
  607. * not mirrored.
  608. */
  609. - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
  610. + MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE);
  611. for (ci = 0; ci < dstinfo->num_components; ci++) {
  612. compptr = dstinfo->comp_info + ci;
  613. comp_height = MCU_rows * compptr->v_samp_factor;
  614. + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  615. + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  616. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  617. dst_blk_y += compptr->v_samp_factor) {
  618. dst_buffer = (*srcinfo->mem->access_virt_barray)
  619. @@ -324,14 +485,15 @@
  620. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  621. dst_blk_x += compptr->h_samp_factor) {
  622. src_buffer = (*srcinfo->mem->access_virt_barray)
  623. - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
  624. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  625. + dst_blk_x + x_crop_blocks,
  626. (JDIMENSION) compptr->h_samp_factor, FALSE);
  627. for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
  628. dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  629. - if (dst_blk_y < comp_height) {
  630. + if (y_crop_blocks + dst_blk_y < comp_height) {
  631. /* Block is within the mirrorable area. */
  632. src_ptr = src_buffer[offset_x]
  633. - [comp_height - dst_blk_y - offset_y - 1];
  634. + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
  635. for (i = 0; i < DCTSIZE; i++) {
  636. for (j = 0; j < DCTSIZE; j++) {
  637. dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
  638. @@ -341,7 +503,8 @@
  639. }
  640. } else {
  641. /* Edge blocks are transposed but not mirrored. */
  642. - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
  643. + src_ptr = src_buffer[offset_x]
  644. + [dst_blk_y + offset_y + y_crop_blocks];
  645. for (i = 0; i < DCTSIZE; i++)
  646. for (j = 0; j < DCTSIZE; j++)
  647. dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
  648. @@ -356,6 +519,7 @@
  649. LOCAL(void)
  650. do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  651. + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  652. jvirt_barray_ptr *src_coef_arrays,
  653. jvirt_barray_ptr *dst_coef_arrays)
  654. /* 180 degree rotation is equivalent to
  655. @@ -365,89 +529,93 @@
  656. */
  657. {
  658. JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
  659. + JDIMENSION x_crop_blocks, y_crop_blocks;
  660. int ci, i, j, offset_y;
  661. JBLOCKARRAY src_buffer, dst_buffer;
  662. JBLOCKROW src_row_ptr, dst_row_ptr;
  663. JCOEFPTR src_ptr, dst_ptr;
  664. jpeg_component_info *compptr;
  665. - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
  666. - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
  667. + MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
  668. + MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
  669. for (ci = 0; ci < dstinfo->num_components; ci++) {
  670. compptr = dstinfo->comp_info + ci;
  671. comp_width = MCU_cols * compptr->h_samp_factor;
  672. comp_height = MCU_rows * compptr->v_samp_factor;
  673. + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  674. + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  675. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  676. dst_blk_y += compptr->v_samp_factor) {
  677. dst_buffer = (*srcinfo->mem->access_virt_barray)
  678. ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
  679. (JDIMENSION) compptr->v_samp_factor, TRUE);
  680. - if (dst_blk_y < comp_height) {
  681. + if (y_crop_blocks + dst_blk_y < comp_height) {
  682. /* Row is within the vertically mirrorable area. */
  683. src_buffer = (*srcinfo->mem->access_virt_barray)
  684. ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  685. - comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
  686. + comp_height - y_crop_blocks - dst_blk_y -
  687. + (JDIMENSION) compptr->v_samp_factor,
  688. (JDIMENSION) compptr->v_samp_factor, FALSE);
  689. } else {
  690. /* Bottom-edge rows are only mirrored horizontally. */
  691. src_buffer = (*srcinfo->mem->access_virt_barray)
  692. - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
  693. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  694. + dst_blk_y + y_crop_blocks,
  695. (JDIMENSION) compptr->v_samp_factor, FALSE);
  696. }
  697. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  698. - if (dst_blk_y < comp_height) {
  699. + dst_row_ptr = dst_buffer[offset_y];
  700. + if (y_crop_blocks + dst_blk_y < comp_height) {
  701. /* Row is within the mirrorable area. */
  702. - dst_row_ptr = dst_buffer[offset_y];
  703. src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
  704. - /* Process the blocks that can be mirrored both ways. */
  705. - for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
  706. + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
  707. dst_ptr = dst_row_ptr[dst_blk_x];
  708. - src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
  709. - for (i = 0; i < DCTSIZE; i += 2) {
  710. - /* For even row, negate every odd column. */
  711. - for (j = 0; j < DCTSIZE; j += 2) {
  712. - *dst_ptr++ = *src_ptr++;
  713. - *dst_ptr++ = - *src_ptr++;
  714. + if (x_crop_blocks + dst_blk_x < comp_width) {
  715. + /* Process the blocks that can be mirrored both ways. */
  716. + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
  717. + for (i = 0; i < DCTSIZE; i += 2) {
  718. + /* For even row, negate every odd column. */
  719. + for (j = 0; j < DCTSIZE; j += 2) {
  720. + *dst_ptr++ = *src_ptr++;
  721. + *dst_ptr++ = - *src_ptr++;
  722. + }
  723. + /* For odd row, negate every even column. */
  724. + for (j = 0; j < DCTSIZE; j += 2) {
  725. + *dst_ptr++ = - *src_ptr++;
  726. + *dst_ptr++ = *src_ptr++;
  727. + }
  728. }
  729. - /* For odd row, negate every even column. */
  730. - for (j = 0; j < DCTSIZE; j += 2) {
  731. - *dst_ptr++ = - *src_ptr++;
  732. - *dst_ptr++ = *src_ptr++;
  733. + } else {
  734. + /* Any remaining right-edge blocks are only mirrored vertically. */
  735. + src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
  736. + for (i = 0; i < DCTSIZE; i += 2) {
  737. + for (j = 0; j < DCTSIZE; j++)
  738. + *dst_ptr++ = *src_ptr++;
  739. + for (j = 0; j < DCTSIZE; j++)
  740. + *dst_ptr++ = - *src_ptr++;
  741. }
  742. }
  743. }
  744. - /* Any remaining right-edge blocks are only mirrored vertically. */
  745. - for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
  746. - dst_ptr = dst_row_ptr[dst_blk_x];
  747. - src_ptr = src_row_ptr[dst_blk_x];
  748. - for (i = 0; i < DCTSIZE; i += 2) {
  749. - for (j = 0; j < DCTSIZE; j++)
  750. - *dst_ptr++ = *src_ptr++;
  751. - for (j = 0; j < DCTSIZE; j++)
  752. - *dst_ptr++ = - *src_ptr++;
  753. - }
  754. - }
  755. } else {
  756. /* Remaining rows are just mirrored horizontally. */
  757. - dst_row_ptr = dst_buffer[offset_y];
  758. src_row_ptr = src_buffer[offset_y];
  759. - /* Process the blocks that can be mirrored. */
  760. - for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
  761. - dst_ptr = dst_row_ptr[dst_blk_x];
  762. - src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
  763. - for (i = 0; i < DCTSIZE2; i += 2) {
  764. - *dst_ptr++ = *src_ptr++;
  765. - *dst_ptr++ = - *src_ptr++;
  766. + for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
  767. + if (x_crop_blocks + dst_blk_x < comp_width) {
  768. + /* Process the blocks that can be mirrored. */
  769. + dst_ptr = dst_row_ptr[dst_blk_x];
  770. + src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
  771. + for (i = 0; i < DCTSIZE2; i += 2) {
  772. + *dst_ptr++ = *src_ptr++;
  773. + *dst_ptr++ = - *src_ptr++;
  774. + }
  775. + } else {
  776. + /* Any remaining right-edge blocks are only copied. */
  777. + jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
  778. + dst_row_ptr + dst_blk_x,
  779. + (JDIMENSION) 1);
  780. }
  781. }
  782. - /* Any remaining right-edge blocks are only copied. */
  783. - for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
  784. - dst_ptr = dst_row_ptr[dst_blk_x];
  785. - src_ptr = src_row_ptr[dst_blk_x];
  786. - for (i = 0; i < DCTSIZE2; i++)
  787. - *dst_ptr++ = *src_ptr++;
  788. - }
  789. }
  790. }
  791. }
  792. @@ -457,6 +625,7 @@
  793. LOCAL(void)
  794. do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  795. + JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  796. jvirt_barray_ptr *src_coef_arrays,
  797. jvirt_barray_ptr *dst_coef_arrays)
  798. /* Transverse transpose is equivalent to
  799. @@ -470,18 +639,21 @@
  800. */
  801. {
  802. JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
  803. + JDIMENSION x_crop_blocks, y_crop_blocks;
  804. int ci, i, j, offset_x, offset_y;
  805. JBLOCKARRAY src_buffer, dst_buffer;
  806. JCOEFPTR src_ptr, dst_ptr;
  807. jpeg_component_info *compptr;
  808. - MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
  809. - MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
  810. + MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE);
  811. + MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE);
  812. for (ci = 0; ci < dstinfo->num_components; ci++) {
  813. compptr = dstinfo->comp_info + ci;
  814. comp_width = MCU_cols * compptr->h_samp_factor;
  815. comp_height = MCU_rows * compptr->v_samp_factor;
  816. + x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  817. + y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  818. for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  819. dst_blk_y += compptr->v_samp_factor) {
  820. dst_buffer = (*srcinfo->mem->access_virt_barray)
  821. @@ -490,17 +662,26 @@
  822. for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
  823. for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
  824. dst_blk_x += compptr->h_samp_factor) {
  825. - src_buffer = (*srcinfo->mem->access_virt_barray)
  826. - ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
  827. - (JDIMENSION) compptr->h_samp_factor, FALSE);
  828. + if (x_crop_blocks + dst_blk_x < comp_width) {
  829. + /* Block is within the mirrorable area. */
  830. + src_buffer = (*srcinfo->mem->access_virt_barray)
  831. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  832. + comp_width - x_crop_blocks - dst_blk_x -
  833. + (JDIMENSION) compptr->h_samp_factor,
  834. + (JDIMENSION) compptr->h_samp_factor, FALSE);
  835. + } else {
  836. + src_buffer = (*srcinfo->mem->access_virt_barray)
  837. + ((j_common_ptr) srcinfo, src_coef_arrays[ci],
  838. + dst_blk_x + x_crop_blocks,
  839. + (JDIMENSION) compptr->h_samp_factor, FALSE);
  840. + }
  841. for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
  842. - if (dst_blk_y < comp_height) {
  843. - src_ptr = src_buffer[offset_x]
  844. - [comp_height - dst_blk_y - offset_y - 1];
  845. - if (dst_blk_x < comp_width) {
  846. + dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  847. + if (y_crop_blocks + dst_blk_y < comp_height) {
  848. + if (x_crop_blocks + dst_blk_x < comp_width) {
  849. /* Block is within the mirrorable area. */
  850. - dst_ptr = dst_buffer[offset_y]
  851. - [comp_width - dst_blk_x - offset_x - 1];
  852. + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
  853. + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
  854. for (i = 0; i < DCTSIZE; i++) {
  855. for (j = 0; j < DCTSIZE; j++) {
  856. dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
  857. @@ -516,7 +697,8 @@
  858. }
  859. } else {
  860. /* Right-edge blocks are mirrored in y only */
  861. - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  862. + src_ptr = src_buffer[offset_x]
  863. + [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
  864. for (i = 0; i < DCTSIZE; i++) {
  865. for (j = 0; j < DCTSIZE; j++) {
  866. dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
  867. @@ -526,11 +708,10 @@
  868. }
  869. }
  870. } else {
  871. - src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
  872. - if (dst_blk_x < comp_width) {
  873. + if (x_crop_blocks + dst_blk_x < comp_width) {
  874. /* Bottom-edge blocks are mirrored in x only */
  875. - dst_ptr = dst_buffer[offset_y]
  876. - [comp_width - dst_blk_x - offset_x - 1];
  877. + src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
  878. + [dst_blk_y + offset_y + y_crop_blocks];
  879. for (i = 0; i < DCTSIZE; i++) {
  880. for (j = 0; j < DCTSIZE; j++)
  881. dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
  882. @@ -540,7 +721,8 @@
  883. }
  884. } else {
  885. /* At lower right corner, just transpose, no mirroring */
  886. - dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
  887. + src_ptr = src_buffer[offset_x]
  888. + [dst_blk_y + offset_y + y_crop_blocks];
  889. for (i = 0; i < DCTSIZE; i++)
  890. for (j = 0; j < DCTSIZE; j++)
  891. dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
  892. @@ -554,8 +736,116 @@
  893. }
  894. +/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
  895. + * Returns TRUE if valid integer found, FALSE if not.
  896. + * *strptr is advanced over the digit string, and *result is set to its value.
  897. + */
  898. +
  899. +LOCAL(boolean)
  900. +jt_read_integer (const char ** strptr, JDIMENSION * result)
  901. +{
  902. + const char * ptr = *strptr;
  903. + JDIMENSION val = 0;
  904. +
  905. + for (; isdigit(*ptr); ptr++) {
  906. + val = val * 10 + (JDIMENSION) (*ptr - '0');
  907. + }
  908. + *result = val;
  909. + if (ptr == *strptr)
  910. + return FALSE; /* oops, no digits */
  911. + *strptr = ptr;
  912. + return TRUE;
  913. +}
  914. +
  915. +
  916. +/* Parse a crop specification (written in X11 geometry style).
  917. + * The routine returns TRUE if the spec string is valid, FALSE if not.
  918. + *
  919. + * The crop spec string should have the format
  920. + * <width>x<height>{+-}<xoffset>{+-}<yoffset>
  921. + * where width, height, xoffset, and yoffset are unsigned integers.
  922. + * Each of the elements can be omitted to indicate a default value.
  923. + * (A weakness of this style is that it is not possible to omit xoffset
  924. + * while specifying yoffset, since they look alike.)
  925. + *
  926. + * This code is loosely based on XParseGeometry from the X11 distribution.
  927. + */
  928. +
  929. +GLOBAL(boolean)
  930. +jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec)
  931. +{
  932. + info->crop = FALSE;
  933. + info->crop_width_set = JCROP_UNSET;
  934. + info->crop_height_set = JCROP_UNSET;
  935. + info->crop_xoffset_set = JCROP_UNSET;
  936. + info->crop_yoffset_set = JCROP_UNSET;
  937. +
  938. + if (isdigit(*spec)) {
  939. + /* fetch width */
  940. + if (! jt_read_integer(&spec, &info->crop_width))
  941. + return FALSE;
  942. + info->crop_width_set = JCROP_POS;
  943. + }
  944. + if (*spec == 'x' || *spec == 'X') {
  945. + /* fetch height */
  946. + spec++;
  947. + if (! jt_read_integer(&spec, &info->crop_height))
  948. + return FALSE;
  949. + info->crop_height_set = JCROP_POS;
  950. + }
  951. + if (*spec == '+' || *spec == '-') {
  952. + /* fetch xoffset */
  953. + info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
  954. + spec++;
  955. + if (! jt_read_integer(&spec, &info->crop_xoffset))
  956. + return FALSE;
  957. + }
  958. + if (*spec == '+' || *spec == '-') {
  959. + /* fetch yoffset */
  960. + info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
  961. + spec++;
  962. + if (! jt_read_integer(&spec, &info->crop_yoffset))
  963. + return FALSE;
  964. + }
  965. + /* We had better have gotten to the end of the string. */
  966. + if (*spec != '\0')
  967. + return FALSE;
  968. + info->crop = TRUE;
  969. + return TRUE;
  970. +}
  971. +
  972. +
  973. +/* Trim off any partial iMCUs on the indicated destination edge */
  974. +
  975. +LOCAL(void)
  976. +trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width)
  977. +{
  978. + JDIMENSION MCU_cols;
  979. +
  980. + MCU_cols = info->output_width / (info->max_h_samp_factor * DCTSIZE);
  981. + if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
  982. + full_width / (info->max_h_samp_factor * DCTSIZE))
  983. + info->output_width = MCU_cols * (info->max_h_samp_factor * DCTSIZE);
  984. +}
  985. +
  986. +LOCAL(void)
  987. +trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height)
  988. +{
  989. + JDIMENSION MCU_rows;
  990. +
  991. + MCU_rows = info->output_height / (info->max_v_samp_factor * DCTSIZE);
  992. + if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
  993. + full_height / (info->max_v_samp_factor * DCTSIZE))
  994. + info->output_height = MCU_rows * (info->max_v_samp_factor * DCTSIZE);
  995. +}
  996. +
  997. +
  998. /* Request any required workspace.
  999. *
  1000. + * This routine figures out the size that the output image will be
  1001. + * (which implies that all the transform parameters must be set before
  1002. + * it is called).
  1003. + *
  1004. * We allocate the workspace virtual arrays from the source decompression
  1005. * object, so that all the arrays (both the original data and the workspace)
  1006. * will be taken into account while making memory management decisions.
  1007. @@ -569,9 +859,13 @@
  1008. jpeg_transform_info *info)
  1009. {
  1010. jvirt_barray_ptr *coef_arrays = NULL;
  1011. + boolean need_workspace, transpose_it;
  1012. jpeg_component_info *compptr;
  1013. - int ci;
  1014. + JDIMENSION xoffset, yoffset, width_in_iMCUs, height_in_iMCUs;
  1015. + JDIMENSION width_in_blocks, height_in_blocks;
  1016. + int ci, h_samp_factor, v_samp_factor;
  1017. + /* Determine number of components in output image */
  1018. if (info->force_grayscale &&
  1019. srcinfo->jpeg_color_space == JCS_YCbCr &&
  1020. srcinfo->num_components == 3) {
  1021. @@ -581,55 +875,181 @@
  1022. /* Process all the components */
  1023. info->num_components = srcinfo->num_components;
  1024. }
  1025. + /* If there is only one output component, force the iMCU size to be 1;
  1026. + * else use the source iMCU size. (This allows us to do the right thing
  1027. + * when reducing color to grayscale, and also provides a handy way of
  1028. + * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
  1029. + */
  1030. switch (info->transform) {
  1031. + case JXFORM_TRANSPOSE:
  1032. + case JXFORM_TRANSVERSE:
  1033. + case JXFORM_ROT_90:
  1034. + case JXFORM_ROT_270:
  1035. + info->output_width = srcinfo->image_height;
  1036. + info->output_height = srcinfo->image_width;
  1037. + if (info->num_components == 1) {
  1038. + info->max_h_samp_factor = 1;
  1039. + info->max_v_samp_factor = 1;
  1040. + } else {
  1041. + info->max_h_samp_factor = srcinfo->max_v_samp_factor;
  1042. + info->max_v_samp_factor = srcinfo->max_h_samp_factor;
  1043. + }
  1044. + break;
  1045. + default:
  1046. + info->output_width = srcinfo->image_width;
  1047. + info->output_height = srcinfo->image_height;
  1048. + if (info->num_components == 1) {
  1049. + info->max_h_samp_factor = 1;
  1050. + info->max_v_samp_factor = 1;
  1051. + } else {
  1052. + info->max_h_samp_factor = srcinfo->max_h_samp_factor;
  1053. + info->max_v_samp_factor = srcinfo->max_v_samp_factor;
  1054. + }
  1055. + break;
  1056. + }
  1057. +
  1058. + /* If cropping has been requested, compute the crop area's position and
  1059. + * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
  1060. + */
  1061. + if (info->crop) {
  1062. + /* Insert default values for unset crop parameters */
  1063. + if (info->crop_xoffset_set == JCROP_UNSET)
  1064. + info->crop_xoffset = 0; /* default to +0 */
  1065. + if (info->crop_yoffset_set == JCROP_UNSET)
  1066. + info->crop_yoffset = 0; /* default to +0 */
  1067. + if (info->crop_xoffset >= info->output_width ||
  1068. + info->crop_yoffset >= info->output_height)
  1069. + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
  1070. + if (info->crop_width_set == JCROP_UNSET)
  1071. + info->crop_width = info->output_width - info->crop_xoffset;
  1072. + if (info->crop_height_set == JCROP_UNSET)
  1073. + info->crop_height = info->output_height - info->crop_yoffset;
  1074. + /* Ensure parameters are valid */
  1075. + if (info->crop_width <= 0 || info->crop_width > info->output_width ||
  1076. + info->crop_height <= 0 || info->crop_height > info->output_height ||
  1077. + info->crop_xoffset > info->output_width - info->crop_width ||
  1078. + info->crop_yoffset > info->output_height - info->crop_height)
  1079. + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
  1080. + /* Convert negative crop offsets into regular offsets */
  1081. + if (info->crop_xoffset_set == JCROP_NEG)
  1082. + xoffset = info->output_width - info->crop_width - info->crop_xoffset;
  1083. + else
  1084. + xoffset = info->crop_xoffset;
  1085. + if (info->crop_yoffset_set == JCROP_NEG)
  1086. + yoffset = info->output_height - info->crop_height - info->crop_yoffset;
  1087. + else
  1088. + yoffset = info->crop_yoffset;
  1089. + /* Now adjust so that upper left corner falls at an iMCU boundary */
  1090. + info->output_width =
  1091. + info->crop_width + (xoffset % (info->max_h_samp_factor * DCTSIZE));
  1092. + info->output_height =
  1093. + info->crop_height + (yoffset % (info->max_v_samp_factor * DCTSIZE));
  1094. + /* Save x/y offsets measured in iMCUs */
  1095. + info->x_crop_offset = xoffset / (info->max_h_samp_factor * DCTSIZE);
  1096. + info->y_crop_offset = yoffset / (info->max_v_samp_factor * DCTSIZE);
  1097. + } else {
  1098. + info->x_crop_offset = 0;
  1099. + info->y_crop_offset = 0;
  1100. + }
  1101. +
  1102. + /* Figure out whether we need workspace arrays,
  1103. + * and if so whether they are transposed relative to the source.
  1104. + */
  1105. + need_workspace = FALSE;
  1106. + transpose_it = FALSE;
  1107. + switch (info->transform) {
  1108. case JXFORM_NONE:
  1109. + if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
  1110. + need_workspace = TRUE;
  1111. + /* No workspace needed if neither cropping nor transforming */
  1112. + break;
  1113. case JXFORM_FLIP_H:
  1114. - /* Don't need a workspace array */
  1115. + if (info->trim)
  1116. + trim_right_edge(info, srcinfo->image_width);
  1117. + if (info->y_crop_offset != 0)
  1118. + need_workspace = TRUE;
  1119. + /* do_flip_h_no_crop doesn't need a workspace array */
  1120. break;
  1121. case JXFORM_FLIP_V:
  1122. - case JXFORM_ROT_180:
  1123. - /* Need workspace arrays having same dimensions as source image.
  1124. - * Note that we allocate arrays padded out to the next iMCU boundary,
  1125. - * so that transform routines need not worry about missing edge blocks.
  1126. - */
  1127. - coef_arrays = (jvirt_barray_ptr *)
  1128. - (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
  1129. - SIZEOF(jvirt_barray_ptr) * info->num_components);
  1130. - for (ci = 0; ci < info->num_components; ci++) {
  1131. - compptr = srcinfo->comp_info + ci;
  1132. - coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
  1133. - ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
  1134. - (JDIMENSION) jround_up((long) compptr->width_in_blocks,
  1135. - (long) compptr->h_samp_factor),
  1136. - (JDIMENSION) jround_up((long) compptr->height_in_blocks,
  1137. - (long) compptr->v_samp_factor),
  1138. - (JDIMENSION) compptr->v_samp_factor);
  1139. - }
  1140. + if (info->trim)
  1141. + trim_bottom_edge(info, srcinfo->image_height);
  1142. + /* Need workspace arrays having same dimensions as source image. */
  1143. + need_workspace = TRUE;
  1144. break;
  1145. case JXFORM_TRANSPOSE:
  1146. + /* transpose does NOT have to trim anything */
  1147. + /* Need workspace arrays having transposed dimensions. */
  1148. + need_workspace = TRUE;
  1149. + transpose_it = TRUE;
  1150. + break;
  1151. case JXFORM_TRANSVERSE:
  1152. + if (info->trim) {
  1153. + trim_right_edge(info, srcinfo->image_height);
  1154. + trim_bottom_edge(info, srcinfo->image_width);
  1155. + }
  1156. + /* Need workspace arrays having transposed dimensions. */
  1157. + need_workspace = TRUE;
  1158. + transpose_it = TRUE;
  1159. + break;
  1160. case JXFORM_ROT_90:
  1161. + if (info->trim)
  1162. + trim_right_edge(info, srcinfo->image_height);
  1163. + /* Need workspace arrays having transposed dimensions. */
  1164. + need_workspace = TRUE;
  1165. + transpose_it = TRUE;
  1166. + break;
  1167. + case JXFORM_ROT_180:
  1168. + if (info->trim) {
  1169. + trim_right_edge(info, srcinfo->image_width);
  1170. + trim_bottom_edge(info, srcinfo->image_height);
  1171. + }
  1172. + /* Need workspace arrays having same dimensions as source image. */
  1173. + need_workspace = TRUE;
  1174. + break;
  1175. case JXFORM_ROT_270:
  1176. - /* Need workspace arrays having transposed dimensions.
  1177. - * Note that we allocate arrays padded out to the next iMCU boundary,
  1178. - * so that transform routines need not worry about missing edge blocks.
  1179. - */
  1180. + if (info->trim)
  1181. + trim_bottom_edge(info, srcinfo->image_width);
  1182. + /* Need workspace arrays having transposed dimensions. */
  1183. + need_workspace = TRUE;
  1184. + transpose_it = TRUE;
  1185. + break;
  1186. + }
  1187. +
  1188. + /* Allocate workspace if needed.
  1189. + * Note that we allocate arrays padded out to the next iMCU boundary,
  1190. + * so that transform routines need not worry about missing edge blocks.
  1191. + */
  1192. + if (need_workspace) {
  1193. coef_arrays = (jvirt_barray_ptr *)
  1194. (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
  1195. - SIZEOF(jvirt_barray_ptr) * info->num_components);
  1196. + SIZEOF(jvirt_barray_ptr) * info->num_components);
  1197. + width_in_iMCUs = (JDIMENSION)
  1198. + jdiv_round_up((long) info->output_width,
  1199. + (long) (info->max_h_samp_factor * DCTSIZE));
  1200. + height_in_iMCUs = (JDIMENSION)
  1201. + jdiv_round_up((long) info->output_height,
  1202. + (long) (info->max_v_samp_factor * DCTSIZE));
  1203. for (ci = 0; ci < info->num_components; ci++) {
  1204. compptr = srcinfo->comp_info + ci;
  1205. + if (info->num_components == 1) {
  1206. + /* we're going to force samp factors to 1x1 in this case */
  1207. + h_samp_factor = v_samp_factor = 1;
  1208. + } else if (transpose_it) {
  1209. + h_samp_factor = compptr->v_samp_factor;
  1210. + v_samp_factor = compptr->h_samp_factor;
  1211. + } else {
  1212. + h_samp_factor = compptr->h_samp_factor;
  1213. + v_samp_factor = compptr->v_samp_factor;
  1214. + }
  1215. + width_in_blocks = width_in_iMCUs * h_samp_factor;
  1216. + height_in_blocks = height_in_iMCUs * v_samp_factor;
  1217. coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
  1218. ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
  1219. - (JDIMENSION) jround_up((long) compptr->height_in_blocks,
  1220. - (long) compptr->v_samp_factor),
  1221. - (JDIMENSION) jround_up((long) compptr->width_in_blocks,
  1222. - (long) compptr->h_samp_factor),
  1223. - (JDIMENSION) compptr->h_samp_factor);
  1224. + width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
  1225. }
  1226. - break;
  1227. }
  1228. +
  1229. info->workspace_coef_arrays = coef_arrays;
  1230. }
  1231. @@ -642,14 +1062,8 @@
  1232. int tblno, i, j, ci, itemp;
  1233. jpeg_component_info *compptr;
  1234. JQUANT_TBL *qtblptr;
  1235. - JDIMENSION dtemp;
  1236. UINT16 qtemp;
  1237. - /* Transpose basic image dimensions */
  1238. - dtemp = dstinfo->image_width;
  1239. - dstinfo->image_width = dstinfo->image_height;
  1240. - dstinfo->image_height = dtemp;
  1241. -
  1242. /* Transpose sampling factors */
  1243. for (ci = 0; ci < dstinfo->num_components; ci++) {
  1244. compptr = dstinfo->comp_info + ci;
  1245. @@ -674,46 +1088,159 @@
  1246. }
  1247. -/* Trim off any partial iMCUs on the indicated destination edge */
  1248. +/* Adjust Exif image parameters.
  1249. + *
  1250. + * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
  1251. + */
  1252. LOCAL(void)
  1253. -trim_right_edge (j_compress_ptr dstinfo)
  1254. +adjust_exif_parameters (JOCTET FAR * data, unsigned int length,
  1255. + JDIMENSION new_width, JDIMENSION new_height)
  1256. {
  1257. - int ci, max_h_samp_factor;
  1258. - JDIMENSION MCU_cols;
  1259. + boolean is_motorola; /* Flag for byte order */
  1260. + unsigned int number_of_tags, tagnum;
  1261. + unsigned int firstoffset, offset;
  1262. + JDIMENSION new_value;
  1263. - /* We have to compute max_h_samp_factor ourselves,
  1264. - * because it hasn't been set yet in the destination
  1265. - * (and we don't want to use the source's value).
  1266. - */
  1267. - max_h_samp_factor = 1;
  1268. - for (ci = 0; ci < dstinfo->num_components; ci++) {
  1269. - int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
  1270. - max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
  1271. + if (length < 12) return; /* Length of an IFD entry */
  1272. +
  1273. + /* Discover byte order */
  1274. + if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
  1275. + is_motorola = FALSE;
  1276. + else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
  1277. + is_motorola = TRUE;
  1278. + else
  1279. + return;
  1280. +
  1281. + /* Check Tag Mark */
  1282. + if (is_motorola) {
  1283. + if (GETJOCTET(data[2]) != 0) return;
  1284. + if (GETJOCTET(data[3]) != 0x2A) return;
  1285. + } else {
  1286. + if (GETJOCTET(data[3]) != 0) return;
  1287. + if (GETJOCTET(data[2]) != 0x2A) return;
  1288. }
  1289. - MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
  1290. - if (MCU_cols > 0) /* can't trim to 0 pixels */
  1291. - dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
  1292. -}
  1293. -LOCAL(void)
  1294. -trim_bottom_edge (j_compress_ptr dstinfo)
  1295. -{
  1296. - int ci, max_v_samp_factor;
  1297. - JDIMENSION MCU_rows;
  1298. + /* Get first IFD offset (offset to IFD0) */
  1299. + if (is_motorola) {
  1300. + if (GETJOCTET(data[4]) != 0) return;
  1301. + if (GETJOCTET(data[5]) != 0) return;
  1302. + firstoffset = GETJOCTET(data[6]);
  1303. + firstoffset <<= 8;
  1304. + firstoffset += GETJOCTET(data[7]);
  1305. + } else {
  1306. + if (GETJOCTET(data[7]) != 0) return;
  1307. + if (GETJOCTET(data[6]) != 0) return;
  1308. + firstoffset = GETJOCTET(data[5]);
  1309. + firstoffset <<= 8;
  1310. + firstoffset += GETJOCTET(data[4]);
  1311. + }
  1312. + if (firstoffset > length - 2) return; /* check end of data segment */
  1313. - /* We have to compute max_v_samp_factor ourselves,
  1314. - * because it hasn't been set yet in the destination
  1315. - * (and we don't want to use the source's value).
  1316. - */
  1317. - max_v_samp_factor = 1;
  1318. - for (ci = 0; ci < dstinfo->num_components; ci++) {
  1319. - int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
  1320. - max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
  1321. + /* Get the number of directory entries contained in this IFD */
  1322. + if (is_motorola) {
  1323. + number_of_tags = GETJOCTET(data[firstoffset]);
  1324. + number_of_tags <<= 8;
  1325. + number_of_tags += GETJOCTET(data[firstoffset+1]);
  1326. + } else {
  1327. + number_of_tags = GETJOCTET(data[firstoffset+1]);
  1328. + number_of_tags <<= 8;
  1329. + number_of_tags += GETJOCTET(data[firstoffset]);
  1330. }
  1331. - MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
  1332. - if (MCU_rows > 0) /* can't trim to 0 pixels */
  1333. - dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
  1334. + if (number_of_tags == 0) return;
  1335. + firstoffset += 2;
  1336. +
  1337. + /* Search for ExifSubIFD offset Tag in IFD0 */
  1338. + for (;;) {
  1339. + if (firstoffset > length - 12) return; /* check end of data segment */
  1340. + /* Get Tag number */
  1341. + if (is_motorola) {
  1342. + tagnum = GETJOCTET(data[firstoffset]);
  1343. + tagnum <<= 8;
  1344. + tagnum += GETJOCTET(data[firstoffset+1]);
  1345. + } else {
  1346. + tagnum = GETJOCTET(data[firstoffset+1]);
  1347. + tagnum <<= 8;
  1348. + tagnum += GETJOCTET(data[firstoffset]);
  1349. + }
  1350. + if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
  1351. + if (--number_of_tags == 0) return;
  1352. + firstoffset += 12;
  1353. + }
  1354. +
  1355. + /* Get the ExifSubIFD offset */
  1356. + if (is_motorola) {
  1357. + if (GETJOCTET(data[firstoffset+8]) != 0) return;
  1358. + if (GETJOCTET(data[firstoffset+9]) != 0) return;
  1359. + offset = GETJOCTET(data[firstoffset+10]);
  1360. + offset <<= 8;
  1361. + offset += GETJOCTET(data[firstoffset+11]);
  1362. + } else {
  1363. + if (GETJOCTET(data[firstoffset+11]) != 0) return;
  1364. + if (GETJOCTET(data[firstoffset+10]) != 0) return;
  1365. + offset = GETJOCTET(data[firstoffset+9]);
  1366. + offset <<= 8;
  1367. + offset += GETJOCTET(data[firstoffset+8]);
  1368. + }
  1369. + if (offset > length - 2) return; /* check end of data segment */
  1370. +
  1371. + /* Get the number of directory entries contained in this SubIFD */
  1372. + if (is_motorola) {
  1373. + number_of_tags = GETJOCTET(data[offset]);
  1374. + number_of_tags <<= 8;
  1375. + number_of_tags += GETJOCTET(data[offset+1]);
  1376. + } else {
  1377. + number_of_tags = GETJOCTET(data[offset+1]);
  1378. + number_of_tags <<= 8;
  1379. + number_of_tags += GETJOCTET(data[offset]);
  1380. + }
  1381. + if (number_of_tags < 2) return;
  1382. + offset += 2;
  1383. +
  1384. + /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
  1385. + do {
  1386. + if (offset > length - 12) return; /* check end of data segment */
  1387. + /* Get Tag number */
  1388. + if (is_motorola) {
  1389. + tagnum = GETJOCTET(data[offset]);
  1390. + tagnum <<= 8;
  1391. + tagnum += GETJOCTET(data[offset+1]);
  1392. + } else {
  1393. + tagnum = GETJOCTET(data[offset+1]);
  1394. + tagnum <<= 8;
  1395. + tagnum += GETJOCTET(data[offset]);
  1396. + }
  1397. + if (tagnum == 0xA002 || tagnum == 0xA003) {
  1398. + if (tagnum == 0xA002)
  1399. + new_value = new_width; /* ExifImageWidth Tag */
  1400. + else
  1401. + new_value = new_height; /* ExifImageHeight Tag */
  1402. + if (is_motorola) {
  1403. + data[offset+2] = 0; /* Format = unsigned long (4 octets) */
  1404. + data[offset+3] = 4;
  1405. + data[offset+4] = 0; /* Number Of Components = 1 */
  1406. + data[offset+5] = 0;
  1407. + data[offset+6] = 0;
  1408. + data[offset+7] = 1;
  1409. + data[offset+8] = 0;
  1410. + data[offset+9] = 0;
  1411. + data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
  1412. + data[offset+11] = (JOCTET)(new_value & 0xFF);
  1413. + } else {
  1414. + data[offset+2] = 4; /* Format = unsigned long (4 octets) */
  1415. + data[offset+3] = 0;
  1416. + data[offset+4] = 1; /* Number Of Components = 1 */
  1417. + data[offset+5] = 0;
  1418. + data[offset+6] = 0;
  1419. + data[offset+7] = 0;
  1420. + data[offset+8] = (JOCTET)(new_value & 0xFF);
  1421. + data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
  1422. + data[offset+10] = 0;
  1423. + data[offset+11] = 0;
  1424. + }
  1425. + }
  1426. + offset += 12;
  1427. + } while (--number_of_tags);
  1428. }
  1429. @@ -736,18 +1263,22 @@
  1430. {
  1431. /* If force-to-grayscale is requested, adjust destination parameters */
  1432. if (info->force_grayscale) {
  1433. - /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
  1434. - * properly. Among other things, the target h_samp_factor & v_samp_factor
  1435. - * will get set to 1, which typically won't match the source.
  1436. - * In fact we do this even if the source is already grayscale; that
  1437. - * provides an easy way of coercing a grayscale JPEG with funny sampling
  1438. - * factors to the customary 1,1. (Some decoders fail on other factors.)
  1439. + /* First, ensure we have YCbCr or grayscale data, and that the source's
  1440. + * Y channel is full resolution. (No reasonable person would make Y
  1441. + * be less than full resolution, so actually coping with that case
  1442. + * isn't worth extra code space. But we check it to avoid crashing.)
  1443. */
  1444. - if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
  1445. - dstinfo->num_components == 3) ||
  1446. - (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
  1447. - dstinfo->num_components == 1)) {
  1448. - /* We have to preserve the source's quantization table number. */
  1449. + if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
  1450. + dstinfo->num_components == 3) ||
  1451. + (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
  1452. + dstinfo->num_components == 1)) &&
  1453. + srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
  1454. + srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
  1455. + /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
  1456. + * properly. Among other things, it sets the target h_samp_factor &
  1457. + * v_samp_factor to 1, which typically won't match the source.
  1458. + * We have to preserve the source's quantization table number, however.
  1459. + */
  1460. int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
  1461. jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
  1462. dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
  1463. @@ -755,50 +1286,52 @@
  1464. /* Sorry, can't do it */
  1465. ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
  1466. }
  1467. + } else if (info->num_components == 1) {
  1468. + /* For a single-component source, we force the destination sampling factors
  1469. + * to 1x1, with or without force_grayscale. This is useful because some
  1470. + * decoders choke on grayscale images with other sampling factors.
  1471. + */
  1472. + dstinfo->comp_info[0].h_samp_factor = 1;
  1473. + dstinfo->comp_info[0].v_samp_factor = 1;
  1474. }
  1475. - /* Correct the destination's image dimensions etc if necessary */
  1476. + /* Correct the destination's image dimensions as necessary
  1477. + * for crop and rotate/flip operations.
  1478. + */
  1479. + dstinfo->image_width = info->output_width;
  1480. + dstinfo->image_height = info->output_height;
  1481. +
  1482. + /* Transpose destination image parameters */
  1483. switch (info->transform) {
  1484. - case JXFORM_NONE:
  1485. - /* Nothing to do */
  1486. - break;
  1487. - case JXFORM_FLIP_H:
  1488. - if (info->trim)
  1489. - trim_right_edge(dstinfo);
  1490. - break;
  1491. - case JXFORM_FLIP_V:
  1492. - if (info->trim)
  1493. - trim_bottom_edge(dstinfo);
  1494. - break;
  1495. case JXFORM_TRANSPOSE:
  1496. - transpose_critical_parameters(dstinfo);
  1497. - /* transpose does NOT have to trim anything */
  1498. - break;
  1499. case JXFORM_TRANSVERSE:
  1500. - transpose_critical_parameters(dstinfo);
  1501. - if (info->trim) {
  1502. - trim_right_edge(dstinfo);
  1503. - trim_bottom_edge(dstinfo);
  1504. - }
  1505. - break;
  1506. case JXFORM_ROT_90:
  1507. - transpose_critical_parameters(dstinfo);
  1508. - if (info->trim)
  1509. - trim_right_edge(dstinfo);
  1510. - break;
  1511. - case JXFORM_ROT_180:
  1512. - if (info->trim) {
  1513. - trim_right_edge(dstinfo);
  1514. - trim_bottom_edge(dstinfo);
  1515. - }
  1516. - break;
  1517. case JXFORM_ROT_270:
  1518. transpose_critical_parameters(dstinfo);
  1519. - if (info->trim)
  1520. - trim_bottom_edge(dstinfo);
  1521. break;
  1522. }
  1523. + /* Adjust Exif properties */
  1524. + if (srcinfo->marker_list != NULL &&
  1525. + srcinfo->marker_list->marker == JPEG_APP0+1 &&
  1526. + srcinfo->marker_list->data_length >= 6 &&
  1527. + GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 &&
  1528. + GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 &&
  1529. + GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 &&
  1530. + GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 &&
  1531. + GETJOCTET(srcinfo->marker_list->data[4]) == 0 &&
  1532. + GETJOCTET(srcinfo->marker_list->data[5]) == 0) {
  1533. + /* Suppress output of JFIF marker */
  1534. + dstinfo->write_JFIF_header = FALSE;
  1535. + /* Adjust Exif image parameters */
  1536. + if (dstinfo->image_width != srcinfo->image_width ||
  1537. + dstinfo->image_height != srcinfo->image_height)
  1538. + /* Align data segment to start of TIFF structure for parsing */
  1539. + adjust_exif_parameters(srcinfo->marker_list->data + 6,
  1540. + srcinfo->marker_list->data_length - 6,
  1541. + dstinfo->image_width, dstinfo->image_height);
  1542. + }
  1543. +
  1544. /* Return the appropriate output data set */
  1545. if (info->workspace_coef_arrays != NULL)
  1546. return info->workspace_coef_arrays;
  1547. @@ -816,38 +1349,106 @@
  1548. */
  1549. GLOBAL(void)
  1550. -jtransform_execute_transformation (j_decompress_ptr srcinfo,
  1551. - j_compress_ptr dstinfo,
  1552. - jvirt_barray_ptr *src_coef_arrays,
  1553. - jpeg_transform_info *info)
  1554. +jtransform_execute_transform (j_decompress_ptr srcinfo,
  1555. + j_compress_ptr dstinfo,
  1556. + jvirt_barray_ptr *src_coef_arrays,
  1557. + jpeg_transform_info *info)
  1558. {
  1559. jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
  1560. + /* Note: conditions tested here should match those in switch statement
  1561. + * in jtransform_request_workspace()
  1562. + */
  1563. switch (info->transform) {
  1564. case JXFORM_NONE:
  1565. + if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
  1566. + do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  1567. + src_coef_arrays, dst_coef_arrays);
  1568. break;
  1569. case JXFORM_FLIP_H:
  1570. - do_flip_h(srcinfo, dstinfo, src_coef_arrays);
  1571. + if (info->y_crop_offset != 0)
  1572. + do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  1573. + src_coef_arrays, dst_coef_arrays);
  1574. + else
  1575. + do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
  1576. + src_coef_arrays);
  1577. break;
  1578. case JXFORM_FLIP_V:
  1579. - do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
  1580. + do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  1581. + src_coef_arrays, dst_coef_arrays);
  1582. break;
  1583. case JXFORM_TRANSPOSE:
  1584. - do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
  1585. + do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  1586. + src_coef_arrays, dst_coef_arrays);
  1587. break;
  1588. case JXFORM_TRANSVERSE:
  1589. - do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
  1590. + do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  1591. + src_coef_arrays, dst_coef_arrays);
  1592. break;
  1593. case JXFORM_ROT_90:
  1594. - do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
  1595. + do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  1596. + src_coef_arrays, dst_coef_arrays);
  1597. break;
  1598. case JXFORM_ROT_180:
  1599. - do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
  1600. + do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  1601. + src_coef_arrays, dst_coef_arrays);
  1602. break;
  1603. case JXFORM_ROT_270:
  1604. - do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
  1605. + do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
  1606. + src_coef_arrays, dst_coef_arrays);
  1607. + break;
  1608. + }
  1609. +}
  1610. +
  1611. +/* jtransform_perfect_transform
  1612. + *
  1613. + * Determine whether lossless transformation is perfectly
  1614. + * possible for a specified image and transformation.
  1615. + *
  1616. + * Inputs:
  1617. + * image_width, image_height: source image dimensions.
  1618. + * MCU_width, MCU_height: pixel dimensions of MCU.
  1619. + * transform: transformation identifier.
  1620. + * Parameter sources from initialized jpeg_struct
  1621. + * (after reading source header):
  1622. + * image_width = cinfo.image_width
  1623. + * image_height = cinfo.image_height
  1624. + * MCU_width = cinfo.max_h_samp_factor * DCTSIZE
  1625. + * MCU_height = cinfo.max_v_samp_factor * DCTSIZE
  1626. + * Result:
  1627. + * TRUE = perfect transformation possible
  1628. + * FALSE = perfect transformation not possible
  1629. + * (may use custom action then)
  1630. + */
  1631. +
  1632. +GLOBAL(boolean)
  1633. +jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
  1634. + int MCU_width, int MCU_height,
  1635. + JXFORM_CODE transform)
  1636. +{
  1637. + boolean result = TRUE; /* initialize TRUE */
  1638. +
  1639. + switch (transform) {
  1640. + case JXFORM_FLIP_H:
  1641. + case JXFORM_ROT_270:
  1642. + if (image_width % (JDIMENSION) MCU_width)
  1643. + result = FALSE;
  1644. + break;
  1645. + case JXFORM_FLIP_V:
  1646. + case JXFORM_ROT_90:
  1647. + if (image_height % (JDIMENSION) MCU_height)
  1648. + result = FALSE;
  1649. + break;
  1650. + case JXFORM_TRANSVERSE:
  1651. + case JXFORM_ROT_180:
  1652. + if (image_width % (JDIMENSION) MCU_width)
  1653. + result = FALSE;
  1654. + if (image_height % (JDIMENSION) MCU_height)
  1655. + result = FALSE;
  1656. break;
  1657. }
  1658. +
  1659. + return result;
  1660. }
  1661. #endif /* TRANSFORMS_SUPPORTED */
  1662. diff -urNad /home/bill/debian/libjpeg/libjpeg6b-6b/transupp.h libjpeg6b-6b/transupp.h
  1663. --- /home/bill/debian/libjpeg/libjpeg6b-6b/transupp.h 2003-09-22 18:15:49.000000000 +0200
  1664. +++ libjpeg6b-6b/transupp.h 2003-09-22 18:16:16.000000000 +0200
  1665. @@ -1,7 +1,7 @@
  1666. /*
  1667. * transupp.h
  1668. *
  1669. - * Copyright (C) 1997, Thomas G. Lane.
  1670. + * Copyright (C) 1997-2001, Thomas G. Lane.
  1671. * This file is part of the Independent JPEG Group's software.
  1672. * For conditions of distribution and use, see the accompanying README file.
  1673. *
  1674. @@ -22,32 +22,6 @@
  1675. #define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
  1676. #endif
  1677. -/* Short forms of external names for systems with brain-damaged linkers. */
  1678. -
  1679. -#ifdef NEED_SHORT_EXTERNAL_NAMES
  1680. -#define jtransform_request_workspace jTrRequest
  1681. -#define jtransform_adjust_parameters jTrAdjust
  1682. -#define jtransform_execute_transformation jTrExec
  1683. -#define jcopy_markers_setup jCMrkSetup
  1684. -#define jcopy_markers_execute jCMrkExec
  1685. -#endif /* NEED_SHORT_EXTERNAL_NAMES */
  1686. -
  1687. -
  1688. -/*
  1689. - * Codes for supported types of image transformations.
  1690. - */
  1691. -
  1692. -typedef enum {
  1693. - JXFORM_NONE, /* no transformation */
  1694. - JXFORM_FLIP_H, /* horizontal flip */
  1695. - JXFORM_FLIP_V, /* vertical flip */
  1696. - JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
  1697. - JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
  1698. - JXFORM_ROT_90, /* 90-degree clockwise rotation */
  1699. - JXFORM_ROT_180, /* 180-degree rotation */
  1700. - JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
  1701. -} JXFORM_CODE;
  1702. -
  1703. /*
  1704. * Although rotating and flipping data expressed as DCT coefficients is not
  1705. * hard, there is an asymmetry in the JPEG format specification for images
  1706. @@ -75,6 +49,19 @@
  1707. * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
  1708. * followed by -rot 180 -trim trims both edges.)
  1709. *
  1710. + * We also offer a lossless-crop option, which discards data outside a given
  1711. + * image region but losslessly preserves what is inside. Like the rotate and
  1712. + * flip transforms, lossless crop is restricted by the JPEG format: the upper
  1713. + * left corner of the selected region must fall on an iMCU boundary. If this
  1714. + * does not hold for the given crop parameters, we silently move the upper left
  1715. + * corner up and/or left to make it so, simultaneously increasing the region
  1716. + * dimensions to keep the lower right crop corner unchanged. (Thus, the
  1717. + * output image covers at least the requested region, but may cover more.)
  1718. + *
  1719. + * If both crop and a rotate/flip transform are requested, the crop is applied
  1720. + * last --- that is, the crop region is specified in terms of the destination
  1721. + * image.
  1722. + *
  1723. * We also offer a "force to grayscale" option, which simply discards the
  1724. * chrominance channels of a YCbCr image. This is lossless in the sense that
  1725. * the luminance channel is preserved exactly. It's not the same kind of
  1726. @@ -83,20 +70,89 @@
  1727. * be aware of the option to know how many components to work on.
  1728. */
  1729. +
  1730. +/* Short forms of external names for systems with brain-damaged linkers. */
  1731. +
  1732. +#ifdef NEED_SHORT_EXTERNAL_NAMES
  1733. +#define jtransform_parse_crop_spec jTrParCrop
  1734. +#define jtransform_request_workspace jTrRequest
  1735. +#define jtransform_adjust_parameters jTrAdjust
  1736. +#define jtransform_execute_transform jTrExec
  1737. +#define jtransform_perfect_transform jTrPerfect
  1738. +#define jcopy_markers_setup jCMrkSetup
  1739. +#define jcopy_markers_execute jCMrkExec
  1740. +#endif /* NEED_SHORT_EXTERNAL_NAMES */
  1741. +
  1742. +
  1743. +/*
  1744. + * Codes for supported types of image transformations.
  1745. + */
  1746. +
  1747. +typedef enum {
  1748. + JXFORM_NONE, /* no transformation */
  1749. + JXFORM_FLIP_H, /* horizontal flip */
  1750. + JXFORM_FLIP_V, /* vertical flip */
  1751. + JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
  1752. + JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
  1753. + JXFORM_ROT_90, /* 90-degree clockwise rotation */
  1754. + JXFORM_ROT_180, /* 180-degree rotation */
  1755. + JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
  1756. +} JXFORM_CODE;
  1757. +
  1758. +/*
  1759. + * Codes for crop parameters, which can individually be unspecified,
  1760. + * positive, or negative. (Negative width or height makes no sense, though.)
  1761. + */
  1762. +
  1763. +typedef enum {
  1764. + JCROP_UNSET,
  1765. + JCROP_POS,
  1766. + JCROP_NEG
  1767. +} JCROP_CODE;
  1768. +
  1769. +/*
  1770. + * Transform parameters struct.
  1771. + * NB: application must not change any elements of this struct after
  1772. + * calling jtransform_request_workspace.
  1773. + */
  1774. +
  1775. typedef struct {
  1776. /* Options: set by caller */
  1777. JXFORM_CODE transform; /* image transform operator */
  1778. + boolean perfect; /* if TRUE, fail if partial MCUs are requested */
  1779. boolean trim; /* if TRUE, trim partial MCUs as needed */
  1780. boolean force_grayscale; /* if TRUE, convert color image to grayscale */
  1781. + boolean crop; /* if TRUE, crop source image */
  1782. +
  1783. + /* Crop parameters: application need not set these unless crop is TRUE.
  1784. + * These can be filled in by jtransform_parse_crop_spec().
  1785. + */
  1786. + JDIMENSION crop_width; /* Width of selected region */
  1787. + JCROP_CODE crop_width_set;
  1788. + JDIMENSION crop_height; /* Height of selected region */
  1789. + JCROP_CODE crop_height_set;
  1790. + JDIMENSION crop_xoffset; /* X offset of selected region */
  1791. + JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */
  1792. + JDIMENSION crop_yoffset; /* Y offset of selected region */
  1793. + JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */
  1794. /* Internal workspace: caller should not touch these */
  1795. int num_components; /* # of components in workspace */
  1796. jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
  1797. + JDIMENSION output_width; /* cropped destination dimensions */
  1798. + JDIMENSION output_height;
  1799. + JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */
  1800. + JDIMENSION y_crop_offset;
  1801. + int max_h_samp_factor; /* destination iMCU size */
  1802. + int max_v_samp_factor;
  1803. } jpeg_transform_info;
  1804. #if TRANSFORMS_SUPPORTED
  1805. +/* Parse a crop specification (written in X11 geometry style) */
  1806. +EXTERN(boolean) jtransform_parse_crop_spec
  1807. + JPP((jpeg_transform_info *info, const char *spec));
  1808. /* Request any required workspace */
  1809. EXTERN(void) jtransform_request_workspace
  1810. JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
  1811. @@ -106,10 +162,24 @@
  1812. jvirt_barray_ptr *src_coef_arrays,
  1813. jpeg_transform_info *info));
  1814. /* Execute the actual transformation, if any */
  1815. -EXTERN(void) jtransform_execute_transformation
  1816. +EXTERN(void) jtransform_execute_transform
  1817. JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  1818. jvirt_barray_ptr *src_coef_arrays,
  1819. jpeg_transform_info *info));
  1820. +/* Determine whether lossless transformation is perfectly
  1821. + * possible for a specified image and transformation.
  1822. + */
  1823. +EXTERN(boolean) jtransform_perfect_transform
  1824. + JPP((JDIMENSION image_width, JDIMENSION image_height,
  1825. + int MCU_width, int MCU_height,
  1826. + JXFORM_CODE transform));
  1827. +
  1828. +/* jtransform_execute_transform used to be called
  1829. + * jtransform_execute_transformation, but some compilers complain about
  1830. + * routine names that long. This macro is here to avoid breaking any
  1831. + * old source code that uses the original name...
  1832. + */
  1833. +#define jtransform_execute_transformation jtransform_execute_transform
  1834. #endif /* TRANSFORMS_SUPPORTED */