Copy link to clipboard
Copied
Hi,
Just from the start I'm going to mention that I don't (or barely) know what I'm doing –so I apologize in advance for anything extra silly about my question. My code is cobbled together from attempts to understand the SDK's sample code, a slight memory of one quarter of C++ instruction decades past, questions lobbed at chatGPT (it's good at seeming confident even when wrong :), google searching to get clarity on mistakes, searches within this forum, etc.
I'm trying to grab all the pixels from my PF_EffectWorld and copy them into a 2D array suitable for use with an algorithm that requires a table of pixels in that form. I've been banging against this a while, looking at the documentation for the PF_PixelPtr accessor macros and at the GLator sample code, and I think I've hit a wall and am not sure how to get past it. I am not finding a lot of information in the sample code or on the net for the use of PF_GET_PIXEL_DATA8 and PF_GET_PIXEL_DATA16, but hopefully someone here understands this well-enough to easily spot my rookie mistake. Here's the relevant section of code that's stumping me:
static PF_Err
MySimplifiedPixelCopyingFunction (
PF_InData *in_data,
PF_OutData *out_data,
PF_ParamDef *params[] )
{
PF_ParamDef checkout;
PF_Err err = PF_Err_NONE;
PF_EffectWorld *input_worldP = NULL;
ERR(PF_CHECKOUT_PARAM( in_data,
renderFileBridge_LAYER,
in_data->current_time,
in_data->time_step,
in_data->time_scale,
&checkout));
if (!checkout.u.ld.data) { // no input image
} else {
input_worldP = &checkout.u.ld;
// Acquire a pointer to the pixel data
PF_Pixel16 *pixel_dataP = NULL;
PF_Pixel8 *pixel_data8P = NULL;
if (input_worldP->world_flags & PF_WorldFlag_DEEP) {
// Pixel data is in 16-bit format
err = PF_GET_PIXEL_DATA16(input_worldP, NULL, &pixel_dataP);
} else {
// Pixel data is in 8-bit format
err = PF_GET_PIXEL_DATA8(input_worldP, NULL, &pixel_data8P);
}
if (err != PF_Err_NONE) {
// Handle the error
}
// Create an array to store the pixel values
int num_pixels = input_worldP->width * input_worldP->height;
PF_Pixel16 *pixel_values = new PF_Pixel16[num_pixels];
// Copy the pixel values from the pixel data pointer to the array
if (input_worldP->world_flags & PF_WorldFlag_DEEP) {
// Copy the pixel values from the pixel data pointer to the array
for (int i = 0; i < num_pixels; i++) {
pixel_values[i] = pixel_dataP[i];
}
} else {
// Copy the pixel values from the pixel data pointer to the array
for (int i = 0; i < num_pixels; i++) {
pixel_values[i].red = pixel_data8P[i].red << 8;
By this point in execution, I've run into the error "Thread 1: EXC_BAD_ACCESS (code=1, address=0x1)" on that last line, because as the debugger's variable view helpfully indicates, "pixel_data8P = (PF_Pixel8 *) NULL".
Rewinding the tape a little, after PF_CHECKOUT_PARAM, the PF_ParamDef named "checkout" does indeed contain a PF_EffectWorld at checkout.u.ld. It contains data, and its width and height variable values match the width and height of the image in the layer that was checked out.
My test for the pixel depth of input_worldP is either working, or failing, but either way because the image's pixels are 8-bit it is in this case resulting in the use of the right accessor macro, PF_GET_PIXEL_DATA8.
Unfortunately this is where everything clearly goes off the rails.
err = PF_GET_PIXEL_DATA8(input_worldP, NULL, &pixel_data8P);
The debugger's variable view helpfully tells me that after this line, "pixel_data8P = (PF_Pixel8 *) NULL". I think I've fed PF_GET_PIXEL_DATA8 a PF_EffectWorld full of image data, and I think I'm calling PF_GET_PIXEL_DATA8 correctly according to the documentation, but clearly I've made a blunder somewhere.
Because pixel_data8P is NULL, all further operations on it are doomed. Hopefully I'm doing something super-obviously-wrong and super-easily-fixable.
Thanks for any help, insights, jokes, etc.
Copy link to clipboard
Copied
I think I'm using the right accessor macro for this particular set of pixel data as I think it's in 8-bit format, but just in case I added a line so that right after it runs PF_GET_PIXEL_DATA8, it does a PF_GET_PIXEL_DATA16. e.g.
err = PF_GET_PIXEL_DATA8(input_worldP, NULL, &pixel_data8P);
err = PF_GET_PIXEL_DATA16(input_worldP, NULL, &pixel_dataP);
But after those lines executed this time, both pixel_data8P and pixel_dataP are NULL. So that wasn't the issue.
It's gotta be that I'm feeding the macro the wrong input, but I haven't yet figured out what's wrong about it.
I do see some examples in this forum in which people are using memcpy for this sort of thing, but I'm hoping to figure out how to do it using these accessors.
Copy link to clipboard
Copied
Tried compiling and debugging GLator, with checkpoints marked a line before all the calls to PF_GET_PIXEL_DATA (8 and 16). I thought maybe I'd be able to see whether, in the one piece of sample code that uses the accessors, they were feeding them different inputs and outputs than I was. But unfortunately the debugger never stopped on those checkpoints and the plugin crashes at:
delete fragmentShaderAssemblyP;
To clarify -- I'm not really interested in getting GLator to run properly. I was just hoping to learn from it.
Copy link to clipboard
Copied
I mis-spoke earlier -- PF_GET_PIXEL_DATA8 will return a pointer to a pixel, not return the pixel's data. So I'll still need to copy it myself. But the problem remains that I think pixel_data8P should nut be NULL after the call to the accessor but should point to a pixel. So my thought is that my input_worldP isn't valid, but I have not been able to yet figure out why.
Copy link to clipboard
Copied
So I just noticed the following caveat in the documentation for the Interaction callback function PF_CHECKOUT_PARAM, "Do not check out layer parameters during UI event handling."
I am of course running PF_CHECKOUT_PARAM in a function that is triggered by a UI event - the user pressing a button. Even though I'm doing that, the function does seem to result in a bunch of data in the checkout variable, including a PF_EffectWorld or PF_LayerDef in checkout.u.ld. Hmm...
Copy link to clipboard
Copied
Hi,
I remember that you can only check out layer parameter in PF_Cmd_RENDER or PF_Cmd_SMART_PRERENDER, not sure enough.
And then, once you've got a PF_LayerDef* named layer, you can access it's pixels by the follow function:
PF_Pixel8* getPixel8P(const PF_LayerDef* layer, int x, int y) {
if (layer) {
if (x > -1 && y > -1 && x < layer->width && y < layer->height) {
// each row of the input layer contains layer->rowbytes bytes, not layer->width * sizeof(PF_Pixel8)
// because each end of a row has some padding, which idk what that means
return (PF_Pixel8*)((char*)layer->data + (y * layer->rowbytes) + (x * sizeof(PF_Pixel8)));
}
}
else return nullptr;
}