Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Polaringu/20070f9d7ecb3810d5d6 to your computer and use it in GitHub Desktop.
Save Polaringu/20070f9d7ecb3810d5d6 to your computer and use it in GitHub Desktop.
template <typename T>
void ConvertAnnotDataToGrey(T* pData)
{
float r = 0, g = 0, b = 0;
CComPtr<PXC::IColor> pFClr;
CComPtr<PXC::IColor> pSClr;
pData->get_FColor(&pFClr);
if (pFClr == nullptr)
return;
PXC::ColorType nType = PXC::ColorType_None;
pFClr->get_Type(&nType);
if (nType != PXC::ColorType_None)
{
pFClr->GetRGB(&r, &g, &b);
float gray = (r * 0.212f) + (g * 0.701f) + (b * 0.087f); // "luminance" grayscale conversion.
pFClr->SetRGB(gray, gray, gray);
pData->put_FColor(pFClr);
}
pData->get_SColor(&pSClr);
if (pSClr == nullptr)
return;
nType = PXC::ColorType_None;
pSClr->get_Type(&nType);
if (nType != PXC::ColorType_None)
{
pSClr->GetRGB(&r, &g, &b);
float gray = (r * 0.212f) + (g * 0.701f) + (b * 0.087f); // "luminance" grayscale conversion.
pSClr->SetRGB(gray, gray, gray);
pData->put_SColor(pSClr);
}
}
bool ConvertColorToGray(PXC::IPXC_Document* pDoc, PXC::IPXC_Color* clr)
{
if (clr == nullptr)
return false;
PXC::PXC_ColorSpaceType csType;
clr->get_CSType(&csType);
if ((csType == PXC::CS_none) || (csType == PXC::CS_DeviceGray))
return false;
CComPtr<PXC::IColor> c;
clr->get_Value(PXC::ColorType_Gray, &c);
float nGrayF;
c->GetGray(&nGrayF);
double v = nGrayF;
CComPtr<PXC::IPXC_ColorSpace> pCS;
pDoc->GetStdColorSpace(PXC::CS_DeviceGray, &pCS);
clr->put_ColorSpace(pCS);
clr->SetComponents(&v, 1);
return true;
}
void ContentToGray(PXC::IPXC_Document* pDoc, PXC::IPXC_Content* pContent)
{
ULONG nCS = 0;
pContent->get_CStatesCount(&nCS);
for (ULONG i = 0; i < nCS; i++)
{
CComPtr<PXC::IPXC_CState> cstate;
pContent->GetCStateByIndex(i, &cstate);
CComPtr<PXC::IPXC_Color> clr;
cstate->get_FillColor(&clr);
bool bModified = false;
if (ConvertColorToGray(pDoc, clr))
{
cstate->put_FillColor(clr);
bModified = true;
}
clr = nullptr;
cstate->get_StrokeColor(&clr);
if (ConvertColorToGray(pDoc, clr))
{
cstate->put_StrokeColor(clr);
bModified = true;
}
if (bModified)
{
pContent->SetCStateByIndex(i, cstate);
}
}
// Next stage - check content for images/inline images and convert them
CComPtr<PXC::IPXC_ContentItems> pItems;
pContent->get_Items(&pItems);
if (pItems == nullptr)
return;
PXC::ULONG_T nCnt = 0;
pItems->get_Count(&nCnt);
for (ULONG j = 0; j < nCnt; j++)
{
CComPtr<PXC::IPXC_ContentItem> pCI;
pItems->get_Item(j, &pCI);
if (pCI == nullptr)
continue;
PXC::PXC_CIType nType = PXC::CIT_Unknown;
pCI->get_Type(&nType);
if ((nType == PXC::CIT_Image) || (nType == PXC::CIT_InlineImage))
{
CComPtr<PXC::IIXC_Page> pIP;
pCI->Image_CreateIXCPage(VARIANT_TRUE, PXC::RI_RelativeColorimecric, &pIP);
if (pIP == nullptr)
continue;
pIP->ConvertToFormat(PXC::PageFormat_8Gray);
CComPtr<PXC::IPXC_Image> pImg;
pDoc->AddImageFromIXCPage(pIP, 0, &pImg);
if (pImg == nullptr)
continue;
pCI->put_Image_Object(pImg);
}
else if (nType == PXC::CIT_XForm)
{
PXC::ULONG_T hHndl = 0;
pCI->get_XForm_Handle(&hHndl);
CComPtr<PXC::IPXC_XForm> pXForm;
pDoc->GetXFormByHandle(hHndl, &pXForm);
if (pXForm == nullptr)
continue;
CComPtr<PXC::IPXC_Content> pXContent;
pXForm->GetContent(PXC::CAccessMode_FullClone, &pXContent);
ContentToGray(pDoc, pXContent);
pXForm->SetContent(pXContent, 0);
}
}
}
HRESULT GetAppearanceStream(PXC::IPXS_PDFVariant* pAnnotDict, PXC::PXC_AnnotAppType nAppType, LPCWSTR annotAS, PXC::IPXS_PDFVariant*& pApp)
{
static const LPCWSTR n[] = { L"N", L"R", L"D" };
pApp = NULL;
CComPtr<PXC::IPXS_PDFVariant> pAP;
pAnnotDict->Dict_Get(L"AP", &pAP);
if (!pAP)
return S_FALSE;
HRESULT hr = S_OK;
BOOL bNative = TRUE;
do
{
CComPtr<PXC::IPXS_PDFVariant> pV;
pAP->Dict_Get((LPWSTR)n[nAppType], &pV);
PXC::PXS_PDFVariantType varType = PXC::PVT_INVALID;
if (pV != NULL)
{
pV->get_Type(&varType);
if ((varType != PXC::PVT_Dictionary) && (varType != PXC::PVT_Stream))
pV = NULL;
}
if (pV == NULL)
{
if (nAppType == PXC::AAT_Normal)
break;
nAppType = PXC::AAT_Normal;
bNative = FALSE;
continue;
}
if (varType == PXC::PVT_Stream)
{
pApp = pV;
break;
}
CComPtr<PXC::IPXS_PDFVariant> pD;
pV->Dict_Get((LPWSTR)annotAS, &pD);
if (pD != nullptr)
{
pD->get_Type(&varType);
if (varType == PXC::PVT_Stream)
{
pApp = pD;
break;
}
}
if (nAppType != PXC::AAT_Normal)
{
nAppType = PXC::AAT_Normal;
bNative = FALSE;
continue;
}
pD = nullptr;
pV->Dict_Get(L"Off", &pD);
if (pD != nullptr)
{
pD->get_Type(&varType);
if (varType == PXC::PVT_Stream)
{
pApp = pD;
break;
}
}
hr = S_FALSE;
break;
} while (TRUE);
if ((hr == S_OK) && !bNative)
hr = S_FALSE;
return hr;
}
HRESULT ConvertPagesContentToGrayscale(PXC::IPXC_Document* pDoc, PXC::IPXC_Inst* pInst)
{
HRESULT hr = S_OK;
do
{
CComPtr<PXC::IPXC_Pages> pPages;
hr = pDoc->get_Pages(&pPages);
if (!pPages)
break;
PXC::ULONG_T nCnt = 0;
pPages->get_Count(&nCnt);
for (DWORD i = 0; i < nCnt; i++)
{
CComPtr<PXC::IPXC_Page> pPage;
hr = pPages->get_Item(i, &pPage);
if (!pPage)
break;
CComPtr<PXC::IPXC_Content> pContent;
hr = pPage->GetContent(PXC::CAccessMode_FullClone, &pContent);
if (FAILED(hr))
break;
ContentToGray(pDoc, pContent);
hr = pPage->PlaceContent(pContent, PXC::PlaceContent_Replace);
if (FAILED(hr))
break;
}
} while (false);
return hr;
}
HRESULT ConvertAnnotationsToGrayscale(PXC::IPXC_Document* pDoc, PXC::IPXC_Inst* pInst, PXC::IPXS_Inst* pSInst)
{
//PXC::ULONG_T freeTextAnnotType = 0;
//pSInst->StrToAtom(L"FreeText", &freeTextAnnotType);
//PXC::ULONG_T lineAnnotType = 0;
//pSInst->StrToAtom(L"Line", &lineAnnotType);
//PXC::ULONG_T squareAnnotType = 0;
//pSInst->StrToAtom(L"Square", &squareAnnotType);
//PXC::ULONG_T circleAnnotType = 0;
//pSInst->StrToAtom(L"Circle", &circleAnnotType);
//PXC::ULONG_T polygonAnnotType = 0;
//pSInst->StrToAtom(L"Polygon", &polygonAnnotType);
//PXC::ULONG_T polylineAnnotType = 0;
//pSInst->StrToAtom(L"PolyLine", &polylineAnnotType);
//PXC::ULONG_T redactAnnotType = 0;
//pSInst->StrToAtom(L"Redact", &redactAnnotType);
CComPtr<PXC::IPXS_Document> pSDoc;
pDoc->get_CosDocument(&pSDoc);
HRESULT hr = S_OK;
do
{
CComPtr<PXC::IPXC_Pages> pPages;
hr = pDoc->get_Pages(&pPages);
if (!pPages)
break;
PXC::ULONG_T nCnt = 0;
pPages->get_Count(&nCnt);
for (DWORD i = 0; i < nCnt; i++)
{
CComPtr<PXC::IPXC_Page> pPage;
hr = pPages->get_Item(i, &pPage);
if (!pPage)
break;
PXC::ULONG_T nACount = 0;
pPage->GetAnnotsCount(&nACount);
for (DWORD j = 0; j < nACount; j++)
{
CComPtr<PXC::IPXC_Annotation> pAnnot;
pPage->GetAnnot(j, &pAnnot);
if (!pAnnot)
continue;
//PXC::ULONG_T nType = 0;
//pAnnot->get_Type(&nType);
//CComPtr<PXC::IPXC_AnnotData> pData;
//hr = pAnnot->get_Data(&pData);
//if (FAILED(hr))
// continue;
//if (nType == freeTextAnnotType)
//{
// //First we modify annotation stroke and fill colors
// CComPtr<PXC::IPXC_AnnotData_FreeText> pFTData = static_cast<PXC::IPXC_AnnotData_FreeText*>(pData.p);
// ConvertAnnotDataToGrey(pFTData.p);
// pAnnot->put_Data(pFTData);
//}
//else if (nType == lineAnnotType)
//{
// CComPtr<PXC::IPXC_AnnotData_Line> pLData = static_cast<PXC::IPXC_AnnotData_Line*>(pData.p);
// ConvertAnnotDataToGrey(pLData.p);
// pAnnot->put_Data(pLData);
//}
//else if ((nType == squareAnnotType) || (nType == circleAnnotType))
//{
// CComPtr<PXC::IPXC_AnnotData_SquareCircle> pSCData = static_cast<PXC::IPXC_AnnotData_SquareCircle*>(pData.p);
// ConvertAnnotDataToGrey(pSCData.p);
// pAnnot->put_Data(pSCData);
//}
//else if ((nType == polygonAnnotType) || (nType == polylineAnnotType))
//{
// CComPtr<PXC::IPXC_AnnotData_Poly> pPData = static_cast<PXC::IPXC_AnnotData_Poly*>(pData.p);
// ConvertAnnotDataToGrey(pPData.p);
// pAnnot->put_Data(pPData);
//}
//else if (nType == redactAnnotType)
//{
// CComPtr<PXC::IPXC_AnnotData_Redaction> pRData = static_cast<PXC::IPXC_AnnotData_Redaction*>(pData.p);
// ConvertAnnotDataToGrey(pRData.p);
// pAnnot->put_Data(pRData);
//}
//else
//{
// float r = 0, g = 0, b = 0;
// CComPtr<PXC::IColor> clr;
// hr = pData->get_Color(&clr);
// if (FAILED(hr))
// continue;
// PXC::ColorType nType = PXC::ColorType_None;
// clr->get_Type(&nType);
// if (nType != PXC::ColorType_None)
// {
// clr->GetRGB(&r, &g, &b);
// float gray = (r * 0.212f) + (g * 0.701f) + (b * 0.087f); // "luminance" grayscale conversion.
// clr->SetRGB(gray, gray, gray);
// pData->put_Color(clr);
// }
//
// pAnnot->put_Data(pData);
//}
//Modifying the annotation appearance
//First we get appearance by using the annotation's handler method to ensure that it would be created if it's not present
CComPtr<PXC::IPXC_AnnotHandler> pAHndl;
pAnnot->get_Handler(&pAHndl);
if (pAHndl == nullptr)
continue;
CComPtr<PXC::IPXC_OCContext> pContext;
pInst->CreateStdOCCtx(&pContext);
CComPtr<IUnknown> pUnk;
pAHndl->GetAppearance(pAnnot, pContext, &pUnk);
if (pUnk == nullptr)
continue;
//Now we know that the appearance exist so we get it from structure to change it
{
//Locking the document for write
pSDoc->LockDocumentExclusive(VARIANT_TRUE);
do
{
CComPtr<PXC::IPXS_PDFVariant> pVar;
pAnnot->get_PDFObject(&pVar);
if (pVar == nullptr)
break;
CComBSTR bstr;
pVar->Dict_GetString(L"AS", L"", &bstr);
CComPtr<PXC::IPXS_PDFVariant> pApp;
hr = GetAppearanceStream(pVar, PXC::AAT_Normal, (LPCWSTR)bstr, pApp.p);
if (pApp != nullptr)
pApp.p->AddRef();
else
break;
//Now we have the appearance stream so we can take the X-Form from it and modify it accordingly
CComPtr<PXC::IPXC_XForm> pXForm;
pDoc->GetXForm(pApp, &pXForm);
if (!pXForm)
break;
//Modifying it's content as we do with normal content
CComPtr<PXC::IPXC_Content> pContent;
pXForm->GetContent(PXC::CAccessMode_FullClone, &pContent);
if (pContent == nullptr)
break;
ContentToGray(pDoc, pContent);
pXForm->SetContent(pContent, 0);
} while (false);
pSDoc->UnlockDocumentExclusive();
}
}
}
} while (FALSE);
return hr;
}
void CDlg_OpenDoc::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
CComPtr<PXC::IPXC_Document> pDoc;
g_Inst->OpenDocumentFromFile(L"D:\\aaa_color_pdf.pdf", nullptr, nullptr, 0, 0, &pDoc);
ConvertPagesContentToGrayscale(pDoc, g_Inst);
ConvertAnnotationsToGrayscale(pDoc, g_Inst, g_COS);
pDoc->WriteToFile(L"D:\\TestFile_res.pdf", nullptr, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment