UTexture2D* PrivateLeapImage::validImagePointer(UTexture2D* Pointer, int32 PWidth, int32 PHeight, EPixelFormat Format, bool GammaCorrectionUsed)
{
	//Make sure we're valid
	if (!Self->IsValid) 
	{
		UE_LOG(LeapPluginLog, Error, TEXT("Warning! Invalid Image."));
		return nullptr;
	}
	//Instantiate the texture if needed
	if (Pointer == nullptr)
	{
		if (PWidth == 0 || PHeight == 0)
		{
			//Spit out only valid errors, two size 0 textures will be attempted per pointer,
			//unable to filter the messages out without this (or a pointer to Leap Controller, but this uses less resources).
			if (IgnoreTwoInvalidSizesDone)
			{
				UE_LOG(LeapPluginLog, Error, TEXT("Warning! Leap Image SDK access is denied, please enable image support from the Leap Controller before events emit (e.g. at BeginPlay)."));
			}
			else
			{
				InvalidSizesReported++;

				if (InvalidSizesReported == 2)
				{
					IgnoreTwoInvalidSizesDone = true;
				}
			}
			
			return nullptr;
		}
		UE_LOG(LeapPluginLog, Log, TEXT("Created Leap Image Texture Sized: %d, %d, format %d"), PWidth, PHeight, (int)Format);
		Pointer = UTexture2D::CreateTransient(PWidth, PHeight, Format); //PF_B8G8R8A8
		Pointer->UpdateResource();
		UpdateTextureRegion = FUpdateTextureRegion2D(0, 0, 0, 0, PWidth, PHeight);
		
		//change texture settings
		if (!GammaCorrectionUsed)
		{
			Pointer->SRGB = 0;
		}
		
		//keep it around?
	}

	//If the size changed, recreate the image (NB: GC may release the platform data in which case we need to recreate it (since 4.7)
	if (!UtilityPointerIsValid(Pointer->PlatformData) ||
		Pointer->PlatformData->SizeX != PWidth ||
		Pointer->PlatformData->SizeY != PHeight)
	{
		UE_LOG(LeapPluginLog, Log, TEXT("ReCreated Leap Image Texture Sized: %d, %d. Old Size: %d, %d"), PWidth, PHeight, Pointer->PlatformData->SizeX, Pointer->PlatformData->SizeY);
		Pointer = UTexture2D::CreateTransient(PWidth, PHeight, Format);
		Pointer->UpdateResource();
		UpdateTextureRegion = FUpdateTextureRegion2D(0, 0, 0, 0, PWidth, PHeight);
	}
	return Pointer;
}
Example #2
0
// Called when the game starts
void UOpenCVComponent::BeginPlay()
{
	Super::BeginPlay();

	// ...
	
	if (nullptr != Texture2D)
	{
		if (cv::ocl::haveOpenCL())
		{
			cv::ocl::Context Context;
			if (Context.create(cv::ocl::Device::TYPE_GPU))
			{
				cv::ocl::Device(Context.device(0));

				//!< Simple OpenCL Code
				const cv::String Code = "__kernel void main(__global uchar* dst, const int pitch, const int offset, const int rows, const int cols) {"
					"const int2 uv = { get_global_id(0), get_global_id(1) };"
					"const int2 dim = { rows, cols };"
					"const int2 grid = { 16, 16 };"
					"const int2 repeate = dim / grid;"
					"const int index = mad24(uv.y, pitch, uv.x + offset);"
					"dst[index] = ((uv.x % grid.x) * repeate.x >> 1) + ((uv.y % grid.y) * repeate.y >> 1);"
					"}";
				const cv::ocl::ProgramSource ProgramSource(Code);

				//!< Build OpenCL
				const cv::String Buildopt = "";
				cv::String Errmsg;
				const auto Program = Context.getProg(ProgramSource, Buildopt, Errmsg);

				const auto Width = Texture2D->GetSizeX();
				const auto Height = Texture2D->GetSizeY();
				//!< Result destination
				const auto Mat = cv::UMat(Height, Width, CV_8U, cv::ACCESS_WRITE, cv::USAGE_ALLOCATE_DEVICE_MEMORY);

				//!< OpenCL function name and arguments
				cv::ocl::Kernel Kernel("main", Program);
				Kernel.args(cv::ocl::KernelArg::ReadWrite(Mat));

				//!< Execute OpenCL
				size_t Threads[] = { Width, Height, 1 };
				if (!Kernel.run(ARRAY_COUNT(Threads), Threads, nullptr, true))
				{
					GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("OpenCL run failed"));
				}

				const auto Result = Mat.getMat(cv::ACCESS_READ);

				//!< Add some OpenCV operations
				cv::putText(Mat, cv::String("Hello OpenCV"), cv::Point(0, 255), CV_FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 127, 127));
				cv::rectangle(Mat, cv::Point(64 + 5, 64 + 5), cv::Point(96 + 5, 96 + 5), cv::Scalar(0, 255, 0));
				cv::circle(Mat, cv::Point(128, 128), 32, cv::Scalar(0, 0, 255));

				//cv::imshow("Result", Result);

				//!< cv::Mat -> TArray<FColor>
				Colors.Empty();
				Colors.Reserve(Width * Height);
				for (auto i = 0; i < Height; ++i)
				{
					for (auto j = 0; j < Width; ++j)
					{
						const auto Value = Result.data[i * Width + j];
						Colors.Add(FColor(Value, Value, Value));
					}
				}

				//!< Update UTexture2D
				ENQUEUE_RENDER_COMMAND(UpdateTexture2D)(
					[Tex = Texture2D, this](FRHICommandListImmediate& RHICmdList)
					{
						const auto TexWidth = Tex->GetSizeX();
						const auto TexHeight = Tex->GetSizeY();
						const auto Pitch = GPixelFormats[Tex->GetPixelFormat()].BlockBytes * TexWidth;
						RHIUpdateTexture2D(Tex->Resource->TextureRHI->GetTexture2D(), 0, FUpdateTextureRegion2D(0, 0, 0, 0, TexWidth, TexHeight), Pitch, reinterpret_cast<const uint8*>(&Colors[0]));
					});
			}
		}
	}
}