Change the color inside a PDF

Colors
7/4/2014

This code sample shows how to change color in a PDF using C# and VB.NET.

PDF before changing color

Black and White PDF.png

PDF after changing color

PDF after converting black and white PDF to color.png

The code sample extracts all the graphics on the original page as a tree of shape objects. It traverses the tree and changes color properties of a selection of shape objects. It then creates a new PDF document from the modified shapes.

The text shapes are modified by setting the Brush property to blue. The brush is used to fill the interior of the glyphs.

The freehand shapes (paths) are modified by setting the Pen property to green and the Brush property to purple. This makes all the lines green and all the fills purple.

The image shapes require a different approach since they have no pen or brush. We extract the GDI+ bitmap and transform the colors using the color matrix. Next we create a new image shape from the transformed bitmap and replace the original image shape. The color matrix is quite versatile. By using different matrices you can implement e.g. a sepia tone or a negative filter. Read more.

Here is the code:

C# code sample

1 static void Main(string[] args) 2 { 3 using (FileStream fileIn = new FileStream(@"..\..\..\inputDocuments\SellingYourHome.pdf", FileMode.Open, FileAccess.Read)) 4 { 5 Document pdfIn = new Document(fileIn); 6 Document pdfOut = ChangeColor(pdfIn); 7 using (FileStream fileOut = new FileStream(@"..\..\out.pdf", FileMode.Create, FileAccess.Write)) 8 { 9 pdfOut.Write(fileOut); 10 } 11 } 12 } 13 14 15 // 16 // Changes the color of all pages in one PDF document 17 // 18 static Document ChangeColor(Document pdf) 19 { 20 Document pdfOut = new Document(); 21 22 foreach (Page page in pdf.Pages) 23 { 24 pdfOut.Pages.Add(ChangeColor(page)); 25 } 26 27 return pdfOut; 28 } 29 30 31 // 32 // Changes the color of all shapes in one PDF page 33 // 34 static Page ChangeColor(Page page) 35 { 36 Page newPage = new Page(page.Width, page.Height) 37 { 38 Orientation = page.Orientation 39 }; 40 ShapeCollection shapes = page.CreateShapes(); 41 ChangeColor(shapes); 42 newPage.Overlay.Add(shapes); 43 44 return newPage; 45 } 46 47 48 // 49 // This tries to find the type of a shape and chooses one of the ways to change the color 50 // 51 static void ChangeColor(ShapeCollection shapes) 52 { 53 for (var i = 0; i < shapes.Count; i++) 54 { 55 Shape shape = shapes[i]; 56 57 if (shape is ShapeCollection) 58 { 59 // recurse 60 ChangeColor(shape as ShapeCollection); 61 } 62 else if (shape is ImageShape) 63 { 64 shapes.RemoveAt(i); 65 var newShape = ChangeColor(shape as ImageShape); 66 shapes.Insert(i, newShape); 67 } 68 else if (shape is TextShape) 69 { 70 shapes.RemoveAt(i); 71 var newShape = ChangeColor(shape as TextShape); 72 shapes.Insert(i, newShape); 73 } 74 else if (shape is FreeHandShape) 75 { 76 shapes.RemoveAt(i); 77 var newShape = ChangeColor(shape as FreeHandShape); 78 shapes.Insert(i, newShape); 79 } 80 else 81 { 82 // other types of shapes remain the same in this code sample 83 } 84 } 85 } 86 87 88 // 89 // Change the color of a Text Shape 90 // All text will be colored blue 91 // 92 static TextShape ChangeColor(TextShape shape) 93 { 94 RgbColor color = new RgbColor(0.00, 0.00, 255.00); 95 shape.Brush = new TallComponents.PDF.Brushes.SolidBrush(color); 96 97 return shape; 98 } 99 100 101 // 102 // Change the color of a freehandshape (like the horizontal lines) 103 // these will be colored with a green brush and a purple pen 104 // 105 static FreeHandShape ChangeColor(FreeHandShape shape) 106 { 107 RgbColor brushColor = new TallComponents.PDF.Colors.RgbColor(192.00, 0.00, 192.00); 108 shape.Brush = new TallComponents.PDF.Brushes.SolidBrush(brushColor); 109 110 RgbColor penColor = new TallComponents.PDF.Colors.RgbColor(128.00, 255.00, 0.00); 111 shape.Pen = new TallComponents.PDF.Pens.Pen(penColor); 112 113 return shape; 114 } 115 116 117 // 118 // Change the color of a image 119 // these will be colored red using a color matrix 120 // 121 // Note: 122 // The color matrix is quite versatile. By using different matrices you can implement 123 // e.g. a sepia tone or a negative filter 124 // 125 // Sepia filter: 126 // var colorMatrix = new ColorMatrix( new float[][] 127 // { 128 // new float[]{0.393f, 0.349f, 0.272f, 0.000f, 0.000f}, 129 // new float[]{0.769f, 0.686f, 0.534f, 0.000f, 0.000f}, 130 // new float[]{0.189f, 0.168f, 0.131f, 0.000f, 0.000f}, 131 // new float[]{0.000f, 0.000f, 0.000f, 1.000f, 0.000f}, 132 // new float[]{0.000f, 0.000f, 0.000f, 0.000f, 1.000f} 133 // } 134 // 135 // Negative filter 136 // var colorMatrix = new ColorMatrix( new float[][] 137 // { 138 // new float[]{-1, 0, 0, 0, 0}, 139 // new float[]{ 0, -1, 0, 0, 0}, 140 // new float[]{ 0, 0, -1, 0, 0}, 141 // new float[]{ 0, 0, 0, 1, 0}, 142 // new float[]{ 1, 1, 1, 1, 1} 143 // } 144 // 145 static ImageShape ChangeColor(ImageShape image) 146 { 147 int height = (int)image.VerticalSize; 148 int width = (int)image.HorizontalSize; 149 150 using (Bitmap bitmap = image.CreateBitmap()) 151 { 152 Bitmap newBitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); 153 using (Graphics graphics = Graphics.FromImage(newBitmap)) 154 { 155 // Info on this color matrix can be found here: 156 // See http://msdn.microsoft.com/library/ys160710.aspx 157 ColorMatrix colorMatrix = new ColorMatrix(new float[][] 158 { 159 new float[]{ 1, 0, 0, 0, 0}, 160 new float[]{ 0, 1, 0, 0, 0}, 161 new float[]{ 0, 0, 1, 0, 0}, 162 new float[]{ 0, 0, 0, 1, 0}, 163 new float[]{0.75f, 0, 0, 0, 1} 164 }); 165 166 ImageAttributes imageAttributes = new ImageAttributes(); 167 imageAttributes.SetColorMatrix(colorMatrix); 168 169 graphics.DrawImage(bitmap, 170 new System.Drawing.Rectangle(0, 0, width, height), // dest 171 0, // X-upper left corner of the source 172 0, // Y-upper left corner of the source 173 width, // Width of the source 174 height, // Height of the source 175 GraphicsUnit.Pixel, 176 imageAttributes); 177 } 178 179 ImageShape changedImage = new ImageShape(newBitmap, true) 180 { 181 Compression = Compression.Jpeg, 182 Width = image.Width, 183 Height = image.Height, 184 Transform = image.Transform, 185 Opacity = image.Opacity, 186 BlendMode = image.BlendMode 187 }; 188 return changedImage; 189 } 190 }

