OpenSDE Packages Database (without history before r20070)
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.

1905 lines
72 KiB

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