The example code for the ImageResize application
The task that performs the actual image processing is this:
class TResizeTask: public TTaskDispatcher::TTask { IMAGEDATA Src, // the source image Dest; // the destination int Start, // the first line in the destination End, // the last -"- Magn; public: TResizeTask(IMAGEDATA &src, IMAGEDATA &dest, int start, int end, int magn): Src(src), Dest(dest), Start(start), End(end), Magn(magn) { } void Execute(); // the virtual Execute(), that performs the transformation }; void TResizeTask::Execute() { int psize = GetPixelSize(Src.Type); for (int y = Start; y <= End; ++y) for (int x = 0; x < Dest.Width; ++x) { // go through the destination pixels void *dp = GetPixelAddr(Dest, x, y), // dest. pixel address *sp = GetPixelAddr(Src, x / Magn, y / Magn); // source pixel, we just get the inversely magnified coordinate - no interpolation memcpy(dp, sp, psize); // O.K., copy the pixel value } } |
After loading the input image and preparing the image data, we can easily create the tasks:
int start = 0, // first line of the chunk end = start + lines - 1; // last line vector<TTaskDispatcher::TTask *> tasks; // the tasks to be executed while (start < dest_bmp.Height) { // go through the destination image end = start + lines - 1; if (end >= dest_bmp.Height) // trim the last line if it doesn't fit into the destination end = dest_bmp.Height - 1; TTaskDispatcher::TTask *t = new TResizeTask(src, dest, start, end, magn); // create the task for the current chunk tasks.push_back(t); start += lines; } |
To execute the tasks parallelly (and to measure the execution time) is as simple as this:
TTaskDispatcher dp(threads); // create the dispatcher with the actual number of threads DWORD st = GetTickCount(); dp.Execute(tasks); // execute the tasks (as fast as we can...) DWORD et = GetTickCount(), |
As one can clearly see, we don't have to do anything with the parallel execution, the parallel task coordination is completely up to the TaskDispatcher. For example if we configure it for one thread, the whole transformation runs as a single-treaded process (with a little overhead of the task coordination) - this makes for example the debugging easier.
Attila NAGY | Last updated: 2016-10-05 |