PageRenderTime 114ms CodeModel.GetById 25ms app.highlight 78ms RepoModel.GetById 1ms app.codeStats 1ms

/src/FreeImage/Source/LibJPEG/transupp.c

https://bitbucket.org/cabalistic/ogredeps/
C | 1597 lines | 1153 code | 105 blank | 339 comment | 333 complexity | 84258ade6bb2fab4c60d5f426edcf963 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * transupp.c
   3 *
   4 * Copyright (C) 1997-2011, Thomas G. Lane, Guido Vollbeding.
   5 * This file is part of the Independent JPEG Group's software.
   6 * For conditions of distribution and use, see the accompanying README file.
   7 *
   8 * This file contains image transformation routines and other utility code
   9 * used by the jpegtran sample application.  These are NOT part of the core
  10 * JPEG library.  But we keep these routines separate from jpegtran.c to
  11 * ease the task of maintaining jpegtran-like programs that have other user
  12 * interfaces.
  13 */
  14
  15/* Although this file really shouldn't have access to the library internals,
  16 * it's helpful to let it call jround_up() and jcopy_block_row().
  17 */
  18#define JPEG_INTERNALS
  19
  20#include "jinclude.h"
  21#include "jpeglib.h"
  22#include "transupp.h"		/* My own external interface */
  23#include <ctype.h>		/* to declare isdigit() */
  24
  25
  26#if TRANSFORMS_SUPPORTED
  27
  28/*
  29 * Lossless image transformation routines.  These routines work on DCT
  30 * coefficient arrays and thus do not require any lossy decompression
  31 * or recompression of the image.
  32 * Thanks to Guido Vollbeding for the initial design and code of this feature,
  33 * and to Ben Jackson for introducing the cropping feature.
  34 *
  35 * Horizontal flipping is done in-place, using a single top-to-bottom
  36 * pass through the virtual source array.  It will thus be much the
  37 * fastest option for images larger than main memory.
  38 *
  39 * The other routines require a set of destination virtual arrays, so they
  40 * need twice as much memory as jpegtran normally does.  The destination
  41 * arrays are always written in normal scan order (top to bottom) because
  42 * the virtual array manager expects this.  The source arrays will be scanned
  43 * in the corresponding order, which means multiple passes through the source
  44 * arrays for most of the transforms.  That could result in much thrashing
  45 * if the image is larger than main memory.
  46 *
  47 * If cropping or trimming is involved, the destination arrays may be smaller
  48 * than the source arrays.  Note it is not possible to do horizontal flip
  49 * in-place when a nonzero Y crop offset is specified, since we'd have to move
  50 * data from one block row to another but the virtual array manager doesn't
  51 * guarantee we can touch more than one row at a time.  So in that case,
  52 * we have to use a separate destination array.
  53 *
  54 * Some notes about the operating environment of the individual transform
  55 * routines:
  56 * 1. Both the source and destination virtual arrays are allocated from the
  57 *    source JPEG object, and therefore should be manipulated by calling the
  58 *    source's memory manager.
  59 * 2. The destination's component count should be used.  It may be smaller
  60 *    than the source's when forcing to grayscale.
  61 * 3. Likewise the destination's sampling factors should be used.  When
  62 *    forcing to grayscale the destination's sampling factors will be all 1,
  63 *    and we may as well take that as the effective iMCU size.
  64 * 4. When "trim" is in effect, the destination's dimensions will be the
  65 *    trimmed values but the source's will be untrimmed.
  66 * 5. When "crop" is in effect, the destination's dimensions will be the
  67 *    cropped values but the source's will be uncropped.  Each transform
  68 *    routine is responsible for picking up source data starting at the
  69 *    correct X and Y offset for the crop region.  (The X and Y offsets
  70 *    passed to the transform routines are measured in iMCU blocks of the
  71 *    destination.)
  72 * 6. All the routines assume that the source and destination buffers are
  73 *    padded out to a full iMCU boundary.  This is true, although for the
  74 *    source buffer it is an undocumented property of jdcoefct.c.
  75 */
  76
  77
  78LOCAL(void)
  79do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
  80	 JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
  81	 jvirt_barray_ptr *src_coef_arrays,
  82	 jvirt_barray_ptr *dst_coef_arrays)
  83/* Crop.  This is only used when no rotate/flip is requested with the crop. */
  84{
  85  JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
  86  int ci, offset_y;
  87  JBLOCKARRAY src_buffer, dst_buffer;
  88  jpeg_component_info *compptr;
  89
  90  /* We simply have to copy the right amount of data (the destination's
  91   * image size) starting at the given X and Y offsets in the source.
  92   */
  93  for (ci = 0; ci < dstinfo->num_components; ci++) {
  94    compptr = dstinfo->comp_info + ci;
  95    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
  96    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
  97    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
  98	 dst_blk_y += compptr->v_samp_factor) {
  99      dst_buffer = (*srcinfo->mem->access_virt_barray)
 100	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
 101	 (JDIMENSION) compptr->v_samp_factor, TRUE);
 102      src_buffer = (*srcinfo->mem->access_virt_barray)
 103	((j_common_ptr) srcinfo, src_coef_arrays[ci],
 104	 dst_blk_y + y_crop_blocks,
 105	 (JDIMENSION) compptr->v_samp_factor, FALSE);
 106      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
 107	jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
 108			dst_buffer[offset_y],
 109			compptr->width_in_blocks);
 110      }
 111    }
 112  }
 113}
 114
 115
 116LOCAL(void)
 117do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
 118		   JDIMENSION x_crop_offset,
 119		   jvirt_barray_ptr *src_coef_arrays)
 120/* Horizontal flip; done in-place, so no separate dest array is required.
 121 * NB: this only works when y_crop_offset is zero.
 122 */
 123{
 124  JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
 125  int ci, k, offset_y;
 126  JBLOCKARRAY buffer;
 127  JCOEFPTR ptr1, ptr2;
 128  JCOEF temp1, temp2;
 129  jpeg_component_info *compptr;
 130
 131  /* Horizontal mirroring of DCT blocks is accomplished by swapping
 132   * pairs of blocks in-place.  Within a DCT block, we perform horizontal
 133   * mirroring by changing the signs of odd-numbered columns.
 134   * Partial iMCUs at the right edge are left untouched.
 135   */
 136  MCU_cols = srcinfo->output_width /
 137    (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
 138
 139  for (ci = 0; ci < dstinfo->num_components; ci++) {
 140    compptr = dstinfo->comp_info + ci;
 141    comp_width = MCU_cols * compptr->h_samp_factor;
 142    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
 143    for (blk_y = 0; blk_y < compptr->height_in_blocks;
 144	 blk_y += compptr->v_samp_factor) {
 145      buffer = (*srcinfo->mem->access_virt_barray)
 146	((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
 147	 (JDIMENSION) compptr->v_samp_factor, TRUE);
 148      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
 149	/* Do the mirroring */
 150	for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
 151	  ptr1 = buffer[offset_y][blk_x];
 152	  ptr2 = buffer[offset_y][comp_width - blk_x - 1];
 153	  /* this unrolled loop doesn't need to know which row it's on... */
 154	  for (k = 0; k < DCTSIZE2; k += 2) {
 155	    temp1 = *ptr1;	/* swap even column */
 156	    temp2 = *ptr2;
 157	    *ptr1++ = temp2;
 158	    *ptr2++ = temp1;
 159	    temp1 = *ptr1;	/* swap odd column with sign change */
 160	    temp2 = *ptr2;
 161	    *ptr1++ = -temp2;
 162	    *ptr2++ = -temp1;
 163	  }
 164	}
 165	if (x_crop_blocks > 0) {
 166	  /* Now left-justify the portion of the data to be kept.
 167	   * We can't use a single jcopy_block_row() call because that routine
 168	   * depends on memcpy(), whose behavior is unspecified for overlapping
 169	   * source and destination areas.  Sigh.
 170	   */
 171	  for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
 172	    jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
 173			    buffer[offset_y] + blk_x,
 174			    (JDIMENSION) 1);
 175	  }
 176	}
 177      }
 178    }
 179  }
 180}
 181
 182
 183LOCAL(void)
 184do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
 185	   JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
 186	   jvirt_barray_ptr *src_coef_arrays,
 187	   jvirt_barray_ptr *dst_coef_arrays)
 188/* Horizontal flip in general cropping case */
 189{
 190  JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
 191  JDIMENSION x_crop_blocks, y_crop_blocks;
 192  int ci, k, offset_y;
 193  JBLOCKARRAY src_buffer, dst_buffer;
 194  JBLOCKROW src_row_ptr, dst_row_ptr;
 195  JCOEFPTR src_ptr, dst_ptr;
 196  jpeg_component_info *compptr;
 197
 198  /* Here we must output into a separate array because we can't touch
 199   * different rows of a single virtual array simultaneously.  Otherwise,
 200   * this is essentially the same as the routine above.
 201   */
 202  MCU_cols = srcinfo->output_width /
 203    (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
 204
 205  for (ci = 0; ci < dstinfo->num_components; ci++) {
 206    compptr = dstinfo->comp_info + ci;
 207    comp_width = MCU_cols * compptr->h_samp_factor;
 208    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
 209    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
 210    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
 211	 dst_blk_y += compptr->v_samp_factor) {
 212      dst_buffer = (*srcinfo->mem->access_virt_barray)
 213	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
 214	 (JDIMENSION) compptr->v_samp_factor, TRUE);
 215      src_buffer = (*srcinfo->mem->access_virt_barray)
 216	((j_common_ptr) srcinfo, src_coef_arrays[ci],
 217	 dst_blk_y + y_crop_blocks,
 218	 (JDIMENSION) compptr->v_samp_factor, FALSE);
 219      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
 220	dst_row_ptr = dst_buffer[offset_y];
 221	src_row_ptr = src_buffer[offset_y];
 222	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
 223	  if (x_crop_blocks + dst_blk_x < comp_width) {
 224	    /* Do the mirrorable blocks */
 225	    dst_ptr = dst_row_ptr[dst_blk_x];
 226	    src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
 227	    /* this unrolled loop doesn't need to know which row it's on... */
 228	    for (k = 0; k < DCTSIZE2; k += 2) {
 229	      *dst_ptr++ = *src_ptr++;	 /* copy even column */
 230	      *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
 231	    }
 232	  } else {
 233	    /* Copy last partial block(s) verbatim */
 234	    jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
 235			    dst_row_ptr + dst_blk_x,
 236			    (JDIMENSION) 1);
 237	  }
 238	}
 239      }
 240    }
 241  }
 242}
 243
 244
 245LOCAL(void)
 246do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
 247	   JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
 248	   jvirt_barray_ptr *src_coef_arrays,
 249	   jvirt_barray_ptr *dst_coef_arrays)
 250/* Vertical flip */
 251{
 252  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
 253  JDIMENSION x_crop_blocks, y_crop_blocks;
 254  int ci, i, j, offset_y;
 255  JBLOCKARRAY src_buffer, dst_buffer;
 256  JBLOCKROW src_row_ptr, dst_row_ptr;
 257  JCOEFPTR src_ptr, dst_ptr;
 258  jpeg_component_info *compptr;
 259
 260  /* We output into a separate array because we can't touch different
 261   * rows of the source virtual array simultaneously.  Otherwise, this
 262   * is a pretty straightforward analog of horizontal flip.
 263   * Within a DCT block, vertical mirroring is done by changing the signs
 264   * of odd-numbered rows.
 265   * Partial iMCUs at the bottom edge are copied verbatim.
 266   */
 267  MCU_rows = srcinfo->output_height /
 268    (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
 269
 270  for (ci = 0; ci < dstinfo->num_components; ci++) {
 271    compptr = dstinfo->comp_info + ci;
 272    comp_height = MCU_rows * compptr->v_samp_factor;
 273    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
 274    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
 275    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
 276	 dst_blk_y += compptr->v_samp_factor) {
 277      dst_buffer = (*srcinfo->mem->access_virt_barray)
 278	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
 279	 (JDIMENSION) compptr->v_samp_factor, TRUE);
 280      if (y_crop_blocks + dst_blk_y < comp_height) {
 281	/* Row is within the mirrorable area. */
 282	src_buffer = (*srcinfo->mem->access_virt_barray)
 283	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 284	   comp_height - y_crop_blocks - dst_blk_y -
 285	   (JDIMENSION) compptr->v_samp_factor,
 286	   (JDIMENSION) compptr->v_samp_factor, FALSE);
 287      } else {
 288	/* Bottom-edge blocks will be copied verbatim. */
 289	src_buffer = (*srcinfo->mem->access_virt_barray)
 290	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 291	   dst_blk_y + y_crop_blocks,
 292	   (JDIMENSION) compptr->v_samp_factor, FALSE);
 293      }
 294      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
 295	if (y_crop_blocks + dst_blk_y < comp_height) {
 296	  /* Row is within the mirrorable area. */
 297	  dst_row_ptr = dst_buffer[offset_y];
 298	  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
 299	  src_row_ptr += x_crop_blocks;
 300	  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
 301	       dst_blk_x++) {
 302	    dst_ptr = dst_row_ptr[dst_blk_x];
 303	    src_ptr = src_row_ptr[dst_blk_x];
 304	    for (i = 0; i < DCTSIZE; i += 2) {
 305	      /* copy even row */
 306	      for (j = 0; j < DCTSIZE; j++)
 307		*dst_ptr++ = *src_ptr++;
 308	      /* copy odd row with sign change */
 309	      for (j = 0; j < DCTSIZE; j++)
 310		*dst_ptr++ = - *src_ptr++;
 311	    }
 312	  }
 313	} else {
 314	  /* Just copy row verbatim. */
 315	  jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
 316			  dst_buffer[offset_y],
 317			  compptr->width_in_blocks);
 318	}
 319      }
 320    }
 321  }
 322}
 323
 324
 325LOCAL(void)
 326do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
 327	      JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
 328	      jvirt_barray_ptr *src_coef_arrays,
 329	      jvirt_barray_ptr *dst_coef_arrays)
 330/* Transpose source into destination */
 331{
 332  JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
 333  int ci, i, j, offset_x, offset_y;
 334  JBLOCKARRAY src_buffer, dst_buffer;
 335  JCOEFPTR src_ptr, dst_ptr;
 336  jpeg_component_info *compptr;
 337
 338  /* Transposing pixels within a block just requires transposing the
 339   * DCT coefficients.
 340   * Partial iMCUs at the edges require no special treatment; we simply
 341   * process all the available DCT blocks for every component.
 342   */
 343  for (ci = 0; ci < dstinfo->num_components; ci++) {
 344    compptr = dstinfo->comp_info + ci;
 345    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
 346    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
 347    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
 348	 dst_blk_y += compptr->v_samp_factor) {
 349      dst_buffer = (*srcinfo->mem->access_virt_barray)
 350	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
 351	 (JDIMENSION) compptr->v_samp_factor, TRUE);
 352      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
 353	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
 354	     dst_blk_x += compptr->h_samp_factor) {
 355	  src_buffer = (*srcinfo->mem->access_virt_barray)
 356	    ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 357	     dst_blk_x + x_crop_blocks,
 358	     (JDIMENSION) compptr->h_samp_factor, FALSE);
 359	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
 360	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
 361	    src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
 362	    for (i = 0; i < DCTSIZE; i++)
 363	      for (j = 0; j < DCTSIZE; j++)
 364		dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 365	  }
 366	}
 367      }
 368    }
 369  }
 370}
 371
 372
 373LOCAL(void)
 374do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
 375	   JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
 376	   jvirt_barray_ptr *src_coef_arrays,
 377	   jvirt_barray_ptr *dst_coef_arrays)
 378/* 90 degree rotation is equivalent to
 379 *   1. Transposing the image;
 380 *   2. Horizontal mirroring.
 381 * These two steps are merged into a single processing routine.
 382 */
 383{
 384  JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
 385  JDIMENSION x_crop_blocks, y_crop_blocks;
 386  int ci, i, j, offset_x, offset_y;
 387  JBLOCKARRAY src_buffer, dst_buffer;
 388  JCOEFPTR src_ptr, dst_ptr;
 389  jpeg_component_info *compptr;
 390
 391  /* Because of the horizontal mirror step, we can't process partial iMCUs
 392   * at the (output) right edge properly.  They just get transposed and
 393   * not mirrored.
 394   */
 395  MCU_cols = srcinfo->output_height /
 396    (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
 397
 398  for (ci = 0; ci < dstinfo->num_components; ci++) {
 399    compptr = dstinfo->comp_info + ci;
 400    comp_width = MCU_cols * compptr->h_samp_factor;
 401    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
 402    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
 403    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
 404	 dst_blk_y += compptr->v_samp_factor) {
 405      dst_buffer = (*srcinfo->mem->access_virt_barray)
 406	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
 407	 (JDIMENSION) compptr->v_samp_factor, TRUE);
 408      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
 409	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
 410	     dst_blk_x += compptr->h_samp_factor) {
 411	  if (x_crop_blocks + dst_blk_x < comp_width) {
 412	    /* Block is within the mirrorable area. */
 413	    src_buffer = (*srcinfo->mem->access_virt_barray)
 414	      ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 415	       comp_width - x_crop_blocks - dst_blk_x -
 416	       (JDIMENSION) compptr->h_samp_factor,
 417	       (JDIMENSION) compptr->h_samp_factor, FALSE);
 418	  } else {
 419	    /* Edge blocks are transposed but not mirrored. */
 420	    src_buffer = (*srcinfo->mem->access_virt_barray)
 421	      ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 422	       dst_blk_x + x_crop_blocks,
 423	       (JDIMENSION) compptr->h_samp_factor, FALSE);
 424	  }
 425	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
 426	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
 427	    if (x_crop_blocks + dst_blk_x < comp_width) {
 428	      /* Block is within the mirrorable area. */
 429	      src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
 430		[dst_blk_y + offset_y + y_crop_blocks];
 431	      for (i = 0; i < DCTSIZE; i++) {
 432		for (j = 0; j < DCTSIZE; j++)
 433		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 434		i++;
 435		for (j = 0; j < DCTSIZE; j++)
 436		  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
 437	      }
 438	    } else {
 439	      /* Edge blocks are transposed but not mirrored. */
 440	      src_ptr = src_buffer[offset_x]
 441		[dst_blk_y + offset_y + y_crop_blocks];
 442	      for (i = 0; i < DCTSIZE; i++)
 443		for (j = 0; j < DCTSIZE; j++)
 444		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 445	    }
 446	  }
 447	}
 448      }
 449    }
 450  }
 451}
 452
 453
 454LOCAL(void)
 455do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
 456	    JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
 457	    jvirt_barray_ptr *src_coef_arrays,
 458	    jvirt_barray_ptr *dst_coef_arrays)
 459/* 270 degree rotation is equivalent to
 460 *   1. Horizontal mirroring;
 461 *   2. Transposing the image.
 462 * These two steps are merged into a single processing routine.
 463 */
 464{
 465  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
 466  JDIMENSION x_crop_blocks, y_crop_blocks;
 467  int ci, i, j, offset_x, offset_y;
 468  JBLOCKARRAY src_buffer, dst_buffer;
 469  JCOEFPTR src_ptr, dst_ptr;
 470  jpeg_component_info *compptr;
 471
 472  /* Because of the horizontal mirror step, we can't process partial iMCUs
 473   * at the (output) bottom edge properly.  They just get transposed and
 474   * not mirrored.
 475   */
 476  MCU_rows = srcinfo->output_width /
 477    (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
 478
 479  for (ci = 0; ci < dstinfo->num_components; ci++) {
 480    compptr = dstinfo->comp_info + ci;
 481    comp_height = MCU_rows * compptr->v_samp_factor;
 482    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
 483    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
 484    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
 485	 dst_blk_y += compptr->v_samp_factor) {
 486      dst_buffer = (*srcinfo->mem->access_virt_barray)
 487	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
 488	 (JDIMENSION) compptr->v_samp_factor, TRUE);
 489      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
 490	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
 491	     dst_blk_x += compptr->h_samp_factor) {
 492	  src_buffer = (*srcinfo->mem->access_virt_barray)
 493	    ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 494	     dst_blk_x + x_crop_blocks,
 495	     (JDIMENSION) compptr->h_samp_factor, FALSE);
 496	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
 497	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
 498	    if (y_crop_blocks + dst_blk_y < comp_height) {
 499	      /* Block is within the mirrorable area. */
 500	      src_ptr = src_buffer[offset_x]
 501		[comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
 502	      for (i = 0; i < DCTSIZE; i++) {
 503		for (j = 0; j < DCTSIZE; j++) {
 504		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 505		  j++;
 506		  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
 507		}
 508	      }
 509	    } else {
 510	      /* Edge blocks are transposed but not mirrored. */
 511	      src_ptr = src_buffer[offset_x]
 512		[dst_blk_y + offset_y + y_crop_blocks];
 513	      for (i = 0; i < DCTSIZE; i++)
 514		for (j = 0; j < DCTSIZE; j++)
 515		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 516	    }
 517	  }
 518	}
 519      }
 520    }
 521  }
 522}
 523
 524
 525LOCAL(void)
 526do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
 527	    JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
 528	    jvirt_barray_ptr *src_coef_arrays,
 529	    jvirt_barray_ptr *dst_coef_arrays)
 530/* 180 degree rotation is equivalent to
 531 *   1. Vertical mirroring;
 532 *   2. Horizontal mirroring.
 533 * These two steps are merged into a single processing routine.
 534 */
 535{
 536  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
 537  JDIMENSION x_crop_blocks, y_crop_blocks;
 538  int ci, i, j, offset_y;
 539  JBLOCKARRAY src_buffer, dst_buffer;
 540  JBLOCKROW src_row_ptr, dst_row_ptr;
 541  JCOEFPTR src_ptr, dst_ptr;
 542  jpeg_component_info *compptr;
 543
 544  MCU_cols = srcinfo->output_width /
 545    (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
 546  MCU_rows = srcinfo->output_height /
 547    (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
 548
 549  for (ci = 0; ci < dstinfo->num_components; ci++) {
 550    compptr = dstinfo->comp_info + ci;
 551    comp_width = MCU_cols * compptr->h_samp_factor;
 552    comp_height = MCU_rows * compptr->v_samp_factor;
 553    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
 554    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
 555    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
 556	 dst_blk_y += compptr->v_samp_factor) {
 557      dst_buffer = (*srcinfo->mem->access_virt_barray)
 558	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
 559	 (JDIMENSION) compptr->v_samp_factor, TRUE);
 560      if (y_crop_blocks + dst_blk_y < comp_height) {
 561	/* Row is within the vertically mirrorable area. */
 562	src_buffer = (*srcinfo->mem->access_virt_barray)
 563	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 564	   comp_height - y_crop_blocks - dst_blk_y -
 565	   (JDIMENSION) compptr->v_samp_factor,
 566	   (JDIMENSION) compptr->v_samp_factor, FALSE);
 567      } else {
 568	/* Bottom-edge rows are only mirrored horizontally. */
 569	src_buffer = (*srcinfo->mem->access_virt_barray)
 570	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 571	   dst_blk_y + y_crop_blocks,
 572	   (JDIMENSION) compptr->v_samp_factor, FALSE);
 573      }
 574      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
 575	dst_row_ptr = dst_buffer[offset_y];
 576	if (y_crop_blocks + dst_blk_y < comp_height) {
 577	  /* Row is within the mirrorable area. */
 578	  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
 579	  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
 580	    dst_ptr = dst_row_ptr[dst_blk_x];
 581	    if (x_crop_blocks + dst_blk_x < comp_width) {
 582	      /* Process the blocks that can be mirrored both ways. */
 583	      src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
 584	      for (i = 0; i < DCTSIZE; i += 2) {
 585		/* For even row, negate every odd column. */
 586		for (j = 0; j < DCTSIZE; j += 2) {
 587		  *dst_ptr++ = *src_ptr++;
 588		  *dst_ptr++ = - *src_ptr++;
 589		}
 590		/* For odd row, negate every even column. */
 591		for (j = 0; j < DCTSIZE; j += 2) {
 592		  *dst_ptr++ = - *src_ptr++;
 593		  *dst_ptr++ = *src_ptr++;
 594		}
 595	      }
 596	    } else {
 597	      /* Any remaining right-edge blocks are only mirrored vertically. */
 598	      src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
 599	      for (i = 0; i < DCTSIZE; i += 2) {
 600		for (j = 0; j < DCTSIZE; j++)
 601		  *dst_ptr++ = *src_ptr++;
 602		for (j = 0; j < DCTSIZE; j++)
 603		  *dst_ptr++ = - *src_ptr++;
 604	      }
 605	    }
 606	  }
 607	} else {
 608	  /* Remaining rows are just mirrored horizontally. */
 609	  src_row_ptr = src_buffer[offset_y];
 610	  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
 611	    if (x_crop_blocks + dst_blk_x < comp_width) {
 612	      /* Process the blocks that can be mirrored. */
 613	      dst_ptr = dst_row_ptr[dst_blk_x];
 614	      src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
 615	      for (i = 0; i < DCTSIZE2; i += 2) {
 616		*dst_ptr++ = *src_ptr++;
 617		*dst_ptr++ = - *src_ptr++;
 618	      }
 619	    } else {
 620	      /* Any remaining right-edge blocks are only copied. */
 621	      jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
 622			      dst_row_ptr + dst_blk_x,
 623			      (JDIMENSION) 1);
 624	    }
 625	  }
 626	}
 627      }
 628    }
 629  }
 630}
 631
 632
 633LOCAL(void)
 634do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
 635	       JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
 636	       jvirt_barray_ptr *src_coef_arrays,
 637	       jvirt_barray_ptr *dst_coef_arrays)
 638/* Transverse transpose is equivalent to
 639 *   1. 180 degree rotation;
 640 *   2. Transposition;
 641 * or
 642 *   1. Horizontal mirroring;
 643 *   2. Transposition;
 644 *   3. Horizontal mirroring.
 645 * These steps are merged into a single processing routine.
 646 */
 647{
 648  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
 649  JDIMENSION x_crop_blocks, y_crop_blocks;
 650  int ci, i, j, offset_x, offset_y;
 651  JBLOCKARRAY src_buffer, dst_buffer;
 652  JCOEFPTR src_ptr, dst_ptr;
 653  jpeg_component_info *compptr;
 654
 655  MCU_cols = srcinfo->output_height /
 656    (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size);
 657  MCU_rows = srcinfo->output_width /
 658    (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size);
 659
 660  for (ci = 0; ci < dstinfo->num_components; ci++) {
 661    compptr = dstinfo->comp_info + ci;
 662    comp_width = MCU_cols * compptr->h_samp_factor;
 663    comp_height = MCU_rows * compptr->v_samp_factor;
 664    x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
 665    y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
 666    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
 667	 dst_blk_y += compptr->v_samp_factor) {
 668      dst_buffer = (*srcinfo->mem->access_virt_barray)
 669	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
 670	 (JDIMENSION) compptr->v_samp_factor, TRUE);
 671      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
 672	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
 673	     dst_blk_x += compptr->h_samp_factor) {
 674	  if (x_crop_blocks + dst_blk_x < comp_width) {
 675	    /* Block is within the mirrorable area. */
 676	    src_buffer = (*srcinfo->mem->access_virt_barray)
 677	      ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 678	       comp_width - x_crop_blocks - dst_blk_x -
 679	       (JDIMENSION) compptr->h_samp_factor,
 680	       (JDIMENSION) compptr->h_samp_factor, FALSE);
 681	  } else {
 682	    src_buffer = (*srcinfo->mem->access_virt_barray)
 683	      ((j_common_ptr) srcinfo, src_coef_arrays[ci],
 684	       dst_blk_x + x_crop_blocks,
 685	       (JDIMENSION) compptr->h_samp_factor, FALSE);
 686	  }
 687	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
 688	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
 689	    if (y_crop_blocks + dst_blk_y < comp_height) {
 690	      if (x_crop_blocks + dst_blk_x < comp_width) {
 691		/* Block is within the mirrorable area. */
 692		src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
 693		  [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
 694		for (i = 0; i < DCTSIZE; i++) {
 695		  for (j = 0; j < DCTSIZE; j++) {
 696		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 697		    j++;
 698		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
 699		  }
 700		  i++;
 701		  for (j = 0; j < DCTSIZE; j++) {
 702		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
 703		    j++;
 704		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 705		  }
 706		}
 707	      } else {
 708		/* Right-edge blocks are mirrored in y only */
 709		src_ptr = src_buffer[offset_x]
 710		  [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
 711		for (i = 0; i < DCTSIZE; i++) {
 712		  for (j = 0; j < DCTSIZE; j++) {
 713		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 714		    j++;
 715		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
 716		  }
 717		}
 718	      }
 719	    } else {
 720	      if (x_crop_blocks + dst_blk_x < comp_width) {
 721		/* Bottom-edge blocks are mirrored in x only */
 722		src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
 723		  [dst_blk_y + offset_y + y_crop_blocks];
 724		for (i = 0; i < DCTSIZE; i++) {
 725		  for (j = 0; j < DCTSIZE; j++)
 726		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 727		  i++;
 728		  for (j = 0; j < DCTSIZE; j++)
 729		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
 730		}
 731	      } else {
 732		/* At lower right corner, just transpose, no mirroring */
 733		src_ptr = src_buffer[offset_x]
 734		  [dst_blk_y + offset_y + y_crop_blocks];
 735		for (i = 0; i < DCTSIZE; i++)
 736		  for (j = 0; j < DCTSIZE; j++)
 737		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
 738	      }
 739	    }
 740	  }
 741	}
 742      }
 743    }
 744  }
 745}
 746
 747
 748/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
 749 * Returns TRUE if valid integer found, FALSE if not.
 750 * *strptr is advanced over the digit string, and *result is set to its value.
 751 */
 752
 753LOCAL(boolean)
 754jt_read_integer (const char ** strptr, JDIMENSION * result)
 755{
 756  const char * ptr = *strptr;
 757  JDIMENSION val = 0;
 758
 759  for (; isdigit(*ptr); ptr++) {
 760    val = val * 10 + (JDIMENSION) (*ptr - '0');
 761  }
 762  *result = val;
 763  if (ptr == *strptr)
 764    return FALSE;		/* oops, no digits */
 765  *strptr = ptr;
 766  return TRUE;
 767}
 768
 769
 770/* Parse a crop specification (written in X11 geometry style).
 771 * The routine returns TRUE if the spec string is valid, FALSE if not.
 772 *
 773 * The crop spec string should have the format
 774 *	<width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset>
 775 * where width, height, xoffset, and yoffset are unsigned integers.
 776 * Each of the elements can be omitted to indicate a default value.
 777 * (A weakness of this style is that it is not possible to omit xoffset
 778 * while specifying yoffset, since they look alike.)
 779 *
 780 * This code is loosely based on XParseGeometry from the X11 distribution.
 781 */
 782
 783GLOBAL(boolean)
 784jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec)
 785{
 786  info->crop = FALSE;
 787  info->crop_width_set = JCROP_UNSET;
 788  info->crop_height_set = JCROP_UNSET;
 789  info->crop_xoffset_set = JCROP_UNSET;
 790  info->crop_yoffset_set = JCROP_UNSET;
 791
 792  if (isdigit(*spec)) {
 793    /* fetch width */
 794    if (! jt_read_integer(&spec, &info->crop_width))
 795      return FALSE;
 796    if (*spec == 'f' || *spec == 'F') {
 797      spec++;
 798      info->crop_width_set = JCROP_FORCE;
 799    } else
 800      info->crop_width_set = JCROP_POS;
 801  }
 802  if (*spec == 'x' || *spec == 'X') {
 803    /* fetch height */
 804    spec++;
 805    if (! jt_read_integer(&spec, &info->crop_height))
 806      return FALSE;
 807    if (*spec == 'f' || *spec == 'F') {
 808      spec++;
 809      info->crop_height_set = JCROP_FORCE;
 810    } else
 811      info->crop_height_set = JCROP_POS;
 812  }
 813  if (*spec == '+' || *spec == '-') {
 814    /* fetch xoffset */
 815    info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
 816    spec++;
 817    if (! jt_read_integer(&spec, &info->crop_xoffset))
 818      return FALSE;
 819  }
 820  if (*spec == '+' || *spec == '-') {
 821    /* fetch yoffset */
 822    info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
 823    spec++;
 824    if (! jt_read_integer(&spec, &info->crop_yoffset))
 825      return FALSE;
 826  }
 827  /* We had better have gotten to the end of the string. */
 828  if (*spec != '\0')
 829    return FALSE;
 830  info->crop = TRUE;
 831  return TRUE;
 832}
 833
 834
 835/* Trim off any partial iMCUs on the indicated destination edge */
 836
 837LOCAL(void)
 838trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width)
 839{
 840  JDIMENSION MCU_cols;
 841
 842  MCU_cols = info->output_width / info->iMCU_sample_width;
 843  if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
 844      full_width / info->iMCU_sample_width)
 845    info->output_width = MCU_cols * info->iMCU_sample_width;
 846}
 847
 848LOCAL(void)
 849trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height)
 850{
 851  JDIMENSION MCU_rows;
 852
 853  MCU_rows = info->output_height / info->iMCU_sample_height;
 854  if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
 855      full_height / info->iMCU_sample_height)
 856    info->output_height = MCU_rows * info->iMCU_sample_height;
 857}
 858
 859
 860/* Request any required workspace.
 861 *
 862 * This routine figures out the size that the output image will be
 863 * (which implies that all the transform parameters must be set before
 864 * it is called).
 865 *
 866 * We allocate the workspace virtual arrays from the source decompression
 867 * object, so that all the arrays (both the original data and the workspace)
 868 * will be taken into account while making memory management decisions.
 869 * Hence, this routine must be called after jpeg_read_header (which reads
 870 * the image dimensions) and before jpeg_read_coefficients (which realizes
 871 * the source's virtual arrays).
 872 *
 873 * This function returns FALSE right away if -perfect is given
 874 * and transformation is not perfect.  Otherwise returns TRUE.
 875 */
 876
 877GLOBAL(boolean)
 878jtransform_request_workspace (j_decompress_ptr srcinfo,
 879			      jpeg_transform_info *info)
 880{
 881  jvirt_barray_ptr *coef_arrays;
 882  boolean need_workspace, transpose_it;
 883  jpeg_component_info *compptr;
 884  JDIMENSION xoffset, yoffset;
 885  JDIMENSION width_in_iMCUs, height_in_iMCUs;
 886  JDIMENSION width_in_blocks, height_in_blocks;
 887  int ci, h_samp_factor, v_samp_factor;
 888
 889  /* Determine number of components in output image */
 890  if (info->force_grayscale &&
 891      srcinfo->jpeg_color_space == JCS_YCbCr &&
 892      srcinfo->num_components == 3)
 893    /* We'll only process the first component */
 894    info->num_components = 1;
 895  else
 896    /* Process all the components */
 897    info->num_components = srcinfo->num_components;
 898
 899  /* Compute output image dimensions and related values. */
 900  jpeg_core_output_dimensions(srcinfo);
 901
 902  /* Return right away if -perfect is given and transformation is not perfect.
 903   */
 904  if (info->perfect) {
 905    if (info->num_components == 1) {
 906      if (!jtransform_perfect_transform(srcinfo->output_width,
 907	  srcinfo->output_height,
 908	  srcinfo->min_DCT_h_scaled_size,
 909	  srcinfo->min_DCT_v_scaled_size,
 910	  info->transform))
 911	return FALSE;
 912    } else {
 913      if (!jtransform_perfect_transform(srcinfo->output_width,
 914	  srcinfo->output_height,
 915	  srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size,
 916	  srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size,
 917	  info->transform))
 918	return FALSE;
 919    }
 920  }
 921
 922  /* If there is only one output component, force the iMCU size to be 1;
 923   * else use the source iMCU size.  (This allows us to do the right thing
 924   * when reducing color to grayscale, and also provides a handy way of
 925   * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
 926   */
 927  switch (info->transform) {
 928  case JXFORM_TRANSPOSE:
 929  case JXFORM_TRANSVERSE:
 930  case JXFORM_ROT_90:
 931  case JXFORM_ROT_270:
 932    info->output_width = srcinfo->output_height;
 933    info->output_height = srcinfo->output_width;
 934    if (info->num_components == 1) {
 935      info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size;
 936      info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size;
 937    } else {
 938      info->iMCU_sample_width =
 939	srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size;
 940      info->iMCU_sample_height =
 941	srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size;
 942    }
 943    break;
 944  default:
 945    info->output_width = srcinfo->output_width;
 946    info->output_height = srcinfo->output_height;
 947    if (info->num_components == 1) {
 948      info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size;
 949      info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size;
 950    } else {
 951      info->iMCU_sample_width =
 952	srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size;
 953      info->iMCU_sample_height =
 954	srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size;
 955    }
 956    break;
 957  }
 958
 959  /* If cropping has been requested, compute the crop area's position and
 960   * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
 961   */
 962  if (info->crop) {
 963    /* Insert default values for unset crop parameters */
 964    if (info->crop_xoffset_set == JCROP_UNSET)
 965      info->crop_xoffset = 0;	/* default to +0 */
 966    if (info->crop_yoffset_set == JCROP_UNSET)
 967      info->crop_yoffset = 0;	/* default to +0 */
 968    if (info->crop_xoffset >= info->output_width ||
 969	info->crop_yoffset >= info->output_height)
 970      ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
 971    if (info->crop_width_set == JCROP_UNSET)
 972      info->crop_width = info->output_width - info->crop_xoffset;
 973    if (info->crop_height_set == JCROP_UNSET)
 974      info->crop_height = info->output_height - info->crop_yoffset;
 975    /* Ensure parameters are valid */
 976    if (info->crop_width <= 0 || info->crop_width > info->output_width ||
 977	info->crop_height <= 0 || info->crop_height > info->output_height ||
 978	info->crop_xoffset > info->output_width - info->crop_width ||
 979	info->crop_yoffset > info->output_height - info->crop_height)
 980      ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
 981    /* Convert negative crop offsets into regular offsets */
 982    if (info->crop_xoffset_set == JCROP_NEG)
 983      xoffset = info->output_width - info->crop_width - info->crop_xoffset;
 984    else
 985      xoffset = info->crop_xoffset;
 986    if (info->crop_yoffset_set == JCROP_NEG)
 987      yoffset = info->output_height - info->crop_height - info->crop_yoffset;
 988    else
 989      yoffset = info->crop_yoffset;
 990    /* Now adjust so that upper left corner falls at an iMCU boundary */
 991    if (info->crop_width_set == JCROP_FORCE)
 992      info->output_width = info->crop_width;
 993    else
 994      info->output_width =
 995        info->crop_width + (xoffset % info->iMCU_sample_width);
 996    if (info->crop_height_set == JCROP_FORCE)
 997      info->output_height = info->crop_height;
 998    else
 999      info->output_height =
1000        info->crop_height + (yoffset % info->iMCU_sample_height);
1001    /* Save x/y offsets measured in iMCUs */
1002    info->x_crop_offset = xoffset / info->iMCU_sample_width;
1003    info->y_crop_offset = yoffset / info->iMCU_sample_height;
1004  } else {
1005    info->x_crop_offset = 0;
1006    info->y_crop_offset = 0;
1007  }
1008
1009  /* Figure out whether we need workspace arrays,
1010   * and if so whether they are transposed relative to the source.
1011   */
1012  need_workspace = FALSE;
1013  transpose_it = FALSE;
1014  switch (info->transform) {
1015  case JXFORM_NONE:
1016    if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
1017      need_workspace = TRUE;
1018    /* No workspace needed if neither cropping nor transforming */
1019    break;
1020  case JXFORM_FLIP_H:
1021    if (info->trim)
1022      trim_right_edge(info, srcinfo->output_width);
1023    if (info->y_crop_offset != 0)
1024      need_workspace = TRUE;
1025    /* do_flip_h_no_crop doesn't need a workspace array */
1026    break;
1027  case JXFORM_FLIP_V:
1028    if (info->trim)
1029      trim_bottom_edge(info, srcinfo->output_height);
1030    /* Need workspace arrays having same dimensions as source image. */
1031    need_workspace = TRUE;
1032    break;
1033  case JXFORM_TRANSPOSE:
1034    /* transpose does NOT have to trim anything */
1035    /* Need workspace arrays having transposed dimensions. */
1036    need_workspace = TRUE;
1037    transpose_it = TRUE;
1038    break;
1039  case JXFORM_TRANSVERSE:
1040    if (info->trim) {
1041      trim_right_edge(info, srcinfo->output_height);
1042      trim_bottom_edge(info, srcinfo->output_width);
1043    }
1044    /* Need workspace arrays having transposed dimensions. */
1045    need_workspace = TRUE;
1046    transpose_it = TRUE;
1047    break;
1048  case JXFORM_ROT_90:
1049    if (info->trim)
1050      trim_right_edge(info, srcinfo->output_height);
1051    /* Need workspace arrays having transposed dimensions. */
1052    need_workspace = TRUE;
1053    transpose_it = TRUE;
1054    break;
1055  case JXFORM_ROT_180:
1056    if (info->trim) {
1057      trim_right_edge(info, srcinfo->output_width);
1058      trim_bottom_edge(info, srcinfo->output_height);
1059    }
1060    /* Need workspace arrays having same dimensions as source image. */
1061    need_workspace = TRUE;
1062    break;
1063  case JXFORM_ROT_270:
1064    if (info->trim)
1065      trim_bottom_edge(info, srcinfo->output_width);
1066    /* Need workspace arrays having transposed dimensions. */
1067    need_workspace = TRUE;
1068    transpose_it = TRUE;
1069    break;
1070  }
1071
1072  /* Allocate workspace if needed.
1073   * Note that we allocate arrays padded out to the next iMCU boundary,
1074   * so that transform routines need not worry about missing edge blocks.
1075   */
1076  if (need_workspace) {
1077    coef_arrays = (jvirt_barray_ptr *)
1078      (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
1079		SIZEOF(jvirt_barray_ptr) * info->num_components);
1080    width_in_iMCUs = (JDIMENSION)
1081      jdiv_round_up((long) info->output_width,
1082		    (long) info->iMCU_sample_width);
1083    height_in_iMCUs = (JDIMENSION)
1084      jdiv_round_up((long) info->output_height,
1085		    (long) info->iMCU_sample_height);
1086    for (ci = 0; ci < info->num_components; ci++) {
1087      compptr = srcinfo->comp_info + ci;
1088      if (info->num_components == 1) {
1089	/* we're going to force samp factors to 1x1 in this case */
1090	h_samp_factor = v_samp_factor = 1;
1091      } else if (transpose_it) {
1092	h_samp_factor = compptr->v_samp_factor;
1093	v_samp_factor = compptr->h_samp_factor;
1094      } else {
1095	h_samp_factor = compptr->h_samp_factor;
1096	v_samp_factor = compptr->v_samp_factor;
1097      }
1098      width_in_blocks = width_in_iMCUs * h_samp_factor;
1099      height_in_blocks = height_in_iMCUs * v_samp_factor;
1100      coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1101	((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
1102	 width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
1103    }
1104    info->workspace_coef_arrays = coef_arrays;
1105  } else
1106    info->workspace_coef_arrays = NULL;
1107
1108  return TRUE;
1109}
1110
1111
1112/* Transpose destination image parameters */
1113
1114LOCAL(void)
1115transpose_critical_parameters (j_compress_ptr dstinfo)
1116{
1117  int tblno, i, j, ci, itemp;
1118  jpeg_component_info *compptr;
1119  JQUANT_TBL *qtblptr;
1120  JDIMENSION jtemp;
1121  UINT16 qtemp;
1122
1123  /* Transpose image dimensions */
1124  jtemp = dstinfo->image_width;
1125  dstinfo->image_width = dstinfo->image_height;
1126  dstinfo->image_height = jtemp;
1127  itemp = dstinfo->min_DCT_h_scaled_size;
1128  dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
1129  dstinfo->min_DCT_v_scaled_size = itemp;
1130
1131  /* Transpose sampling factors */
1132  for (ci = 0; ci < dstinfo->num_components; ci++) {
1133    compptr = dstinfo->comp_info + ci;
1134    itemp = compptr->h_samp_factor;
1135    compptr->h_samp_factor = compptr->v_samp_factor;
1136    compptr->v_samp_factor = itemp;
1137  }
1138
1139  /* Transpose quantization tables */
1140  for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
1141    qtblptr = dstinfo->quant_tbl_ptrs[tblno];
1142    if (qtblptr != NULL) {
1143      for (i = 0; i < DCTSIZE; i++) {
1144	for (j = 0; j < i; j++) {
1145	  qtemp = qtblptr->quantval[i*DCTSIZE+j];
1146	  qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
1147	  qtblptr->quantval[j*DCTSIZE+i] = qtemp;
1148	}
1149      }
1150    }
1151  }
1152}
1153
1154
1155/* Adjust Exif image parameters.
1156 *
1157 * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1158 */
1159
1160LOCAL(void)
1161adjust_exif_parameters (JOCTET FAR * data, unsigned int length,
1162			JDIMENSION new_width, JDIMENSION new_height)
1163{
1164  boolean is_motorola; /* Flag for byte order */
1165  unsigned int number_of_tags, tagnum;
1166  unsigned int firstoffset, offset;
1167  JDIMENSION new_value;
1168
1169  if (length < 12) return; /* Length of an IFD entry */
1170
1171  /* Discover byte order */
1172  if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
1173    is_motorola = FALSE;
1174  else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
1175    is_motorola = TRUE;
1176  else
1177    return;
1178
1179  /* Check Tag Mark */
1180  if (is_motorola) {
1181    if (GETJOCTET(data[2]) != 0) return;
1182    if (GETJOCTET(data[3]) != 0x2A) return;
1183  } else {
1184    if (GETJOCTET(data[3]) != 0) return;
1185    if (GETJOCTET(data[2]) != 0x2A) return;
1186  }
1187
1188  /* Get first IFD offset (offset to IFD0) */
1189  if (is_motorola) {
1190    if (GETJOCTET(data[4]) != 0) return;
1191    if (GETJOCTET(data[5]) != 0) return;
1192    firstoffset = GETJOCTET(data[6]);
1193    firstoffset <<= 8;
1194    firstoffset += GETJOCTET(data[7]);
1195  } else {
1196    if (GETJOCTET(data[7]) != 0) return;
1197    if (GETJOCTET(data[6]) != 0) return;
1198    firstoffset = GETJOCTET(data[5]);
1199    firstoffset <<= 8;
1200    firstoffset += GETJOCTET(data[4]);
1201  }
1202  if (firstoffset > length - 2) return; /* check end of data segment */
1203
1204  /* Get the number of directory entries contained in this IFD */
1205  if (is_motorola) {
1206    number_of_tags = GETJOCTET(data[firstoffset]);
1207    number_of_tags <<= 8;
1208    number_of_tags += GETJOCTET(data[firstoffset+1]);
1209  } else {
1210    number_of_tags = GETJOCTET(data[firstoffset+1]);
1211    number_of_tags <<= 8;
1212    number_of_tags += GETJOCTET(data[firstoffset]);
1213  }
1214  if (number_of_tags == 0) return;
1215  firstoffset += 2;
1216
1217  /* Search for ExifSubIFD offset Tag in IFD0 */
1218  for (;;) {
1219    if (firstoffset > length - 12) return; /* check end of data segment */
1220    /* Get Tag number */
1221    if (is_motorola) {
1222      tagnum = GETJOCTET(data[firstoffset]);
1223      tagnum <<= 8;
1224      tagnum += GETJOCTET(data[firstoffset+1]);
1225    } else {
1226      tagnum = GETJOCTET(data[firstoffset+1]);
1227      tagnum <<= 8;
1228      tagnum += GETJOCTET(data[firstoffset]);
1229    }
1230    if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
1231    if (--number_of_tags == 0) return;
1232    firstoffset += 12;
1233  }
1234
1235  /* Get the ExifSubIFD offset */
1236  if (is_motorola) {
1237    if (GETJOCTET(data[firstoffset+8]) != 0) return;
1238    if (GETJOCTET(data[firstoffset+9]) != 0) return;
1239    offset = GETJOCTET(data[firstoffset+10]);
1240    offset <<= 8;
1241    offset += GETJOCTET(data[firstoffset+11]);
1242  } else {
1243    if (GETJOCTET(data[firstoffset+11]) != 0) return;
1244    if (GETJOCTET(data[firstoffset+10]) != 0) return;
1245    offset = GETJOCTET(data[firstoffset+9]);
1246    offset <<= 8;
1247    offset += GETJOCTET(data[firstoffset+8]);
1248  }
1249  if (offset > length - 2) return; /* check end of data segment */
1250
1251  /* Get the number of directory entries contained in this SubIFD */
1252  if (is_motorola) {
1253    number_of_tags = GETJOCTET(data[offset]);
1254    number_of_tags <<= 8;
1255    number_of_tags += GETJOCTET(data[offset+1]);
1256  } else {
1257    number_of_tags = GETJOCTET(data[offset+1]);
1258    number_of_tags <<= 8;
1259    number_of_tags += GETJOCTET(data[offset]);
1260  }
1261  if (number_of_tags < 2) return;
1262  offset += 2;
1263
1264  /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1265  do {
1266    if (offset > length - 12) return; /* check end of data segment */
1267    /* Get Tag number */
1268    if (is_motorola) {
1269      tagnum = GETJOCTET(data[offset]);
1270      tagnum <<= 8;
1271      tagnum += GETJOCTET(data[offset+1]);
1272    } else {
1273      tagnum = GETJOCTET(data[offset+1]);
1274      tagnum <<= 8;
1275      tagnum += GETJOCTET(data[offset]);
1276    }
1277    if (tagnum == 0xA002 || tagnum == 0xA003) {
1278      if (tagnum == 0xA002)
1279	new_value = new_width; /* ExifImageWidth Tag */
1280      else
1281	new_value = new_height; /* ExifImageHeight Tag */
1282      if (is_motorola) {
1283	data[offset+2] = 0; /* Format = unsigned long (4 octets) */
1284	data[offset+3] = 4;
1285	data[offset+4] = 0; /* Number Of Components = 1 */
1286	data[offset+5] = 0;
1287	data[offset+6] = 0;
1288	data[offset+7] = 1;
1289	data[offset+8] = 0;
1290	data[offset+9] = 0;
1291	data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
1292	data[offset+11] = (JOCTET)(new_value & 0xFF);
1293      } else {
1294	data[offset+2] = 4; /* Format = unsigned long (4 octets) */
1295	data[offset+3] = 0;
1296	data[offset+4] = 1; /* Number Of Components = 1 */
1297	data[offset+5] = 0;
1298	data[offset+6] = 0;
1299	data[offset+7] = 0;
1300	data[offset+8] = (JOCTET)(new_value & 0xFF);
1301	data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
1302	data[offset+10] = 0;
1303	data[offset+11] = 0;
1304      }
1305    }
1306    offset += 12;
1307  } while (--number_of_tags);
1308}
1309
1310
1311/* Adjust output image parameters as needed.
1312 *
1313 * This must be called after jpeg_copy_critical_parameters()
1314 * and before jpeg_write_coefficients().
1315 *
1316 * The return value is the set of virtual coefficient arrays to be written
1317 * (either the ones allocated by jtransform_request_workspace, or the
1318 * original source data arrays).  The caller will need to pass this value
1319 * to jpeg_write_coefficients().
1320 */
1321
1322GLOBAL(jvirt_barray_ptr *)
1323jtransform_adjust_parameters (j_decompress_ptr srcinfo,
1324			      j_compress_ptr dstinfo,
1325			      jvirt_barray_ptr *src_coef_arrays,
1326			      jpeg_transform_info *info)
1327{
1328  /* If force-to-grayscale is requested, adjust destination parameters */
1329  if (info->force_grayscale) {
1330    /* First, ensure we have YCbCr or grayscale data, and that the source's
1331     * Y channel is full resolution.  (No reasonable person would make Y
1332     * be less than full resolution, so actually coping with that case
1333     * isn't worth extra code space.  But we check it to avoid crashing.)
1334     */
1335    if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
1336	  dstinfo->num_components == 3) ||
1337	 (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
1338	  dstinfo->num_components == 1)) &&
1339	srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
1340	srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
1341      /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
1342       * properly.  Among other things, it sets the target h_samp_factor &
1343       * v_samp_factor to 1, which typically won't match the source.
1344       * We have to preserve the source's quantization table number, however.
1345       */
1346      int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
1347      jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
1348      dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
1349    } else {
1350      /* Sorry, can't do it */
1351      ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
1352    }
1353  } else if (info->num_components == 1) {
1354    /* For a single-component source, we force the destination sampling factors
1355     * to 1x1, with or without force_grayscale.  This is useful because some
1356     * decoders choke on grayscale images with other sampling factors.
1357     */
1358    dstinfo->comp_info[0].h_samp_factor = 1;
1359    dstinfo->comp_info[0].v_samp_factor = 1;
1360  }
1361
1362  /* Correct the destination's image dimensions as necessary
1363   * for rotate/flip, resize, and crop operations.
1364   */
1365  dstinfo->jpeg_width = info->output_width;
1366  dstinfo->jpeg_height = info->output_height;
1367
1368  /* Transpose destination image parameters */
1369  switch (info->transform) {
1370  case JXFORM_TRANSPOSE:
1371  case JXFORM_TRANSVERSE:
1372  case JXFORM_ROT_90:
1373  case JXFORM_ROT_270:
1374    transpose_critical_parameters(dstinfo);
1375    break;
1376  default:
1377    break

Large files files are truncated, but you can click here to view the full file