array of pointers to float

  • Thread starter Thread starter Marc Pelletier
  • Start date Start date
M

Marc Pelletier

Hello,


I am having trouble implementing the following callback:
CNCSError CECWCompressor::WriteReadLine(UINT32 nNextLine, void
**ppInputArray)

where ppInputArray is a 3 by x array. The length of x is not known at
compile time.

I can't seem to dereference ppInputArray in a way that the compiler is
happy with. This is what I would like to do, but I get a 'Cannot convert
from void* to float[]' error.

float Red[] = ppInputArray[0];
float Green[] = ppInputArray[1];
float Blue[] = ppInputArray[2];
for ( UINT32 x = 0; x < pInfo->nSizeX; x++ ) {
rgb = image.GetPixel( x, nNextLine );
Red[x] = (float)GetRValue( rgb );
Green[x] = (float)GetGValue( rgb );
Blue[x] = (float)GetBValue( rgb );
}

Every other permutation I can think of also cannot be converted for one
reason or another. How can I fill this structure?

Thanks for any help.

Marc Pelletier
 
I can't seem to dereference ppInputArray in a way that the compiler is
happy with. This is what I would like to do, but I get a 'Cannot convert
from void* to float[]' error.

float Red[] = ppInputArray[0];
float Green[] = ppInputArray[1];
float Blue[] = ppInputArray[2];
for ( UINT32 x = 0; x < pInfo->nSizeX; x++ ) {
rgb = image.GetPixel( x, nNextLine );
Red[x] = (float)GetRValue( rgb );
Green[x] = (float)GetGValue( rgb );
Blue[x] = (float)GetBValue( rgb );
}

Sorry, I should have mentioned that the compiler error is actually on the
first line above

float Red[] = ppInputArray[0];

cheers

Marc
 
Marc Pelletier said:
I can't seem to dereference ppInputArray in a way that the compiler is
happy with. This is what I would like to do, but I get a 'Cannot convert
from void* to float[]' error.

float Red[] = ppInputArray[0];
float Green[] = ppInputArray[1];
float Blue[] = ppInputArray[2];
for ( UINT32 x = 0; x < pInfo->nSizeX; x++ ) {
rgb = image.GetPixel( x, nNextLine );
Red[x] = (float)GetRValue( rgb );
Green[x] = (float)GetGValue( rgb );
Blue[x] = (float)GetBValue( rgb );
}

Sorry, I should have mentioned that the compiler error is actually on the
first line above

float Red[] = ppInputArray[0];

Hard to say anything if you don't even provide
the definition of 'ppInputArray'.

Schobi

--
(e-mail address removed) is never read
I'm Schobi at suespammers dot org

"Coming back to where you started is not the same as never leaving"
Terry Pratchett
 
Marc said:
Hello,


I am having trouble implementing the following callback:
CNCSError CECWCompressor::WriteReadLine(UINT32 nNextLine, void
**ppInputArray)

where ppInputArray is a 3 by x array. The length of x is not known at
compile time.

I can't seem to dereference ppInputArray in a way that the compiler is
happy with. This is what I would like to do, but I get a 'Cannot
convert from void* to float[]' error.

float Red[] = ppInputArray[0];
float Green[] = ppInputArray[1];
float Blue[] = ppInputArray[2];
for ( UINT32 x = 0; x < pInfo->nSizeX; x++ ) {
rgb = image.GetPixel( x, nNextLine );
Red[x] = (float)GetRValue( rgb );
Green[x] = (float)GetGValue( rgb );
Blue[x] = (float)GetBValue( rgb );
}

<code>
float** ppf = static_cast<float**>(ppInputArray);

float* Red = ppf[0];
float* Green = ppf[1];
float* Blue = ppf[2];

for (...)
</code>

Note that this is an odd organization for an array of triples. In memory,
this will have all of the Red values, followed by all of the Blue values,
follwed by all of the Green values.

It seems unlikely to me that that's what you really wanted, since more
typically the RGB values of a particular triple will be adjacent in memory.
In that case, you would want something like:

<code>
float* pf = static_cast<float*>(*ppInputArray);
for (...)
pf[0] = (float)GetRValue(...);
pf[1] = (float)GetGValue(...);
pf[2] = (float)GetBValue(...);
pf += 3;
</code>

If you have any control over the defintion of this callback (i.e. control
over the caller of the code), I'd strongly recommend changing the signature
to avoid passing void** parameters. Instead, this callback really ought to
be defined something like:

struct rgb_t
{
float r;
float g;
float b;
};

CNCSError CECWCompressor::WriteReadLine(UINT32 nNextLine, rgb_t*
pInputArray);

But if you don't control the caller, or this is but one overload of a
general purpose mechanism (which I suspect it might be), then you're
probably stuck with the signature you've got.

One other comment: passing the input array as a double-indirect pointer
often implies that the called routine is expected to allocate the memory to
be filled and assign the pointer to the newly allocated memory through the
given pointer-to-pointer.

<code>
float* pf = (float*)malloc(3*sizeof(float)*???);

for (...)
pf[0] = (float)GetRValue(...);
pf[1] = (float)GetGValue(...);
pf[2] = (float)GetBValue(...);
pf += 3;

*ppInputArray = pf;

</code>

If you're not allocating the array in the callback, there's really no point
in passing a pointer to pointer parameter.

