UE4C++获取鼠标像素点颜色与获取图片像素点
- 注:代码很简单,此章直接附上,代码也给大家注释好了
- .h头文件
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "PixelBlueprintFunctionLibrary.generated.h"
UCLASS()
class GAME_SANDBOX_API UPixelBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
//获取鼠标对应像素点
UFUNCTION(BlueprintCallable)
static FColor GetMousePointColor(float x = 0.f, float y = 0.f, bool InUsingMosuePoint = true);
//获取图片像素点Texture2D
UFUNCTION(BlueprintCallable, category = "GetPicPixel")
static TArray<FColor> GetPictureRGBPixel(class UTexture2D* RGBTexture, int& OutX, int& OutY);
};
- .CPP文件
// Fill out your copyright notice in the Description page of Project Settings.
#include "PixelBlueprintFunctionLibrary.h"
#include "Windows/MinimalWindowsApi.h"
#include "Misc/FeedbackContextMarkup.h"
#include "Windows/COMPointer.h"
#include "Windows/AllowWindowsPlatformTypes.h"
#include <commdlg.h>
#include <shlobj.h>
#include "Engine/Texture2D.h"
#include "Engine/Texture.h"
FColor UPixelBlueprintFunctionLibrary::GetMousePointColor(float x, float y, bool InUsingMosuePoint)
{
//获取当前HDC,不懂HDC的,可以看看C++窗口编程
//::前面啥也不写,代表全局函数的调用
HDC tempHDC = ::GetDC(NULL);
//创建临时变量存储鼠标值
POINT pt1;
//判断是否用鼠标位置获取,不是的话,则用输入值获取,是的话用鼠标位置获取像素
if (InUsingMosuePoint)
GetCursorPos(&pt1);
else { pt1.x = x; pt1.y = y; }
//获取当前像素点颜色值
COLORREF clr = ::GetPixel(tempHDC, pt1.x, pt1.y);
//获取颜色的R G B值
int R = GetRValue(clr);
int G = GetGValue(clr);
int B = GetBValue(clr);
//释放当前HDC
::ReleaseDC(NULL, tempHDC);
//创建应当返回的颜色值
FColor Color;
Color.R = R;
Color.G = G;
Color.B = B;
Color.A = 255;
return Color;
}
TArray<FColor> UPixelBlueprintFunctionLibrary::GetPictureRGBPixel(UTexture2D* RGBTexture, int& OutX, int& OutY)
{
//存放每个点的颜色值TArray64<uint8>类型,用于临时转换
TArray64<uint8>PicData;
//存放每个点的颜色值
TArray<FColor>PixelColorArray;
//读取图片的像素值R,G,G,A
RGBTexture->Source.GetMipData(PicData, 0);
//每四个数(RGBA)组成一个颜色数组
FColor* Colors = (FColor*)PicData.GetData();
//获取图片的长宽
OutX = RGBTexture->Source.GetSizeX();
OutY = RGBTexture->Source.GetSizeY();
//将颜色转换成FColor类型存放在PixelColorArray中
for (int y = 0; y < OutY; y++)
{
for (int x = 0; x < OutX; x++)
{
FColor PixelColor = Colors[y * OutX + x];
PixelColorArray.Add(PixelColor);
}
}
return PixelColorArray;
}
由于Source在打包时候不可用,因此此处采用另一种方式进行获取图片
TArray<FColor> UPixelBlueprintFunctionLibrary::GetPictureRGBPixel(UTexture2D* RGBTexture, int& OutX, int& OutY)
{
TArray<FColor>PixelColorArray;//存放每个点的颜色值
const FColor* Colors = static_cast<FColor*>(RGBTexture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_ONLY));
OutX = RGBTexture->GetSizeX();
OutY = RGBTexture->GetSizeY();
for (int y = 0; y < OutY; y++)
{
for (int x = 0; x < OutX; x++)
{
FColor PixelColor = Colors[y * OutX + x];
PixelColorArray.Add(PixelColor);
}
}
return PixelColorArray;
}
static_cast<FColor*>(RGBTexture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_ONLY));可能返回值为空,因此,此时我们需要设置RGBTexture的一些参数,然后读取数据之后再改回来
TArray<FColor> UPixelBlueprintFunctionLibrary::GetPictureRGBPixel(UTexture2D* RGBTexture, int& OutX, int& OutY)
{
if (!IsValid(RGBTexture)|| !RGBTexture->PlatformData)
return TArray<FColor>();
TArray<FColor>ColorArray;
TextureCompressionSettings OldCompressionSettings = RGBTexture->CompressionSettings;
TextureMipGenSettings OldMipGenSettings = RGBTexture->MipGenSettings;
bool OldSRGB = RGBTexture->SRGB;
RGBTexture->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
RGBTexture->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
RGBTexture->SRGB = false;
RGBTexture->UpdateResource();
const FColor* Colors = static_cast<const FColor*>(RGBTexture->PlatformData->Mips[0].BulkData.LockReadOnly());
OutX = RGBTexture->GetSizeX();
OutY = RGBTexture->GetSizeY();
for (int y = 0; y < OutY; y++)
{
for (int x = 0; x < OutX; x++)
{
FColor PixelColor = Colors[y * OutX + x];
ColorArray.Add(PixelColor);
}
}
RGBTexture->PlatformData->Mips[0].BulkData.Unlock();
RGBTexture->CompressionSettings = OldCompressionSettings;
RGBTexture->MipGenSettings = OldMipGenSettings;
RGBTexture->SRGB = OldSRGB;
RGBTexture->UpdateResource();
return ColorArray;
}
至此,我们发现打包依旧有数据是在编辑器模式下的,因此,我们手动将代码中所用到的图片设置成对应模式就行,我们发现打包出错的地方在默认的Texture2d里面是对的,因此将它注释掉就行
TArray<FColor> UPixelBlueprintFunctionLibrary::GetPictureRGBPixel(UTexture2D* RGBTexture, int& OutX, int& OutY)
{
if (!IsValid(RGBTexture)|| !RGBTexture->PlatformData)
return TArray<FColor>();
TArray<FColor> ColorArray;
//TextureCompressionSettings OldCompressionSettings = RGBTexture->CompressionSettings;
//TextureMipGenSettings OldMipGenSettings = RGBTexture->MipGenSettings;
bool OldSRGB = RGBTexture->SRGB;
RGBTexture->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
//RGBTexture->MipGenSettings = TextureMipGenSettings::TMGS_NoMipmaps;
RGBTexture->SRGB = false;
RGBTexture->UpdateResource();
const FColor* Colors = static_cast<const FColor*>(RGBTexture->PlatformData->Mips[0].BulkData.LockReadOnly());
OutX = RGBTexture->GetSizeX();
OutY = RGBTexture->GetSizeY();
for (int y = 0; y < OutY; y++)
{
for (int x = 0; x < OutX; x++)
{
FColor PixelColor = Colors[y * OutX + x];
ColorArray.Add(PixelColor);
}
}
RGBTexture->PlatformData->Mips[0].BulkData.Unlock();
//RGBTexture->CompressionSettings = OldCompressionSettings;
//RGBTexture->MipGenSettings = OldMipGenSettings;
RGBTexture->SRGB = OldSRGB;
RGBTexture->UpdateResource();
return ColorArray;
}