On 15/09/2016 at 09:34, xxxxxxxx wrote:
User Information:
Cinema 4D Version:
Platform: Windows ;
Language(s) : C++ ;
---------
Hi,
I'm trying to get the rgba colors from a render done with a .c4d file using Melange.
AFAIK. This is done by using the rgba_data in the UpdateImage() callback. But it's returning jibberish values for me.
What am I doing wrong?
How do I get the correct rgba color values for each pixel in the rendered image?
Here is a very simple (but complete) example that I've built for testing purposes:
//This is a very simple example that uses only one thread to render a .c4d file
//NOTE: the file paths to my c4d.exe server and .c4d file are hard coded to make the code simpler
//In the .c4d file being rendered. There is no image output path set in the render settings. The rendered image is created in memory only
//I'm just rendering a cube with a dark colored material on it as a test case
//I'm trying to get the rgba color values from the rendered image that's in memory. So I can write a copy of it in my Qt application
//The renderconnection example does this somehow with win32 code using the WinUpdateImage() callback function
//I cannot figure out how this is being done. How do I get the rgba colors from this callback?
//The rgba_data values I get from it are jibberish!!
#include <windows.h>
#include <iostream>
using namespace std;
#include "c4d_file.h"
#include "default_alien_overloads.h"
#include <c4d_renderconnection.h> //Needed for rendering
using namespace melange;
enum
{
APPID = 1234567 //Temporary ID ONLY!!!
};
void GetWriterInfo(Int32 &id, String &appname)
{
id = APPID;
appname = "My Melange Example";
}
void MyUpdateImage(void *userdata, Int32 xpos, Int32 ypos, Int32 xcnt, ColorResolution bpp, UChar *rgba_data)
{
//How do I use this thing?!!!
//cout << xpos << "," << ypos <<endl;
//if (bpp == 4) cout << "float" << endl;
//else cout << "Int" << endl;
//These values do not make any sense
//They produce values like 124,99,210 for a scene rendering a black object?!!!
int r = static_cast<int>(rgba_data[0]);
int g = static_cast<int>(rgba_data[1]);
int b = static_cast<int>(rgba_data[2]);
cout << r << "," << g << "," << b <<endl;
}
//Thread used to manage the rendering
class RenderThread : public IpCommunicationThread
{
public:
int counter = 0; //frame counter...Is there another way to get the current frame being rendered in the .c4d file?
virtual void Main()
{
//The file to render
String renderedFile = "C:\\Users\\user\\Desktop\\myfile.c4d";
BaseDocument *c4dDoc = LoadDocument(renderedFile, SCENEFILTER_OBJECTS);
RenderData *rdata = c4dDoc->GetFirstRenderData();
//Get the render dimensions from the render settings
GeData sizeX;
rdata->GetParameter(RDATA_XRES, sizeX);
Int32 sx = sizeX.GetInt32();
GeData sizeY;
rdata->GetParameter(RDATA_YRES, sizeY);
Int32 sy = sizeY.GetInt32();
//Get the last frame to render from the render settings
Float32 fps = c4dDoc->GetFps();
GeData d;
rdata->GetParameter(RDATA_FRAMETO, d);
BaseTime to = d.GetTime();
Int32 frameTo = to.GetFrame(fps);
Int32 rendererror = RENDERERROR_OK, renderphase = PROGRESSTYPE_BEFORERENDERING;
Float percent_done = 0.0;
Bool running = true;
// open communication to the server
// (local host + port used when starting, UID of your application, initial timeout, connection timeout)
Open("127.0.0.1:1234", APPID, 10, 60);
// send the scene to the renderer
// (pass path of CINEMA 4D file or an optional BaseDocument reference as second parameter)
Bool file = SendScenefile(renderedFile);
if (!file) { cout << "No .c4d file found!" << endl; return; }
//Start rendering
//(X resolution, Y resolution, bitmap color mode, allow saving the render image, high priority)
StartRender(sx, sy, COLORRESOLUTION_FLOAT, false, false);
//Get the render image and progress while rendering
while (!TestBreak() && running)
{
//printf("\n running");
//printf(this->GetThreadName());
//Calls your callback "UpdateImage" to get the image update
GetImageUpdate(MyUpdateImage, nullptr, &running);
//Check for error and how much rendering is done
GetRenderStatus(&running, &rendererror, &percent_done, &renderphase);
//The percent rendering done for each frame in the scene file
//if (renderphase == PROGRESSTYPE_DURINGRENDERING)
//cout << "Work Done: " << percent_done*100.0 << endl;
//Count the number of frames being rendered (better way to do this?)
if (renderphase == PROGRESSTYPE_AFTERRENDERING)
counter++;
//cout << counter << endl;
if (counter > frameTo) running = false; //Stop the thread when done rendering all the frames in the scene
}
//Free the session on the server and close the thread
FreeSession();
Close(true);
//Free Melange network and thread
GeIpCloseNetwork();
GeEndThreads();
cout << "Finished" << endl;
}
};
RenderThread *rThread = nullptr;
int main(int argc, Char* argv[])
{
BaseDocument *doc = BaseDocument::Alloc();
GeInitThreads();
GeIpInitNetwork();
Bool server = StartRenderServer("C:\\Program Files\\MAXON\\CINEMA 4D R13\\CINEMA 4D 64 Bit.exe", 1234);
if (!server) { cout << "No Server" << endl; return 0; }
rThread = NewObj(RenderThread);
rThread->Start(true);
//Note: The OS will reclaim the memory from rThread when the console closes
// So there is no need to create another thread just to free it
// Free it yourself only if you are creating an app that stays open and runs for a while (to prevent memory leaks)
system("pause");
return 0;
}
-ScottA