From ff12c4a4bad58bd6f2803832bd00a41d7a5e145a Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Fri, 22 Dec 2023 10:38:36 +0300 Subject: [PATCH] Return getButtonIcons only XObject image --- PdfFile/PdfReader.cpp | 505 +++++++++++++++--------------------------- 1 file changed, 176 insertions(+), 329 deletions(-) diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 70cbd90ad3..fcda979f31 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -1209,39 +1209,11 @@ BYTE* CPdfReader::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor if (sIconView && strcmp(sIconView, arrMKName[j]) != 0) continue; std::string sMKName(arrMKName[j]); - Object oStr, oStrRef; - int nView; + Object oStr; if (!oMK.dictLookup(sMKName.c_str(), &oStr)->isStream()) { - if (oStr.isNull()) - { - oStr.free(); - continue; - } oStr.free(); - - Object oIF; - if (!oMK.dictLookup("IF", &oIF)->isDict()) - { - oIF.free(); - continue; - } - oIF.free(); - - Object oAP; - if (!pField->fieldLookup("AP", &oAP)->isDict() || !oAP.dictLookup("N", &oStr)->isStream()) - { - oAP.free(); oStr.free(); - continue; - } - oAP.dictLookupNF("N", &oStrRef); - nView = oStrRef.getRefNum(); - oAP.free(); - } - else - { - oMK.dictLookupNF(sMKName.c_str(), &oStrRef); - nView = oStrRef.getRefNum(); + continue; } if (bFirst) @@ -1251,8 +1223,9 @@ BYTE* CPdfReader::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor // Номер аннотации для сопоставления с AP oRes.AddInt(oFieldRef.getRefNum()); oFieldRef.free(); - nMKPos = oRes.GetSize(); + // Количество иконок 1-3 + nMKPos = oRes.GetSize(); oRes.AddInt(nMKLength); bFirst = false; } @@ -1264,272 +1237,101 @@ BYTE* CPdfReader::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor Object oResources; oStreamDict->lookup("Resources", &oResources); Dict* oResourcesDict = oResources.isDict() ? oResources.getDict() : (Dict *)NULL; + oStr.free(); // Получение единственного XObject из Resources, если возможно - bool bImage = false; Object oXObject, oIm; - if (oResourcesDict && oResourcesDict->lookup("XObject", &oXObject)->isDict() && oXObject.dictGetLength() == 1 && oXObject.dictGetVal(0, &oIm)->isStream()) + if (!oResourcesDict || !oResourcesDict->lookup("XObject", &oXObject)->isDict() || oXObject.dictGetLength() != 1 || !oXObject.dictGetVal(0, &oIm)->isStream()) { - Dict *oImDict = oIm.streamGetDict(); - Object oType, oSubtype; - if (oImDict->lookup("Type", &oType)->isName("XObject") && oImDict->lookup("Subtype", &oSubtype)->isName("Image")) - { - bImage = true; - - Object oStrRef; - oXObject.dictGetValNF(0, &oStrRef); - int nView = oStrRef.getRefNum(); - oRes.AddInt(nView); - oStrRef.free(); - if (std::find(arrUniqueImage.begin(), arrUniqueImage.end(), nView) != arrUniqueImage.end()) - { - oStr.free(); oResources.free(); - oType.free(); oSubtype.free(); - oXObject.free(); oIm.free(); - oRes.WriteBYTE(0); - nMKLength++; - continue; - } - arrUniqueImage.push_back(nView); - oRes.WriteBYTE(1); - - // Width & Height - Object oWidth, oHeight; - int nWidth = 0; - int nHeight = 0; - if (oImDict->lookup("Width", &oWidth)->isInt() && oImDict->lookup("Height", &oHeight)->isInt()) - { - nWidth = oWidth.getInt(); - nHeight = oHeight.getInt(); - } - oRes.AddInt(nWidth); - oRes.AddInt(nHeight); - oWidth.free(); oHeight.free(); - - if (bBase64) - { - int nLength = 0; - Object oLength; - if (oImDict->lookup("Length", &oLength)->isInt()) - nLength = oLength.getInt(); - oLength.free(); - if (oImDict->lookup("DL", &oLength)->isInt()) - nLength = oLength.getInt(); - oLength.free(); - - bool bNew = false; - BYTE* pBuffer = NULL; - Stream* pImage = oIm.getStream()->getUndecodedStream(); - pImage->reset(); - MemStream* pMemory = dynamic_cast(pImage); - if (pImage->getKind() == strWeird && pMemory) - { - if (pMemory->getBufPtr() + nLength == pMemory->getBufEnd()) - pBuffer = (BYTE*)pMemory->getBufPtr(); - else - nLength = 0; - } - else - { - bNew = true; - pBuffer = new BYTE[nLength]; - BYTE* pBufferPtr = pBuffer; - for (int nI = 0; nI < nLength; ++nI) - *pBufferPtr++ = (BYTE)pImage->getChar(); - } - - char* cData64 = NULL; - int nData64Dst = 0; - NSFile::CBase64Converter::Encode(pBuffer, nLength, cData64, nData64Dst, NSBase64::B64_BASE64_FLAG_NOCRLF); - - oRes.WriteString((BYTE*)cData64, nData64Dst); - - nMKLength++; - if (bNew) - RELEASEARRAYOBJECTS(pBuffer); - RELEASEARRAYOBJECTS(cData64); - continue; - } - - BYTE* pBgraData = new BYTE[nWidth * nHeight * 4]; - unsigned int nColor = (unsigned int)nBackgroundColor; - unsigned int nSize = (unsigned int)(nWidth * nHeight); - unsigned int* pTemp = (unsigned int*)pBgraData; - for (unsigned int k = 0; k < nSize; ++k) - *pTemp++ = nColor; - - int bits = 0; - StreamColorSpaceMode csMode = streamCSNone; - oIm.getStream()->getImageParams(&bits, &csMode); - - if (bits == 0) - { - Object oBits; - if (oImDict->lookup("BitsPerComponent", &oBits)->isNull()) - { - oBits.free(); - oImDict->lookup("BPC", &oBits); - } - bits = oBits.isInt() ? oBits.getInt() : 8; - oBits.free(); - } - - GfxColorSpace* colorSpace = NULL; - Object oColorSpace; - if (oImDict->lookup("ColorSpace", &oColorSpace)->isNull()) - { - oColorSpace.free(); - oImDict->lookup("CS", &oColorSpace); - } - if (oColorSpace.isName()) - { - // TODO - } - if (!oColorSpace.isNull()) - colorSpace = GfxColorSpace::parse(&oColorSpace); - else if (csMode == streamCSDeviceGray) - colorSpace = GfxColorSpace::create(csDeviceGray); - else if (csMode == streamCSDeviceRGB) - colorSpace = GfxColorSpace::create(csDeviceRGB); - else if (csMode == streamCSDeviceCMYK) - colorSpace = GfxColorSpace::create(csDeviceCMYK); - else - colorSpace = NULL; - oColorSpace.free(); - - Object oDecode; - if (oImDict->lookup("Decode", &oDecode)->isNull()) - { - oDecode.free(); - oImDict->lookup("D", &oDecode); - } - - GfxImageColorMap* pColorMap = new GfxImageColorMap(bits, &oDecode, colorSpace); - oDecode.free(); - - ImageStream *pImageStream = new ImageStream(oIm.getStream(), nWidth, pColorMap->getNumPixelComps(), pColorMap->getBits()); - pImageStream->reset(); - - int nComps = pImageStream->getComps(); - int nCheckWidth = std::min(nWidth, pImageStream->getVals() / nComps); - - int nColorMapType = pColorMap->getFillType(); - GfxColorComp** pColorMapLookup = pColorMap->getLookup(); - if (!pColorMapLookup) - nColorMapType = 0; - - for (int nY = 0; nY < nHeight; ++nY) - { - unsigned char* pLine = pImageStream->getLine(); - unsigned char* pLineDst = pBgraData + 4 * nWidth * nY; - - if (!pLine) - { - memset(pLineDst, 0, 4 * nWidth); - continue; - } - - for (int nX = 0; nX < nCheckWidth; ++nX) - { - if (2 == nColorMapType) - { - pLineDst[0] = colToByte(clip01(pColorMapLookup[0][pLine[0]])); - pLineDst[1] = colToByte(clip01(pColorMapLookup[1][pLine[1]])); - pLineDst[2] = colToByte(clip01(pColorMapLookup[2][pLine[2]])); - } - else if (1 == nColorMapType) - { - pLineDst[0] = pLineDst[1] = pLineDst[2] = colToByte(clip01(pColorMapLookup[0][pLine[0]])); - } - else - { - GfxRGB oRGB; - pColorMap->getRGB(pLine, &oRGB, gfxRenderingIntentAbsoluteColorimetric); - pLineDst[0] = colToByte(oRGB.r); - pLineDst[1] = colToByte(oRGB.g); - pLineDst[2] = colToByte(oRGB.b); - } - - pLineDst[3] = 255; - pLine += nComps; - pLineDst += 4; - } - } - delete pColorMap; - - nMKLength++; - unsigned long long npSubMatrix = (unsigned long long)pBgraData; - unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF; - oRes.AddInt(npSubMatrix1); - oRes.AddInt(npSubMatrix >> 32); - } - oType.free(); oSubtype.free(); - } - oXObject.free(); oIm.free(); - - // else - if (bImage) - { - oStr.free(); oStrRef.free(); oResources.free(); + oXObject.free(); oIm.free(); + oResources.free(); continue; } + oResources.free(); + Dict *oImDict = oIm.streamGetDict(); + Object oType, oSubtype; + if (!oImDict->lookup("Type", &oType)->isName("XObject") || !oImDict->lookup("Subtype", &oSubtype)->isName("Image")) + { + oType.free(); oSubtype.free(); + oXObject.free(); oIm.free(); + continue; + } + oType.free(); oSubtype.free(); + + Object oStrRef; + oXObject.dictGetValNF(0, &oStrRef); + int nView = oStrRef.getRefNum(); oRes.AddInt(nView); + oStrRef.free(); if (std::find(arrUniqueImage.begin(), arrUniqueImage.end(), nView) != arrUniqueImage.end()) { - oStr.free(); oStrRef.free(); oResources.free(); + oXObject.free(); oIm.free(); oRes.WriteBYTE(0); nMKLength++; continue; } + oXObject.free(); arrUniqueImage.push_back(nView); oRes.WriteBYTE(1); - // BBox - Object bboxObj; - double bbox[4]; - if (oStreamDict->lookup("BBox", &bboxObj)->isArray()) + // Width & Height + Object oWidth, oHeight; + int nWidth = 0; + int nHeight = 0; + if (oImDict->lookup("Width", &oWidth)->isInt() && oImDict->lookup("Height", &oHeight)->isInt()) { - for (int k = 0; k < 4; ++k) - { - Object obj1; - bboxObj.arrayGet(k, &obj1); - bbox[k] = obj1.getNum(); - obj1.free(); - } + nWidth = oWidth.getInt(); + nHeight = oHeight.getInt(); } - else - { - bbox[0] = 0; bbox[1] = 0; - bbox[2] = 0; bbox[3] = 0; - } - bboxObj.free(); - - // Matrix - double m[6]; - Object matrixObj; - if (oStreamDict->lookup("Matrix", &matrixObj)->isArray()) - { - for (int k = 0; k < 6; ++k) - { - Object obj1; - matrixObj.arrayGet(k, &obj1); - m[k] = obj1.getNum(); - obj1.free(); - } - } - else - { - m[0] = 1; m[1] = 0; - m[2] = 0; m[3] = 1; - m[4] = 0; m[5] = 0; - } - matrixObj.free(); - - int nWidth = (bbox[2] > 0) ? (int)round(bbox[2] * (double)nRasterW / dWidth) : (int)((int)dWidth * 96 / dPageDpiX); - int nHeight = (bbox[3] > 0) ? (int)round(bbox[3] * (double)nRasterH / dHeight): (int)((int)dHeight * 96 / dPageDpiY); oRes.AddInt(nWidth); oRes.AddInt(nHeight); + oWidth.free(); oHeight.free(); + + if (bBase64) + { + int nLength = 0; + Object oLength; + if (oImDict->lookup("Length", &oLength)->isInt()) + nLength = oLength.getInt(); + oLength.free(); + if (oImDict->lookup("DL", &oLength)->isInt()) + nLength = oLength.getInt(); + oLength.free(); + + bool bNew = false; + BYTE* pBuffer = NULL; + Stream* pImage = oIm.getStream()->getUndecodedStream(); + pImage->reset(); + MemStream* pMemory = dynamic_cast(pImage); + if (pImage->getKind() == strWeird && pMemory) + { + if (pMemory->getBufPtr() + nLength == pMemory->getBufEnd()) + pBuffer = (BYTE*)pMemory->getBufPtr(); + else + nLength = 0; + } + else + { + bNew = true; + pBuffer = new BYTE[nLength]; + BYTE* pBufferPtr = pBuffer; + for (int nI = 0; nI < nLength; ++nI) + *pBufferPtr++ = (BYTE)pImage->getChar(); + } + + char* cData64 = NULL; + int nData64Dst = 0; + NSFile::CBase64Converter::Encode(pBuffer, nLength, cData64, nData64Dst, NSBase64::B64_BASE64_FLAG_NOCRLF); + + oRes.WriteString((BYTE*)cData64, nData64Dst); + + nMKLength++; + if (bNew) + RELEASEARRAYOBJECTS(pBuffer); + RELEASEARRAYOBJECTS(cData64); + continue; + } BYTE* pBgraData = new BYTE[nWidth * nHeight * 4]; unsigned int nColor = (unsigned int)nBackgroundColor; @@ -1538,67 +1340,112 @@ BYTE* CPdfReader::GetButtonIcon(int nRasterW, int nRasterH, int nBackgroundColor for (unsigned int k = 0; k < nSize; ++k) *pTemp++ = nColor; - CBgraFrame* pFrame = new CBgraFrame(); - pFrame->put_Data(pBgraData); - pFrame->put_Width(nWidth); - pFrame->put_Height(nHeight); - pFrame->put_Stride(4 * nWidth); - pFrame->put_IsRGBA(true); + int bits = 0; + StreamColorSpaceMode csMode = streamCSNone; + oIm.getStream()->getImageParams(&bits, &csMode); - NSGraphics::IGraphicsRenderer* pRenderer = NSGraphics::Create(); - pRenderer->SetFontManager(m_pFontManager); - pRenderer->CreateFromBgraFrame(pFrame); - pRenderer->SetSwapRGB(true); - pRenderer->put_Width (bbox[2] * 25.4 / dPageDpiX); - pRenderer->put_Height(bbox[3] * 25.4 / dPageDpiX); - if (nBackgroundColor != 0xFFFFFF) - pRenderer->CommandLong(c_nDarkMode, 1); + if (bits == 0) + { + Object oBits; + if (oImDict->lookup("BitsPerComponent", &oBits)->isNull()) + { + oBits.free(); + oImDict->lookup("BPC", &oBits); + } + bits = oBits.isInt() ? oBits.getInt() : 8; + oBits.free(); + } - PdfReader::RendererOutputDev oRendererOut(pRenderer, m_pFontManager, m_pFontList); - oRendererOut.NewPDF(m_pPDFDocument->getXRef()); + GfxColorSpace* colorSpace = NULL; + Object oColorSpace; + if (oImDict->lookup("ColorSpace", &oColorSpace)->isNull()) + { + oColorSpace.free(); + oImDict->lookup("CS", &oColorSpace); + } + if (oColorSpace.isName()) + { + // TODO + } + if (!oColorSpace.isNull()) + colorSpace = GfxColorSpace::parse(&oColorSpace); + else if (csMode == streamCSDeviceGray) + colorSpace = GfxColorSpace::create(csDeviceGray); + else if (csMode == streamCSDeviceRGB) + colorSpace = GfxColorSpace::create(csDeviceRGB); + else if (csMode == streamCSDeviceCMYK) + colorSpace = GfxColorSpace::create(csDeviceCMYK); + else + colorSpace = NULL; + oColorSpace.free(); - // Создание Gfx - GBool crop = gTrue; - PDFRectangle box; - pPage->makeBox(72.0, 72.0, 0, gFalse, oRendererOut.upsideDown(), -1, -1, -1, -1, &box, &crop); - PDFRectangle* cropBox = pPage->getCropBox(); + Object oDecode; + if (oImDict->lookup("Decode", &oDecode)->isNull()) + { + oDecode.free(); + oImDict->lookup("D", &oDecode); + } - Gfx* gfx = new Gfx(m_pPDFDocument, &oRendererOut, nPageIndex + 1, pPage->getAttrs()->getResourceDict(), 72.0, 72.0, &box, cropBox ? cropBox : (PDFRectangle *)NULL, 0, NULL, NULL); + GfxImageColorMap* pColorMap = new GfxImageColorMap(bits, &oDecode, colorSpace); + oDecode.free(); - pRenderer->SetCoordTransformOffset(0, bbox[3] * (double)nRasterH / dHeight - nRasterH); - gfx->drawForm(&oStrRef, oResourcesDict, m, bbox, gFalse, gFalse, gFalse, gFalse); - oStr.free(); oStrRef.free(); oResources.free(); + ImageStream *pImageStream = new ImageStream(oIm.getStream(), nWidth, pColorMap->getNumPixelComps(), pColorMap->getBits()); + pImageStream->reset(); + + int nComps = pImageStream->getComps(); + int nCheckWidth = std::min(nWidth, pImageStream->getVals() / nComps); + + int nColorMapType = pColorMap->getFillType(); + GfxColorComp** pColorMapLookup = pColorMap->getLookup(); + if (!pColorMapLookup) + nColorMapType = 0; + + for (int nY = 0; nY < nHeight; ++nY) + { + unsigned char* pLine = pImageStream->getLine(); + unsigned char* pLineDst = pBgraData + 4 * nWidth * nY; + + if (!pLine) + { + memset(pLineDst, 0, 4 * nWidth); + continue; + } + + for (int nX = 0; nX < nCheckWidth; ++nX) + { + if (2 == nColorMapType) + { + pLineDst[0] = colToByte(clip01(pColorMapLookup[0][pLine[0]])); + pLineDst[1] = colToByte(clip01(pColorMapLookup[1][pLine[1]])); + pLineDst[2] = colToByte(clip01(pColorMapLookup[2][pLine[2]])); + } + else if (1 == nColorMapType) + { + pLineDst[0] = pLineDst[1] = pLineDst[2] = colToByte(clip01(pColorMapLookup[0][pLine[0]])); + } + else + { + GfxRGB oRGB; + pColorMap->getRGB(pLine, &oRGB, gfxRenderingIntentAbsoluteColorimetric); + pLineDst[0] = colToByte(oRGB.r); + pLineDst[1] = colToByte(oRGB.g); + pLineDst[2] = colToByte(oRGB.b); + } + + pLineDst[3] = 255; + pLine += nComps; + pLineDst += 4; + } + } + delete pColorMap; nMKLength++; + unsigned long long npSubMatrix = (unsigned long long)pBgraData; + unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF; + oRes.AddInt(npSubMatrix1); + oRes.AddInt(npSubMatrix >> 32); - if (bBase64) - { - BYTE* pPngBuffer = NULL; - int nPngSize = 0; - pFrame->Encode(pPngBuffer, nPngSize, 4); - - char* cData64 = NULL; - int nData64Dst = 0; - NSFile::CBase64Converter::Encode(pPngBuffer, nPngSize, cData64, nData64Dst, NSBase64::B64_BASE64_FLAG_NOCRLF); - - oRes.WriteString((BYTE*)cData64, nData64Dst); - - RELEASEARRAYOBJECTS(cData64); - RELEASEARRAYOBJECTS(pPngBuffer); - } - else - { - unsigned long long npSubMatrix = (unsigned long long)pBgraData; - unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF; - oRes.AddInt(npSubMatrix1); - oRes.AddInt(npSubMatrix >> 32); - - pFrame->ClearNoAttack(); - } - - delete gfx; - RELEASEOBJECT(pFrame); - RELEASEOBJECT(pRenderer); + oIm.free(); } oMK.free();