Some test text!

Discord Logo

Chat with us

PDFTron is now Apryse, learn more here.

PDF layers (OCG) in VB

More languages

More languages
JavaScript
Java (Android)
C++
C#
C# (.NET Core)
Go
Java
Kotlin
Obj-C
JS (Node.js)
PHP
Python
Ruby
Swift
C# (UWP)
VB
C# (Xamarin)

Sample VB code to use PDFTron SDK for creating and manipulating PDF layers (also known as Optional Content Groups - OCGs). These samples demonstrate how to create and extract layers, as well as to selectively render them (show, hide) in conforming PDF readers or printers. Learn more about our VB PDF Library.

Get Started Samples Download

To run this sample, get started with a free trial of Apryse SDK.

'
' Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
'

Imports System

Imports pdftron
Imports pdftron.Common
Imports pdftron.Filters
Imports pdftron.SDF
Imports PDFTRON.PDF
Imports PDFTRON.PDF.OCG


'-----------------------------------------------------------------------------------
' This sample demonstrates how to create layers in PDF.
' The sample also shows how to extract and render PDF layers in documents 
' that contain optional content groups (OCGs)
'
' With the introduction of PDF version 1.5 came the concept of Layers. 
' Layers, or as they are more formally known Optional Content Groups (OCGs),
' refer to sections of content in a PDF document that can be selectively 
' viewed or hidden by document authors or consumers. This capability is useful 
' in CAD drawings, layered artwork, maps, multi-language documents etc.
'
' Notes: 
' ---------------------------------------
' - This sample is using CreateLayer() utility method to create new OCGs. 
'   CreateLayer() is relatively basic, however it can be extended to set 
'   other optional entries in the 'OCG' and 'OCProperties' dictionary. For 
'   a complete listing of possible entries in OC dictionary please refer to 
'   section 4.10 'Optional Content' in the PDF Reference Manual.
' - The sample is grouping all layer content into separate Form XObjects. 
'   Although using PDFNet is is also possible to specify Optional Content in 
'   Content Streams (Section 4.10.2 in PDF Reference), Optional Content in  
'   XObjects results in PDFs that are cleaner, less-error prone, and faster 
'   to process.
'-----------------------------------------------------------------------------------