-cd
 
Carl,

Thanks for your comments. I've replied below.

<code>
float** ppf = static_cast<float**>(ppInputArray);

float* Red = ppf[0];
float* Green = ppf[1];
float* Blue = ppf[2];

for (...)
</code>

This gives me an "error C2440: 'static_cast': cannot convert from
'void**' to 'float**'". I'm new to c++ and am surprised at how hard it is
to get the compiler to swallow this. What is the purpose of void pointers
if the compiler won't allow you to cast them? Is there a project option I
can use?

Note that this is an odd organization for an array of triples. In
memory, this will have all of the Red values, followed by all of the
Blue values, follwed by all of the Green values.

It seems unlikely to me that that's what you really wanted, since more
typically the RGB values of a particular triple will be adjacent in
memory. In that case, you would want something like:

This format (and library) is inherited from satellite imagery which can
have many bands. Its known as BIL or binary interleaved (I think). Its
from the ERMapper ECW/JPeg200 sdk.

...snip..
One other comment: passing the input array as a double-indirect
pointer often implies that the called routine is expected to allocate
the memory to be filled and assign the pointer to the newly allocated
memory through the given pointer-to-pointer.

<code>
float* pf = (float*)malloc(3*sizeof(float)*???);

for (...)
pf[0] = (float)GetRValue(...);
pf[1] = (float)GetGValue(...);
pf[2] = (float)GetBValue(...);
pf += 3;

*ppInputArray = pf;

</code>

If you're not allocating the array in the callback, there's really no
point in passing a pointer to pointer parameter.

Well this is interesting. I dont think this is the case as there are some
working examples for the C interface that don't allocate memory. In those
examples it is dereferenced like this:
float *pRed = ppInputArray[0];

but that won't compile in c++ either.

cheers

Marc
 
Hard to say anything if you don't even provide
the definition of 'ppInputArray'.

Sorry, I could have been clearer. ppInputArray is a 3 (in my case) element
array of pointers to arrays of float. It represents storage for one line of
multiband raster data.

cheers

Marc
 
This gives me an "error C2440: 'static_cast': cannot convert from
'void**' to 'float**'". I'm new to c++ and am surprised at how hard it
is to get the compiler to swallow this. What is the purpose of void
pointers if the compiler won't allow you to cast them? Is there a
project option I can use?

I should probably also mention I am using visual studio .net 7.1.3088


cheers

Marc
 
Marc Pelletier said:
Sorry, I could have been clearer. ppInputArray is a 3 (in my case) element
array of pointers to arrays of float. It represents storage for one line of
multiband raster data.

That's an explanation of what you think
'ppInputArray' is, not the definition.
(Your answer to Carl's reply indicates
that it is not what you write above.)
Show the exact definition.

Schobi

--
(e-mail address removed) is never read
I'm Schobi at suespammers dot org

"Coming back to where you started is not the same as never leaving"
Terry Pratchett
 
That's an explanation of what you think
'ppInputArray' is, not the definition.
(Your answer to Carl's reply indicates
that it is not what you write above.)
Show the exact definition.

Well... I'm not trying to be vague. The header file defines it as:
/**
* Read input line for compression.
* In progressive (pull) mode scanlines will be sequentially
* read by the overloaded WriteReadLine() method
* @param nNextLine Next input line to read
* @param ppInputArray Array of buffer pointers, one buffer for
each band
* @return CNCSError Write status code
*/
virtual CNCSError WriteReadLine(UINT32 nNextLine, void **ppInputArray);


My understanding of what it is comes from reading the examples. The
clearest use of this variable is in a C example that looks like this:
/*
** Read callback function - called once for each input line
*/
static BOOLEAN ReadCallback(NCSEcwCompressClient *pClient,
UINT32 nNextLine,
IEEE4 **ppInputArray)
{
ReadInfo *pRI = (ReadInfo*)pClient->pClientData;
UINT32 nBand;

for(nBand = 0; nBand < pClient->nInputBands; nBand++) {
UINT32 nCell;
IEEE4 *pLine = ppInputArray[nBand];

if(pClient->nInputBands == 1) {
/* 1 band, do a grid pattern */
for(nCell = 0; nCell < pClient->nInOutSizeX; nCell++) {
if(((nCell / 30) % 2 == nBand) || ((nNextLine / 30) % 2 ==
nBand)) {
pLine[nCell] = 1000.0f;
} else {
pLine[nCell] = 0.0f;
}
}
} else {
for(nCell = 0; nCell < pClient->nInOutSizeX; nCell++) {
if(((nCell / 30) % pClient->nInputBands == nBand) &&
((nNextLine / 30) % pClient->nInputBands == nBand)) {
pLine[nCell] = 1000.0f;
} else {
pLine[nCell] = 0.0f;
}
}
}
}
return(TRUE); /* would return FALSE on an error */





Hope this helps...

Marc
 
float** ppf = static_cast said:
This gives me an "error C2440: 'static_cast': cannot convert from
'void**' to 'float**'".

Try reinterpret_cast rather than static_cast.

Dave
 
Try reinterpret_cast rather than static_cast.

That works!

So does this
float *Red = (float *)(ppInputArray[0]);
float *Green = (float *)(ppInputArray[1]);
float *Blue = (float *)(ppInputArray[2]);

Thanks everyone.

cheers

Marc
 
Back
Top