170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * transupp.c
370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Copyright (C) 1997, Thomas G. Lane.
570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file is part of the Independent JPEG Group's software.
670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * For conditions of distribution and use, see the accompanying README file.
770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This file contains image transformation routines and other utility code
970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * used by the jpegtran sample application.  These are NOT part of the core
1070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * JPEG library.  But we keep these routines separate from jpegtran.c to
1170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * ease the task of maintaining jpegtran-like programs that have other user
1270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * interfaces.
1370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
1470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
1570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Although this file really shouldn't have access to the library internals,
1670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * it's helpful to let it call jround_up() and jcopy_block_row().
1770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
1870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#define JPEG_INTERNALS
1970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "jinclude.h"
2170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "jpeglib.h"
2270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#include "transupp.h"		/* My own external interface */
2370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#if TRANSFORMS_SUPPORTED
2670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
2770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/*
2870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Lossless image transformation routines.  These routines work on DCT
2970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * coefficient arrays and thus do not require any lossy decompression
3070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * or recompression of the image.
3170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Thanks to Guido Vollbeding for the initial design and code of this feature.
3270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
3370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Horizontal flipping is done in-place, using a single top-to-bottom
3470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * pass through the virtual source array.  It will thus be much the
3570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * fastest option for images larger than main memory.
3670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
3770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * The other routines require a set of destination virtual arrays, so they
3870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * need twice as much memory as jpegtran normally does.  The destination
3970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * arrays are always written in normal scan order (top to bottom) because
4070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * the virtual array manager expects this.  The source arrays will be scanned
4170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * in the corresponding order, which means multiple passes through the source
4270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * arrays for most of the transforms.  That could result in much thrashing
4370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * if the image is larger than main memory.
4470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
4570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Some notes about the operating environment of the individual transform
4670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * routines:
4770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 1. Both the source and destination virtual arrays are allocated from the
4870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *    source JPEG object, and therefore should be manipulated by calling the
4970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *    source's memory manager.
5070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 2. The destination's component count should be used.  It may be smaller
5170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *    than the source's when forcing to grayscale.
5270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 3. Likewise the destination's sampling factors should be used.  When
5370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *    forcing to grayscale the destination's sampling factors will be all 1,
5470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *    and we may as well take that as the effective iMCU size.
5570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 4. When "trim" is in effect, the destination's dimensions will be the
5670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *    trimmed values but the source's will be untrimmed.
5770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * 5. All the routines assume that the source and destination buffers are
5870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *    padded out to a full iMCU boundary.  This is true, although for the
5970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *    source buffer it is an undocumented property of jdcoefct.c.
6070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Notes 2,3,4 boil down to this: generally we should use the destination's
6170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * dimensions and ignore the source's.
6270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
6370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
6470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
6570a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
6670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinedo_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
6770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   jvirt_barray_ptr *src_coef_arrays)
6870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Horizontal flip; done in-place, so no separate dest array is required */
6970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
7070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
7170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, k, offset_y;
7270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JBLOCKARRAY buffer;
7370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JCOEFPTR ptr1, ptr2;
7470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JCOEF temp1, temp2;
7570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info *compptr;
7670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
7770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Horizontal mirroring of DCT blocks is accomplished by swapping
7870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * pairs of blocks in-place.  Within a DCT block, we perform horizontal
7970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * mirroring by changing the signs of odd-numbered columns.
8070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * Partial iMCUs at the right edge are left untouched.
8170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
8270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
8370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
8470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
8570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr = dstinfo->comp_info + ci;
8670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    comp_width = MCU_cols * compptr->h_samp_factor;
8770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (blk_y = 0; blk_y < compptr->height_in_blocks;
8870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 blk_y += compptr->v_samp_factor) {
8970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      buffer = (*srcinfo->mem->access_virt_barray)
9070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
9170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) compptr->v_samp_factor, TRUE);
9270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
9370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
9470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  ptr1 = buffer[offset_y][blk_x];
9570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  ptr2 = buffer[offset_y][comp_width - blk_x - 1];
9670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  /* this unrolled loop doesn't need to know which row it's on... */
9770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (k = 0; k < DCTSIZE2; k += 2) {
9870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    temp1 = *ptr1;	/* swap even column */
9970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    temp2 = *ptr2;
10070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    *ptr1++ = temp2;
10170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    *ptr2++ = temp1;
10270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    temp1 = *ptr1;	/* swap odd column with sign change */
10370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    temp2 = *ptr2;
10470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    *ptr1++ = -temp2;
10570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    *ptr2++ = -temp1;
10670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
10770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
10870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
10970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
11070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
11170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
11270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
11370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
11470a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
11570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinedo_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
11670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   jvirt_barray_ptr *src_coef_arrays,
11770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   jvirt_barray_ptr *dst_coef_arrays)
11870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Vertical flip */
11970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
12070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
12170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, i, j, offset_y;
12270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JBLOCKARRAY src_buffer, dst_buffer;
12370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JBLOCKROW src_row_ptr, dst_row_ptr;
12470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JCOEFPTR src_ptr, dst_ptr;
12570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info *compptr;
12670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
12770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* We output into a separate array because we can't touch different
12870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * rows of the source virtual array simultaneously.  Otherwise, this
12970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * is a pretty straightforward analog of horizontal flip.
13070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * Within a DCT block, vertical mirroring is done by changing the signs
13170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * of odd-numbered rows.
13270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * Partial iMCUs at the bottom edge are copied verbatim.
13370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
13470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
13570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
13670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
13770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr = dstinfo->comp_info + ci;
13870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    comp_height = MCU_rows * compptr->v_samp_factor;
13970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
14070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 dst_blk_y += compptr->v_samp_factor) {
14170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      dst_buffer = (*srcinfo->mem->access_virt_barray)
14270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
14370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) compptr->v_samp_factor, TRUE);
14470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (dst_blk_y < comp_height) {
14570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	/* Row is within the mirrorable area. */
14670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	src_buffer = (*srcinfo->mem->access_virt_barray)
14770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
14870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
14970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   (JDIMENSION) compptr->v_samp_factor, FALSE);
15070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      } else {
15170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	/* Bottom-edge blocks will be copied verbatim. */
15270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	src_buffer = (*srcinfo->mem->access_virt_barray)
15370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
15470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   (JDIMENSION) compptr->v_samp_factor, FALSE);
15570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
15670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
15770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	if (dst_blk_y < comp_height) {
15870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  /* Row is within the mirrorable area. */
15970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  dst_row_ptr = dst_buffer[offset_y];
16070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
16170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
16270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	       dst_blk_x++) {
16370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    dst_ptr = dst_row_ptr[dst_blk_x];
16470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    src_ptr = src_row_ptr[dst_blk_x];
16570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    for (i = 0; i < DCTSIZE; i += 2) {
16670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      /* copy even row */
16770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (j = 0; j < DCTSIZE; j++)
16870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		*dst_ptr++ = *src_ptr++;
16970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      /* copy odd row with sign change */
17070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (j = 0; j < DCTSIZE; j++)
17170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		*dst_ptr++ = - *src_ptr++;
17270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    }
17370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
17470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	} else {
17570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  /* Just copy row verbatim. */
17670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
17770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			  compptr->width_in_blocks);
17870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
17970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
18070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
18170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
18270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
18370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
18470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
18570a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
18670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinedo_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
18770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      jvirt_barray_ptr *src_coef_arrays,
18870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      jvirt_barray_ptr *dst_coef_arrays)
18970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Transpose source into destination */
19070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
19170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION dst_blk_x, dst_blk_y;
19270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, i, j, offset_x, offset_y;
19370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JBLOCKARRAY src_buffer, dst_buffer;
19470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JCOEFPTR src_ptr, dst_ptr;
19570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info *compptr;
19670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
19770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Transposing pixels within a block just requires transposing the
19870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * DCT coefficients.
19970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * Partial iMCUs at the edges require no special treatment; we simply
20070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * process all the available DCT blocks for every component.
20170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
20270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
20370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr = dstinfo->comp_info + ci;
20470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
20570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 dst_blk_y += compptr->v_samp_factor) {
20670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      dst_buffer = (*srcinfo->mem->access_virt_barray)
20770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
20870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) compptr->v_samp_factor, TRUE);
20970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
21070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
21170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     dst_blk_x += compptr->h_samp_factor) {
21270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  src_buffer = (*srcinfo->mem->access_virt_barray)
21370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
21470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     (JDIMENSION) compptr->h_samp_factor, FALSE);
21570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
21670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
21770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
21870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    for (i = 0; i < DCTSIZE; i++)
21970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (j = 0; j < DCTSIZE; j++)
22070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
22170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
22270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
22370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
22470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
22570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
22670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
22770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
22870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
22970a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
23070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinedo_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
23170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   jvirt_barray_ptr *src_coef_arrays,
23270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   jvirt_barray_ptr *dst_coef_arrays)
23370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 90 degree rotation is equivalent to
23470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   1. Transposing the image;
23570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   2. Horizontal mirroring.
23670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * These two steps are merged into a single processing routine.
23770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
23870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
23970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
24070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, i, j, offset_x, offset_y;
24170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JBLOCKARRAY src_buffer, dst_buffer;
24270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JCOEFPTR src_ptr, dst_ptr;
24370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info *compptr;
24470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
24570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Because of the horizontal mirror step, we can't process partial iMCUs
24670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * at the (output) right edge properly.  They just get transposed and
24770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * not mirrored.
24870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
24970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
25070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
25170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
25270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr = dstinfo->comp_info + ci;
25370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    comp_width = MCU_cols * compptr->h_samp_factor;
25470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
25570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 dst_blk_y += compptr->v_samp_factor) {
25670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      dst_buffer = (*srcinfo->mem->access_virt_barray)
25770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
25870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) compptr->v_samp_factor, TRUE);
25970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
26070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
26170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     dst_blk_x += compptr->h_samp_factor) {
26270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  src_buffer = (*srcinfo->mem->access_virt_barray)
26370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
26470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     (JDIMENSION) compptr->h_samp_factor, FALSE);
26570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
26670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
26770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    if (dst_blk_x < comp_width) {
26870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      /* Block is within the mirrorable area. */
26970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      dst_ptr = dst_buffer[offset_y]
27070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		[comp_width - dst_blk_x - offset_x - 1];
27170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (i = 0; i < DCTSIZE; i++) {
27270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		for (j = 0; j < DCTSIZE; j++)
27370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
27470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		i++;
27570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		for (j = 0; j < DCTSIZE; j++)
27670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
27770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      }
27870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    } else {
27970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      /* Edge blocks are transposed but not mirrored. */
28070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
28170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (i = 0; i < DCTSIZE; i++)
28270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		for (j = 0; j < DCTSIZE; j++)
28370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
28470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    }
28570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
28670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
28770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
28870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
28970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
29070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
29170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
29270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
29370a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
29470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinedo_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
29570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    jvirt_barray_ptr *src_coef_arrays,
29670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    jvirt_barray_ptr *dst_coef_arrays)
29770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 270 degree rotation is equivalent to
29870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   1. Horizontal mirroring;
29970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   2. Transposing the image.
30070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * These two steps are merged into a single processing routine.
30170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
30270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
30370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
30470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, i, j, offset_x, offset_y;
30570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JBLOCKARRAY src_buffer, dst_buffer;
30670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JCOEFPTR src_ptr, dst_ptr;
30770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info *compptr;
30870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
30970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Because of the horizontal mirror step, we can't process partial iMCUs
31070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * at the (output) bottom edge properly.  They just get transposed and
31170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * not mirrored.
31270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
31370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
31470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
31570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
31670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr = dstinfo->comp_info + ci;
31770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    comp_height = MCU_rows * compptr->v_samp_factor;
31870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
31970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 dst_blk_y += compptr->v_samp_factor) {
32070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      dst_buffer = (*srcinfo->mem->access_virt_barray)
32170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
32270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) compptr->v_samp_factor, TRUE);
32370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
32470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
32570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     dst_blk_x += compptr->h_samp_factor) {
32670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  src_buffer = (*srcinfo->mem->access_virt_barray)
32770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
32870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     (JDIMENSION) compptr->h_samp_factor, FALSE);
32970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
33070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
33170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    if (dst_blk_y < comp_height) {
33270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      /* Block is within the mirrorable area. */
33370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      src_ptr = src_buffer[offset_x]
33470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		[comp_height - dst_blk_y - offset_y - 1];
33570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (i = 0; i < DCTSIZE; i++) {
33670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		for (j = 0; j < DCTSIZE; j++) {
33770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
33870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  j++;
33970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
34070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		}
34170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      }
34270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    } else {
34370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      /* Edge blocks are transposed but not mirrored. */
34470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
34570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (i = 0; i < DCTSIZE; i++)
34670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		for (j = 0; j < DCTSIZE; j++)
34770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
34870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    }
34970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
35070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
35170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
35270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
35370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
35470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
35570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
35670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
35770a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
35870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinedo_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
35970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    jvirt_barray_ptr *src_coef_arrays,
36070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    jvirt_barray_ptr *dst_coef_arrays)
36170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* 180 degree rotation is equivalent to
36270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   1. Vertical mirroring;
36370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   2. Horizontal mirroring.
36470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * These two steps are merged into a single processing routine.
36570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
36670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
36770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
36870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, i, j, offset_y;
36970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JBLOCKARRAY src_buffer, dst_buffer;
37070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JBLOCKROW src_row_ptr, dst_row_ptr;
37170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JCOEFPTR src_ptr, dst_ptr;
37270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info *compptr;
37370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
37470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
37570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
37670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
37770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
37870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr = dstinfo->comp_info + ci;
37970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    comp_width = MCU_cols * compptr->h_samp_factor;
38070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    comp_height = MCU_rows * compptr->v_samp_factor;
38170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
38270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 dst_blk_y += compptr->v_samp_factor) {
38370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      dst_buffer = (*srcinfo->mem->access_virt_barray)
38470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
38570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) compptr->v_samp_factor, TRUE);
38670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      if (dst_blk_y < comp_height) {
38770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	/* Row is within the vertically mirrorable area. */
38870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	src_buffer = (*srcinfo->mem->access_virt_barray)
38970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  ((j_common_ptr) srcinfo, src_coef_arrays[ci],
39070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
39170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   (JDIMENSION) compptr->v_samp_factor, FALSE);
39270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      } else {
39370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	/* Bottom-edge rows are only mirrored horizontally. */
39470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	src_buffer = (*srcinfo->mem->access_virt_barray)
39570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
39670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	   (JDIMENSION) compptr->v_samp_factor, FALSE);
39770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
39870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
39970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	if (dst_blk_y < comp_height) {
40070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  /* Row is within the mirrorable area. */
40170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  dst_row_ptr = dst_buffer[offset_y];
40270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
40370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  /* Process the blocks that can be mirrored both ways. */
40470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
40570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    dst_ptr = dst_row_ptr[dst_blk_x];
40670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
40770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    for (i = 0; i < DCTSIZE; i += 2) {
40870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      /* For even row, negate every odd column. */
40970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (j = 0; j < DCTSIZE; j += 2) {
41070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		*dst_ptr++ = *src_ptr++;
41170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		*dst_ptr++ = - *src_ptr++;
41270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      }
41370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      /* For odd row, negate every even column. */
41470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (j = 0; j < DCTSIZE; j += 2) {
41570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		*dst_ptr++ = - *src_ptr++;
41670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		*dst_ptr++ = *src_ptr++;
41770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      }
41870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    }
41970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
42070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  /* Any remaining right-edge blocks are only mirrored vertically. */
42170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
42270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    dst_ptr = dst_row_ptr[dst_blk_x];
42370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    src_ptr = src_row_ptr[dst_blk_x];
42470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    for (i = 0; i < DCTSIZE; i += 2) {
42570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (j = 0; j < DCTSIZE; j++)
42670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		*dst_ptr++ = *src_ptr++;
42770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      for (j = 0; j < DCTSIZE; j++)
42870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		*dst_ptr++ = - *src_ptr++;
42970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    }
43070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
43170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	} else {
43270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  /* Remaining rows are just mirrored horizontally. */
43370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  dst_row_ptr = dst_buffer[offset_y];
43470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  src_row_ptr = src_buffer[offset_y];
43570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  /* Process the blocks that can be mirrored. */
43670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
43770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    dst_ptr = dst_row_ptr[dst_blk_x];
43870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
43970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    for (i = 0; i < DCTSIZE2; i += 2) {
44070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      *dst_ptr++ = *src_ptr++;
44170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      *dst_ptr++ = - *src_ptr++;
44270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    }
44370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
44470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  /* Any remaining right-edge blocks are only copied. */
44570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
44670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    dst_ptr = dst_row_ptr[dst_blk_x];
44770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    src_ptr = src_row_ptr[dst_blk_x];
44870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    for (i = 0; i < DCTSIZE2; i++)
44970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      *dst_ptr++ = *src_ptr++;
45070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
45170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
45270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
45370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
45470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
45570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
45670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
45770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
45870a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
45970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinedo_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
46070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	       jvirt_barray_ptr *src_coef_arrays,
46170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	       jvirt_barray_ptr *dst_coef_arrays)
46270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Transverse transpose is equivalent to
46370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   1. 180 degree rotation;
46470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   2. Transposition;
46570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * or
46670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   1. Horizontal mirroring;
46770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   2. Transposition;
46870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *   3. Horizontal mirroring.
46970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * These steps are merged into a single processing routine.
47070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
47170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
47270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
47370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, i, j, offset_x, offset_y;
47470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JBLOCKARRAY src_buffer, dst_buffer;
47570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JCOEFPTR src_ptr, dst_ptr;
47670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info *compptr;
47770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
47870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
47970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
48070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
48170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
48270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr = dstinfo->comp_info + ci;
48370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    comp_width = MCU_cols * compptr->h_samp_factor;
48470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    comp_height = MCU_rows * compptr->v_samp_factor;
48570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
48670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 dst_blk_y += compptr->v_samp_factor) {
48770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      dst_buffer = (*srcinfo->mem->access_virt_barray)
48870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
48970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) compptr->v_samp_factor, TRUE);
49070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
49170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
49270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     dst_blk_x += compptr->h_samp_factor) {
49370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  src_buffer = (*srcinfo->mem->access_virt_barray)
49470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
49570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	     (JDIMENSION) compptr->h_samp_factor, FALSE);
49670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
49770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    if (dst_blk_y < comp_height) {
49870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      src_ptr = src_buffer[offset_x]
49970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		[comp_height - dst_blk_y - offset_y - 1];
50070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      if (dst_blk_x < comp_width) {
50170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		/* Block is within the mirrorable area. */
50270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		dst_ptr = dst_buffer[offset_y]
50370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  [comp_width - dst_blk_x - offset_x - 1];
50470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		for (i = 0; i < DCTSIZE; i++) {
50570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  for (j = 0; j < DCTSIZE; j++) {
50670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
50770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    j++;
50870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
50970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  }
51070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  i++;
51170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  for (j = 0; j < DCTSIZE; j++) {
51270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
51370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    j++;
51470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
51570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  }
51670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		}
51770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      } else {
51870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		/* Right-edge blocks are mirrored in y only */
51970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
52070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		for (i = 0; i < DCTSIZE; i++) {
52170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  for (j = 0; j < DCTSIZE; j++) {
52270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
52370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    j++;
52470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
52570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  }
52670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		}
52770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      }
52870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    } else {
52970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
53070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      if (dst_blk_x < comp_width) {
53170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		/* Bottom-edge blocks are mirrored in x only */
53270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		dst_ptr = dst_buffer[offset_y]
53370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  [comp_width - dst_blk_x - offset_x - 1];
53470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		for (i = 0; i < DCTSIZE; i++) {
53570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  for (j = 0; j < DCTSIZE; j++)
53670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
53770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  i++;
53870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  for (j = 0; j < DCTSIZE; j++)
53970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
54070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		}
54170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      } else {
54270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		/* At lower right corner, just transpose, no mirroring */
54370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
54470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		for (i = 0; i < DCTSIZE; i++)
54570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		  for (j = 0; j < DCTSIZE; j++)
54670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		    dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
54770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	      }
54870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	    }
54970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  }
55070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
55170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
55270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
55370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
55470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
55570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
55670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
55770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Request any required workspace.
55870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
55970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * We allocate the workspace virtual arrays from the source decompression
56070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * object, so that all the arrays (both the original data and the workspace)
56170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * will be taken into account while making memory management decisions.
56270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Hence, this routine must be called after jpeg_read_header (which reads
56370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * the image dimensions) and before jpeg_read_coefficients (which realizes
56470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * the source's virtual arrays).
56570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
56670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
56770a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineGLOBAL(void)
56870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinejtransform_request_workspace (j_decompress_ptr srcinfo,
56970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			      jpeg_transform_info *info)
57070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
57170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jvirt_barray_ptr *coef_arrays = NULL;
57270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info *compptr;
57370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci;
57470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
57570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (info->force_grayscale &&
57670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      srcinfo->jpeg_color_space == JCS_YCbCr &&
57770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      srcinfo->num_components == 3) {
57870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* We'll only process the first component */
57970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    info->num_components = 1;
58070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  } else {
58170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Process all the components */
58270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    info->num_components = srcinfo->num_components;
58370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
58470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
58570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  switch (info->transform) {
58670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_NONE:
58770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_FLIP_H:
58870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Don't need a workspace array */
58970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
59070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_FLIP_V:
59170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_ROT_180:
59270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Need workspace arrays having same dimensions as source image.
59370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * Note that we allocate arrays padded out to the next iMCU boundary,
59470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * so that transform routines need not worry about missing edge blocks.
59570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     */
59670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    coef_arrays = (jvirt_barray_ptr *)
59770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
59870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	SIZEOF(jvirt_barray_ptr) * info->num_components);
59970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (ci = 0; ci < info->num_components; ci++) {
60070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      compptr = srcinfo->comp_info + ci;
60170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
60270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
60370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) jround_up((long) compptr->width_in_blocks,
60470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				(long) compptr->h_samp_factor),
60570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) jround_up((long) compptr->height_in_blocks,
60670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				(long) compptr->v_samp_factor),
60770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) compptr->v_samp_factor);
60870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
60970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
61070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_TRANSPOSE:
61170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_TRANSVERSE:
61270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_ROT_90:
61370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_ROT_270:
61470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Need workspace arrays having transposed dimensions.
61570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * Note that we allocate arrays padded out to the next iMCU boundary,
61670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * so that transform routines need not worry about missing edge blocks.
61770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     */
61870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    coef_arrays = (jvirt_barray_ptr *)
61970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
62070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	SIZEOF(jvirt_barray_ptr) * info->num_components);
62170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (ci = 0; ci < info->num_components; ci++) {
62270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      compptr = srcinfo->comp_info + ci;
62370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
62470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
62570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) jround_up((long) compptr->height_in_blocks,
62670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				(long) compptr->v_samp_factor),
62770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) jround_up((long) compptr->width_in_blocks,
62870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				(long) compptr->h_samp_factor),
62970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 (JDIMENSION) compptr->h_samp_factor);
63070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
63170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
63270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
63370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  info->workspace_coef_arrays = coef_arrays;
63470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
63570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
63670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
63770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Transpose destination image parameters */
63870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
63970a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
64070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetranspose_critical_parameters (j_compress_ptr dstinfo)
64170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
64270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int tblno, i, j, ci, itemp;
64370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_component_info *compptr;
64470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JQUANT_TBL *qtblptr;
64570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION dtemp;
64670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  UINT16 qtemp;
64770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
64870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Transpose basic image dimensions */
64970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  dtemp = dstinfo->image_width;
65070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  dstinfo->image_width = dstinfo->image_height;
65170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  dstinfo->image_height = dtemp;
65270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
65370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Transpose sampling factors */
65470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
65570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr = dstinfo->comp_info + ci;
65670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    itemp = compptr->h_samp_factor;
65770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr->h_samp_factor = compptr->v_samp_factor;
65870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    compptr->v_samp_factor = itemp;
65970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
66070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
66170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Transpose quantization tables */
66270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
66370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    qtblptr = dstinfo->quant_tbl_ptrs[tblno];
66470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (qtblptr != NULL) {
66570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (i = 0; i < DCTSIZE; i++) {
66670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	for (j = 0; j < i; j++) {
66770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  qtemp = qtblptr->quantval[i*DCTSIZE+j];
66870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
66970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	  qtblptr->quantval[j*DCTSIZE+i] = qtemp;
67070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	}
67170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      }
67270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
67370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
67470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
67570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
67670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
67770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Trim off any partial iMCUs on the indicated destination edge */
67870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
67970a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
68070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetrim_right_edge (j_compress_ptr dstinfo)
68170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
68270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, max_h_samp_factor;
68370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION MCU_cols;
68470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
68570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* We have to compute max_h_samp_factor ourselves,
68670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * because it hasn't been set yet in the destination
68770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * (and we don't want to use the source's value).
68870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
68970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  max_h_samp_factor = 1;
69070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
69170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
69270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
69370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
69470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
69570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (MCU_cols > 0)		/* can't trim to 0 pixels */
69670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
69770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
69870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
69970a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineLOCAL(void)
70070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinetrim_bottom_edge (j_compress_ptr dstinfo)
70170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
70270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int ci, max_v_samp_factor;
70370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  JDIMENSION MCU_rows;
70470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
70570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* We have to compute max_v_samp_factor ourselves,
70670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * because it hasn't been set yet in the destination
70770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * (and we don't want to use the source's value).
70870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
70970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  max_v_samp_factor = 1;
71070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (ci = 0; ci < dstinfo->num_components; ci++) {
71170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
71270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
71370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
71470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
71570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (MCU_rows > 0)		/* can't trim to 0 pixels */
71670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
71770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
71870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
71970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
72070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Adjust output image parameters as needed.
72170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
72270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This must be called after jpeg_copy_critical_parameters()
72370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * and before jpeg_write_coefficients().
72470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
72570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * The return value is the set of virtual coefficient arrays to be written
72670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * (either the ones allocated by jtransform_request_workspace, or the
72770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * original source data arrays).  The caller will need to pass this value
72870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * to jpeg_write_coefficients().
72970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
73070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
73170a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineGLOBAL(jvirt_barray_ptr *)
73270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinejtransform_adjust_parameters (j_decompress_ptr srcinfo,
73370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			      j_compress_ptr dstinfo,
73470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			      jvirt_barray_ptr *src_coef_arrays,
73570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine			      jpeg_transform_info *info)
73670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
73770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* If force-to-grayscale is requested, adjust destination parameters */
73870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (info->force_grayscale) {
73970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
74070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * properly.  Among other things, the target h_samp_factor & v_samp_factor
74170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * will get set to 1, which typically won't match the source.
74270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * In fact we do this even if the source is already grayscale; that
74370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * provides an easy way of coercing a grayscale JPEG with funny sampling
74470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     * factors to the customary 1,1.  (Some decoders fail on other factors.)
74570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine     */
74670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
74770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 dstinfo->num_components == 3) ||
74870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	(dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
74970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	 dstinfo->num_components == 1)) {
75070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      /* We have to preserve the source's quantization table number. */
75170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
75270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
75370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
75470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    } else {
75570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      /* Sorry, can't do it */
75670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
75770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
75870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
75970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
76070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Correct the destination's image dimensions etc if necessary */
76170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  switch (info->transform) {
76270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_NONE:
76370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* Nothing to do */
76470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
76570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_FLIP_H:
76670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (info->trim)
76770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      trim_right_edge(dstinfo);
76870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
76970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_FLIP_V:
77070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (info->trim)
77170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      trim_bottom_edge(dstinfo);
77270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
77370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_TRANSPOSE:
77470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    transpose_critical_parameters(dstinfo);
77570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* transpose does NOT have to trim anything */
77670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
77770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_TRANSVERSE:
77870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    transpose_critical_parameters(dstinfo);
77970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (info->trim) {
78070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      trim_right_edge(dstinfo);
78170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      trim_bottom_edge(dstinfo);
78270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
78370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
78470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_ROT_90:
78570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    transpose_critical_parameters(dstinfo);
78670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (info->trim)
78770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      trim_right_edge(dstinfo);
78870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
78970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_ROT_180:
79070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (info->trim) {
79170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      trim_right_edge(dstinfo);
79270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      trim_bottom_edge(dstinfo);
79370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
79470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
79570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_ROT_270:
79670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    transpose_critical_parameters(dstinfo);
79770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (info->trim)
79870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      trim_bottom_edge(dstinfo);
79970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
80070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
80170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
80270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Return the appropriate output data set */
80370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (info->workspace_coef_arrays != NULL)
80470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    return info->workspace_coef_arrays;
80570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  return src_coef_arrays;
80670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
80770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
80870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
80970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Execute the actual transformation, if any.
81070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
81170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This must be called *after* jpeg_write_coefficients, because it depends
81270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * on jpeg_write_coefficients to have computed subsidiary values such as
81370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * the per-component width and height fields in the destination object.
81470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine *
81570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Note that some transformations will modify the source data arrays!
81670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
81770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
81870a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineGLOBAL(void)
81970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinejtransform_execute_transformation (j_decompress_ptr srcinfo,
82070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				   j_compress_ptr dstinfo,
82170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				   jvirt_barray_ptr *src_coef_arrays,
82270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine				   jpeg_transform_info *info)
82370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
82470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
82570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
82670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  switch (info->transform) {
82770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_NONE:
82870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
82970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_FLIP_H:
83070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    do_flip_h(srcinfo, dstinfo, src_coef_arrays);
83170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
83270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_FLIP_V:
83370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
83470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
83570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_TRANSPOSE:
83670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
83770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
83870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_TRANSVERSE:
83970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
84070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
84170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_ROT_90:
84270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
84370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
84470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_ROT_180:
84570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
84670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
84770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  case JXFORM_ROT_270:
84870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
84970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    break;
85070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
85170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
85270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
85370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif /* TRANSFORMS_SUPPORTED */
85470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
85570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
85670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Setup decompression object to save desired markers in memory.
85770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This must be called before jpeg_read_header() to have the desired effect.
85870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
85970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
86070a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineGLOBAL(void)
86170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinejcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
86270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
86370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef SAVE_MARKERS_SUPPORTED
86470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  int m;
86570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
86670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Save comments except under NONE option */
86770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (option != JCOPYOPT_NONE) {
86870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
86970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
87070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* Save all types of APPn markers iff ALL option */
87170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  if (option == JCOPYOPT_ALL) {
87270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    for (m = 0; m < 16; m++)
87370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
87470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
87570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif /* SAVE_MARKERS_SUPPORTED */
87670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
87770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
87870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine/* Copy markers saved in the given source object to the destination object.
87970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * This should be called just after jpeg_start_compress() or
88070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * jpeg_write_coefficients().
88170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * Note that those routines will have written the SOI, and also the
88270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine * JFIF APP0 or Adobe APP14 markers if selected.
88370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine */
88470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
88570a18cd874a22452aca9e39e22275ed4538ed20bVladimir ChtchetkineGLOBAL(void)
88670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkinejcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
88770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		       JCOPY_OPTION option)
88870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine{
88970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  jpeg_saved_marker_ptr marker;
89070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine
89170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  /* In the current implementation, we don't actually need to examine the
89270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * option flag here; we just copy everything that got saved.
89370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
89470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   * if the encoder library already wrote one.
89570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine   */
89670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
89770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (dstinfo->write_JFIF_header &&
89870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	marker->marker == JPEG_APP0 &&
89970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	marker->data_length >= 5 &&
90070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[0]) == 0x4A &&
90170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[1]) == 0x46 &&
90270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[2]) == 0x49 &&
90370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[3]) == 0x46 &&
90470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[4]) == 0)
90570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      continue;			/* reject duplicate JFIF */
90670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    if (dstinfo->write_Adobe_marker &&
90770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	marker->marker == JPEG_APP0+14 &&
90870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	marker->data_length >= 5 &&
90970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[0]) == 0x41 &&
91070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[1]) == 0x64 &&
91170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[2]) == 0x6F &&
91270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[3]) == 0x62 &&
91370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	GETJOCTET(marker->data[4]) == 0x65)
91470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      continue;			/* reject duplicate Adobe */
91570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#ifdef NEED_FAR_POINTERS
91670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    /* We could use jpeg_write_marker if the data weren't FAR... */
91770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    {
91870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      unsigned int i;
91970a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
92070a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine      for (i = 0; i < marker->data_length; i++)
92170a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine	jpeg_write_m_byte(dstinfo, marker->data[i]);
92270a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    }
92370a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#else
92470a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine    jpeg_write_marker(dstinfo, marker->marker,
92570a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine		      marker->data, marker->data_length);
92670a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine#endif
92770a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine  }
92870a18cd874a22452aca9e39e22275ed4538ed20bVladimir Chtchetkine}
929