1 line
5.4 KiB
C
1 line
5.4 KiB
C
/*
|
|
* jcdctmgr.c
|
|
*
|
|
* Copyright (C) 1994, 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 the forward-DCT management logic.
|
|
* This code selects a particular DCT implementation to be used,
|
|
* and it performs related housekeeping chores including coefficient
|
|
* quantization.
|
|
*/
|
|
|
|
#define JPEG_INTERNALS
|
|
#include "jinclude.h"
|
|
#include "jpeglib.h"
|
|
#include "jdct.h" /* Private declarations for DCT subsystem */
|
|
|
|
|
|
/* Private subobject for this module */
|
|
|
|
typedef struct {
|
|
struct jpeg_forward_dct pub; /* public fields */
|
|
/* no private fields for now */
|
|
} my_fdct_controller;
|
|
|
|
typedef my_fdct_controller * my_fdct_ptr;
|
|
|
|
|
|
/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
|
|
|
|
static const int ZAG[DCTSIZE2] = {
|
|
0, 1, 8, 16, 9, 2, 3, 10,
|
|
17, 24, 32, 25, 18, 11, 4, 5,
|
|
12, 19, 26, 33, 40, 48, 41, 34,
|
|
27, 20, 13, 6, 7, 14, 21, 28,
|
|
35, 42, 49, 56, 57, 50, 43, 36,
|
|
29, 22, 15, 23, 30, 37, 44, 51,
|
|
58, 59, 52, 45, 38, 31, 39, 46,
|
|
53, 60, 61, 54, 47, 55, 62, 63
|
|
};
|
|
|
|
|
|
/*
|
|
* Initialize for a processing pass.
|
|
* Verify that all referenced Q-tables are present, and set up
|
|
* the multiplier tables for each one.
|
|
*/
|
|
|
|
METHODDEF void
|
|
start_pass (j_compress_ptr cinfo)
|
|
{
|
|
int ci, qtblno, i;
|
|
JCQUANT_TBL * qtbl;
|
|
|
|
for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
|
|
qtblno = cinfo->cur_comp_info[ci]->quant_tbl_no;
|
|
/* Make sure specified quantization table is present */
|
|
if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
|
|
cinfo->quant_tbl_ptrs[qtblno] == NULL)
|
|
ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
|
|
/* Compute divisors for this quant table */
|
|
/* We may do this more than once for same table, but it's not a big deal */
|
|
qtbl = (JCQUANT_TBL *) cinfo->quant_tbl_ptrs[qtblno];
|
|
for (i = 0; i < DCTSIZE2; i++) {
|
|
/* For now, divisors are same as raw quantization coefficients */
|
|
qtbl->divisors[i] = (MULTIPLIER) qtbl->pub.quantval[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Perform forward DCT on one or more blocks of a component.
|
|
*
|
|
* The input samples are taken from the sample_data[] array starting at
|
|
* position start_row/start_col, and moving to the right for any additional
|
|
* blocks. The quantized, zigzagged coefficients are returned in coef_blocks[].
|
|
*/
|
|
|
|
METHODDEF void
|
|
forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
|
|
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
|
JDIMENSION start_row, JDIMENSION start_col,
|
|
JDIMENSION num_blocks)
|
|
{
|
|
/* This routine is heavily used, so it's worth coding it tightly. */
|
|
int workspace[DCTSIZE2]; /* work area for FDCT subroutine */
|
|
JDIMENSION bi;
|
|
JCQUANT_TBL * qtbl;
|
|
|
|
qtbl = (JCQUANT_TBL *) cinfo->quant_tbl_ptrs[compptr->quant_tbl_no];
|
|
|
|
sample_data += start_row; /* fold in the vertical offset once */
|
|
|
|
for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
|
|
{ register int *workspaceptr;
|
|
register JSAMPROW elemptr;
|
|
register int elemr;
|
|
|
|
workspaceptr = workspace;
|
|
for (elemr = 0; elemr < DCTSIZE; elemr++) {
|
|
elemptr = sample_data[elemr] + start_col;
|
|
#if DCTSIZE == 8 /* unroll the inner loop */
|
|
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
|
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
|
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
|
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
|
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
|
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
|
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
|
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
|
#else
|
|
{ register int elemc;
|
|
for (elemc = DCTSIZE; elemc > 0; elemc--) {
|
|
*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
jpeg_fdct_llm(workspace);
|
|
|
|
{ register MULTIPLIER temp;
|
|
register MULTIPLIER qval;
|
|
register int i;
|
|
register JCOEFPTR output_ptr = coef_blocks[bi];
|
|
|
|
for (i = 0; i < DCTSIZE2; i++) {
|
|
qval = qtbl->divisors[i];
|
|
temp = (MULTIPLIER) workspace[ZAG[i]];
|
|
/* Divide the coefficient value by qval, ensuring proper rounding.
|
|
* Since C does not specify the direction of rounding for negative
|
|
* quotients, we have to force the dividend positive for portability.
|
|
*
|
|
* In most files, at least half of the output values will be zero
|
|
* (at default quantization settings, more like three-quarters...)
|
|
* so we should ensure that this case is fast. On many machines,
|
|
* a comparison is enough cheaper than a divide to make a special test
|
|
* a win. Since both inputs will be nonnegative, we need only test
|
|
* for a < b to discover whether a/b is 0.
|
|
* If your machine's division is fast enough, define FAST_DIVIDE.
|
|
*/
|
|
#ifdef FAST_DIVIDE
|
|
#define DIVIDE_BY(a,b) a /= b
|
|
#else
|
|
#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
|
|
#endif
|
|
if (temp < 0) {
|
|
temp = -temp;
|
|
temp += qval>>1; /* for rounding */
|
|
DIVIDE_BY(temp, qval);
|
|
temp = -temp;
|
|
} else {
|
|
temp += qval>>1; /* for rounding */
|
|
DIVIDE_BY(temp, qval);
|
|
}
|
|
output_ptr[i] = (JCOEF) temp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Initialize FDCT manager.
|
|
*/
|
|
|
|
GLOBAL void
|
|
jinit_forward_dct (j_compress_ptr cinfo)
|
|
{
|
|
my_fdct_ptr fdct;
|
|
|
|
fdct = (my_fdct_ptr)
|
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
|
SIZEOF(my_fdct_controller));
|
|
cinfo->fdct = (struct jpeg_forward_dct *) fdct;
|
|
|
|
fdct->pub.start_pass = start_pass;
|
|
fdct->pub.forward_DCT = forward_DCT;
|
|
}
|