PDA

View Full Version : ImageBuffer.ImageDataPtr() does not point to type 'byte' - please advise!



sapbucket
December 12, 2004, 04:35:37
Hello,

I am having fun using Perl with ActiveX and ran into a snag trying to access image data using ImageDataPtr(). The documentation states that the type 'long' returned by ImageDataPtr() is the memory address of the first 'byte' in the image. However, using the C function Peek(), which returns the contents of a memory location, I am getting something that is at least a 32-bit value (4 bytes long). How should I resolve this? What is the structure of the data block stored in memory? I was expecting to find a single byte value stored at the memory location.

I actually tried examining the memory location returned by ImageDataPtr in several ways.


#---------------------------------
# This section is used by all following sections.
$imaging->LoadDeviceStateFromFile("c:\\ocr\\device_state.xml",1);
$imaging->MemorySnapImage();
$imaging->MemorySaveImage("c:\\ocr\\test1.bmp");
$buffer = $imaging->ImageBuffers->Item(1);
#---------------------------------


#-------------------------------------------
# This section tries to use ImageDataPtr() to access image data.
# Hopefully it will not interfere with saving the image.
# start section
$ptrData=$buffer->ImageDataPtr();
print "ptrData: $ptrData\n";

$value = peek($ptrData);
print "value: $value\n";
$hexp = sprintf("%X", $value);
print "hex value: $hexp\n";
# end section
#-------------------------------------------

You can see in the above code I pass the memory address to peek() and it returns the contents. Lets look at the output of the print statements:


C:\OCR\Dev>perl testActiveX.pl
ptrData: 136052768
value: 6712064
hex value: 666B00
640, 480
elapsed time is 1.300655 s

C:\OCR\Dev>perl testActiveX.pl
ptrData: 136052768
value: 6843648
hex value: 686D00
640, 480
elapsed time is 1.284834 s

C:\OCR\Dev>perl testActiveX.pl
ptrData: 136052768
value: 6514432
hex value: 636700
640, 480
elapsed time is 1.252727 s

C:\OCR\Dev>perl testActiveX.pl
ptrData: 136052768
value: 291859985
hex value: 11656E11
640, 480
elapsed time is 1.269461 s

C:\OCR\Dev>perl testActiveX.pl
ptrData: 136052768
value: 6778368
hex value: 676E00
640, 480
elapsed time is 1.269305 s

C:\OCR\Dev>perl testActiveX.pl
ptrData: 136052768
value: 6842880
hex value: 686A00
640, 480
elapsed time is 1.26939 s

note: The elapsed time is long because we have to load the device state before snapping an image. Each image captured by the firewire camera is identical: the camera is pointed at a static image and captures at 640x480 resolution in RGB.

Examining the output shows what I would call garbage return values from the memory location specified by ImageDataPtr(). I can imagine all types of possible layouts for the image data. The third time I ran the testscript it returned a much larger value at the address then I expected. The rest of the time the values were relatively similar. However, I am speculating about the structure of the image data in memory: the documentation does not clearly describe what to expect when using the ImageDataPtr().

see: http://www.imagingcontrol.com/ic/docs/html/activex/prop_descImageBuffer_ImageDataPtr.htm


Another method I used was plain old C. This test function uses C's built in functionality for handling pointers. However, keep in mind that I am using Inline C within a PERL script, because of this only the following fundamental C data types available:




# basic C types
int T_IV
unsigned T_UV
unsigned int T_UV
long T_IV
unsigned long T_UV
short T_IV
unsigned short T_UV
char T_CHAR
unsigned char T_U_CHAR
char * T_PV
unsigned char * T_PV
const char * T_PV
caddr_t T_PV
wchar_t * T_PV
wchar_t T_IV
# bool_t is defined in <rpc/rpc.h>
bool_t T_IV
size_t T_UV
ssize_t T_IV
time_t T_NV
unsigned long * T_OPAQUEPTR
char ** T_PACKEDARRAY
void * T_PTR
Time_t * T_PV
SV * T_SV
SVREF T_SVREF
AV * T_AVREF
HV * T_HVREF
CV * T_CVREF

IV T_IV
UV T_UV
NV T_NV
I32 T_IV
I16 T_IV
I8 T_IV
STRLEN T_UV
U32 T_U_LONG
U16 T_U_SHORT
U8 T_UV
Result T_U_CHAR
Boolean T_BOOL
float T_FLOAT
double T_DOUBLE
SysRet T_SYSRET
SysRetLong T_SYSRET
FILE * T_STDIO
PerlIO * T_INOUT
FileHandle T_PTROBJ
InputStream T_IN
InOutStream T_INOUT
OutputStream T_OUT
bool T_BOOL


Stefan suggested using ImageDataPtr() in the following manner:


