Last active
May 6, 2016 07:39
-
-
Save Polaringu/20070f9d7ecb3810d5d6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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