//-----------------------------------------------------------------------------
// Demonstracni priklad k serialu "Graficke formaty"
// http://www.root.cz/
//
// Autor: Pavel Tisnovsky
//
// Tento program vytvori obrazek s prubehem bazovych funkci pouzitych
// v dvourozmerne diskretni kosinove transformaci (2D DCT).
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
// stupen DCT (smysluplne hodnoty jsou: 8, 16, 32)
#define N 8
// jmeno souboru, se kterym se pracuje
#define FILE_NAME "2d_dct.tga"
// datova struktura popisujici pixmapu
typedef struct {
unsigned int width;
unsigned int height;
unsigned char *pixels;
} pixmap;
// pracovni pixmapa
pixmap *pix;
//-----------------------------------------------------------------------------
// vytvoreni pixmapy ve formatu truecolor
//-----------------------------------------------------------------------------
pixmap * createPixmap(unsigned int width, unsigned int height)
{
pixmap *px;
unsigned int size;
assert(width>0);
assert(height>0);
// alokace pameti pro hlavicku pixmapy
px=(pixmap*)malloc(sizeof(pixmap));
// kontrola alokace pameti
assert(px);
px->width=width;
px->height=height;
size=3*width*height;
// alokace pameti pro pixely
px->pixels=(unsigned char *)malloc(sizeof(unsigned char)*size);
// kontrola alokace pameti
assert(px->pixels);
return px;
}
//-----------------------------------------------------------------------------
// ulozeni pixmapy do externiho souboru
//-----------------------------------------------------------------------------
void savePixmap(const pixmap *p, const char *filename)
{
FILE *fout;
unsigned int i, j;
unsigned char tgaHeader[18]={ // hlavicka formatu typu TGA
0x00, // typ hlavicky TGA
0x00, // nepouzivame paletu
0x02, // typ obrazku je grayscale
0x00, 0x00, // delka palety je nulova
0x00, 0x00, 0x00, // pozice v palete nas nezajima
0x00, 0x00, 0x00, 0x00, // obrazek je umisteny na pozici [0, 0]
0x00, 0x00, 0x00, 0x00, // sirka a vyska obrazku (dva byty na polozku)
0x18, // format je 8 bitu na pixel
0x20 // orientace bitmapy v obrazku
};
assert(p); // je pixmapa v poradku?
assert(p->pixels);
printf("pixmap info:\n\tname:\t%s\n\twidth:\t%d\n\theight:\t%d\n\tbpp:\t%d\n", filename, p->width, p->height, 24);
memcpy(tgaHeader+12, &(p->width), 2); // do hlavicky TGA zapsat velikost obrazku
memcpy(tgaHeader+14, &(p->height), 2);
fout=fopen(filename, "wb");
assert(fout);
fwrite(tgaHeader, 18, 1, fout); // zapsat hlavicku TGA do souboru
for (i=0; i<p->height; i++) { // postupny zapis vsech radku
unsigned int yoff=3*i*p->width; // y-ovy offset v poli
unsigned char *p1=p->pixels+yoff;
for (j=0; j<p->width; j++) { // prohozeni BGR na RGB a ulozeni radku do souboru
int result;
result=fputc(*(p1+2), fout); assert(result!=EOF);
result=fputc(*(p1+1), fout); assert(result!=EOF);
result=fputc(*(p1), fout); assert(result!=EOF);
p1+=3;
}
}
fclose(fout);
puts("pixmap saved");
}
//-----------------------------------------------------------------------------
// ulozeni barvy pixelu na souradnice x, y
//-----------------------------------------------------------------------------
void putpixel(const pixmap *pix, int x, int y, int r, int g, int b)
{
unsigned char *p;
assert(pix);
assert(pix->pixels);
assert(x>=0 && x<pix->width);
assert(y>=0);
assert(y<pix->height);
p=pix->pixels+3*(x+y*pix->width);
*p++=r;
*p++=g;
*p=b;
}
//-----------------------------------------------------------------------------
// vykresleni horizontalni usecky
//-----------------------------------------------------------------------------
void hline(const pixmap *pix, int x1, int x2, int y, int r, int g, int b)
{
int i;
for (i=x1; i<=x2; i++)
putpixel(pix, i, y, r, g, b);
}
//-----------------------------------------------------------------------------
// vykresleni vertikalni usecky (povoleno prohozeni souradnic y1 <=> y2)
//-----------------------------------------------------------------------------
void vline(const pixmap *pix, int x, int y1, int y2, int r, int g, int b)
{
int i;
if (y1<y2)
for (i=y1; i<=y2; i++)
putpixel(pix, x, i, r, g, b);
else
for (i=y2; i<=y1; i++)
putpixel(pix, x, i, r, g, b);
}
//-----------------------------------------------------------------------------
// vykresleni osove orientovaneho obdelnika
//-----------------------------------------------------------------------------
void box(const pixmap *pix, int x1, int y1, int x2, int y2, int r, int g, int b)
{
int i, j;
for (j=y1; j<=y2; j++) {
for (i=x1; i<=x2; i++) {
putpixel(pix, i, j, r, g, b);
}
}
}
//-----------------------------------------------------------------------------
// vykresleni bazovych funkci dvourozmerne DCT
//-----------------------------------------------------------------------------
void draw2d_dct(const pixmap *pix, int n)
{
#define PI 3.1415927
int u, v;
// zmena koeficientu "v" ve vertikalnim smeru
for (v=0; v<n; v++) {
// zmena koeficientu "u" v horizontalnim smeru
for (u=0; u<n; u++) {
// vypocet pocatecnich souradnic ctverce
int x0=u*100;
int y0=v*100;
int x, y;
// vypocet hodnot 2D DCT pro dane "u" a "v"
for (y=0; y<n; y++) {
for (x=0; x<n; x++) {
float alfa=PI*(2.0*x+1.0)*u/(2.0*n);
float beta=PI*(2.0*y+1.0)*v/(2.0*n);
// prepocet na stupne sedi
float value=127.5+127.5*cos(alfa)*cos(beta);
// vykresleni jedne hodnoty 2D DCT
box(pix,
x0+64*x/n, // x1
y0+64*y/n, // y1
x0+64*(x+1)/n, // x2
y0+64*(y+1)/n, // y2
value, // cervena barvova slozka
value, // zelena barvova
value); // modra barvova slozka
}
}
}
}
}
//-----------------------------------------------------------------------------
// hlavni funkce konzolove aplikace
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
char *full_name;
printf("\nprocessing...\n");
pix=createPixmap(N*100, N*100);
draw2d_dct(pix, N);
savePixmap(pix, FILE_NAME);
printf("\ndone!\n");
return 0;
}
//-----------------------------------------------------------------------------
// finito
//-----------------------------------------------------------------------------