Return getButtonIcons only XObject image

This commit is contained in:
Svetlana Kulikova
2023-12-22 10:38:36 +03:00
parent 752829d819
commit ff12c4a4ba

View File

@ -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<MemStream*>(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<MemStream*>(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();