Module PDFLayersTestVB
	Dim pdfNetLoader As PDFNetLoader
	Sub New()
		pdfNetLoader = pdftron.PDFNetLoader.Instance()
	End Sub

	' Relative path to the folder containing test files.
	Dim input_path As String = "../../../../TestFiles/"
	Dim output_path As String = "../../../../TestFiles/Output/"

	Sub Main()

		PDFNet.Initialize(PDFTronLicense.Key)

		Try
			Using doc As PDFDoc = New PDFDoc
				' Create three layers...
				Dim image_layer As Group = CreateLayer(doc, "Image Layer")
				Dim text_layer As Group = CreateLayer(doc, "Text Layer")
				Dim vector_layer As Group = CreateLayer(doc, "Vector Layer")

				' Start a new page ------------------------------------
				Dim page As Page = doc.PageCreate()

				Using builder As ElementBuilder = New ElementBuilder			' ElementBuilder is used to build new Element objects
					Using writer As ElementWriter = New ElementWriter		  ' ElementWriter is used to write Elements to the page	
						writer.Begin(page)			 ' begin writing to this page           

						' Add new content to the page and associate it with one of the layers.
						Dim element As Element = builder.CreateForm(CreateGroup1(doc, image_layer.GetSDFObj()))
						writer.WriteElement(element)

						element = builder.CreateForm(CreateGroup2(doc, vector_layer.GetSDFObj()))
						writer.WriteElement(element)

						element = builder.CreateForm(CreateGroup3(doc, text_layer.GetSDFObj()))
						writer.WriteElement(element)

						' Add some content to the page that does not belong to any layer...
						' In this case this is a rectangle representing the page border.
						element = builder.CreateRect(0, 0, page.GetPageWidth(), page.GetPageHeight())
						element.SetPathFill(False)
						element.SetPathStroke(True)
						element.GetGState().SetLineWidth(40)
						writer.WriteElement(element)

						writer.End()			  ' save changes to the current page
						doc.PagePushBack(page)

						doc.Save(output_path + "pdf_layers.pdf", SDF.SDFDoc.SaveOptions.e_linearized)

					End Using
				End Using

			End Using
			Console.WriteLine("Done.")

		Catch ex As PDFNetException
			Console.WriteLine(ex.Message)
		Catch ex As Exception
			MsgBox(ex.Message)
		End Try


		' The following is a code snippet shows how to selectively render 
		' and export PDF layers.
		Try
			Using doc As PDFDoc = New PDFDoc(output_path + "pdf_layers.pdf")
				doc.InitSecurityHandler()

				If doc.HasOC() = False Then
					Console.WriteLine("The document does not contain 'Optional Content'")
				Else
					Dim init_cfg As Config = doc.GetOCGConfig()
					Dim ctx As Context = New Context(init_cfg)

					Using pdfdraw As PDFDraw = New PDFDraw
						pdfdraw.SetImageSize(1000, 1000)
						pdfdraw.SetOCGContext(ctx)			 ' Render the page using the given OCG context.

						Dim page As Page = doc.GetPage(1)			 ' Get the first page in the document.
						pdfdraw.Export(page, output_path + "pdf_layers_default.png")

						' Disable drawing of content that is not optional (i.e. is not part of any layer).
						ctx.SetNonOCDrawing(False)

						' Now render each layer in the input document to a separate image.
						Dim ocgs As Obj = doc.GetOCGs()			 ' Get the array of all OCGs in the document.
						If Not ocgs Is Nothing Then
							Dim i As Integer = 0
							Dim sz As Integer = ocgs.Size()
							While (i < sz)
								Dim ocg As Group = New Group(ocgs.GetAt(i))
								ctx.ResetStates(False)
								ctx.SetState(ocg, True)
								Dim fname As String = "pdf_layers_" + ocg.GetName() + ".png"
								Console.WriteLine(fname)
								pdfdraw.Export(page, output_path + fname)
								i = i + 1
							End While
						End If

						' Now draw content that is not part of any layer...
						ctx.SetNonOCDrawing(True)
						ctx.SetOCDrawMode(Context.OCDrawMode.e_NoOC)
						pdfdraw.Export(page, output_path + "pdf_layers_non_oc.png")
					End Using
					Console.WriteLine("Done.")
				End If
			End Using
		Catch ex As PDFNetException
			Console.WriteLine(ex.Message)
		Catch ex As Exception
			MsgBox(ex.Message)
		End Try
		PDFNet.Terminate()
	End Sub

	' A utility function used to add new Content Groups (Layers) to the document.
	Function CreateLayer(ByRef doc As PDFDoc, ByVal layer_name As String) As Group

		Dim grp As Group = Group.Create(doc, layer_name)
		Dim cfg As Config = doc.GetOCGConfig()
		If cfg Is Nothing Then
			cfg = Config.Create(doc, True)
			cfg.SetName("Default")
		End If

		' Add the new OCG to the list of layers that should appear in PDF viewer GUI.
		Dim layer_order_array As Obj = cfg.GetOrder()
		If layer_order_array Is Nothing Then
			layer_order_array = doc.CreateIndirectArray()
			cfg.SetOrder(layer_order_array)
		End If
		layer_order_array.PushBack(grp.GetSDFObj())

		Return grp
	End Function

	' Creates some content (3 images) and associate them with the image layer
	Function CreateGroup1(ByRef doc As PDFDoc, ByRef layer As Obj) As Obj

		Using writer As ElementWriter = New ElementWriter
			writer.Begin(doc.GetSDFDoc())

			' Create an Image that can be reused in the document or on the same page.		
			Dim img As Image = Image.Create(doc.GetSDFDoc(), (input_path + "peppers.jpg"))

			Using builder As ElementBuilder = New ElementBuilder

				Dim element As Element = builder.CreateImage(img, New Matrix2D(img.GetImageWidth() / 2, -145, 20, img.GetImageHeight() / 2, 200, 150))
				writer.WritePlacedElement(element)

				Dim gstate As GState = element.GetGState()		  ' use the same image (just change its matrix)
				gstate.SetTransform(200, 0, 0, 300, 50, 450)
				writer.WritePlacedElement(element)

				' use the same image again (just change its matrix).
				writer.WritePlacedElement(builder.CreateImage(img, 300, 600, 200, -150))

				Dim grp_obj As Obj = writer.End()

				' Indicate that this form (content group) belongs to the given layer (OCG).
				grp_obj.PutName("Subtype", "Form")
				grp_obj.Put("OC", layer)
				grp_obj.PutRect("BBox", 0, 0, 1000, 1000)		' Set the clip box for the content.

				Return grp_obj
			End Using
		End Using
	End Function

	' Creates some content (a path in the shape of a heart) and associate it with the vector layer
	Function CreateGroup2(ByRef doc As PDFDoc, ByRef layer As Obj) As Obj

		Using writer As ElementWriter = New ElementWriter
			writer.Begin(doc.GetSDFDoc())

			Using builder As ElementBuilder = New ElementBuilder
				' Create a path object in the shape of a heart.
				builder.PathBegin()		' start constructing the path
				builder.MoveTo(306, 396)
				builder.CurveTo(681, 771, 399.75, 864.75, 306, 771)
				builder.CurveTo(212.25, 864.75, -69, 771, 306, 396)
				builder.ClosePath()
				Dim element As Element = builder.PathEnd()		  ' the path geometry is now specified.

				' Set the path FILL color space and color.
				element.SetPathFill(True)
				Dim gstate As GState = element.GetGState()
				gstate.SetFillColorSpace(ColorSpace.CreateDeviceCMYK())
				gstate.SetFillColor(New ColorPt(1, 0, 0, 0))		' cyan

				' Set the path STROKE color space and color.
				element.SetPathStroke(True)
				gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
				gstate.SetStrokeColor(New ColorPt(1, 0, 0))		' red
				gstate.SetLineWidth(20)

				gstate.SetTransform(0.5, 0, 0, 0.5, 280, 300)

				writer.WriteElement(element)

				Dim grp_obj As Obj = writer.End()

				' Indicate that this form (content group) belongs to the given layer (OCG).
				grp_obj.PutName("Subtype", "Form")
				grp_obj.Put("OC", layer)
				grp_obj.PutRect("BBox", 0, 0, 1000, 1000)		' Set the clip box for the content.

				Return grp_obj
			End Using
		End Using
	End Function

	' Creates some text and associate it with the text layer
	Function CreateGroup3(ByRef doc As PDFDoc, ByRef layer As Obj) As Obj

		Using writer As ElementWriter = New ElementWriter
			writer.Begin(doc.GetSDFDoc())

			Using builder As ElementBuilder = New ElementBuilder

				' Begin writing a block of text
				Dim element As Element = builder.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman), 120)
				writer.WriteElement(element)

				element = builder.CreateTextRun("A text layer!")

				' Rotate text 45 degrees, than translate 180 pts horizontally and 100 pts vertically.
				Dim transform As Matrix2D = Matrix2D.RotationMatrix(-45 * (3.1415 / 180.0))
				transform.Concat(1, 0, 0, 1, 180, 100)
				element.SetTextMatrix(transform)

				writer.WriteElement(element)
				writer.WriteElement(builder.CreateTextEnd())

				Dim grp_obj As Obj = writer.End()

				' Indicate that this form (content group) belongs to the given layer (OCG).
				grp_obj.PutName("Subtype", "Form")
				grp_obj.Put("OC", layer)
				grp_obj.PutRect("BBox", 0, 0, 1000, 1000)		' Set the clip box for the content.

				Return grp_obj
			End Using
		End Using
	End Function

End Module