issue 1957: Added support for reading embedded content (textures) in ASCII FBX. In ASCII FBX embedded content is encoded in Base64 and is surrounded by double quotation marks. The decoding functions are based on those used in the glTF importer.
parent
a43ac5b3fd
commit
b3177a2a9a
|
@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <assimp/ByteSwapper.h>
|
#include <assimp/ByteSwapper.h>
|
||||||
|
|
||||||
#include <algorithm> // std::transform
|
#include <algorithm> // std::transform
|
||||||
|
#include "FBXUtil.h"
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
@ -307,7 +308,22 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
|
||||||
const Token& token = GetRequiredToken(*Content, 0);
|
const Token& token = GetRequiredToken(*Content, 0);
|
||||||
const char* data = token.begin();
|
const char* data = token.begin();
|
||||||
if (!token.IsBinary()) {
|
if (!token.IsBinary()) {
|
||||||
DOMWarning("video content is not binary data, ignoring", &element);
|
if (*data != '"') {
|
||||||
|
DOMError("embedded content is not surrounded by quotation marks", &element);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const char* encodedData = data + 1;
|
||||||
|
size_t encodedDataLen = static_cast<size_t>(token.end() - token.begin());
|
||||||
|
// search for last quotation mark
|
||||||
|
while (encodedDataLen > 1 && encodedData[encodedDataLen] != '"')
|
||||||
|
encodedDataLen--;
|
||||||
|
if (encodedDataLen % 4 != 0) {
|
||||||
|
DOMError("embedded content is invalid, needs to be in base64", &element);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
contentLength = Util::DecodeBase64(encodedData, encodedDataLen, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (static_cast<size_t>(token.end() - data) < 5) {
|
else if (static_cast<size_t>(token.end() - data) < 5) {
|
||||||
DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
|
DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
|
||||||
|
|
|
@ -113,6 +113,49 @@ std::string AddTokenText(const std::string& prefix, const std::string& text, con
|
||||||
text) );
|
text) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const uint8_t base64DecodeTable[128] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
|
||||||
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0,
|
||||||
|
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||||
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
|
||||||
|
0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t DecodeBase64(char ch)
|
||||||
|
{
|
||||||
|
return base64DecodeTable[ch];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
|
||||||
|
{
|
||||||
|
if (inLength < 4) {
|
||||||
|
out = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t outLength = (inLength * 3) / 4;
|
||||||
|
out = new uint8_t[outLength];
|
||||||
|
memset(out, 0, outLength);
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
size_t j = 0;
|
||||||
|
for (i = 0; i < inLength - 4; i += 4)
|
||||||
|
{
|
||||||
|
uint8_t b0 = Util::DecodeBase64(in[i]);
|
||||||
|
uint8_t b1 = Util::DecodeBase64(in[i + 1]);
|
||||||
|
uint8_t b2 = Util::DecodeBase64(in[i + 2]);
|
||||||
|
uint8_t b3 = Util::DecodeBase64(in[i + 3]);
|
||||||
|
|
||||||
|
out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
|
||||||
|
out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
|
||||||
|
out[j++] = (uint8_t)((b2 << 6) | b3);
|
||||||
|
}
|
||||||
|
return outLength;
|
||||||
|
}
|
||||||
|
|
||||||
} // !Util
|
} // !Util
|
||||||
} // !FBX
|
} // !FBX
|
||||||
} // !Assimp
|
} // !Assimp
|
||||||
|
|
|
@ -98,6 +98,20 @@ std::string AddLineAndColumn(const std::string& prefix, const std::string& text,
|
||||||
* @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/
|
* @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/
|
||||||
std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok);
|
std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok);
|
||||||
|
|
||||||
|
/** Decode a single Base64-encoded character.
|
||||||
|
*
|
||||||
|
* @param ch Character to decode (from base64 to binary).
|
||||||
|
* @return decoded byte value*/
|
||||||
|
uint8_t DecodeBase64(char ch);
|
||||||
|
|
||||||
|
/** Decode a Base64-encoded string
|
||||||
|
*
|
||||||
|
* @param in Characters to decode.
|
||||||
|
* @param inLength Number of characters to decode.
|
||||||
|
* @param out Reference to pointer where we will store the decoded data.
|
||||||
|
* @return size of the decoded data (number of bytes)*/
|
||||||
|
size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue