ObjectPtr MedianCutSampler::doOperation( const CompoundObject * operands ) { ImagePrimitivePtr image = static_cast<ImagePrimitive *>( imageParameter()->getValue() )->copy(); Box2i dataWindow = image->getDataWindow(); // find the right channel const std::string &channelName = m_channelNameParameter->getTypedValue(); FloatVectorDataPtr luminance = image->getChannel<float>( channelName ); if( !luminance ) { throw Exception( str( format( "No FloatVectorData channel named \"%s\"." ) % channelName ) ); } // if the projection requires it, weight the luminances so they're less // important towards the poles of the sphere Projection projection = (Projection)m_projectionParameter->getNumericValue(); if( projection==LatLong ) { float radiansPerPixel = M_PI / (dataWindow.size().y + 1); float angle = ( M_PI - radiansPerPixel ) / 2.0f; float *p = &(luminance->writable()[0]); for( int y=dataWindow.min.y; y<=dataWindow.max.y; y++ ) { float *pEnd = p + dataWindow.size().x + 1; float w = cosf( angle ); while( p < pEnd ) { *p *= w; p++; } angle -= radiansPerPixel; } } // make a summed area table for speed FloatVectorDataPtr summedLuminance = luminance; luminance = luminance->copy(); // we need this for the centroid computation SummedAreaOpPtr summedAreaOp = new SummedAreaOp(); summedAreaOp->inputParameter()->setValue( image ); summedAreaOp->copyParameter()->setTypedValue( false ); summedAreaOp->channelNamesParameter()->getTypedValue().clear(); summedAreaOp->channelNamesParameter()->getTypedValue().push_back( "Y" ); summedAreaOp->operate(); // do the median cut thing CompoundObjectPtr result = new CompoundObject; V2fVectorDataPtr centroids = new V2fVectorData; Box2iVectorDataPtr areas = new Box2iVectorData; result->members()["centroids"] = centroids; result->members()["areas"] = areas; dataWindow.max -= dataWindow.min; dataWindow.min -= dataWindow.min; // let's start indexing from 0 shall we? Array2D array( &(luminance->writable()[0]), extents[dataWindow.size().x+1][dataWindow.size().y+1], fortran_storage_order() ); Array2D summedArray( &(summedLuminance->writable()[0]), extents[dataWindow.size().x+1][dataWindow.size().y+1], fortran_storage_order() ); medianCut( array, summedArray, projection, dataWindow, areas->writable(), centroids->writable(), 0, subdivisionDepthParameter()->getNumericValue() ); return result; }