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.

pull/2407/head
Matias Lavik 2019-04-06 19:31:56 +02:00
parent a43ac5b3fd
commit b3177a2a9a
3 changed files with 74 additions and 1 deletions

View File

@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ByteSwapper.h>
#include <algorithm> // std::transform
#include "FBXUtil.h"
namespace Assimp {
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 char* data = token.begin();
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) {
DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);

View File

@ -113,6 +113,49 @@ std::string AddTokenText(const std::string& prefix, const std::string& text, con
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
} // !FBX
} // !Assimp

View File

@ -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}*/
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);
}
}
}