--- joko/Uni/BSArch/04/bmp_fractal.c 2006/06/30 20:39:33 1.1 +++ joko/Uni/BSArch/04/bmp_fractal.c 2006/07/01 22:10:42 1.8 @@ -4,6 +4,10 @@ * * Uebung 4.4 */ + +// $Id: bmp_fractal.c,v 1.8 2006/07/01 22:10:42 joko Exp $ + +#include #include #include @@ -11,7 +15,8 @@ #define YSIZE 500 #include "algorithm.h" -/* BMP Header + +/* BMP Header */ unsigned char header[54]={0x42,0x4d, // signature BM 0xe6,0x71,0x0b,0x0, // filesize 750054 0x0,0x0,0x0,0x0, // reserved @@ -28,94 +33,274 @@ 0x0,0x0,0x0,0x0, // number of colortables 0x0,0x0,0x0,0x0 // number of important colors }; -*/ -int main(int argc, char *argv[]) -{ - FILE *fd; - int len,x,y; - char bgr[3]; - short svalue; - int lvalue; - unsigned char header[54],*ptr=&header[0]; + +void printErrorAndExit(const char *msg, DWORD err) { + LPSTR lpMsgBuf; + if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER| + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL )) + { + fprintf(stderr,"%s : %s\n",msg,lpMsgBuf); + LocalFree(lpMsgBuf); + } + else + { + fprintf(stderr,"Error at FormatMesage: %d\n",err=GetLastError()); + } + exit(err); +} + + +void write_blank_file(char *filename) { + + FILE *fd; + int len, i, img_size; + + // open file handle + fd = fopen(filename, "wb+"); + if (NULL == fd) { + perror("open"); + exit(1); + } + + // write bmp header to file + len = fwrite(header, 1, sizeof(header), fd); + + // error checking + if (-1 == len || len != sizeof(header)) { + perror("write"); + exit(2); + } + + // write three null-bytes for each pixel to file to create a black picture + img_size = XSIZE * YSIZE; + for (i = 0; i < img_size; i++) { + len = fwrite("\0\0\0", 1, 3, fd); + if (-1 == len || len != 3) { + perror("write"); + exit(4); + } + } + + // close file handle + fclose(fd); +} + + +// arguments for each thread +typedef struct _WorkerArguments { + int start_row; + int number_of_rows; + unsigned char * pBitmap; +} WORKERARGS, *PWORKERARGS; + +// worker thread - main entry function +DWORD WINAPI fractal_thread (LPVOID lpParam) { + + // thread stuff + int thread_id; + PWORKERARGS args; + unsigned char *pDataBitmapSegment; + + // fractal calculation + int x, y; + char bgr[3]; + + thread_id = GetCurrentThreadId(); + + // get worker arguments + args = (PWORKERARGS)lpParam; + + printf("----------------------------------------------\n"); + printf("thread_id: %i\n", thread_id); + printf("arg.start_row: %i\n", args->start_row); + printf("arg.number_of_rows: %i\n", args->number_of_rows); + + // calculate pointer to beginning of segment + pDataBitmapSegment = (unsigned char *)((INT_PTR)args->pBitmap + (YSIZE - (args->start_row + args->number_of_rows)) * 3 * XSIZE); + printf("segment_start: %p\n", pDataBitmapSegment); + + // calculate fractal + for (y = (args->start_row + args->number_of_rows) - 1; y >= args->start_row; y--) { + //printf("calc: thread=%i; y=%i limits: %i,%i p: %p\n", thread_id, y, args->start_row, args->number_of_rows, pDataBitmapSegment); + for (x = 0; x < XSIZE; x++) { + getColorValuesAt(x * (2.0 / XSIZE) - 1.5, y * (2.0 / YSIZE) - 1.0, &bgr[2], &bgr[1], &bgr[0]); + + // debugging + //printf("pointer: %p\n", pDataBitmapCurrent); + + // transfer color values to current pixel + pDataBitmapSegment[0] = bgr[0]; + pDataBitmapSegment[1] = bgr[1]; + pDataBitmapSegment[2] = bgr[2]; + + // move pointer to next pixel + pDataBitmapSegment += 3; - fd=fopen("test.bmp","wb+"); - if(NULL==fd) - { - perror("open"); exit(1); } -/* Der folgende Abschnitt dient nur zur information und kann durch - schreiben der auskommentierten Variable header ersetzt werden */ - svalue=0x4d42; - memcpy(ptr,&svalue,2);//signatur - ptr+=2; - lvalue=XSIZE*YSIZE*3+54; - memcpy(ptr,&lvalue,4); //filesize - ptr+=4; - lvalue=0; - memcpy(ptr,&lvalue,4);//reserved - ptr+=4; - lvalue=54; - memcpy(ptr,&lvalue,4);//image offset - ptr+=4; - lvalue=40; - memcpy(ptr,&lvalue,4);//size of header follows - ptr+=4; - lvalue=XSIZE; - memcpy(ptr,&lvalue,4);//with of image - ptr+=4; - lvalue=YSIZE; - memcpy(ptr,&lvalue,4); //height of image - ptr+=4; - svalue=1; - memcpy(ptr,&svalue,2); //number of planes - ptr+=2; - svalue=24; - memcpy(ptr,&svalue,2); //number of pixel - ptr+=2; - lvalue=0; //compression - memcpy(ptr,&lvalue,4); //compression - ptr+=4; - lvalue=XSIZE*YSIZE*3; - memcpy(ptr,&lvalue,4); //size of image - ptr+=4; - lvalue=0; - memcpy(ptr,&lvalue,4); //xres - ptr+=4; - lvalue=0; - memcpy(ptr,&lvalue,4); //yres - ptr+=4; - lvalue=0; - memcpy(ptr,&lvalue,4); //number of colortables - ptr+=4; - lvalue=0; - memcpy(ptr,&lvalue,4); //number of important colors - ptr+=4; -/* Ende Information */ - - len=fwrite(header,1,sizeof(header),fd); //write header - - if(-1==len || len!=sizeof(header)) - { - perror("write"); - exit(2); + //no padding required because 1500%4 =0 + } + + printf("thread finished: %i\n", thread_id); + return 0; + +} + + +int main(int argc, char *argv[]) { + + // MMF support + DWORD err; + HANDLE hMap, hFile; + LPVOID pData; + unsigned char *pDataBitmap, *pDataBitmapCurrent; + + // workers + int workers = 5; + int worker_index, worker_rows, worker_startrow; + HANDLE *worker_handles; + //struct WorkerArguments *worker_args; + PWORKERARGS worker_args; + + + // create empty bmp-file (black background) + write_blank_file("test.bmp"); + + /* open file for reading and writing */ + hFile = CreateFile("test.bmp", GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (INVALID_HANDLE_VALUE == hFile) { + err = GetLastError(); + printErrorAndExit("Error at CreateFile",err); + } + + /* create the file mapping object */ + hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); + if (NULL == hMap) { + printErrorAndExit("Error at CreateFileMapping", GetLastError()); + } + + /* map the whole file into the process context */ + pData = MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); + if (NULL == pData) { + printErrorAndExit("Error at MapViewOfFile", GetLastError()); + } + + + // calculate pointer to beginning of bitmap + pDataBitmap = (unsigned char *)((INT_PTR)pData + sizeof(header)); + + // debugging + printf("pos. of file: %p\n", pData); + printf("pos. of bitmap: %p\n", pDataBitmap); + + // pointer to current pixel + pDataBitmapCurrent = pDataBitmap; + + /* + // turn bitmap into white wand + for (offset = 0; offset < 500 * 500 * 3; offset++) { + //pDataBitmap[offset] = 255; + *pDataBitmapCurrent = 255; + pDataBitmapCurrent++; + } + */ + + + // allocate memory for table of all worker handles + if ((worker_handles = malloc(workers * sizeof worker_handles[0])) == NULL) + perror("malloc"), exit(1); + + // allocate memory for table of all worker arguments + if ((worker_args = malloc(workers * sizeof worker_args[0])) == NULL) + perror("malloc"), exit(1); + + // allocate memory for table of all worker arguments + /* + worker_args = (PWORKERARGS) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, workers * sizeof(WORKERARGS)); + + if (worker_args == NULL) { + printErrorAndExit("Failed to allocate on heap", GetLastError()); + } + */ + + // calculate segments of bitmap for worker threads/processes and start them + worker_rows = YSIZE / workers; + printf("rows for each worker: %i\n", worker_rows); + for (worker_index = 0; worker_index < workers; worker_index++) { + + // debugging: just run with single thread + //if (worker_index == 1) + // continue; + + // number of row to start for each worker + worker_startrow = worker_index * worker_rows; + + // recalculate number of rows for last worker if (YSIZE mod workers) != 0 + if (worker_index == workers - 1) { + worker_rows = YSIZE - worker_startrow; + printf("rows for last worker: %i\n", worker_rows); } - for(y=YSIZE-1;y>=0;y--) - { - for(x=0;x