[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