//-----------------------------------------------------------------------------
// Demonstracni priklad k serialu "Graficke formaty"
// http://www.root.cz/
//
// Autor: Pavel Tisnovsky
//
// Tento program vytvori obrazek s prubehem bazovych funkci pouzitych
// v jednorozmerne diskretni kosinove transformaci (1D 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 "1d_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 bazovych funkci jednorozmerne DCT
//-----------------------------------------------------------------------------
void draw1d_dct(const pixmap *pix, int n)
{
#define PI 3.1415927
int u;
// pozicovani prubehu bazovych funkci v pixmape
int xoffset=25*8/N, yoffset=50;
int xdelta=50*8/N, ydelta=100;
float amplitude=40.0;
// vykreslit vsech "n" bazovych funkci
for (u=0; u<n; u++) {
int x;
// pozice horizontalni osy pro danou bazovou funkci
int y0=yoffset+ydelta*u;
float y;
// horizontalni osa
hline(pix, 0, pix->width-1, y0, 255, 128, 0);
// vypocet vsech bodu bazove funkce
for (x=0; x<n; x++) {
float alfa=PI*(2.0*x+1.0)*u/(2.0*n);
// hodnota bazove funkce pro dane "x"
y=amplitude*cos(alfa);
//printf("%d %d -> %f\n", u, x, alfa);
// vykresleni vertikalni hodnoty
vline(pix, xoffset+xdelta*x, y0, y0-y, 0, 255, 128);
// zvyrazneni koncoveho bodu pomoci horizontalni carky
hline(pix, xoffset+xdelta*x-3, xoffset+xdelta*x+3, y0-y, 0, 255, 128);
}
}
}
//-----------------------------------------------------------------------------
// hlavni funkce konzolove aplikace
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
char *full_name;
printf("\nprocessing...\n");
pix=createPixmap(400, N*100);
draw1d_dct(pix, N);
savePixmap(pix, FILE_NAME);
printf("\ndone!\n");
return 0;
}
//-----------------------------------------------------------------------------
// finito
//-----------------------------------------------------------------------------