From a4ab4fdafc33088429a6c6bcdcf3c072b3a834a9 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Mon, 12 Dec 2016 15:23:55 +0100 Subject: [PATCH 2/2] emit bmps with color palette correctly Change-Id: I731ab9629fdc08c54b43cdcb21a81633bd89f569 --- src/lib/VSDContentCollector.cpp | 52 +++++++++++++++++++++++++++++++++++++---- src/lib/libvisio_utils.h | 2 ++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/lib/VSDContentCollector.cpp b/src/lib/VSDContentCollector.cpp index c20e626..229120f 100644 --- a/src/lib/VSDContentCollector.cpp +++ b/src/lib/VSDContentCollector.cpp @@ -7,6 +7,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include #include // for memcpy #include #include @@ -33,6 +34,48 @@ static unsigned bitmapId = 0; #define SURROGATE_VALUE(h,l) (((h) - 0xd800) * 0x400 + (l) - 0xdc00 + 0x10000) +namespace +{ + +unsigned computeBMPDataOffset(librevenge::RVNGInputStream *const input, const unsigned long maxLength) +{ + assert(input); + + using namespace libvisio; + + // determine header size + unsigned headerSize = readU32(input); + if (headerSize > maxLength) + headerSize = 40; // assume v.3 bitmap header size + unsigned off = headerSize; + + // determine palette size + input->seek(10, librevenge::RVNG_SEEK_CUR); + unsigned bpp = readU16(input); + // sanitize bpp + if (bpp > 32) + bpp = 32; + const unsigned allowedBpp[] = {1, 4, 8, 16, 24, 32}; + size_t bppIdx = 0; + while (bppIdx < VSD_NUM_ELEMENTS(allowedBpp) && bpp < allowedBpp[bppIdx]) + ++bppIdx; + if (bpp < allowedBpp[bppIdx]) + bpp = allowedBpp[bppIdx]; + input->seek(16, librevenge::RVNG_SEEK_CUR); + unsigned paletteColors = readU32(input); + if (bpp < 16 && paletteColors == 0) + paletteColors = 1 << bpp; + assert(maxLength >= off); + if (paletteColors > 0 && (paletteColors < (maxLength - off) / 4)) + off += 4 * paletteColors; + + off += 14; // file header size + + return off; +} + +} // anonymous namespace + libvisio::VSDContentCollector::VSDContentCollector( librevenge::RVNGDrawingInterface *painter, std::vector > &groupXFormsSequence, @@ -1359,10 +1402,11 @@ void libvisio::VSDContentCollector::_handleForeignData(const librevenge::RVNGBin m_currentForeignData.append((unsigned char)0x00); m_currentForeignData.append((unsigned char)0x00); - m_currentForeignData.append((unsigned char)0x36); - m_currentForeignData.append((unsigned char)0x00); - m_currentForeignData.append((unsigned char)0x00); - m_currentForeignData.append((unsigned char)0x00); + const unsigned dataOff = computeBMPDataOffset(binaryData.getDataStream(), binaryData.size()); + m_currentForeignData.append((unsigned char)(dataOff & 0xff)); + m_currentForeignData.append((unsigned char)((dataOff >> 8) & 0xff)); + m_currentForeignData.append((unsigned char)((dataOff >> 16) & 0xff)); + m_currentForeignData.append((unsigned char)((dataOff >> 24) & 0xff)); } m_currentForeignData.append(binaryData); diff --git a/src/lib/libvisio_utils.h b/src/lib/libvisio_utils.h index c6c3a03..2a4880e 100644 --- a/src/lib/libvisio_utils.h +++ b/src/lib/libvisio_utils.h @@ -70,6 +70,8 @@ typedef unsigned __int64 uint64_t; #define VSD_DEBUG(M) #endif +#define VSD_NUM_ELEMENTS(array) (sizeof(array)/sizeof((array)[0])) + namespace libvisio { -- 2.9.3