void RenderLayersNode::testSocketConnection(ExecutionSystem *system, CompositorContext *context, int outputSocketNumber, RenderLayersBaseProg *operation)
{
	OutputSocket *outputSocket = this->getOutputSocket(outputSocketNumber);
	Scene *scene = (Scene *)this->getbNode()->id;
	short layerId = this->getbNode()->custom1;

	if (outputSocket->isConnected()) {
		operation->setScene(scene);
		operation->setLayerId(layerId);
		operation->setRenderData(context->getRenderData());
		outputSocket->relinkConnections(operation->getOutputSocket());
		system->addOperation(operation);
		if (outputSocketNumber == 0) { // only do for image socket if connected
			addPreviewOperation(system, context, operation->getOutputSocket());
		}
	}
	else {
		if (outputSocketNumber == 0) {
			system->addOperation(operation);
			operation->setScene(scene);
			operation->setLayerId(layerId);
			operation->setRenderData(context->getRenderData());
			addPreviewOperation(system, context, operation->getOutputSocket());
		}
		else {
			delete operation;
		}
	}
}
void DistanceMatteNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	InputSocket *inputSocketImage = this->getInputSocket(0);
	InputSocket *inputSocketKey = this->getInputSocket(1);
	OutputSocket *outputSocketImage = this->getOutputSocket(0);
	OutputSocket *outputSocketMatte = this->getOutputSocket(1);

	DistanceMatteOperation *operation = new DistanceMatteOperation();
	bNode *editorsnode = getbNode();
	operation->setSettings((NodeChroma *)editorsnode->storage);

	inputSocketImage->relinkConnections(operation->getInputSocket(0), 0, graph);
	inputSocketKey->relinkConnections(operation->getInputSocket(1), 1, graph);

	if (outputSocketMatte->isConnected()) {
		outputSocketMatte->relinkConnections(operation->getOutputSocket());
	}

	graph->addOperation(operation);

	SetAlphaOperation *operationAlpha = new SetAlphaOperation();
	addLink(graph, operation->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0));
	addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));

	graph->addOperation(operationAlpha);
	addPreviewOperation(graph, operationAlpha->getOutputSocket());

	if (outputSocketImage->isConnected()) {
		outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
	}
}
void DistanceMatteNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	InputSocket *inputSocketImage = this->getInputSocket(0);
	InputSocket *inputSocketKey = this->getInputSocket(1);
	OutputSocket *outputSocketImage = this->getOutputSocket(0);
	OutputSocket *outputSocketMatte = this->getOutputSocket(1);

	NodeOperation *operation;
	bNode *editorsnode = getbNode();
	NodeChroma *storage = (NodeChroma *)editorsnode->storage;

	/* work in RGB color space */
	if (storage->channel == 1) {
		operation = new DistanceRGBMatteOperation();
		((DistanceRGBMatteOperation *) operation)->setSettings(storage);

		inputSocketImage->relinkConnections(operation->getInputSocket(0), 0, graph);
		inputSocketKey->relinkConnections(operation->getInputSocket(1), 1, graph);
	}
	/* work in YCbCr color space */
	else {
		operation = new DistanceYCCMatteOperation();
		((DistanceYCCMatteOperation *) operation)->setSettings(storage);

		ConvertRGBToYCCOperation *operationYCCImage = new ConvertRGBToYCCOperation();
		inputSocketImage->relinkConnections(operationYCCImage->getInputSocket(0), 0, graph);
		addLink(graph, operationYCCImage->getOutputSocket(), operation->getInputSocket(0));
		graph->addOperation(operationYCCImage);

		ConvertRGBToYCCOperation *operationYCCMatte = new ConvertRGBToYCCOperation();
		inputSocketKey->relinkConnections(operationYCCMatte->getInputSocket(0), 1, graph);
		addLink(graph, operationYCCMatte->getOutputSocket(), operation->getInputSocket(1));
		graph->addOperation(operationYCCMatte);
	}

	if (outputSocketMatte->isConnected()) {
		outputSocketMatte->relinkConnections(operation->getOutputSocket());
	}

	graph->addOperation(operation);

	SetAlphaOperation *operationAlpha = new SetAlphaOperation();
	addLink(graph, operation->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0));
	addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));

	graph->addOperation(operationAlpha);
	addPreviewOperation(graph, context, operationAlpha->getOutputSocket());

	if (outputSocketImage->isConnected()) {
		outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
	}
}
void FilterNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	InputSocket *inputSocket = this->getInputSocket(0);
	InputSocket *inputImageSocket = this->getInputSocket(1);
	OutputSocket *outputSocket = this->getOutputSocket(0);
	ConvolutionFilterOperation *operation = NULL;
	
	switch (this->getbNode()->custom1) {
		case CMP_FILT_SOFT:
			operation = new ConvolutionFilterOperation();
			operation->set3x3Filter(1 / 16.0f, 2 / 16.0f, 1 / 16.0f, 2 / 16.0f, 4 / 16.0f, 2 / 16.0f, 1 / 16.0f, 2 / 16.0f, 1 / 16.0f);
			break;
		case CMP_FILT_SHARP:
			operation = new ConvolutionFilterOperation();
			operation->set3x3Filter(-1, -1, -1, -1, 9, -1, -1, -1, -1);
			break;
		case CMP_FILT_LAPLACE:
			operation = new ConvolutionFilterOperation();
			operation->set3x3Filter(-1 / 8.0f, -1 / 8.0f, -1 / 8.0f, -1 / 8.0f, 1.0f, -1 / 8.0f, -1 / 8.0f, -1 / 8.0f, -1 / 8.0f);
			break;
		case CMP_FILT_SOBEL:
			operation = new ConvolutionEdgeFilterOperation();
			operation->set3x3Filter(1, 2, 1, 0, 0, 0, -1, -2, -1);
			break;
		case CMP_FILT_PREWITT:
			operation = new ConvolutionEdgeFilterOperation();
			operation->set3x3Filter(1, 1, 1, 0, 0, 0, -1, -1, -1);
			break;
		case CMP_FILT_KIRSCH:
			operation = new ConvolutionEdgeFilterOperation();
			operation->set3x3Filter(5, 5, 5, -3, -3, -3, -2, -2, -2);
			break;
		case CMP_FILT_SHADOW:
			operation = new ConvolutionFilterOperation();
			operation->set3x3Filter(1, 2, 1, 0, 1, 0, -1, -2, -1);
			break;
		default:
			operation = new ConvolutionFilterOperation();
			operation->set3x3Filter(0, 0, 0, 0, 1, 0, 0, 0, 0);
			break;
	}
	operation->setbNode(this->getbNode());
	inputImageSocket->relinkConnections(operation->getInputSocket(0), 1, graph);
	inputSocket->relinkConnections(operation->getInputSocket(1), 0, graph);
	outputSocket->relinkConnections(operation->getOutputSocket());
	addPreviewOperation(graph, operation->getOutputSocket(0));
	
	graph->addOperation(operation);
}
void DespeckleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	bNode *editorNode = this->getbNode();
	InputSocket *inputSocket = this->getInputSocket(0);
	InputSocket *inputImageSocket = this->getInputSocket(1);
	OutputSocket *outputSocket = this->getOutputSocket(0);
	DespeckleOperation *operation = new DespeckleOperation();

	operation->setbNode(editorNode);
	operation->setThreshold(editorNode->custom3);
	operation->setThresholdNeighbor(editorNode->custom4);

	inputImageSocket->relinkConnections(operation->getInputSocket(0), 1, graph);
	inputSocket->relinkConnections(operation->getInputSocket(1), 0, graph);
	outputSocket->relinkConnections(operation->getOutputSocket());
	addPreviewOperation(graph, context, operation->getOutputSocket(0));

	graph->addOperation(operation);
}
void ChromaMatteNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	InputSocket *inputSocketImage = this->getInputSocket(0);
	InputSocket *inputSocketKey = this->getInputSocket(1);
	OutputSocket *outputSocketImage = this->getOutputSocket(0);
	OutputSocket *outputSocketMatte = this->getOutputSocket(1);

	ConvertRGBToYCCOperation *operationRGBToYCC_Image = new ConvertRGBToYCCOperation();
	ConvertRGBToYCCOperation *operationRGBToYCC_Key = new ConvertRGBToYCCOperation();
	operationRGBToYCC_Image->setMode(0); /* BLI_YCC_ITU_BT601 */
	operationRGBToYCC_Key->setMode(0); /* BLI_YCC_ITU_BT601 */

	ChromaMatteOperation *operation = new ChromaMatteOperation();
	bNode *editorsnode = getbNode();
	operation->setSettings((NodeChroma *)editorsnode->storage);

	inputSocketImage->relinkConnections(operationRGBToYCC_Image->getInputSocket(0), 0, graph);
	inputSocketKey->relinkConnections(operationRGBToYCC_Key->getInputSocket(0), 0, graph);

	addLink(graph, operationRGBToYCC_Image->getOutputSocket(), operation->getInputSocket(0));
	addLink(graph, operationRGBToYCC_Key->getOutputSocket(), operation->getInputSocket(1));

	graph->addOperation(operationRGBToYCC_Image);
	graph->addOperation(operationRGBToYCC_Key);
	graph->addOperation(operation);

	if (outputSocketMatte->isConnected()) {
		outputSocketMatte->relinkConnections(operation->getOutputSocket());
	}

	SetAlphaOperation *operationAlpha = new SetAlphaOperation();
	addLink(graph, operationRGBToYCC_Image->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0));
	addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));

	graph->addOperation(operationAlpha);
	addPreviewOperation(graph, context, operationAlpha->getOutputSocket());

	if (outputSocketImage->isConnected()) {
		outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
	}
}
void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	/// Image output
	OutputSocket *outputImage = this->getOutputSocket(0);
	bNode *editorNode = this->getbNode();
	Image *image = (Image *)editorNode->id;
	ImageUser *imageuser = (ImageUser *)editorNode->storage;
	int framenumber = context->getFramenumber();
	int numberOfOutputs = this->getNumberOfOutputSockets();
	BKE_image_user_frame_calc(imageuser, context->getFramenumber(), 0);

	/* force a load, we assume iuser index will be set OK anyway */
	if (image && image->type == IMA_TYPE_MULTILAYER) {
		bool is_multilayer_ok = false;
		ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL);
		if (image->rr) {
			RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer);
			if (rl) {
				OutputSocket *socket;
				int index;

				is_multilayer_ok = true;

				for (index = 0; index < numberOfOutputs; index++) {
					NodeOperation *operation = NULL;
					socket = this->getOutputSocket(index);
					if (socket->isConnected() || index == 0) {
						bNodeSocket *bnodeSocket = socket->getbNodeSocket();
						NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;
						int passindex = storage->pass_index;
						
						RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex);
						if (rpass) {
							imageuser->pass = passindex;
							switch (rpass->channels) {
								case 1:
									operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VALUE);
									break;
								/* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
								/* XXX any way to detect actual vector images? */
								case 3:
									operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VECTOR);
									break;
								case 4:
									operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR);
									break;
								default:
									/* dummy operation is added below */
									break;
							}

							if (index == 0 && operation) {
								addPreviewOperation(graph, context, operation->getOutputSocket());
							}
						}
					}

					/* incase we can't load the layer */
					if (operation == NULL) {
						convertToOperations_invalid_index(graph, index);
					}
				}
			}
		}
		BKE_image_release_ibuf(image, ibuf, NULL);

		/* without this, multilayer that fail to load will crash blender [#32490] */
		if (is_multilayer_ok == false) {
			convertToOperations_invalid(graph, context);
		}
	}
	else {
		if (numberOfOutputs >  0) {
			ImageOperation *operation = new ImageOperation();
			if (outputImage->isConnected()) {
				outputImage->relinkConnections(operation->getOutputSocket());
			}
			operation->setImage(image);
			operation->setImageUser(imageuser);
			operation->setFramenumber(framenumber);
			graph->addOperation(operation);
			addPreviewOperation(graph, context, operation->getOutputSocket());
		}
		
		if (numberOfOutputs > 1) {
			OutputSocket *alphaImage = this->getOutputSocket(1);
			if (alphaImage->isConnected()) {
				ImageAlphaOperation *alphaOperation = new ImageAlphaOperation();
				alphaOperation->setImage(image);
				alphaOperation->setImageUser(imageuser);
				alphaOperation->setFramenumber(framenumber);
				alphaImage->relinkConnections(alphaOperation->getOutputSocket());
				graph->addOperation(alphaOperation);
			}
		}
		if (numberOfOutputs > 2) {
			OutputSocket *depthImage = this->getOutputSocket(2);
			if (depthImage->isConnected()) {
				ImageDepthOperation *depthOperation = new ImageDepthOperation();
				depthOperation->setImage(image);
				depthOperation->setImageUser(imageuser);
				depthOperation->setFramenumber(framenumber);
				depthImage->relinkConnections(depthOperation->getOutputSocket());
				graph->addOperation(depthOperation);
			}
		}
		if (numberOfOutputs > 3) {
			/* happens when unlinking image datablock from multilayer node */
			for (int i = 3; i < numberOfOutputs; i++) {
				OutputSocket *output = this->getOutputSocket(i);
				NodeOperation *operation = NULL;
				switch (output->getDataType()) {
					case COM_DT_VALUE:
					{
						SetValueOperation *valueoperation = new SetValueOperation();
						valueoperation->setValue(0.0f);
						operation = valueoperation;
						break;
					}
					case COM_DT_VECTOR:
					{
						SetVectorOperation *vectoroperation = new SetVectorOperation();
						vectoroperation->setX(0.0f);
						vectoroperation->setY(0.0f);
						vectoroperation->setW(0.0f);
						operation = vectoroperation;
						break;
					}
					case COM_DT_COLOR:
					{
						SetColorOperation *coloroperation = new SetColorOperation();
						coloroperation->setChannel1(0.0f);
						coloroperation->setChannel2(0.0f);
						coloroperation->setChannel3(0.0f);
						coloroperation->setChannel4(0.0f);
						operation = coloroperation;
						break;
					}
				}

				if (operation) {
					output->relinkConnections(operation->getOutputSocket());
					graph->addOperation(operation);
				}
			}
		}
	}
}
void MixNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	InputSocket *valueSocket = this->getInputSocket(0);
	InputSocket *color1Socket = this->getInputSocket(1);
	InputSocket *color2Socket = this->getInputSocket(2);
	OutputSocket *outputSocket = this->getOutputSocket(0);
	bNode *editorNode = this->getbNode();
	bool useAlphaPremultiply = this->getbNode()->custom2 & 1;
	bool useClamp = this->getbNode()->custom2 & 2;
	
	MixBaseOperation *convertProg;
	
	switch (editorNode->custom1) {
		case MA_RAMP_ADD:
			convertProg = new MixAddOperation();
			break;
		case MA_RAMP_MULT:
			convertProg = new MixMultiplyOperation();
			break;
		case MA_RAMP_LIGHT:
			convertProg = new MixLightenOperation();
			break;
		case MA_RAMP_BURN:
			convertProg = new MixBurnOperation();
			break;
		case MA_RAMP_HUE:
			convertProg = new MixHueOperation();
			break;
		case MA_RAMP_COLOR:
			convertProg = new MixColorOperation();
			break;
		case MA_RAMP_SOFT:
			convertProg = new MixSoftLightOperation();
			break;
		case MA_RAMP_SCREEN:
			convertProg = new MixScreenOperation();
			break;
		case MA_RAMP_LINEAR:
			convertProg = new MixLinearLightOperation();
			break;
		case MA_RAMP_DIFF:
			convertProg = new MixDifferenceOperation();
			break;
		case MA_RAMP_SAT:
			convertProg = new MixSaturationOperation();
			break;
		case MA_RAMP_DIV:
			convertProg = new MixDivideOperation();
			break;
		case MA_RAMP_SUB:
			convertProg = new MixSubtractOperation();
			break;
		case MA_RAMP_DARK:
			convertProg = new MixDarkenOperation();
			break;
		case MA_RAMP_OVERLAY:
			convertProg = new MixOverlayOperation();
			break;
		case MA_RAMP_VAL:
			convertProg = new MixValueOperation();
			break;
		case MA_RAMP_DODGE:
			convertProg = new MixDodgeOperation();
			break;

		case MA_RAMP_BLEND:
		default:
			convertProg = new MixBlendOperation();
			break;
	}
	convertProg->setUseValueAlphaMultiply(useAlphaPremultiply);
	convertProg->setUseClamp(useClamp);

	if (color1Socket->isConnected()) {
		convertProg->setResolutionInputSocketIndex(1);
	}
	else {
		if (color2Socket->isConnected())
			convertProg->setResolutionInputSocketIndex(2);
		else
			convertProg->setResolutionInputSocketIndex(0);
	}

	valueSocket->relinkConnections(convertProg->getInputSocket(0), 0, graph);
	color1Socket->relinkConnections(convertProg->getInputSocket(1), 1, graph);
	color2Socket->relinkConnections(convertProg->getInputSocket(2), 2, graph);
	outputSocket->relinkConnections(convertProg->getOutputSocket(0));
	addPreviewOperation(graph, context, convertProg->getOutputSocket(0));
	
	convertProg->getInputSocket(2)->setResizeMode(color2Socket->getResizeMode());
	
	graph->addOperation(convertProg);
}
void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	OutputSocket *outputMovieClip = this->getOutputSocket(0);
	OutputSocket *alphaMovieClip = this->getOutputSocket(1);
	OutputSocket *offsetXMovieClip = this->getOutputSocket(2);
	OutputSocket *offsetYMovieClip = this->getOutputSocket(3);
	OutputSocket *scaleMovieClip = this->getOutputSocket(4);
	OutputSocket *angleMovieClip = this->getOutputSocket(5);
	
	bNode *editorNode = this->getbNode();
	MovieClip *movieClip = (MovieClip *)editorNode->id;
	MovieClipUser *movieClipUser = (MovieClipUser *)editorNode->storage;
	bool cacheFrame = !context->isRendering();

	ImBuf *ibuf = NULL;
	if (movieClip) {
		if (cacheFrame)
			ibuf = BKE_movieclip_get_ibuf(movieClip, movieClipUser);
		else
			ibuf = BKE_movieclip_get_ibuf_flag(movieClip, movieClipUser, movieClip->flag, MOVIECLIP_CACHE_SKIP);
	}
	
	// always connect the output image
	MovieClipOperation *operation = new MovieClipOperation();
	
	addPreviewOperation(graph, context, operation->getOutputSocket());
	if (outputMovieClip->isConnected()) {
		outputMovieClip->relinkConnections(operation->getOutputSocket());
	}

	operation->setMovieClip(movieClip);
	operation->setMovieClipUser(movieClipUser);
	operation->setFramenumber(context->getFramenumber());
	operation->setCacheFrame(cacheFrame);
	graph->addOperation(operation);

	if (alphaMovieClip->isConnected()) {
		MovieClipAlphaOperation *alphaOperation = new MovieClipAlphaOperation();
		alphaOperation->setMovieClip(movieClip);
		alphaOperation->setMovieClipUser(movieClipUser);
		alphaOperation->setFramenumber(context->getFramenumber());
		alphaOperation->setCacheFrame(cacheFrame);
		alphaMovieClip->relinkConnections(alphaOperation->getOutputSocket());
		graph->addOperation(alphaOperation);
	}

	MovieTrackingStabilization *stab = &movieClip->tracking.stabilization;
	float loc[2], scale, angle;
	loc[0] = 0.0f;
	loc[1] = 0.0f;
	scale = 1.0f;
	angle = 0.0f;

	if (ibuf) {
		if (stab->flag & TRACKING_2D_STABILIZATION) {
			int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(movieClip, context->getFramenumber());

			BKE_tracking_stabilization_data_get(&movieClip->tracking, clip_framenr, ibuf->x, ibuf->y, loc, &scale, &angle);
		}
	}

	if (offsetXMovieClip->isConnected()) {
		SetValueOperation *operationSetValue = new SetValueOperation();
		operationSetValue->setValue(loc[0]);
		offsetXMovieClip->relinkConnections(operationSetValue->getOutputSocket());
		graph->addOperation(operationSetValue);
	}
	if (offsetYMovieClip->isConnected()) {
		SetValueOperation *operationSetValue = new SetValueOperation();
		operationSetValue->setValue(loc[1]);
		offsetYMovieClip->relinkConnections(operationSetValue->getOutputSocket());
		graph->addOperation(operationSetValue);
	}
	if (scaleMovieClip->isConnected()) {
		SetValueOperation *operationSetValue = new SetValueOperation();
		operationSetValue->setValue(scale);
		scaleMovieClip->relinkConnections(operationSetValue->getOutputSocket());
		graph->addOperation(operationSetValue);
	}
	if (angleMovieClip->isConnected()) {
		SetValueOperation *operationSetValue = new SetValueOperation();
		operationSetValue->setValue(angle);
		angleMovieClip->relinkConnections(operationSetValue->getOutputSocket());
		graph->addOperation(operationSetValue);
	}

	if (ibuf) {
		IMB_freeImBuf(ibuf);
	}
}
Beispiel #10
0
void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	/// Image output
	OutputSocket *outputImage = this->getOutputSocket(0);
	bNode *editorNode = this->getbNode();
	Image *image = (Image *)editorNode->id;
	ImageUser *imageuser = (ImageUser *)editorNode->storage;
	int framenumber = context->getFramenumber();
	int numberOfOutputs = this->getNumberOfOutputSockets();
	bool outputStraightAlpha = (editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0;
	BKE_image_user_frame_calc(imageuser, context->getFramenumber(), 0);

	/* force a load, we assume iuser index will be set OK anyway */
	if (image && image->type == IMA_TYPE_MULTILAYER) {
		bool is_multilayer_ok = false;
		ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL);
		if (image->rr) {
			RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer);
			if (rl) {
				OutputSocket *socket;
				int index;

				is_multilayer_ok = true;

				for (index = 0; index < numberOfOutputs; index++) {
					NodeOperation *operation = NULL;
					socket = this->getOutputSocket(index);
					if (socket->isConnected() || index == 0) {
						bNodeSocket *bnodeSocket = socket->getbNodeSocket();
						/* Passes in the file can differ from passes stored in sockets (#36755).
						 * Look up the correct file pass using the socket identifier instead.
						 */
						#if 0
						NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;*/
						int passindex = storage->pass_index;*/
						RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex);
						#endif
						int passindex;
						RenderPass *rpass;
						for (rpass = (RenderPass *)rl->passes.first, passindex = 0; rpass; rpass = rpass->next, ++passindex)
							if (STREQ(rpass->name, bnodeSocket->identifier))
								break;
						if (rpass) {
							imageuser->pass = passindex;
							switch (rpass->channels) {
								case 1:
									operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VALUE);
									break;
								/* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
								/* XXX any way to detect actual vector images? */
								case 3:
									operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_VECTOR);
									break;
								case 4:
									operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR);
									break;
								default:
									/* dummy operation is added below */
									break;
							}

							if (index == 0 && operation) {
								addPreviewOperation(graph, context, operation->getOutputSocket());
							}
						}
					}

					/* incase we can't load the layer */
					if (operation == NULL) {
						convertToOperations_invalid_index(graph, index);
					}
				}
			}