Sample Obj-C code for using Apryse SDK to embed U3D content (3 dimensional models) in PDF files. Learn more about our iOS SDK.
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6#import <OBJC/PDFNetOBJC.h>
7#import <Foundation/Foundation.h>
8
9void Create3DAnnotation(PTPDFDoc* doc, PTObj* annots)
10{
11 // ---------------------------------------------------------------------------------
12 // Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability
13 // for collections of three-dimensional objects, such as those used by CAD software,
14 // to be embedded in PDF files.
15 PTObj * link_3D = [doc CreateIndirectDict];
16 [link_3D PutName: @"Subtype" name: @"3D"];
17
18 // Annotation location on the page
19 PTPDFRect * link_3D_rect = [[PTPDFRect alloc] init];
20 [link_3D_rect Set: 25 y1: 180 x2: 585 y2: 643];
21 [link_3D PutRect: @"Rect" x1: [link_3D_rect GetX1] y1: [link_3D_rect GetY1] x2: [link_3D_rect GetX2] y2: [link_3D_rect GetY2]];
22 [annots PushBack: link_3D];
23
24 // The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual)
25 // that determines how the state of the annotation and its associated artwork can change.
26 PTObj * activation_dict_3D = [link_3D PutDict: @"3DA"];
27
28 // Set the annotation so that it is activated as soon as the page containing the
29 // annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
30 [activation_dict_3D PutName: @"A" name: @"PO"];
31
32 // Embed U3D Streams (3D Model/Artwork).
33 {
34 PTMappedFile *u3d_file = [[PTMappedFile alloc] initWithFilename: @"../../TestFiles/dice.u3d"];
35 PTFilterReader *u3d_reader = [[PTFilterReader alloc] initWithFilter: u3d_file];
36
37 // To embed 3D stream without compression, you can omit the second parameter in CreateIndirectStream.
38 PTFilter *f = [[PTFilter alloc] init];
39 PTObj * u3d_data_dict = [doc CreateIndirectStream: u3d_reader filter_chain: [[PTFlateEncode alloc] initWithInput_filter: [[PTFilter alloc] init] compression_level: -1 buf_sz: 256]];
40 [u3d_data_dict PutName: @"Subtype" name: @"U3D"];
41 [link_3D Put: @"3DD" obj: u3d_data_dict];
42 }
43
44 // Set the initial view of the 3D artwork that should be used when the annotation is activated.
45 PTObj * view3D_dict = [link_3D PutDict: @"3DV"];
46 {
47 [view3D_dict PutString: @"IN" value: @"Unnamed"];
48 [view3D_dict PutString: @"XN" value: @"Default"];
49 [view3D_dict PutName: @"MS" name: @"M"];
50 [view3D_dict PutNumber: @"CO" value: 27.5];
51
52 // A 12-element 3D transformation matrix that specifies a position and orientation
53 // of the camera in world coordinates.
54 PTObj * tr3d = [view3D_dict PutArray: @"C2W"];
55 [tr3d PushBackNumber: 1]; [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: 0];
56 [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: -1];
57 [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: 1]; [tr3d PushBackNumber: 0];
58 [tr3d PushBackNumber: 0]; [tr3d PushBackNumber: -27.5]; [tr3d PushBackNumber: 0];
59
60 }
61
62 // Create annotation appearance stream, a thumbnail which is used during printing or
63 // in PDF processors that do not understand 3D data.
64 PTObj * ap_dict = [link_3D PutDict: @"AP"];
65 {
66 PTElementBuilder *builder = [[PTElementBuilder alloc] init];
67 PTElementWriter *writer = [[PTElementWriter alloc] init];
68 [writer WriterBeginWithSDFDoc: [doc GetSDFDoc] compress: true];
69
70 NSString *thumb_pathname = @"../../TestFiles/dice.jpg";
71 PTImage *image = [PTImage CreateWithFile: [doc GetSDFDoc] filename: thumb_pathname encoder_hints: [[PTObj alloc] init]];
72 [writer WritePlacedElement: [builder CreateImageWithCornerAndScale: image x: 0.0 y: 0.0 hscale: [link_3D_rect Width] vscale: [link_3D_rect Height]]];
73
74 PTObj * normal_ap_stream = [writer End];
75 [normal_ap_stream PutName: @"Subtype" name: @"Form"];
76 [normal_ap_stream PutRect: @"BBox" x1: 0 y1: 0 x2: [link_3D_rect Width] y2: [link_3D_rect Height]];
77 [ap_dict Put: @"N" obj: normal_ap_stream];
78 }
79}
80
81int main(int argc, char *argv[])
82{
83 @autoreleasepool {
84 int ret = 0;
85 [PTPDFNet Initialize: 0];
86
87 @try
88 {
89 PTPDFDoc *doc = [[PTPDFDoc alloc] init];
90 PTPDFRect * rect = [[PTPDFRect alloc] init];
91 [rect Set: 0 y1: 0 x2: 612 y2: 792];
92 PTPage *page = [doc PageCreate: rect];
93 [doc PagePushBack: page];
94 PTObj * annots = [doc CreateIndirectArray];
95 [[page GetSDFObj] Put: @"Annots" obj: annots];
96
97 Create3DAnnotation(doc, annots);
98 [doc SaveToFile: @"../../TestFiles/Output/dice_u3d.pdf" flags: e_ptlinearized];
99 NSLog(@"Done");
100 }
101 @catch(NSException *e)
102 {
103 NSLog(@"%@", e.reason);
104 ret = 1;
105 }
106 [PTPDFNet Terminate: 0];
107 return ret;
108 }
109}
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6import PDFNet
7import Foundation
8
9func Create3DAnnotation(doc: PTPDFDoc, annots: PTObj) {
10 // ---------------------------------------------------------------------------------
11 // Create a 3D annotation based on U3D content. PDF 1.6 introduces the capability
12 // for collections of three-dimensional objects, such as those used by CAD software,
13 // to be embedded in PDF files.
14 let link_3D: PTObj = doc.createIndirectDict()
15 link_3D.putName("Subtype", name: "3D")
16
17 // Annotation location on the page
18 let link_3D_rect: PTPDFRect = PTPDFRect(x1: 25, y1: 180, x2: 585, y2: 643)
19 link_3D.putRect("Rect", x1: link_3D_rect.getX1(), y1: link_3D_rect.getY1(), x2: link_3D_rect.getX2(), y2: link_3D_rect.getY2())
20 annots.pushBack(link_3D)
21
22 // The 3DA entry is an activation dictionary (see Table 9.34 in the PDF Reference Manual)
23 // that determines how the state of the annotation and its associated artwork can change.
24 let activation_dict_3D: PTObj = link_3D.putDict("3DA")
25
26 // Set the annotation so that it is activated as soon as the page containing the
27 // annotation is opened. Other options are: PV (page view) and XA (explicit) activation.
28 activation_dict_3D.putName("A", name: "PO")
29
30 // Embed U3D Streams (3D Model/Artwork).
31 do {
32 let u3d_file = PTMappedFile(filename: Bundle.main.path(forResource: "dice", ofType: "u3d"))
33 let u3d_reader = PTFilterReader(filter: u3d_file)
34 // To embed 3D stream without compression, you can omit the second parameter in CreateIndirectStream.
35 let u3d_data_dict: PTObj = doc.createIndirectStream(u3d_reader, filter_chain: PTFlateEncode(input_filter: PTFilter(), compression_level: -1, buf_sz: 256))
36 u3d_data_dict.putName("Subtype", name: "U3D")
37 link_3D.put("3DD", obj: u3d_data_dict)
38 }
39
40 // Set the initial view of the 3D artwork that should be used when the annotation is activated.
41 let view3D_dict: PTObj = link_3D.putDict("3DV")
42 do {
43 view3D_dict.put("IN", value: "Unnamed")
44 view3D_dict.put("XN", value: "Default")
45 view3D_dict.putName("MS", name: "M")
46 view3D_dict.putNumber("CO", value: 27.5)
47
48 // A 12-element 3D transformation matrix that specifies a position and orientation
49 // of the camera in world coordinates.
50 let tr3d: PTObj = view3D_dict.putArray("C2W")
51 tr3d.pushBackNumber(1)
52 tr3d.pushBackNumber(0)
53 tr3d.pushBackNumber(0)
54 tr3d.pushBackNumber(0)
55 tr3d.pushBackNumber(0)
56 tr3d.pushBackNumber(-1)
57 tr3d.pushBackNumber(0)
58 tr3d.pushBackNumber(1)
59 tr3d.pushBackNumber(0)
60 tr3d.pushBackNumber(0)
61 tr3d.pushBackNumber(-27.5)
62 tr3d.pushBackNumber(0)
63 }
64
65 // Create annotation appearance stream, a thumbnail which is used during printing or
66 // in PDF processors that do not understand 3D data.
67 let ap_dict: PTObj = link_3D.putDict("AP")
68 do {
69 let builder: PTElementBuilder = PTElementBuilder()
70 let writer: PTElementWriter = PTElementWriter()
71 writer.writerBegin(with: doc.getSDFDoc(), compress: true)
72
73 let thumb_pathname: String! = Bundle.main.path(forResource: "dice", ofType: "jpg")
74 let image = PTImage.create(withFile: doc.getSDFDoc(), filename: thumb_pathname, encoder_hints: PTObj())
75 writer.writePlacedElement(builder.createImage(withCornerAndScale: image, x: 0.0, y: 0.0, hscale: link_3D_rect.width(), vscale: link_3D_rect.height()))
76
77 let normal_ap_stream: PTObj = writer.end()
78 normal_ap_stream.putName("Subtype", name: "Form")
79 normal_ap_stream.putRect("BBox", x1: 0, y1: 0, x2: link_3D_rect.width(), y2: link_3D_rect.height())
80 ap_dict.put("N", obj: normal_ap_stream)
81 }
82}
83
84func runU3DTest() -> Int {
85 return autoreleasepool {
86 var ret: Int = 0
87
88
89 do {
90 try PTPDFNet.catchException {
91 let doc: PTPDFDoc = PTPDFDoc()
92 let rect: PTPDFRect = PTPDFRect()
93 rect.set(0, y1: 0, x2: 612, y2: 792)
94 let page: PTPage = doc.pageCreate(rect)
95 doc.pagePushBack(page)
96 let annots: PTObj = doc.createIndirectArray()
97 page.getSDFObj().put("Annots", obj: annots)
98
99 Create3DAnnotation(doc: doc, annots: annots)
100 doc.save(toFile: URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]).appendingPathComponent("dice_u3d.pdf").path, flags: e_ptlinearized.rawValue)
101 print("Done")
102 }
103 } catch let e as NSError {
104 print("\(e)")
105 ret = 1
106 }
107
108 return ret
109 }
110}
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales