--- joko/Uni/BSArch/04/bmp_fractal.c 2006/07/01 09:40:29 1.2 +++ joko/Uni/BSArch/04/bmp_fractal.c 2006/07/01 13:56:54 1.6 @@ -4,6 +4,10 @@ * * Uebung 4.4 */ + +// $Id: bmp_fractal.c,v 1.6 2006/07/01 13:56:54 joko Exp $ + +#include #include #include @@ -11,6 +15,7 @@ #define YSIZE 500 #include "algorithm.h" + /* BMP Header */ unsigned char header[54]={0x42,0x4d, // signature BM 0xe6,0x71,0x0b,0x0, // filesize 750054 @@ -29,44 +34,239 @@ 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 { + unsigned int start_row; + unsigned 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; + + // fractal calculation + int x, y; + char bgr[3]; + + thread_id = GetCurrentThreadId(); + + // get worker arguments + args = (PWORKERARGS)lpParam; + + 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 fractal + for (y = (args->start_row + args->number_of_rows) - 1; y >= args->start_row; y--) { + 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 + args->pBitmap[0] = bgr[0]; + args->pBitmap[1] = bgr[1]; + args->pBitmap[2] = bgr[2]; + + // move pointer to next pixel + args->pBitmap += 3; - fd=fopen("test.bmp","wb+"); - if(NULL==fd) - { - perror("open"); exit(1); } + //no padding required because 1500%4 =0 + } - len=fwrite(header,1,sizeof(header),fd); //write header + return 0; + +} + + +int main(int argc, char *argv[]) { + + // MMF support + DWORD err; + HANDLE hMap, hFile; + LPVOID pData; + unsigned char *pDataBitmap, *pDataBitmapCurrent; + + // workers + unsigned int workers = 3; + unsigned 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, workers * sizeof(WORKERARGS)); + + // 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++) { - if(-1==len || len!=sizeof(header)) - { - perror("write"); - exit(2); + // 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