📄 transupp.c
字号:
/* * transupp.c * * Copyright (C) 1997, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains image transformation routines and other utility code * used by the jpegtran sample application. These are NOT part of the core * JPEG library. But we keep these routines separate from jpegtran.c to * ease the task of maintaining jpegtran-like programs that have other user * interfaces. *//* Although this file really shouldn't have access to the library internals, * it's helpful to let it call jround_up() and jcopy_block_row(). */#define JPEG_INTERNALS#include "jinclude.h"#include "jpeglib.h"#include "transupp.h" /* My own external interface */#if TRANSFORMS_SUPPORTED/* * Lossless image transformation routines. These routines work on DCT * coefficient arrays and thus do not require any lossy decompression * or recompression of the image. * Thanks to Guido Vollbeding for the initial design and code of this feature. * * Horizontal flipping is done in-place, using a single top-to-bottom * pass through the virtual source array. It will thus be much the * fastest option for images larger than main memory. * * The other routines require a set of destination virtual arrays, so they * need twice as much memory as jpegtran normally does. The destination * arrays are always written in normal scan order (top to bottom) because * the virtual array manager expects this. The source arrays will be scanned * in the corresponding order, which means multiple passes through the source * arrays for most of the transforms. That could result in much thrashing * if the image is larger than main memory. * * Some notes about the operating environment of the individual transform * routines: * 1. Both the source and destination virtual arrays are allocated from the * source JPEG object, and therefore should be manipulated by calling the * source's memory manager. * 2. The destination's component count should be used. It may be smaller * than the source's when forcing to grayscale. * 3. Likewise the destination's sampling factors should be used. When * forcing to grayscale the destination's sampling factors will be all 1, * and we may as well take that as the effective iMCU size. * 4. When "trim" is in effect, the destination's dimensions will be the * trimmed values but the source's will be untrimmed. * 5. All the routines assume that the source and destination buffers are * padded out to a full iMCU boundary. This is true, although for the * source buffer it is an undocumented property of jdcoefct.c. * Notes 2,3,4 boil down to this: generally we should use the destination's * dimensions and ignore the source's. */LOCAL(void)do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays)/* Horizontal flip; done in-place, so no separate dest array is required */{ JDIMENSION MCU_cols, comp_width, blk_x, blk_y; int ci, k, offset_y; JBLOCKARRAY buffer; JCOEFPTR ptr1, ptr2; JCOEF temp1, temp2; jpeg_component_info *compptr; /* Horizontal mirroring of DCT blocks is accomplished by swapping * pairs of blocks in-place. Within a DCT block, we perform horizontal * mirroring by changing the signs of odd-numbered columns. * Partial iMCUs at the right edge are left untouched. */ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; comp_width = MCU_cols * compptr->h_samp_factor; for (blk_y = 0; blk_y < compptr->height_in_blocks; blk_y += compptr->v_samp_factor) { buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) { ptr1 = buffer[offset_y][blk_x]; ptr2 = buffer[offset_y][comp_width - blk_x - 1]; /* this unrolled loop doesn't need to know which row it's on... */ for (k = 0; k < DCTSIZE2; k += 2) { temp1 = *ptr1; /* swap even column */ temp2 = *ptr2; *ptr1++ = temp2; *ptr2++ = temp1; temp1 = *ptr1; /* swap odd column with sign change */ temp2 = *ptr2; *ptr1++ = -temp2; *ptr2++ = -temp1; } } } } }}LOCAL(void)do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays)/* Vertical flip */{ JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; int ci, i, j, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JBLOCKROW src_row_ptr, dst_row_ptr; JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; /* We output into a separate array because we can't touch different * rows of the source virtual array simultaneously. Otherwise, this * is a pretty straightforward analog of horizontal flip. * Within a DCT block, vertical mirroring is done by changing the signs * of odd-numbered rows. * Partial iMCUs at the bottom edge are copied verbatim. */ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; comp_height = MCU_rows * compptr->v_samp_factor; for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); if (dst_blk_y < comp_height) { /* Row is within the mirrorable area. */ src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } else { /* Bottom-edge blocks will be copied verbatim. */ src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, FALSE); } for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { if (dst_blk_y < comp_height) { /* Row is within the mirrorable area. */ dst_row_ptr = dst_buffer[offset_y]; src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1]; for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) { dst_ptr = dst_row_ptr[dst_blk_x]; src_ptr = src_row_ptr[dst_blk_x]; for (i = 0; i < DCTSIZE; i += 2) { /* copy even row */ for (j = 0; j < DCTSIZE; j++) *dst_ptr++ = *src_ptr++; /* copy odd row with sign change */ for (j = 0; j < DCTSIZE; j++) *dst_ptr++ = - *src_ptr++; } } } else { /* Just copy row verbatim. */ jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y], compptr->width_in_blocks); } } } }}LOCAL(void)do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays)/* Transpose source into destination */{ JDIMENSION dst_blk_x, dst_blk_y; int ci, i, j, offset_x, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; /* Transposing pixels within a block just requires transposing the * DCT coefficients. * Partial iMCUs at the edges require no special treatment; we simply * process all the available DCT blocks for every component. */ for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) { src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, (JDIMENSION) compptr->h_samp_factor, FALSE); for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; for (i = 0; i < DCTSIZE; i++) for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; } } } } }}LOCAL(void)do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays)/* 90 degree rotation is equivalent to * 1. Transposing the image; * 2. Horizontal mirroring. * These two steps are merged into a single processing routine. */{ JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y; int ci, i, j, offset_x, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; /* Because of the horizontal mirror step, we can't process partial iMCUs * at the (output) right edge properly. They just get transposed and * not mirrored. */ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; comp_width = MCU_cols * compptr->h_samp_factor; for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; dst_blk_y += compptr->v_samp_factor) { dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x += compptr->h_samp_factor) { src_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x, (JDIMENSION) compptr->h_samp_factor, FALSE); for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) { src_ptr = src_buffer[offset_x][dst_blk_y + offset_y]; if (dst_blk_x < comp_width) { /* Block is within the mirrorable area. */ dst_ptr = dst_buffer[offset_y] [comp_width - dst_blk_x - offset_x - 1]; for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; i++; for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j]; } } else { /* Edge blocks are transposed but not mirrored. */ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x]; for (i = 0; i < DCTSIZE; i++) for (j = 0; j < DCTSIZE; j++) dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j]; } } } } } }}LOCAL(void)do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays)/* 270 degree rotation is equivalent to * 1. Horizontal mirroring; * 2. Transposing the image. * These two steps are merged into a single processing routine. */{ JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y; int ci, i, j, offset_x, offset_y; JBLOCKARRAY src_buffer, dst_buffer; JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; /* Because of the horizontal mirror step, we can't process partial iMCUs * at the (output) bottom edge properly. They just get transposed and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -