Is it possible to write a python script to load an asset Thumbnail image into a new Texture2d asset that I can use at runtime in my UI?
Hello, did you find a solution?
I think if you want to export the thumbnail and import it as a texture assets in python or bp, you need do a little c++ work: export a Blueprint callable function which export the thumbnail as a image, then import it as texture2D assets with python script or bp.
The source of the export function from JoeRadak:
Exporting Thumbnails to PNGs - Pipeline & Plugins / Editor Scripting - Unreal Engine Forums
/** .h
* Save the Thumbnail of assets to disc.
*
* @param ObjectPath The specified path of asset
* @param OutputPath Thumbnail output path
*/
UFUNCTION(BlueprintCallable, meta = (Keywords = "Python Editor"), Category = "PythonEditor")
static void SaveThumbnail(FString ObjectPath, FString OutputPath);
and the implementation in .cpp
/** .cpp */
void UPythonBPLib::SaveThumbnail(FString ObjectPath, FString OutputPath)
{
FAssetRegistryModule& AssetRegistryModule = FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
FAssetData AssetData = AssetRegistryModule.Get().GetAssetByObjectPath(*ObjectPath);
UObject* MyObject = AssetData.GetAsset();
if (MyObject)
{
FObjectThumbnail* ObjectThumbnail = ThumbnailTools::GenerateThumbnailForObjectToSaveToDisk(MyObject);
if (ObjectThumbnail)
{
IImageWrapperModule& ImageWrapperModule = FModuleManager::Get().LoadModuleChecked<IImageWrapperModule>(TEXT("ImageWrapper"));
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
ImageWrapper->SetRaw(ObjectThumbnail->GetUncompressedImageData().GetData(), ObjectThumbnail->GetUncompressedImageData().Num(), ObjectThumbnail->GetImageWidth(), ObjectThumbnail->GetImageHeight(), ERGBFormat::BGRA, 8);
if (ImageWrapper)
{
const TArray64<uint8>& CompressedByteArray = ImageWrapper->GetCompressed();
FFileHelper::SaveArrayToFile(CompressedByteArray, *OutputPath);
}
}
}
}
Then, we can export the thumbnail with python like this:
def on_button_ExportThumbnail_click(self):
print('on_button_ExportThumbnail_click')
folder = "/Game/YourAssetsFolder"
asset_paths = unreal.EditorAssetLibrary.list_assets(folder, recursive=True)
target_folder = r"D:\YouArtSourceFolder"
for i, asset_path in enumerate(asset_paths):
asset = unreal.load_asset(asset_path)
if type(asset) is not unreal.StaticMesh: # change the types
continue
name_with_folder = asset_path[len(folder)+1:].split(".")[0]
target_file_path = os.path.join(target_folder, f"{name_with_folder.replace('/', '_')}.png")
unreal.PythonBPLib.save_thumbnail(asset_path, target_file_path)
After that, import the exported thumbnail as texture
import_task = unreal.AssetImportTask()
# set the import_task.filename, destination_path, options and so on
import_task.filename = texture_path
# ...
unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([import_task])
Hope, that helps.
For posterity, here’s a way to generate a UTexture2D asset from an Asset’s thumbnail, using only C++. Thanks to @chpsemail and IsaraTech from UE4 - Save a procedurally generated texture as a new asset - Isara Tech.
UTexture2D* SaveThumbnailAsTexture2d(UObject* obj, FString TextureName, FString GamePath) {
int32 pathSeparatorIdx;
if (TextureName.FindChar('/', pathSeparatorIdx)) {
// TextureName should not have any path separators in it
return nullptr;
}
FObjectThumbnail* thumb = ThumbnailTools::GenerateThumbnailForObjectToSaveToDisk(obj);
if (!thumb) {
return nullptr;
}
FString PackageName = GamePath;
if (!PackageName.EndsWith("/")) {
PackageName += "/";
}
PackageName += TextureName;
UPackage* Package = CreatePackage(*PackageName);
Package->FullyLoad();
UTexture2D* NewTexture = NewObject<UTexture2D>(Package, *TextureName, RF_Public | RF_Standalone | RF_MarkAsRootSet);
NewTexture->AddToRoot();
FTexturePlatformData* platformData = new FTexturePlatformData();
platformData->SizeX = thumb->GetImageWidth();
platformData->SizeY = thumb->GetImageHeight();
//platformData->NumSlices = 1;
platformData->PixelFormat = EPixelFormat::PF_B8G8R8A8;
NewTexture->SetPlatformData(platformData);
FTexture2DMipMap* Mip = new FTexture2DMipMap();
platformData->Mips.Add(Mip);
Mip->SizeX = thumb->GetImageWidth();
Mip->SizeY = thumb->GetImageHeight();
Mip->BulkData.Lock(LOCK_READ_WRITE);
uint8* TextureData = (uint8*)Mip->BulkData.Realloc(thumb->GetUncompressedImageData().Num() * 4);
FMemory::Memcpy(TextureData, thumb->GetUncompressedImageData().GetData(), thumb->GetUncompressedImageData().Num());
Mip->BulkData.Unlock();
NewTexture->Source.Init(thumb->GetImageWidth(), thumb->GetImageHeight(), 1, 1, ETextureSourceFormat::TSF_BGRA8, thumb->GetUncompressedImageData().GetData());
NewTexture->UpdateResource();
Package->MarkPackageDirty();
FAssetRegistryModule::AssetCreated(NewTexture);
FSavePackageArgs SaveArgs;
SaveArgs.TopLevelFlags = EObjectFlags::RF_Public | EObjectFlags::RF_Standalone;
SaveArgs.SaveFlags = SAVE_NoError;
SaveArgs.bForceByteSwapping = true;
FString PackageFileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension());
bool bSaved = UPackage::SavePackage(Package, NewTexture, *PackageFileName, SaveArgs);
return NewTexture;
}
UTexture2D* SaveThumbnailAsTexture2d(UObject* obj) {
FString GamePath = obj->GetPathName();
FString AssetName;
int32 pathEnd;
if (GamePath.FindLastChar('/', pathEnd)) {
++pathEnd;
AssetName = GamePath;
AssetName.RightChopInline(pathEnd);
int32 extensionIdx;
if (AssetName.FindChar('.', extensionIdx)) {
AssetName.LeftInline(extensionIdx);
}
AssetName += "_Thumbnail";
GamePath.LeftInline(pathEnd);
}
else {
AssetName = "Thumbnail";
}
return SaveThumbnailAsTexture2d(obj, AssetName, GamePath);
}
ue 5.0 not work
It works for me in UE 5.3.
Is there a way to save this with a transparent background instead of the checkered background?