VB.NET code sample

1 Shared Sub Main() 2 Using fileIn As FileStream = New FileStream("..\..\..\inputDocuments\SellingYourHome.pdf", FileMode.Open, FileAccess.Read) 3 Dim pdfIn As Document 4 Dim pdfOut As Document 5 6 pdfIn = New Document(fileIn) 7 pdfOut = ChangeColor(pdfIn) 8 Using fileOut As FileStream = New FileStream("..\..\out.pdf", FileMode.Create, FileAccess.Write) 9 pdfOut.Write(fileOut) 10 End Using 11 End Using 12 End Sub 13 14 15 ' 16 ' Changes the color of all pages in one PDF document 17 ' 18 Private Shared Function ChangeColor(pdf As Document) As Document 19 Dim pdfOut As Document 20 21 pdfOut = New Document() 22 For Each page As Page In pdf.Pages 23 pdfOut.Pages.Add(ChangeColor(page)) 24 Next 25 26 Return pdfOut 27 End Function 28 29 30 ' 31 ' Changes the color of all shapes in one PDF page 32 ' 33 Private Shared Function ChangeColor(page As Page) As Page 34 Dim newPage As Page 35 Dim shapes As ShapeCollection 36 37 newPage = New Page(page.Width, page.Height) 38 newPage.Orientation = page.Orientation 39 shapes = page.CreateShapes() 40 ChangeColor(shapes) 41 newPage.Overlay.Add(shapes) 42 43 Return newPage 44 End Function 45 46 47 ' 48 ' This tries to find the type of a shape and chooses one of the ways to change the color 49 ' 50 Private Shared Sub ChangeColor(shapes As ShapeCollection) 51 Dim shape As Shape 52 53 For i As Integer = 0 To shapes.Count - 1 54 shape = shapes(i) 55 56 If TypeOf shape Is ShapeCollection Then 57 ' recurse 58 ChangeColor(TryCast(shape, ShapeCollection)) 59 60 ElseIf TypeOf shape Is ImageShape Then 61 Dim newShape As ImageShape 62 shapes.RemoveAt(i) 63 newShape = ChangeColor(TryCast(shape, ImageShape)) 64 shapes.Insert(i, newShape) 65 66 ElseIf TypeOf shape Is TextShape Then 67 Dim newShape As TextShape 68 shapes.RemoveAt(i) 69 newShape = ChangeColor(TryCast(shape, TextShape)) 70 shapes.Insert(i, newShape) 71 72 ElseIf TypeOf shape Is FreeHandShape Then 73 Dim newShape As FreeHandShape 74 shapes.RemoveAt(i) 75 newShape = ChangeColor(TryCast(shape, FreeHandShape)) 76 shapes.Insert(i, newShape) 77 78 Else 79 ' other types of shapes remain the same in this code sample 80 End If 81 Next 82 End Sub 83 84 85 ' 86 ' Change the color of a Text Shape 87 ' All text will be colored blue 88 ' 89 Private Shared Function ChangeColor(shape As TextShape) As TextShape 90 Dim color As TallComponents.PDF.Colors.RgbColor 91 92 color = New TallComponents.PDF.Colors.RgbColor(0.0, 0.0, 255.0) 93 shape.Brush = New TallComponents.PDF.Brushes.SolidBrush(color) 94 95 Return shape 96 End Function 97 98 99 ' 100 ' Change the color of a freehandshape (like the horizontal lines) 101 ' these will be colored with a green brush and a purple pen 102 ' 103 Private Shared Function ChangeColor(shape As FreeHandShape) As FreeHandShape 104 Dim brushColor As TallComponents.PDF.Colors.RgbColor 105 Dim penColor As TallComponents.PDF.Colors.RgbColor 106 107 brushColor = New TallComponents.PDF.Colors.RgbColor(192.0, 0.0, 192.0) 108 shape.Brush = New TallComponents.PDF.Brushes.SolidBrush(brushColor) 109 penColor = New TallComponents.PDF.Colors.RgbColor(128.0, 255.0, 0.0) 110 shape.Pen = New TallComponents.PDF.Pens.Pen(penColor) 111 112 Return shape 113 End Function 114 115 116 ' 117 ' Change the color of a image 118 ' these will be colored red using a color matrix 119 ' 120 ' 121 ' Change the color of a image 122 ' these will be colored red using a color matrix 123 ' 124 ' Note: 125 ' The color matrix is quite versatile. By using different matrices you can implement 126 ' e.g. a sepia tone or a negative filter 127 ' 128 ' Sepia filter: 129 ' var colorMatrix = new ColorMatrix( new float[][] 130 ' { 131 ' new float[]{0.393f, 0.349f, 0.272f, 0.000f, 0.000f}, 132 ' new float[]{0.769f, 0.686f, 0.534f, 0.000f, 0.000f}, 133 ' new float[]{0.189f, 0.168f, 0.131f, 0.000f, 0.000f}, 134 ' new float[]{0.000f, 0.000f, 0.000f, 1.000f, 0.000f}, 135 ' new float[]{0.000f, 0.000f, 0.000f, 0.000f, 1.000f} 136 ' } 137 ' 138 ' Negative filter: 139 ' var colorMatrix = new ColorMatrix( new float[][] 140 ' { 141 ' new float[]{-1, 0, 0, 0, 0}, 142 ' new float[]{ 0, -1, 0, 0, 0}, 143 ' new float[]{ 0, 0, -1, 0, 0}, 144 ' new float[]{ 0, 0, 0, 1, 0}, 145 ' new float[]{ 1, 1, 1, 1, 1} 146 ' } 147 ' 148 149 Private Shared Function ChangeColor(image As ImageShape) As ImageShape 150 Dim height As Integer 151 Dim width As Integer 152 153 height = CInt(image.VerticalSize) 154 width = CInt(image.HorizontalSize) 155 156 Using bitmap As Bitmap = image.CreateBitmap() 157 Dim newBitmap As Bitmap 158 Dim changedImage As ImageShape 159 160 newBitmap = New Bitmap(width, height, PixelFormat.Format32bppArgb) 161 Using graphics__1 As Graphics = Graphics.FromImage(newBitmap) 162 Dim colorMatrix As ColorMatrix 163 Dim imageAttributes As ImageAttributes 164 165 ' Info on this color matrix can be found here: 166 ' See http://msdn.microsoft.com/library/ys160710.aspx 167 colorMatrix = New ColorMatrix(New Single()() _ 168 { _ 169 New Single() {1, 0, 0, 0, 0}, _ 170 New Single() {0, 1, 0, 0, 0}, _ 171 New Single() {0, 0, 1, 0, 0}, _ 172 New Single() {0, 0, 0, 1, 0}, _ 173 New Single() {0.75F, 0, 0, 0, 1} _ 174 }) 175 176 imageAttributes = New ImageAttributes() 177 imageAttributes.SetColorMatrix(colorMatrix) 178 179 ' dest 180 ' X-upper left corner of the source 181 ' Y-upper left corner of the source 182 ' Width of the source 183 ' Height of the source 184 graphics__1.DrawImage(bitmap, 185 New System.Drawing.Rectangle(0, 0, width, height), 186 0, 187 0, 188 width, 189 height, 190 GraphicsUnit.Pixel, 191 imageAttributes) 192 End Using 193 194 changedImage = New ImageShape(newBitmap, True) With _ 195 { _ 196 .Compression = Compression.Jpeg, _ 197 .Width = image.Width, _ 198 .Height = image.Height, _ 199 .Transform = image.Transform, _ 200 .Opacity = image.Opacity, _ 201 .BlendMode = image.BlendMode _ 202 } 203 Return changedImage 204 End Using 205 End Function