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