From 6b5f930a1e608489dd6c3658b100dfd8d0e40d7d Mon Sep 17 00:00:00 2001 From: Oleg Korshul Date: Sat, 27 Apr 2024 01:44:26 +0300 Subject: [PATCH] Add custom image storage to docxrenderer --- DesktopEditor/common/CalculatorCRC32.h | 33 ++--- .../graphics/pro/js/drawingfile.json | 2 +- .../graphics/pro/js/wasm/src/drawingfile.h | 7 ++ DocxRenderer/DocxRenderer.cpp | 13 ++ DocxRenderer/DocxRenderer.h | 3 + .../src/logic/managers/ImageManager.cpp | 113 ++++++++++++++++++ .../src/logic/managers/ImageManager.h | 12 +- DocxRenderer/test/main.cpp | 7 +- 8 files changed, 166 insertions(+), 24 deletions(-) diff --git a/DesktopEditor/common/CalculatorCRC32.h b/DesktopEditor/common/CalculatorCRC32.h index 4c22530107..0d003e2d88 100644 --- a/DesktopEditor/common/CalculatorCRC32.h +++ b/DesktopEditor/common/CalculatorCRC32.h @@ -34,24 +34,25 @@ #include -const int g_clFilePartSize = 20*1024; +const int g_clFilePartSize = 20 * 1024; class CCalculatorCRC32 -{ +{ public: CCalculatorCRC32() { - m_dwMagicWord = 0xEDB88320; - m_dwInitCrc = 0xFFFFFFFF; - m_bInitTable = false; + m_dwMagicWord = 0xEDB88320; + m_dwInitCrc = 0xFFFFFFFF; + m_bInitTable = false; } + public: unsigned int Calc(const unsigned char* pStream, unsigned int nSize) { InitCRCTable(); - unsigned int dwRes = m_dwInitCrc; - for (unsigned int i=0;i> 8); + dwRes = m_arCRCTable[(dwRes ^ pStream[i]) & 0xFF] ^ (dwRes >> 8); } dwRes = dwRes ^ 0xFFFFFFFF; @@ -64,13 +65,13 @@ private: if (m_bInitTable) return; - unsigned int dwTemp; - for (int i=0;i<256;i++) + unsigned int dwTemp; + for (int i = 0; i < 256; i++) { dwTemp = i; - for (int j=0;j<8;j++) + for (int j = 0; j < 8; j++) { - if (0x1==(dwTemp & 0x1)) + if (0x1 == (dwTemp & 0x1)) dwTemp = (dwTemp >> 1) ^ m_dwMagicWord; else dwTemp = dwTemp >> 1; @@ -80,10 +81,10 @@ private: m_bInitTable = true; } - unsigned int m_dwMagicWord; - unsigned int m_dwInitCrc; - unsigned int m_arCRCTable[255]; - bool m_bInitTable; + unsigned int m_dwMagicWord; + unsigned int m_dwInitCrc; + unsigned int m_arCRCTable[255]; + bool m_bInitTable; }; #endif // _ASC_COMMON_CALCULATOR_CRC32_ diff --git a/DesktopEditor/graphics/pro/js/drawingfile.json b/DesktopEditor/graphics/pro/js/drawingfile.json index 9b77693ad4..f19239e88d 100644 --- a/DesktopEditor/graphics/pro/js/drawingfile.json +++ b/DesktopEditor/graphics/pro/js/drawingfile.json @@ -86,7 +86,7 @@ }, { "folder": "../../../cximage/CxImage/", - "files": ["ximaenc.cpp", "ximaexif.cpp", "ximage.cpp", "ximainfo.cpp", "ximajpg.cpp", "ximalpha.cpp", "ximapal.cpp", "ximasel.cpp", "xmemfile.cpp", "ximapng.cpp", "ximabmp.cpp", "ximatran.cpp", "ximatif.cpp", "tif_xfile.cpp", "ximajas.cpp", "ximagif.cpp", "ximaico.cpp", "ximatga.cpp", "ximapcx.cpp", "ximawbmp.cpp", "ximamng.cpp", "ximapsd.cpp", "ximaska.cpp", "ximaraw.cpp"] + "files": ["ximaenc.cpp", "ximaexif.cpp", "ximage.cpp", "ximainfo.cpp", "ximajpg.cpp", "ximalpha.cpp", "ximapal.cpp", "ximasel.cpp", "xmemfile.cpp", "ximapng.cpp", "ximabmp.cpp", "ximatran.cpp", "ximatif.cpp", "tif_xfile.cpp", "ximajas.cpp", "ximagif.cpp", "ximaico.cpp", "ximatga.cpp", "ximapcx.cpp", "ximawbmp.cpp", "ximamng.cpp", "ximapsd.cpp", "ximaska.cpp", "ximaraw.cpp", "ximaint.cpp"] }, { "folder": "../../../cximage/jpeg/", diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h index 0f159b34a0..4a79910fb5 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.h @@ -17,12 +17,14 @@ private: NSFonts::IApplicationFonts* pApplicationFonts; NSFonts::IFontManager* pFontManager; NSHtmlRenderer::CHTMLRendererText* pTextRenderer; + NSDocxRenderer::IImageStorage* pImageStorage; int nType; public: CGraphicsFileDrawing(NSFonts::IApplicationFonts* pFonts) { pReader = NULL; pTextRenderer = NULL; + pImageStorage = NULL; pApplicationFonts = pFonts; pApplicationFonts->AddRef(); @@ -40,6 +42,7 @@ public: RELEASEOBJECT(pTextRenderer); RELEASEOBJECT(pFontManager); RELEASEINTERFACE(pApplicationFonts); + RELEASEOBJECT(pImageStorage); nType = -1; } bool Open(BYTE* data, DWORD length, int _nType, const char* password) @@ -189,7 +192,11 @@ public: BYTE* GetPageShapes(const int& nPageIndex, int mode) { + if (NULL == pImageStorage) + pImageStorage = NSDocxRenderer::CreateWasmImageStorage(); + CDocxRenderer oRenderer(pApplicationFonts); + oRenderer.SetExternalImageStorage(pImageStorage); oRenderer.SetTextAssociationType(NSDocxRenderer::TextAssociationType::tatParagraphToShape); std::vector arShapes; diff --git a/DocxRenderer/DocxRenderer.cpp b/DocxRenderer/DocxRenderer.cpp index 65457fb0fb..5cba4ed522 100644 --- a/DocxRenderer/DocxRenderer.cpp +++ b/DocxRenderer/DocxRenderer.cpp @@ -126,6 +126,14 @@ std::vector CDocxRenderer::ScanPage(IOfficeDrawingFile* pFile, siz xml_shapes.push_back(writer->GetData()); delete writer; } + for (const auto& shape : m_pInternal->m_oDocument.m_oCurrentPage.m_arImages) + { + if (!shape) continue; + auto writer = new NSStringUtils::CStringBuilder(); + shape->ToXml(*writer); + xml_shapes.push_back(writer->GetData()); + delete writer; + } std::vector& arComleteObjects = m_pInternal->m_oDocument.m_oCurrentPage.m_arCompleteObjectsXml; if (!arComleteObjects.empty()) @@ -163,6 +171,11 @@ std::vector CDocxRenderer::ScanPagePptx(IOfficeDrawingFile* pFile, return xml_shapes; } +void CDocxRenderer::SetExternalImageStorage(NSDocxRenderer::IImageStorage* pStorage) +{ + m_pInternal->m_oDocument.m_oImageManager.m_pExternalStorage = pStorage; +} + void CDocxRenderer::DrawPage(IOfficeDrawingFile* pFile, size_t nPage) { //std::cout << "Page " << i + 1 << "/" << nPagesCount << std::endl; diff --git a/DocxRenderer/DocxRenderer.h b/DocxRenderer/DocxRenderer.h index cfe625defd..c8ce4f2125 100644 --- a/DocxRenderer/DocxRenderer.h +++ b/DocxRenderer/DocxRenderer.h @@ -44,6 +44,7 @@ #endif #include "convert_params.h" +#include "src/logic/managers/ExternalImageStorage.h" class CDocxRenderer_Private; class DOCXRENDERER_DECL_EXPORT CDocxRenderer : public IRenderer @@ -196,6 +197,8 @@ public: std::vector ScanPage(IOfficeDrawingFile* pFile, size_t nPage); std::vector ScanPagePptx(IOfficeDrawingFile* pFile, size_t nPage); + void SetExternalImageStorage(NSDocxRenderer::IImageStorage* pStorage); + virtual HRESULT IsSupportAdvancedCommand(const IAdvancedCommand::AdvancedCommandType& type); virtual HRESULT AdvancedCommand(IAdvancedCommand* command); diff --git a/DocxRenderer/src/logic/managers/ImageManager.cpp b/DocxRenderer/src/logic/managers/ImageManager.cpp index a7cd7f98ee..f5c89bf1ca 100644 --- a/DocxRenderer/src/logic/managers/ImageManager.cpp +++ b/DocxRenderer/src/logic/managers/ImageManager.cpp @@ -1,6 +1,116 @@ #include "ImageManager.h" #include "../../../../DesktopEditor/common/Directory.h" +namespace NSDocxRenderer +{ + IImageStorage::IImageStorage(){} + IImageStorage::~IImageStorage(){} + + class CDataImageStorage : public IImageStorage + { + private: + std::map> m_mapImageData; + std::map m_mapImages; + + int m_lMaxSizeImage{1200}; + int m_lNextIDImage{0}; + + CCalculatorCRC32 m_oCRC; + + public: + CDataImageStorage() : IImageStorage() + { + } + virtual ~CDataImageStorage() + { + } + + virtual std::shared_ptr GenerateImageID(Aggplus::CImage* pImage) + { + BYTE* pData = pImage->GetData(); + DWORD nWidth = pImage->GetWidth(); + DWORD nHeight = pImage->GetHeight(); + long nStride = pImage->GetStride(); + + int nSize = pImage->GetStride() * nHeight; + if (nSize < 0) + nSize = -nSize; + + DWORD dwSum = m_oCRC.Calc(pData, nSize); + + auto find = m_mapImageData.find(dwSum); + if (find != m_mapImageData.end()) + return find->second; + + ++m_lNextIDImage; + + auto pInfo = std::make_shared(); + pInfo->m_nId = m_lNextIDImage; + pInfo->m_eType = CImageManager::GetImageType(pImage); + pInfo->m_strFileName = L"image" + std::to_wstring(pInfo->m_nId) + ((pInfo->m_eType == CImageInfo::itJPG) ? L".jpg" : L".png"); + + CBgraFrame oBgraFrame; + oBgraFrame.put_Width(nWidth); + oBgraFrame.put_Height(nHeight); + oBgraFrame.put_Stride(nStride); + oBgraFrame.put_Data(pData); + bool bIsResized = false; + + if (nWidth > m_lMaxSizeImage || nHeight > m_lMaxSizeImage) + { + int lW = 0; + int lH = 0; + double dAspect = (double)nWidth / nHeight; + + if (nWidth >= nHeight) + { + lW = m_lMaxSizeImage; + lH = (int)((double)lW / dAspect); + if (lH < 1) lH = 1; + } + else + { + lH = m_lMaxSizeImage; + lW = (int)(dAspect * lH); + if (lW < 1) lW = 1; + } + + bIsResized = true; + oBgraFrame.Resize(lW, lH, false); + } + + BYTE* pEncodeBuffer = NULL; + int nEncodeBufferSize = 0; + oBgraFrame.Encode(pEncodeBuffer, nEncodeBufferSize, (pInfo->m_eType == CImageInfo::itJPG) ? 3 : 4); + + if (!bIsResized) + oBgraFrame.put_Data(NULL); + + int nBase64DataSize = NSBase64::Base64EncodeGetRequiredLength(nEncodeBufferSize); + char* pBase64Data = new char[nBase64DataSize]; + + NSBase64::Base64Encode(pEncodeBuffer, nEncodeBufferSize, (BYTE*)pBase64Data, &nBase64DataSize, NSBase64::B64_BASE64_FLAG_NOCRLF); + RELEASEARRAYOBJECTS(pEncodeBuffer); + + m_mapImages.insert(std::pair(pInfo->m_strFileName, std::string(pBase64Data, nBase64DataSize))); + RELEASEARRAYOBJECTS(pBase64Data); + + m_mapImageData.insert(std::pair>(dwSum, pInfo)); + return pInfo; + } + + virtual std::map* GetImages() + { + return &m_mapImages; + } + }; + + IImageStorage* CreateWasmImageStorage() + { + return new CDataImageStorage(); + } +} + namespace NSDocxRenderer { void CImageManager::Clear() @@ -86,6 +196,9 @@ namespace NSDocxRenderer std::shared_ptr CImageManager::GenerateImageID(Aggplus::CImage* pImage) { + if (m_pExternalStorage) + return m_pExternalStorage->GenerateImageID(pImage); + BYTE* pData = pImage->GetData(); int nSize = pImage->GetStride() * pImage->GetHeight(); if (nSize < 0) diff --git a/DocxRenderer/src/logic/managers/ImageManager.h b/DocxRenderer/src/logic/managers/ImageManager.h index 2d66dd1fea..357b4c9d70 100644 --- a/DocxRenderer/src/logic/managers/ImageManager.h +++ b/DocxRenderer/src/logic/managers/ImageManager.h @@ -1,9 +1,6 @@ #pragma once #include "../../../../DesktopEditor/common/CalculatorCRC32.h" -#include "../../../../DesktopEditor/raster/BgraFrame.h" -#include "../../resources/ImageInfo.h" -#include -#include +#include "./ExternalImageStorage.h" namespace NSDocxRenderer { @@ -20,6 +17,8 @@ namespace NSDocxRenderer CCalculatorCRC32 m_oCRC; + IImageStorage* m_pExternalStorage = nullptr; + public: CImageManager(){}; @@ -42,10 +41,11 @@ namespace NSDocxRenderer std::shared_ptr GenerateImageID(const std::wstring& strFileName); - CImageInfo::ImageType GetImageType(Aggplus::CImage* pFrame); - void FlipY(Aggplus::CImage* pImage); void FlipX(CBgraFrame* pImage); + + public: + static CImageInfo::ImageType GetImageType(Aggplus::CImage* pFrame); }; } diff --git a/DocxRenderer/test/main.cpp b/DocxRenderer/test/main.cpp index 1e416fcf32..5ada59aa56 100644 --- a/DocxRenderer/test/main.cpp +++ b/DocxRenderer/test/main.cpp @@ -170,14 +170,19 @@ int main(int argc, char *argv[]) //taType = NSDocxRenderer::TextAssociationType::tatPlainParagraph; taType = NSDocxRenderer::TextAssociationType::tatParagraphToShape; + NSDocxRenderer::IImageStorage* pExternalImagheStorage = NSDocxRenderer::CreateWasmImageStorage(); + //oDocxRenderer.SetExternalImageStorage(pExternalImagheStorage); + oDocxRenderer.SetTextAssociationType(taType); - //oDocxRenderer.Convert(pReader, sTextDirOut+sDocx); + oDocxRenderer.Convert(pReader, sTextDirOut+sDocx); //auto shapes = oDocxRenderer.ScanPage(pReader, 0); //Если сразу нужен zip-архив //oDocxRenderer.Convert(pReader, sPlainParagraphDirOut+sZip); #endif RELEASEOBJECT(pReader); + + RELEASEOBJECT(pExternalImagheStorage); } pFonts->Release();