Update3: I’ve posted a tutorial on taking screen shots and have posted my entire code for my own custom screen shot save system that is BP friendly, and you can choose base filename and save directory from the BP.
[Complete Game Feature Code: My Custom Screen Shot Save System][1]
Update2: I have it almost fully working! I got rid of that black border, but I am still having to pass through the entire color buffer and manually set the alpha to 255
surely there is a setting somewhere in viewport client or some function I can run first
so that the alpha gets set to 255 during ReadPixels
so I dont have to pass through the huge buffer a second time to set the alpha to 255 ?
Update: I achieved major progress by manually changing the alpha channel to 255, I probably should not have to do this, but it mostly works, clearly I have some format non-understanding here, what’s the fast way to adjust all this?
I am manually going through color buffer (a 2nd pass from its creation, double processing time), and setting alpha to 255
//set alpha back to 255
int32 total2 = viewportSize.X * viewportSize.Y;
for (int32 i = 0; i < total2; i++ )
{
VictoryPC->PNGScreenShot_ColorBuffer[i].A = 255;
}
Result:
Dear Friends at Epic,
Hi there!
I hope you can spare a moment or 2 to look for any errors in my logic, or maybe I am missing some fancy parameters somewhere I dont know about.
Thanks for taking the time to read this!
My Goal:
-I am trying to use readpixels to get a portion of the viewport client window
-put this info in a color buffer
-compress this color buffer to png format, binary array
-write out the binary array to file
When I output my color buffer pre-compression it looks quite reasonable for what is on the screen, as you will see in pics below
But the png is quite clearly meaningless garbage that does not even reflect the contents of the color buffer
the only oddities is the occasional completely zeroed FColor pixel in the color buffer and the alpha channel being 0
Here’s the area of screen I am screen shotting:
Here’s the color buffer output to my console
Again there’s a few odd 0s and the fact that alpha is always 0,
but it certainly does not look like the output I get in the PNG file at all: (well actually it does because alpha is getting set to 0 some reason)
Here’s my code, I left out the logic of how I choose a filename, and I am only getting the portion of the screen in rectangle (0,0,25,25)
//viewport client
void UVictoryGameViewport::VictoryTakeScreenShot()
{
if (!VictoryPC) return;
if (!Viewport) return;
//if (!VictoryColorBuffer) return;
//~~~~~~~~~~~~~~~~~~~~~~
//get viewport size
FVector2D viewportSize;
GetViewportSize(viewportSize);
//output viewport dimensions
FString text = "x= ";
text += FString::FromInt(viewportSize.X);
text += "y= ";
text += FString::FromInt(viewportSize.Y);
VictoryPC->Optimize(text);
//~~~ Invalid View Port Size ~~~
if (viewportSize.X <= 0 || viewportSize.Y <= 0) return;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//entire buffer invalidated if exceed viewport size
viewportSize.X=25;
viewportSize.Y=25;
//Adjusted Image Size
VictoryPC->PNG_Width = viewportSize.X;
VictoryPC->PNG_Height = viewportSize.Y;
//~~~~~~~~~~~~~~~~~~~~~~~~
//~~~ Empty Color Buffer ~~~
VictoryPC->PNGScreenShot_ColorBuffer.Empty();
//~~~~~~~~~~~~~~~~~~~~~~~~
//
//Get Screen Shot!
if (!Viewport->ReadPixels(
VictoryPC->PNGScreenShot_ColorBuffer,
FReadSurfaceDataFlags(),
FIntRect(0,0,viewportSize.X,viewportSize.Y)
)){
VictoryPC->Optimize("Failed to ReadPixels");
return;
//~~~~~~~~~~~~~~~~~~~~~~~~~
}
//pixels read
VictoryPC->OptInt("Success!!!!", VictoryPC->PNGScreenShot_ColorBuffer.Num() );
//Start timer
VictoryPC->StartScreenShotSaveToDiskTimer();
//print image to console
int32 total = viewportSize.X * viewportSize.Y;
for (int32 i = 0; i < total; i++ )
{
VictoryPC->Optimize(VictoryPC->PNGScreenShot_ColorBuffer[i].ToString());
}
}
Here is my color buffer → PNG binary array → to disk code
//saving to disk in controller class (VictoryPC)
void saveColorBufferAsPNG
{
Optimize("SaveScreenshotToDisk ran!");
//~~~ Temp Data ~~~
TArray PNG_Compressed_ImageData;
//~~~~~~~~~~~~~~~~
// Compress to PNG
//~~~~~~~~~~~~~~~~
FImageUtils::CompressImageArray(
PNG_Width,
PNG_Height,
PNGScreenShot_ColorBuffer,
PNG_Compressed_ImageData
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Save binary array PNG image file to disk!
FFileHelper::SaveArrayToFile(
PNG_Compressed_ImageData,
*PNGFileName
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~ Empty PNG Buffer ~~~
PNG_Compressed_ImageData.Empty();
//~~~~~~~~~~~~~~~~~~~~~~~~
//~~~ Empty Color Buffer ~~~
PNGScreenShot_ColorBuffer.Empty();
//~~~~~~~~~~~~~~~~~~~~~~~~
}
I am hoping I am missing some sort of parameter setting or dont understand the format of what Readpixels takes in vs what comes back out?
Why is the Alpha 0 in color buffer?
I dont know much about the internal working of readpixels or what format the PNG compressing function is expecting,
any ideas?
Thanks!
Rama