Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/LibJXR/jxrgluelib/JXRMeta.c view on Meta::CPAN
U16 cDir;
U16 i;
U16 ofsEXIFIFDEntry = 0;
U16 ofsGPSInfoIFDEntry = 0;
U16 ofsInteroperabilityIFDEntry = 0;
U32 ofsEXIFIFD = 0;
U32 ofsGPSInfoIFD = 0;
U32 ofsInteroperabilityIFD = 0;
U32 ofsdstnextdata;
U32 ofsdst = *pofsdst;
U32 ofssrcdir;
U32 ofsdstdir;
U32 ofsnextifd;
Call(getbfwe(pbsrc, cbsrc, ofssrc, &cDir, endian));
Call(setbfw(pbdst, cbdst, ofsdst, cDir));
ofsnextifd = ofsdst + sizeof(U16) + SizeofIFDEntry * cDir;
ofsdstnextdata = ofsnextifd + sizeof(U32);
ofssrcdir = ofssrc + sizeof(U16);
ofsdstdir = ofsdst + sizeof(U16);
for ( i = 0; i < cDir; i++ )
{
U16 tag;
U16 type;
U32 count;
U32 value;
U32 size;
Call(getbfwe(pbsrc, cbsrc, ofssrcdir, &tag, endian));
Call(setbfw(pbdst, cbdst, ofsdstdir, tag));
Call(getbfwe(pbsrc, cbsrc, ofssrcdir + sizeof(U16), &type, endian));
Call(setbfw(pbdst, cbdst, ofsdstdir + sizeof(U16), type));
Call(getbfdwe(pbsrc, cbsrc, ofssrcdir + 2 * sizeof(U16), &count, endian));
Call(setbfdw(pbdst, cbdst, ofsdstdir + 2 * sizeof(U16), count));
Call(getbfdwe(pbsrc, cbsrc, ofssrcdir + 2 * sizeof(U16) + sizeof(U32), &value, endian));
Call(setbfdw(pbdst, cbdst, ofsdstdir + 2 * sizeof(U16) + sizeof(U32), 0));
FailIf(type == 0 || type >= sizeof(IFDEntryTypeSizes) / sizeof(IFDEntryTypeSizes[0]), WMP_errFail);
if ( tag == WMP_tagEXIFMetadata )
{
ofsEXIFIFDEntry = (U16) ofsdstdir;
ofsEXIFIFD = value;
}
else if ( tag == WMP_tagGPSInfoMetadata )
{
ofsGPSInfoIFDEntry = (U16) ofsdstdir;
ofsGPSInfoIFD = value;
}
else if ( tag == WMP_tagInteroperabilityIFD )
{
ofsInteroperabilityIFDEntry = (U16) ofsdstdir;
ofsInteroperabilityIFD = value;
}
else
{
U32 ofsdstdata = ofsdstdir + 2 * sizeof(U16) + sizeof(U32);
U32 ofssrcdata = ofssrcdir + 2 * sizeof(U16) + sizeof(U32);
size = count * IFDEntryTypeSizes[type];
if ( size > 4 )
{
ofssrcdata = value;
Call(setbfdw(pbdst, cbdst, ofsdstdata, ofsdstnextdata));
ofsdstdata = ofsdstnextdata;
ofsdstnextdata += size;
}
FailIf(ofssrcdata + size > cbsrc || ofsdstdata + size > cbdst, WMP_errBufferOverflow);
if ( size == count || endian == WMP_INTEL_ENDIAN )
// size == count means 8-bit data means endian doesn't matter
memcpy(&pbdst[ofsdstdata], &pbsrc[ofssrcdata], size);
else
{ // big endian source and endian matters
U32 j;
switch ( IFDEntryTypeSizes[type] )
{
case 2:
for ( j = 0; j < count; j++ )
{
U16 w;
getbfwbig(pbsrc, cbsrc, ofssrcdata + j * sizeof(U16), &w);
setbfw(pbdst, cbdst, ofsdstdata + j * sizeof(U16), w);
}
break;
case 8:
if ( type == WMP_typDOUBLE )
{
for ( j = 0; j < count; j++ )
{
U32 dwlo;
U32 dwhi;
getbfdwbig(pbsrc, cbsrc, ofssrcdata + j * 8, &dwhi);
getbfdwbig(pbsrc, cbsrc, ofssrcdata + j * 8 + sizeof(U32), &dwlo);
setbfdw(pbdst, cbdst, ofsdstdata + j * 8, dwlo);
setbfdw(pbdst, cbdst, ofsdstdata + j * 8 + sizeof(U32), dwhi);
}
break;
}
count *= 2;
// RATIONAL's fall through to be handled as LONG's
case 4:
for ( j = 0; j < count; j++ )
{
U32 dw;
getbfdwbig(pbsrc, cbsrc, ofssrcdata + j * sizeof(U32), &dw);
setbfdw(pbdst, cbdst, ofsdstdata + j * sizeof(U32), dw);
}
break;
}
}
}
ofssrcdir += SizeofIFDEntry;
ofsdstdir += SizeofIFDEntry;
}
Call(setbfdw(pbdst, cbdst, ofsnextifd, 0)); // no nextIFD
if ( ofsEXIFIFDEntry != 0 )
{
ofsdstnextdata += ( ofsdstnextdata & 1 );
Call(setbfdw(pbdst, cbdst, ofsEXIFIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata));
Call(BufferCopyIFD(pbsrc, cbsrc, ofsEXIFIFD, endian, pbdst, cbdst, &ofsdstnextdata));
}
if ( ofsGPSInfoIFDEntry != 0 )
{
ofsdstnextdata += ( ofsdstnextdata & 1 );
Call(setbfdw(pbdst, cbdst, ofsGPSInfoIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata));
Call(BufferCopyIFD(pbsrc, cbsrc, ofsGPSInfoIFD, endian, pbdst, cbdst, &ofsdstnextdata));
}
if ( ofsInteroperabilityIFDEntry != 0 )
{
ofsdstnextdata += ( ofsdstnextdata & 1 );
Call(setbfdw(pbdst, cbdst, ofsInteroperabilityIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata));
Call(BufferCopyIFD(pbsrc, cbsrc, ofsInteroperabilityIFD, endian, pbdst, cbdst, &ofsdstnextdata));
}
*pofsdst = ofsdstnextdata;
Cleanup:
return err;
}
// src IFD copied to dst IFD with any nested IFD's
// src IFD is little endian, arbitrary data arrangement
// dst IFD is little endian, data arranged in tag order
// dst IFD tags are ordered the same as src IFD so src IFD tags must be in order
ERR StreamCopyIFD(struct WMPStream* pWS, U32 ofssrc, U8* pbdst, U32 cbdst, U32* pofsdst)
{
ERR err = WMP_errSuccess;
size_t offCurPos = 0;
Bool GetPosOK = FALSE;
U16 cDir;
U16 i;
U16 ofsEXIFIFDEntry = 0;
U16 ofsGPSInfoIFDEntry = 0;
U16 ofsInteroperabilityIFDEntry = 0;
U32 ofsEXIFIFD = 0;
U32 ofsGPSInfoIFD = 0;
U32 ofsInteroperabilityIFD = 0;
U32 ofsdstnextdata;
U32 ofsdst = *pofsdst;
U32 ofssrcdir;
U32 ofsdstdir;
U32 ofsnextifd;
Call(pWS->GetPos(pWS, &offCurPos));
GetPosOK = TRUE;
Call(GetUShort(pWS, ofssrc, &cDir));
Call(setbfw(pbdst, cbdst, ofsdst, cDir));
ofsnextifd = ofsdst + sizeof(U16) + SizeofIFDEntry * cDir;
ofsdstnextdata = ofsnextifd + sizeof(U32);
ofssrcdir = ofssrc + sizeof(U16);
ofsdstdir = ofsdst + sizeof(U16);
for ( i = 0; i < cDir; i++ )
{
U16 tag;
U16 type;
U32 count;
U32 value;
U32 size;
Call(GetUShort(pWS, ofssrcdir, &tag));
Call(setbfw(pbdst, cbdst, ofsdstdir, tag));
Call(GetUShort(pWS, ofssrcdir + sizeof(U16), &type));
Call(setbfw(pbdst, cbdst, ofsdstdir + sizeof(U16), type));
Call(GetULong(pWS, ofssrcdir + 2 * sizeof(U16), &count));
Call(setbfdw(pbdst, cbdst, ofsdstdir + 2 * sizeof(U16), count));
Call(GetULong(pWS, ofssrcdir + 2 * sizeof(U16) + sizeof(U32), &value));
Call(setbfdw(pbdst, cbdst, ofsdstdir + 2 * sizeof(U16) + sizeof(U32), 0));
FailIf(type == 0 || type >= sizeof(IFDEntryTypeSizes) / sizeof(IFDEntryTypeSizes[0]), WMP_errFail);
if ( tag == WMP_tagEXIFMetadata )
{
ofsEXIFIFDEntry = (U16) ofsdstdir;
ofsEXIFIFD = value;
}
else if ( tag == WMP_tagGPSInfoMetadata )
{
ofsGPSInfoIFDEntry = (U16) ofsdstdir;
ofsGPSInfoIFD = value;
}
else if ( tag == WMP_tagInteroperabilityIFD )
{
ofsInteroperabilityIFDEntry = (U16) ofsdstdir;
ofsInteroperabilityIFD = value;
}
else
{
U32 ofsdstdata = ofsdstdir + 2 * sizeof(U16) + sizeof(U32);
U32 ofssrcdata = ofssrcdir + 2 * sizeof(U16) + sizeof(U32);
size = count * IFDEntryTypeSizes[type];
if ( size > 4 )
{
ofssrcdata = value;
Call(setbfdw(pbdst, cbdst, ofsdstdata, ofsdstnextdata));
ofsdstdata = ofsdstnextdata;
ofsdstnextdata += size;
}
FailIf(ofsdstdata + size > cbdst, WMP_errBufferOverflow);
Call(pWS->SetPos(pWS, ofssrcdata));
Call(pWS->Read(pWS, &pbdst[ofsdstdata], size));
}
ofssrcdir += SizeofIFDEntry;
ofsdstdir += SizeofIFDEntry;
}
Call(setbfdw(pbdst, cbdst, ofsnextifd, 0)); // no nextIFD
if ( ofsEXIFIFDEntry != 0 )
{
ofsdstnextdata += ( ofsdstnextdata & 1 );
Call(setbfdw(pbdst, cbdst, ofsEXIFIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata));
Call(StreamCopyIFD(pWS, ofsEXIFIFD, pbdst, cbdst, &ofsdstnextdata));
}
if ( ofsGPSInfoIFDEntry != 0 )
{
ofsdstnextdata += ( ofsdstnextdata & 1 );
Call(setbfdw(pbdst, cbdst, ofsGPSInfoIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata));
Call(StreamCopyIFD(pWS, ofsGPSInfoIFD, pbdst, cbdst, &ofsdstnextdata));
}
if ( ofsInteroperabilityIFDEntry != 0 )
{
ofsdstnextdata += ( ofsdstnextdata & 1 );
Call(setbfdw(pbdst, cbdst, ofsInteroperabilityIFDEntry + 2 * sizeof(U16) + sizeof(U32), ofsdstnextdata));
Call(StreamCopyIFD(pWS, ofsInteroperabilityIFD, pbdst, cbdst, &ofsdstnextdata));
}
*pofsdst = ofsdstnextdata;
Cleanup:
if ( GetPosOK )
Call(pWS->SetPos(pWS, offCurPos));
return err;
}
//================================================================
ERR GetUShort(
__in_ecount(1) struct WMPStream* pWS,
size_t offPos,
__out_ecount(1) U16* puValue)
{
ERR err = WMP_errSuccess;
U8 cVal;
Call(pWS->SetPos(pWS, offPos));
Call(pWS->Read(pWS, &cVal, sizeof(cVal)));
puValue[0] = (U16) cVal;
Call(pWS->Read(pWS, &cVal, sizeof(cVal)));
puValue[0] += ((U16) cVal) << 8;
Cleanup:
return err;
}
ERR PutUShort(
__in_ecount(1) struct WMPStream* pWS,
size_t offPos,
U16 uValue)
{
ERR err = WMP_errSuccess;
( run in 0.838 second using v1.01-cache-2.11-cpan-754626df90b )