175 lines
5.8 KiB
Diff
175 lines
5.8 KiB
Diff
From 969907789e687469a9ee5c003656f761e77fe15d Mon Sep 17 00:00:00 2001
|
|
From: Peter Hillman <peterh@wetafx.co.nz>
|
|
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 <CharPtrIO> (writePtr, *(const float *) readPtr);
|
|
+ union bytesOrFloat tmp;
|
|
+ tmp.b = * reinterpret_cast<const FBytes *>( readPtr );
|
|
+ Xdr::write <CharPtrIO> (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<class T> 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<activechans)
|
|
{
|
|
|
|
@@ -419,6 +456,7 @@ setupBuffer (const Header& hdr, // header to grab datawindow from
|
|
1,1,0.4));
|
|
|
|
char * pre_offset = offset-&readingBuffer[0]+&preReadBuffer[0];
|
|
+
|
|
prereadbuf.insert (passivechannels[i-activechans],
|
|
Slice (type,
|
|
pre_offset,
|