You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
4.8 KiB
182 lines
4.8 KiB
/* Copyright (C) 2005 Ole André Vadla Ravnås <oleavr@gmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "mimic-private.h"
|
|
|
|
extern guchar _col_zag[64];
|
|
|
|
void _fdct_quant_block(MimCtx *ctx, gint *block, const guchar *src,
|
|
gint stride, gboolean is_chrom, gint num_coeffs)
|
|
{
|
|
gint sum1, sum2, sum3, sum4;
|
|
gint diff1, diff2, diff3, diff4;
|
|
gint ex1, ex2, ex3, ex4, ex5;
|
|
gint i, j;
|
|
const guchar *p1;
|
|
gint *iptr;
|
|
|
|
/*
|
|
* Forward DCT, first pass (horizontal).
|
|
*/
|
|
p1 = src;
|
|
iptr = block;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
sum1 = p1[0] + p1[7];
|
|
sum2 = p1[1] + p1[6];
|
|
sum3 = p1[2] + p1[5];
|
|
sum4 = p1[3] + p1[4];
|
|
|
|
diff1 = p1[0] - p1[7];
|
|
diff2 = p1[1] - p1[6];
|
|
diff3 = p1[2] - p1[5];
|
|
diff4 = p1[3] - p1[4];
|
|
|
|
ex1 = ((diff1 + diff4) * 851) - (diff1 * 282);
|
|
ex2 = ((diff2 + diff3) * 1004) - (diff2 * 804);
|
|
ex3 = ((diff2 + diff3) * 1004) - (diff3 * 1204);
|
|
ex4 = ((diff1 + diff4) * 851) - (diff4 * 1420);
|
|
|
|
iptr[0] = sum1 + sum2 + sum3 + sum4;
|
|
iptr[2] = (((sum1 - sum4) * 1337) + ((sum2 - sum3) * 554)) >> 10;
|
|
iptr[4] = sum1 - sum2 - sum3 + sum4;
|
|
|
|
iptr[1] = (ex1 + ex2 + ex3 + ex4) >> 10;
|
|
iptr[3] = ((ex4 - ex2) * 181) >> 17;
|
|
iptr[5] = ((ex1 - ex3) * 181) >> 17;
|
|
|
|
p1 += stride;
|
|
iptr += 8;
|
|
}
|
|
|
|
p1 = src;
|
|
iptr = block;
|
|
|
|
/*
|
|
* Forward DCT, first pass (vertical).
|
|
*
|
|
* This is only known to be correct for i == 0, though it seems to be ...
|
|
*/
|
|
for (i = 0; i < 6; i++) {
|
|
sum1 = iptr[ 0 + i] + iptr[56 + i];
|
|
sum2 = iptr[ 8 + i] + iptr[48 + i];
|
|
sum3 = iptr[16 + i] + iptr[40 + i];
|
|
sum4 = iptr[24 + i] + iptr[32 + i];
|
|
|
|
diff1 = iptr[ 0 + i] - iptr[56 + i];
|
|
diff2 = iptr[ 8 + i] - iptr[48 + i];
|
|
diff3 = iptr[16 + i] - iptr[40 + i];
|
|
diff4 = iptr[24 + i] - iptr[32 + i];
|
|
|
|
ex1 = ((diff1 + diff4) * 851) - (diff1 * 282);
|
|
ex2 = ((diff2 + diff3) * 1004) - (diff2 * 804);
|
|
ex3 = ((diff2 + diff3) * 1004) - (diff3 * 1204);
|
|
ex4 = ((diff1 + diff4) * 851) - (diff4 * 1420);
|
|
|
|
ex5 = (sum1 + sum2 - sum3 - sum4) * 554;
|
|
|
|
for (j = 0; j < 7 - i; j++) {
|
|
switch (j) {
|
|
|
|
case 0:
|
|
iptr[ 0 + i] = (16 + sum1 + sum2 + sum3 + sum4) >> 5;
|
|
break;
|
|
|
|
case 1:
|
|
iptr[ 8 + i] = (16384 + ex1 + ex2 + ex3 + ex4) >> 15;
|
|
break;
|
|
|
|
case 2:
|
|
iptr[16 + i] = (16384 + ((sum1 - sum4) * 783) + ex5) >> 15;
|
|
break;
|
|
|
|
case 3:
|
|
iptr[24 + i] = (8192 + (((ex4 - ex2) >> 8) * 181)) >> 14;
|
|
break;
|
|
|
|
case 4:
|
|
iptr[32 + i] = (16 + sum1 - sum2 - sum3 + sum4) >> 5;
|
|
break;
|
|
|
|
case 5:
|
|
iptr[40 + i] = (8192 + (((ex1 - ex3) >> 8) * 181)) >> 14;
|
|
break;
|
|
|
|
case 6:
|
|
iptr[48 + i] = (16384 - ((sum2 - sum3) * 1891) + ex5) >> 15;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Quantize.
|
|
*/
|
|
block[0] /= 2;
|
|
block[8] /= 4;
|
|
block[1] /= 4;
|
|
block[6] = 0;
|
|
|
|
if (num_coeffs > 3) {
|
|
|
|
gdouble s = (10000 - ctx->quality) * 10.0 * (gfloat) 9.9999997e-5;
|
|
|
|
if (s > 10.0)
|
|
s = 10.0;
|
|
else if (is_chrom != 0 && s < 1.0)
|
|
s = 1.0;
|
|
else if (s < 2.0)
|
|
s = 2.0;
|
|
|
|
s = 1.0 / s;
|
|
|
|
for (i = 3; i < num_coeffs; i++) {
|
|
|
|
gdouble coeff, r;
|
|
|
|
coeff = block[_col_zag[i]] * s;
|
|
r = coeff - (gint) coeff;
|
|
|
|
if (r >= 0.6)
|
|
block[_col_zag[i]] = (gint) (coeff + 1.0);
|
|
else if (r <= -0.6)
|
|
block[_col_zag[i]] = (gint) (coeff - 1.0);
|
|
else
|
|
block[_col_zag[i]] = (gint) coeff;
|
|
|
|
if (block[_col_zag[i]] > 120)
|
|
block[_col_zag[i]] = 120;
|
|
else if (block[_col_zag[i]] < -120)
|
|
block[_col_zag[i]] = -120;
|
|
}
|
|
}
|
|
|
|
if (block[8] > 120)
|
|
block[8] = 120;
|
|
else if (block[8] < -120)
|
|
block[8] = -120;
|
|
|
|
if (block[1] > 120)
|
|
block[1] = 120;
|
|
else if (block[1] < -120)
|
|
block[1] = -120;
|
|
|
|
for (i = num_coeffs; i < 64; i++)
|
|
block[_col_zag[i]] = 0;
|
|
}
|
|
|