- DEMO.DESIGN (2:5030/1334.67) ---------------------------------- DEMO.DESIGN -
Сооб : 5 из 7
От : Yura Schapov 2:5012/28.18 07 Апр 01 22:06:05
Кому : Stanislav Tihohod 09 Апр 01 00:21:33
Тема : JPEG
-------------------------------------------------------------------------------
Как поживаете, Stanislav ?
Мои бортовые системы запеленговали, что в Суббота Апрель 07 2001 01:10,
Stanislav Tihohod писал Yura Schapov:
ST> Кстати, а зачем тебе нужны термы 16х16?
Да вот, сегодня проверил, оказывается не нужны... ;)
Еще пробовал сделать DCT на матрице float-ов 256x256 - эхх... жалко,
не продают пока еще суперкомпьютеры... ;)
Могу исходником поделиться... все-таки почти два дня отлаживал. =)
---cut---
Дискретное косинусное преобразование в JPEG
Специально для DEMO.DESIGN
(c)Д.Мастрюков, журнал "Монитор" 6.94
(c)Ю.Щапов, 2:5012/28.18 =)
Принцип: (работаем с блоком 8x8 - матрица Точки)
encoding: DCT = C * Точки * Ct
decoding: Точки = C * DCT * Ct
Где: C(i,j) = 1/sqrt(N), i=0
C(i,j) = sqrt(2/N) * cos(((2*j+1)*i*PI)/(2*N)), i<>0
Ct - транспонированная С.
Для округления коэффициентов (а мы должны все поместить в unsigned char),
используем матрицу округления, считается она таким вот образом:
for (i=0;i<N;i++) for (j=0;j<N;j++) Quantum[i][j]=16+(1+i+j)*quality;
Как ее использовать: просто после кодирования делим на
нее поэлементно, а потом, чтобы восстановить информацию,
поэлементно на нее умножаем. Так как числа в ней возрастают
по диагонали, получается что больше всего информации остается
по низкочастотным компонентам DCT, а высокочастотные обращаются
в ноль. (Там еще некоторые тонкости, например обход по зигзагу
чтобы получились длинные цепочки нулей, но это не суть важно).
Пример DCT-iDCT преобразования 32-х битных текстур 256x256.
//tc.h
#define PI 3.14159265358979323846
#define ROUND(a) (((a)<0)?(int)((a)-0.5):(int)((a)+0.5))
#define NORMALIZE(n) ((n<0) ? 0 : ((n>255) ? 255 : n));
#define ROWS 256
#define COLS 256
#define N 8
//globals
float C[N][N];
float Ct[N][N];
int Quantum[N][N];
int InputRunLength;
int OutputRunLength;
float input_array[N][N];
float output_array[N][N];
struct zigzag
{
int row;
int col;
};
zigzag ZigZag[N*N];
int ZigZag8[8*8]=
{
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63
};
void Initalise(int quality)
{
int i,j;
//subsampling matrix
for (i=0;i<N;i++)
for (j=0;j<N;j++)
Quantum[i][j] = 16 + ( 1 + i + j ) * quality;
// define DCT and transposed DCT matrix:
// C(i,j) = 1/sqrt(N), i=0
// C(i,j) = sqrt(2/N) * cos(((2*j+1)*i*PI)/(2*N)), i<>0
for(j=0;j<N;j++)
{
C[0][j]= 1.0 / sqrt((float) N);
Ct[j][0]=C[0][j];
}
for (i=1;i<N;i++)
for (j=0;j<N;j++)
{
C[i][j]= sqrt(2.0/N) * cos( ((2*j+1)*i*PI)/(2.0*N) );
Ct[j][i]=C[i][j];
}
int x,y,dx,dy;
x,y,dy=0; dx=1;
for (i=0;i<N*N;i++)
{
ZigZag[i].row = ZigZag8[i]%N;
ZigZag[i].col = ZigZag8[i]/N;
}
}
void MatrixMul(float input[N][N], float output[N][N],
float C[N][N],float Ct[N][N])
{
float temp[N][N];
float temp1;
int i,j,k;
//output = C * input * Ct;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
{
temp[i][j]=0.0;
for(k=0;k<N;k++)
temp[i][j]+=input[i][k] * Ct[k][j];
}
for (i=0;i<N;i++)
for (j=0;j<N;j++)
{
temp1=0.0;
for (k=0;k<N;k++)
temp1+=C[i][k]*temp[k][j];
output[i][j]=temp1;
}
}
void DCT(float input[N][N],float output[N][N])
{
int i,row,col;
MatrixMul(input,output,C,Ct);
for (i=0;i<(N*N);i++)
{
row=ZigZag[i].row;
col=ZigZag[i].col;
output[row][col] = ROUND( output[row][col] / Quantum[row][col] );
//he-he, Beavis, hi says ROUND ;-)
}
}
void iDCT(float input[N][N],float output[N][N])
{
int i,j,row,col;
float result;
for (i=0;i<(N*N);i++)
{
row=ZigZag[i].row;
col=ZigZag[i].col;
input[row][col] = (signed char)input[row][col] * Quantum[row][col];
}
MatrixMul(input,output,Ct,C);
for (i=0;i<N;i++)
for (j=0;j<N;j++)
output[i][j]=NORMALIZE(output[i][j]);
}
void Read_BOX(int x, int y, byte *input, float array[N][N], int layer)
{
int i,j;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
array[i][j] = input[ ( (x+i) + (y+j)*256 )*4+layer ];
}
void Write_BOX(int x, int y, byte *output, float array[N][N], int layer)
{
int i,j;
for (i=0;i<N;i++)
for (j=0;j<N;j++)
output[ ( (x+i) + (y+j)*256 )*4+layer ] = array[i][j];
}
void CompressTexture(int *input_texture, int *output_texture, int quality)
{
int i,j,k,layer;
byte *input=(byte*)input_texture;
byte *output=(byte*)output_texture;
Initalise(quality);
for (layer=0;layer<3;layer++)
for (i=0;i<256;i+=N)
for (j=0;j<256;j+=N)
{
Read_BOX(i, j, input, input_array, layer);
DCT(input_array, output_array);
Write_BOX(i, j, output, output_array, layer);
}
}
void DeCompressTexture(int *input_texture, int *output_texture, int quality)
{
int i,j,k,layer;
byte *input=(byte*)input_texture;
byte *output=(byte*)output_texture;
Initalise(quality);
for (layer=0;layer<3;layer++)
for (i=0;i<256;i+=N)
for (j=0;j<256;j+=N)
{
Read_BOX(i, j, input, input_array, layer);
iDCT(input_array, output_array);
Write_BOX(i, j, output, output_array,layer);
}
}
---cut---
C уважением, Yura Schapov.
--- [Team FM-4307]
* Origin: :nigirO * (2:5012/28.18)
|
|