Copy link to clipboard
Copied
Hello , Im using c++ sdk , I've created function to create the 3d annotation with embedded data ( my embedded data is GLTF file 😞
ASBool EmbedDataTo3dAnnot(PDPage pdPage,
PDAnnot theAnnot, // 3D annot
ASPathName GLTFPathName, // ASPathName to the U3D file
ASPathName* asPosterPathName, // ASPathName to the poster file
const char* strJsFileName) // Path to the JavaScript file
{
CosObj cosAnnot = PDAnnotGetCosObj(theAnnot);
CosDoc cosDoc = CosObjGetDoc(cosAnnot);
ASPathName jsPathName = NULL;
ASBool bRet = true;
DURING
// *** Create the required 3D stream dictionary
// Open data file
ASFile asGLTFFile = NULL;
ASInt32 iRet = ASFileSysOpenFile(ASGetDefaultUnicodeFileSys(), GLTFPathName, ASFILE_READ, &asGLTFFile);
if ((iRet != 0) || (asGLTFFile == NULL)) {
AVAlertNote("error opening 3D data file.");
E_RETURN (false);
}
// Read data stream from the file
ASStm fileStm = ASFileStmRdOpen(asGLTFFile, 0);
if(fileStm == NULL){
AVAlertNote("empty 3D data stream.");
E_RETURN (false);
}
// Set the stream's entries
CosObj attrObj = CosNewDict(cosDoc, false, 1);
CosDictPutKeyString(attrObj, "Subtype", CosNewName(cosDoc, false, ASAtomFromString("GLTF")));
CosDictPutKeyString(attrObj, "Type", CosNewNameFromString(cosDoc, false, "3D"));
CosDictPutKeyString(attrObj, "Filter", CosNewNameFromString(cosDoc, false, "FlateDecode"));
PDDoc pdDoc = PDPageGetDoc(pdPage);
// Create the optional "VA" entry
CosObj cosArray = CosNewArray(cosDoc, true, 0);
if(CosObjGetType(cosArray) == CosArray) {
CosDictPutKeyString(attrObj, "VA", cosArray);
ASUns32 i = 0;
for(ASUns32 iCounter = 0; iCounter < NUM_VIEWS; iCounter++) {
CosObj cosOneView = BuildOneView(pdDoc, cosAnnot, VIEW_NAMES[iCounter]);
if(CosObjGetType(cosOneView) == CosDict) {
CosArrayPut(cosArray, i, cosOneView);
i++;
}
}
}
// Create a new 3D stream and set it under 3DD key in the annot dictionary
CosObj stm3D = CosNewStream(cosDoc, true, fileStm, 0, true, attrObj, CosNewNull(), -1);
CosDictPutKeyString(cosAnnot, "3DD", stm3D);
ASStmClose(fileStm);
ASFileClose(asGLTFFile);
// Embed optional JavaScript code in the 3D stream
// Open JavaScript file
#ifdef WIN_PLATFORM
const char* strPathFlag = "Cstring";
#else
const char* strPathFlag = "POSIXPath";
#endif
jsPathName = ASFileSysCreatePathName (ASGetDefaultFileSys(),
ASAtomFromString(strPathFlag), strJsFileName, 0);
ASFile asJsFile = NULL;
iRet = ASFileSysOpenFile(ASGetDefaultFileSys(), jsPathName, ASFILE_READ, &asJsFile);
ASFileSysReleasePath (ASGetDefaultFileSys(), jsPathName);
if ((iRet == 0) && (asJsFile != NULL)) {
// Read js code from the js file and set it in the 3D stream
ASStm jsFileStm = ASFileStmRdOpen(asJsFile, 0);
if (jsFileStm != NULL) {
CosObj cosJs = CosNewDict(cosDoc, false, 1);
CosDictPutKeyString(cosJs, "Filter", CosNewNameFromString(cosDoc, false, "FlateDecode"));
CosObj stm3dJsCode = CosNewStream(cosDoc, true, jsFileStm, 0, true, cosJs, CosNewNull(), -1);
CosDictPutKeyString(attrObj, "OnInstantiate", stm3dJsCode);
}
ASStmClose(jsFileStm);
ASFileClose(asJsFile);
}
// Set the optional animation style dictionary in the 3D stream
CosObj animationDict = CosNewDict(cosDoc, false, 1);
if(CosObjGetType(animationDict) == CosDict) {
CosDictPutKeyString(attrObj, "AN", animationDict);
CosDictPutKeyString(animationDict, "Type",
CosNewName(cosDoc, false, ASAtomFromString("3DAnimationStyle")));
CosDictPutKeyString(animationDict, "Subtype",
CosNewName(cosDoc, false, ASAtomFromString("Linear")));
CosDictPutKeyString(animationDict, "PC", CosNewInteger(cosDoc, false, -1));
CosDictPutKeyString(animationDict, "TM", CosNewInteger(cosDoc, false, 1));
}
// Set the optional indirect reference to the page object in the annot dictionary
CosDictPutKeyString(cosAnnot, "P", PDPageGetCosObj(pdPage));
// Set the optional "Contents" entry in the annot dictionary
CosDictPutKeyString(cosAnnot, "Contents", CosNewString(cosDoc, false, "3D Model", strlen("3D Model")));
// Create a poster for the 3D annotation
CosObj formXObj = BuildFormXObj(asPosterPathName, pdDoc);
if (!CosObjEqual(formXObj, CosNewNull())){
// Build the required "AP" entry for the 3D annotation
CosObj apprDict = CosNewDict(cosDoc, false, 1);
CosDictPutKeyString(apprDict, "N", formXObj);
CosDictPutKeyString(cosAnnot, "AP", apprDict);
}
// *** Set the optional default initial view of the 3D artwork
// You are supposed to parse the U3D model file and retrieve the format spec
// such as transformation matrix for the view. Then construct the "MS", "CO", "C2W"
// (if value for "MS" is "M"), etc. entries.
// *** Set the optional activation dictionary
CosObj activationDict = CosNewDict(cosDoc, false, 1);
if(CosObjGetType(activationDict) == CosDict) {
CosDictPutKeyString(cosAnnot, "3DA", activationDict);
CosDictPutKeyString(activationDict, "DIS", CosNewName(cosDoc, false, ASAtomFromString("I")));
// Set the optional activation choice
CosDictPutKeyString(activationDict, "A", CosNewName(cosDoc, false, ASAtomFromString("PO")));
}
HANDLER
DisplayExceptionMsg();
bRet = false;
END_HANDLER
return bRet;
}
And also I have a function to create pdf with 3d annotation
How can i extract the GlTF file from my annotation and save it as a temp file ?
Copy link to clipboard
Copied
Since you have a detailed knowledge of the PDF structures, I'm not sure what advice to give. You find the annotation, fetch the relevant Cos object, and write the file. What obstacle do you face?
Copy link to clipboard
Copied
I'm new to sdk,im only learning, sorry for the poorly posed question , but can you explain more deeply please ? This fucnction is from acrobat samples ( embbeded u3d) , i know how to get annotation from the page, but how i can get relevat cos obj ( is it dictionary or strem ? ) an how to write file from the given cosobject
Copy link to clipboard
Copied
You said you that you have a function to make a 3d Annot with your embedded data. Since you already have this code, it is a simple matter to look through the code for the bit where the data is embedded. This will tell you all you need to know about extracting the data.
If you are going to be mucking about with the PDF COS structure, you'll need this tool, which manipulates COS structure, so you can see what's going on and prototype the structures you'll be working with.
Windjack Solutions, Inc. - PDf CanOpener
Copy link to clipboard
Copied
I think, that we embedded data here
// Create a new 3D stream and set it under 3DD key in the annot dictionary
CosObj stm3D = CosNewStream(cosDoc, true, fileStm, 0, true, attrObj, CosNewNull(), -1);
CosDictPutKeyString(cosAnnot, "3DD", stm3D);
ASStmClose(fileStm);
ASFileClose(asGLTFFile);
As i think at first we can get PDAnnot from the current page with the help of PDPageGetannotation, and the we can get Cos object ( PDAnnotGetCosObj) , but after this i still have no idea how to write new temp file from cos object , can you write corresponding methods to get my aim done , please ?
Copy link to clipboard
Copied
Should i find 3dd cos object ?
Copy link to clipboard
Copied
Have you studied the PDF specification in detail? You cannot proceed without detailed knowledge of the structure of your objects. You can enumerate PDAnnots to find it, and write using ASStm methods or platform file writing.
Copy link to clipboard
Copied
Im new to pdf techs, im trying as hard as i can , but i need to complete my work as fast as i can , and only the thing left is this part wit hthe new file , can you write corresponding methods if its possible , please ?
Copy link to clipboard
Copied
To read the data in a stream the key method is CosStreamGetStm.
You can write the data to a file with any method for writing files, or using the ASFile API. You already have the code for reading files. Have you read the detailed description of every method used in your sample code you are working with? (If it was up to me, I would ban sample code).
Copy link to clipboard
Copied
I've read the methods in sample , I came to this , thanks to your help. And now as I think , I need to youse ASStmRead method , but how I can get ASTArraySize and ASTCount , if I really need to use ASStmRead method
for (i2 = 0; i2 < PDPageGetNumAnnots(page); i2++)
{
//Get a specific annotation
annot = PDPageGetAnnot(page,i2);
//Checking annotation
if(!PDAnnotIsValid(annot))
{
sprintf(buf2, "No valid annotations");
AVAlertNote(buf1);
}
//open annotation
else
{
ASFile asGLTFFile = NULL;
CosObj stm = PDAnnotGetCosObj(annot);
ASStm a = CosStreamOpenStm(stm,0);
Copy link to clipboard
Copied
ASStmRead is very like the C "read" method. The two sizes are multiplied together to give a number of bytes. I always set itemSize to 1, so that the nItems value is the number of bytes in your buffer. Usefully, in this case, the return value is the number of bytes actually read.
Copy link to clipboard
Copied
Okay , Now I get number of items read from stm into memory , but how I need to write this into file ?
char* ptr1 = NULL;
ASFile asGLTFFile = NULL;
CosObj stm = PDAnnotGetCosObj(annot);
ASStm streamopen = CosStreamOpenStm(stm,0);
ASTCount streamlength = CosStreamPos(stm);
ASTCount a = ASStmRead(ptr1,1,streamlength,streamopen);
Copy link to clipboard
Copied
How can I get the number of bytes to write the file ?
Copy link to clipboard
Copied
Return value from Read is number of bytes read. This is well described in the documentation.
Copy link to clipboard
Copied
Maybe you should. What specific problem do you face? Please be detailed so we can help you find the information you need in the documentation.
Copy link to clipboard
Copied
Hello , again , I have the problem with opening the file , Now I have the code , that's searching the annotation on the current page , and writing data from it to the memory , and then to the temp file , but i have the problem with this file : adobe write files to the annotation dict in compressed format , and after extracting the file from annotation , I also have compressed file , that I can't open.
char* ptr1 = new char[1900000];
ASFile asGLTFFile = NULL;
CosObj stm = PDAnnotGetCosObj(annot);
if(CosObjGetType(stm) != 6)
{
AVAlertNote("Error in getting Cos from annotation");
}
CosObj stm3d = CosDictGetKeyString(stm,"3DD");
if((CosObjGetType(stm3d)!= 8))
{
AVAlertNote("Error in getting 3DD Key");
}
ASStm streamopen = CosStreamOpenStm(stm3d,cosOpenRaw);
//ASTCount streamlength = CosStreamPos(stm3d);
ASTArraySize lenghth = CosStreamLength(stm3d);
ASTCount a = ASStmRead(ptr1,1,lenghth,streamopen);
#if WIN_PLATFORM
const char* GLTFStringName = "C:\\setDefaultCamera.gltf";
#else
const char* GLTFStringName = "/Users/Shared/file1.gltf";
#endif
BuildFile(GLTFStringName);
#ifdef WIN_PLATFORM
const char* strPathFlag = "Cstring";
#else
const char* strPathFlag = "POSIXPath";
#endif
ASPathName GLTFPathName = ASFileSysCreatePathName (ASGetDefaultFileSys(),
ASAtomFromString(strPathFlag), GLTFStringName, 0);
ASInt32 BRet = ASFileSysOpenFile(ASGetDefaultFileSys(), GLTFPathName, ASFILE_WRITE, &asGLTFFile);
if ((BRet != 0) || (asGLTFFile == NULL)) {
AVAlertNote("error opening 3D data file.");
}
ASFileSysReleasePath (ASGetDefaultFileSys(), GLTFPathName);
if ((BRet == 0) && (asGLTFFile != NULL))
{
//Cast the ASAtom object to a character pointer
ASTArraySize Bret = ASFileWrite(asGLTFFile,ptr1,lenghth);
if(Bret!=0)
{
ASStmClose(streamopen);
ASFileClose(asGLTFFile);
}
else
{
AVAlertNote("Error in writting");
}
}
Copy link to clipboard
Copied
Look at the options for CosStreamOpenStm.
Copy link to clipboard
Copied
I actually did , i've tried cosOpenUnfiltered, cosOpenRaw, cosOpenUnfiltered, and it didnt help
Copy link to clipboard
Copied
Unfiltered (from memory) is what you need. That is what is actually in the PDF in terms of the data. How are you testing the U3D data?
Copy link to clipboard
Copied
Actually it helped , but now I can extract all my file in temp file ( not in compressed format ) only immediately after creating this file , I can't do this after I already saved my file with annotation as pdf , it extracts file from pdf with my annotation which already exists in compressed format.
Copy link to clipboard
Copied
And it helped (Now i can open file exactly before saving pdf file with annotation ) after I removed this from stream entries in my annotation
CosDictPutKeyString(attrObj, "Filter", CosNewNameFromString(cosDoc, false, "FlateDecode"));