//----------------------------------------------------------------------------- // 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 //-----------------------------------------------------------------------------