[Lazarus] Copy buffer of PWord to TMemoryStream

Leonardo M. Ramé l.rame at griensu.com
Sun Mar 24 19:57:29 CET 2013


On 2013-03-24 19:46:09 +0100, Sven Barth wrote:
> On 24.03.2013 19:30, Leonardo M. Ramé wrote:
> >On 2013-03-24 19:21:49 +0100, Sven Barth wrote:
> >>On 24.03.2013 19:19, Joao Morais wrote:
> >>>2013/3/24 Leonardo M. Ramé <l.rame at griensu.com>:
> >>>>Hi, I'm copying a buffer of PWord to a TMemoryStream using this code:
> >>>>
> >>>>lTmpBuff := lBuffer;
> >>>>I := 0;
> >>>>while I < lBufSize do
> >>>>begin
> >>>>   lStream.Write(lTmpBuff^, SizeOf(PWord));
> >>>>   inc(lTmpBuff, 1);
> >>>>   inc(I, 1);
> >>>
> >>>What about:
> >>>
> >>>    inc(lTmpBuff, SizeOf(PWord));
> >>>    inc(I, SizeOf(PWord));
> >>
> >>If lTmpBuff is declared as PWord then "Inc" already increases in
> >>multiplies of "SizeOf(PWord)".
> >>Regarding lBufSize it will be important to know whether the C code
> >>returns the size in elements or in byte.
> >>
> >
> >Heres the interface of the library:
> >
> >myfunction(void * &buffer, unsigned long& bufSize)
> >{
> >     bufsize = interdata->getcount() * sizeof(uint16);
> 
> So bufsize contains the amount of Bytes.
> 
> >     buffer = new uint16[bufSize];
> 
> Ehm... shouldn't this be "new uint16[interdata->getcount()]"?
> Because currently if your "getcount()" function returns e.g. 42 you
> will allocate an array containing 84 elements...
> 
> >     // interdata is an object containing image data
> >     memcpy((void *)buffer, interdata->getData(), interdata->getCount());
> >}
> 
> So assuming that lBuffer is passed as the buffer argument and
> lBufSize as the bufSize one then your old code is wrong.
> 
> It should look like this:
> 
> === code begin ===
> 
> I := 0;
> while I < lBufSize do begin
>   lStream.Write(lTmpBuffer^, SizeOf(Word)); // do you really have
> "SizeOf(PWord)" there?
>   Inc(lTmpBuff); // move pointer by one element
>   Inc(I, SizeOf(Word)); // we need to increase I by the element size
> end;
> 
> === code end ===
> 
> An alternative would be:
> 
> === code begin ===
> 
> for I := 0 to lBufSize div SizeOf(Word) do
>   lStream.Write(lBuffer[I], SizeOf(Word));
> 
> === code end ===
> 
> And to finally write all data at once:
> 
> === code begin ===
> 
> lStream.Write(lBuffer^, lBufSize); // as lBufSize is the byte size,
> this is correct without further multiplication
> 
> === code end ===
> 
> Now if your C function is written correctly, all three should give
> you the same result.
> 

Thanks Sven, I modified the C function as this:

bufSize = interdata->getCount(); // <- returns number of pixels
buffer = new Uint16[bufSize];
memcpy((void *)buffer, interdata->getData(), interdata->getCount());

Here's the getCount() documentation:
http://support.dcmtk.org/docs/classDiPixel.html#15bbe5e57b15ea67bbc9541752ccccce

Hence, my confusion is because I thought getCount was number of bytes,
but it is number of pixels :)

After changing the C function, now I can do this:

lStream.Write(lTmpBuff^, SizeOf(PWord));
inc(lTmpBuff);
inc(I, 2); // it also works with inc(I, 1) but not using inc(I,
sizeof(Word));

-- 
Leonardo M. Ramé
http://leonardorame.blogspot.com




More information about the Lazarus mailing list