From 969907789e687469a9ee5c003656f761e77fe15d Mon Sep 17 00:00:00 2001 From: Peter Hillman Date: Fri, 26 Jul 2019 18:25:44 +1200 Subject: [PATCH] Fix #452: read floats with 32 bit alignment --- IlmImf/ImfMisc.cpp | 18 +++++++- .../testOptimizedInterleavePatterns.cpp | 46 +++++++++++++++++-- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/IlmImf/ImfMisc.cpp b/IlmImf/ImfMisc.cpp index 4622c4170..277554320 100644 --- a/IlmImf/ImfMisc.cpp +++ b/IlmImf/ImfMisc.cpp @@ -1381,6 +1381,20 @@ skipChannel (const char *& readPtr, } +namespace +{ +// +// helper function to realign floats +// for architectures that require 32-bit alignment for float reading +// + +struct FBytes { uint8_t b[4]; }; +union bytesOrFloat { + FBytes b; + float f; +} ; +} + void convertInPlace (char *& writePtr, const char *& readPtr, @@ -1411,7 +1425,9 @@ convertInPlace (char *& writePtr, for (size_t j = 0; j < numPixels; ++j) { - Xdr::write (writePtr, *(const float *) readPtr); + union bytesOrFloat tmp; + tmp.b = * reinterpret_cast( readPtr ); + Xdr::write (writePtr, tmp.f); readPtr += sizeof(float); } break; diff --git a/IlmImfTest/testOptimizedInterleavePatterns.cpp b/IlmImfTest/testOptimizedInterleavePatterns.cpp index 1ed74d2e7..f24c09cab 100644 --- a/IlmImfTest/testOptimizedInterleavePatterns.cpp +++ b/IlmImfTest/testOptimizedInterleavePatterns.cpp @@ -171,6 +171,14 @@ Schema Schemes[] = {NULL,NULL,NULL,0,NULL,NULL} }; +template inline T alignToFour(T input) +{ + while( (intptr_t(input)&3) !=0 ) + { + input++; + } + return input; +} bool compare(const FrameBuffer& asRead, @@ -192,6 +200,7 @@ bool compare(const FrameBuffer& asRead, switch (i.slice().type) { case IMF::FLOAT : + assert(alignToFour(ptr)==ptr); readHalf = half(*(float*) ptr); break; case IMF::HALF : @@ -213,6 +222,7 @@ bool compare(const FrameBuffer& asRead, switch (p.slice().type) { case IMF::FLOAT : + assert(alignToFour(ptr)==ptr); writtenHalf = half(*(float*) ptr); break; case IMF::HALF : @@ -250,6 +260,8 @@ bool compare(const FrameBuffer& asRead, return true; } + + // // allocate readingBuffer or writingBuffer, setting up a framebuffer to point to the right thing // @@ -272,7 +284,7 @@ setupBuffer (const Header& hdr, // header to grab datawindow from // int activechans = 0; int bytes_per_pixel =0; - + bool has32BitValue = false; while (channels[activechans]!=NULL) { if (pt==NULL) @@ -284,7 +296,15 @@ setupBuffer (const Header& hdr, // header to grab datawindow from switch (pt[activechans]) { case IMF::HALF : bytes_per_pixel+=2;break; - case IMF::FLOAT : case IMF::UINT : bytes_per_pixel+=4;break; + case IMF::FLOAT : case IMF::UINT : + // some architectures (e.g arm7 cannot write 32 bit values + // to addresses which aren't aligned to 32 bit addresses) + // so bump to next multiple of four + bytes_per_pixel = alignToFour(bytes_per_pixel); + bytes_per_pixel+=4; + has32BitValue = true; + break; + default : cout << "Unexpected PixelType?\n"; exit(1); @@ -306,7 +326,11 @@ setupBuffer (const Header& hdr, // header to grab datawindow from switch (pt[passivechans+activechans]) { case IMF::HALF : bytes_per_pixel+=2;break; - case IMF::FLOAT : case IMF::UINT : bytes_per_pixel+=4;break; + case IMF::FLOAT : case IMF::UINT : + bytes_per_pixel = alignToFour(bytes_per_pixel); + bytes_per_pixel+=4; + has32BitValue = true; + break; default : cout << "Unexpected PixelType?\n"; exit(1); @@ -314,6 +338,11 @@ setupBuffer (const Header& hdr, // header to grab datawindow from } passivechans++; } + + if(has32BitValue) + { + bytes_per_pixel = alignToFour(bytes_per_pixel); + } int chans = activechans+passivechans; @@ -350,7 +379,9 @@ setupBuffer (const Header& hdr, // header to grab datawindow from } else { + write_ptr = alignToFour(write_ptr); *(float*)write_ptr = float(v); + write_ptr+=4; } chan++; @@ -395,7 +426,13 @@ setupBuffer (const Header& hdr, // header to grab datawindow from offset = (writing ? &writingBuffer[0] : &readingBuffer[0]) + bank*bytes_per_bank_row - first_pixel_index; } - + + + if(type==FLOAT || type==UINT) + { + offset = alignToFour(offset); + } + if (i