byte *pointer = ImageDataPtr();
&pointer = 255 - &pointer; // Change the content of the byte
pointer++; // get the next byte


Which won't work with Inline C because type 'byte *' is not in the typemap def listing above. So what I am looking for is C code that performs the same as what Stefan suggested, but using another data type. This is where I get a little confused. It should be fairly obvious to a skilled C programmer about what to do to solve this 'type' problem. Any suggestions?

This is what I tried (this is executed appended to the script above, I'm not going to repeat it):


use Inline C;
muck($ptrData);
__END__
__C__
void muck(SV* sv_name) {
printf("Hello string representation: %s!\n", SvPV(sv_name, PL_na));
printf("Hello hexadecimal representation: %x!\n", sv_name);
byte* ptr = sv_name;

}


Which doesn't work at all:


C:\OCR\Dev>perl testActiveX.pl

Microsoft (R) Program Maintenance Utility Version 1.50
Copyright (c) Microsoft Corp 1988-94. All rights reserved.

C:\Perl\bin\perl.exe C:\Perl\lib\ExtUtils/xsubpp -typemap C:\Perl\lib\ExtUtils\typemap testActiveX_pl_4dd
2.xs > testActiveX_pl_4dd2.xsc && C:\Perl\bin\perl.exe -MExtUtils::Command -e mv testActiveX_pl_4dd2.xsc testActive
X_pl_4dd2.c
cl -c -IC:/OCR/Dev -nologo -Gf -W3 -MD -Zi -DNDEBUG -O1 -DWIN32 -D_CONSOLE -DNO_STRICT -DHAVE_DES_FCRYPT
-DNO_HASH_SEED -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -DPERL_MSVCRT_READFIX -MD -Zi -DNDEBUG -O1
-DVERSION=\"0.00\" -DXS_VERSION=\"0.00\" "-IC:\Perl\lib\CORE" testActiveX_pl_4dd2.c
testActiveX_pl_4dd2.c
testActiveX_pl_4dd2.xs(8) : error C2065: 'byte' : undeclared identifier
testActiveX_pl_4dd2.xs(8) : error C2065: 'ptr' : undeclared identifier
testActiveX_pl_4dd2.xs(8) : warning C4047: '=' : 'int' differs in levels of indirection from 'SV *'
testActiveX_pl_4dd2.xs(8) : error C2106: '=' : left operand must be l-value
NMAKE : fatal error U1077: 'C:\WINDOWS\system32\cmd.exe' : return code '0x2'
Stop.

A problem was encountered while attempting to compile and install your Inline
C code. The command that failed was:
nmake > out.make 2>&1

The build directory was:
C:\OCR\Dev\_Inline\build\testActiveX_pl_4dd2

To debug the problem, cd to the build directory, and inspect the output files.

at testActiveX.pl line 0
INIT failed--call queue aborted.


I know this is a long post - but I am stuck and willing to try anything. Any useful suggestions would be most appreciated.

Stefan Geissler
December 13, 2004, 07:59:13
Hello,

the data type "byte" should be one byte and unsigned. The C equivalent for handling one byte is "char". Also should "byte" be defined as "unsigned char". I know, "byte" is no standard C-Type, it was my fault to use this data type.

I do not know, how the function "peek()" is implemented in your C /PERL libraries, but is assume, it is implemented as something like
int peek(long lAdress)
Therefore a 32 bit value is returned. This value contains the 4 bytes at the adress "lAdress".

To get the content of a byte at a specified adress, use:


unsigned char *pointer = (unsigned char*)ImageDataPtr();
printf( "Adress %u, content %c\n",pointer, *pointer);


The first line performes a type cast from long (return value of ImageDataPtr) to unsigned char*.

sapbucket
December 13, 2004, 08:26:32
Stefan,


print "ptrData prior to muck() is $ptrData\n";
muck("$ptrData");
use Inline C;
__END__
__C__
void muck(SV* sv_name) {
long lp;
unsigned char *pointer;
printf("Hello string %s!\n", SvPV(sv_name, PL_na));
lp = atol(SvPV(sv_name, PL_na));
printf("Hello long: %ld!\n", lp);
*pointer = (unsigned char*)lp;
printf("Adress %u, content %c\n",pointer, *pointer);
}

prints out:



C:\OCR\Dev>perl testActiveX.pl
ptrData: 140574752
value using peek(): 342517269
hex value using peek(): 146A6615
640, 480
elapsed time is 2.02099 s
ptrData prior to muck() is 140574752
Hello string 140574752!
Hello long: 140574752!
Adress 27800872, content



are %u and %c correct?

Stefan Geissler
December 13, 2004, 09:52:09
Can you send me your complete script, so i can test it?

sapbucket
December 13, 2004, 10:28:41
sent it to your email