// and do some processing void multiThreadProcessImages(OfxRectI procWindow) { OFX::Image *srcRedImg = _srcLeftImg; OFX::Image *srcCyanImg = _srcRightImg; if (_swap) { std::swap(srcRedImg, srcCyanImg); } OfxRectI srcRedBounds = srcRedImg->getBounds(); OfxRectI srcCyanBounds = srcCyanImg->getBounds(); for (int y = procWindow.y1; y < procWindow.y2; y++) { if (_effect.abort()) { break; } PIX *dstPix = (PIX *) _dstImg->getPixelAddress(procWindow.x1, y); for (int x = procWindow.x1; x < procWindow.x2; x++) { // clamp x to avoid black borders int xRed = std::min(std::max(srcRedBounds.x1,x+(_offset+1)/2),srcRedBounds.x2-1); int xCyan = std::min(std::max(srcCyanBounds.x1,x-_offset/2),srcCyanBounds.x2-1); const PIX *srcRedPix = (const PIX *)(srcRedImg ? srcRedImg->getPixelAddress(xRed, y) : 0); const PIX *srcCyanPix = (const PIX *)(srcCyanImg ? srcCyanImg->getPixelAddress(xCyan, y) : 0); dstPix[3] = 0; // start with transparent if (srcRedPix) { PIX srcLuminance = luminance(srcRedPix[0],srcRedPix[1],srcRedPix[2]); dstPix[0] = srcLuminance*(1.-_amtcolour) + srcRedPix[0]*_amtcolour; dstPix[3] += 0.5*srcRedPix[3]; } else { // no src pixel here, be black and transparent dstPix[0] = 0; } if (srcCyanPix) { PIX srcLuminance = luminance(srcCyanPix[0],srcCyanPix[1],srcCyanPix[2]); dstPix[1] = srcLuminance*(1.-_amtcolour) + srcCyanPix[1]*_amtcolour; dstPix[2] = srcLuminance*(1.-_amtcolour) + srcCyanPix[2]*_amtcolour; dstPix[3] += 0.5*srcCyanPix[3]; } else { // no src pixel here, be black and transparent dstPix[1] = 0; dstPix[2] = 0; } // increment the dst pixel dstPix += 4; } } }
/** @brief called to process everything */ virtual void process(void) { // If _dstImg was set, check that the _renderWindow is lying into dstBounds if (_dstImg) { const OfxRectI& dstBounds = _dstImg->getBounds(); // is the renderWindow within dstBounds ? assert(dstBounds.x1 <= _renderWindow.x1 && _renderWindow.x2 <= dstBounds.x2 && dstBounds.y1 <= _renderWindow.y1 && _renderWindow.y2 <= dstBounds.y2); // exit gracefully in case of error if (!(dstBounds.x1 <= _renderWindow.x1 && _renderWindow.x2 <= dstBounds.x2 && dstBounds.y1 <= _renderWindow.y1 && _renderWindow.y2 <= dstBounds.y2) || (_renderWindow.x1 >= _renderWindow.x2) || (_renderWindow.y1 >= _renderWindow.y2)) { return; } } // call the pre MP pass preProcess(); // make sure there are at least 4096 pixels per CPU and at least 1 line par CPU unsigned int nCPUs = ((std::min)(_renderWindow.x2 - _renderWindow.x1, 4096) * (_renderWindow.y2 - _renderWindow.y1)) / 4096; // make sure the number of CPUs is valid (and use at least 1 CPU) nCPUs = std::max(1u, (std::min)(nCPUs, OFX::MultiThread::getNumCPUs())); // call the base multi threading code, should put a pre & post thread calls in too multiThread(nCPUs); // call the post MP pass postProcess(); }