Wednesday, May 2, 2012

PDF Layer Merger

 

Recently I’ve created a simple .NET tool, to merge 2 PDF files, one as a layer on top of the other.

The reason behind this, was to be able to digitally remark/comment/mark-up on a PDF file using AutoCAD.  People tend to print out a PDF file, use some highlighters and draw some clouds and comments on this PDF, only to re-scan this afterwards.
This is the way we used to work, but today we live in a digital era…

The tool has been built in VB.NET targeting the NET 2.0 framework, with the use of the excellent PDF library iTextSharp (based on iText).

image


Snippet of the actual transformation function:

  
'''
''' Combines two source pdf's to one single pdf.
'''

''' The file-location incl. the name of the original pdf.
''' The file-location incl. the name of the mark-up pdf.
''' The file-location incl. the name of the generated combined pdf.
''' The name which the added mark-up layer will have in the new pdf.
''' The transformation which is executed on the original pdf: rotation, scaleX, scaleY, offsetX, offsetY
''' Return boolean indication whether the combination of the pdf's was successful.
'''
Public Function PDFCombineLayer(ByVal sourceOriginal As String, ByVal sourceMarkup As String, ByVal destination As String, Optional ByVal NewLayer As String = "SOURCE-DRAWING", Optional ByVal Transform As String = "0;1;1;0;0") As Boolean
Dim oPdfOriginal As iTextSharp.text.pdf.PdfReader = Nothing
Dim oPdfMarkup As iTextSharp.text.pdf.PdfReader = Nothing
Dim oPdfStamper As iTextSharp.text.pdf.PdfStamper = Nothing
Dim PDFDirectContent As iTextSharp.text.pdf.PdfContentByte
Dim iNumberOfPages As Integer = Nothing
Dim iPage As Integer = 0
Dim matrix1 As Drawing2D.Matrix = Nothing
Dim matrix2 As Drawing2D.Matrix = Nothing

Try
'Read the source pdf-files and prepare new file.
oPdfOriginal = New iTextSharp.text.pdf.PdfReader(sourceOriginal)
oPdfMarkup = New iTextSharp.text.pdf.PdfReader(sourceMarkup)
oPdfStamper = New iTextSharp.text.pdf.PdfStamper(oPdfMarkup, New IO.FileStream(destination, IO.FileMode.Create, IO.FileAccess.Write))

'Count pages in original pdf and create new pdf wih same amount of pages.
iNumberOfPages = oPdfOriginal.NumberOfPages
oPdfStamper.GetPdfLayers()

'Make transformation matrix
If Transform = "" Then Transform = "0;1;1;0;0" 'Note transform: rotation(degrees), scaleX, scaleY, offsetX, offsetY
Dim ar() As String = Split(Transform, ";")
If Not ar.Length = 5 Then ar = New String() {0, 1, 1, 0, 0}
If ar(1) <= 0 Or ar(2) <= 0 Then Throw New ArgumentOutOfRangeException("transform", "Make sure that scaling factors of the transformation are larger than zero.")
matrix1 = New Drawing2D.Matrix
matrix1.Rotate(-CSng(ar(0)))
matrix1.Scale(CSng(ar(1)), CSng(ar(2)))
matrix1.Translate(CSng(ar(3)), CSng(ar(4)))
matrix2 = New Drawing2D.Matrix

'Add the new layer to each of the pdf-pages.
If NewLayer = "" Then NewLayer = "SOURCE-DRAWING"
Dim PDFNewLayer As New iTextSharp.text.pdf.PdfLayer(NewLayer, oPdfStamper.Writer)
Dim PDFLayerMem As New iTextSharp.text.pdf.PdfLayerMembership(oPdfStamper.Writer)
PDFLayerMem.AddMember(PDFNewLayer)
Do While (iPage < iNumberOfPages)
'Get new page
iPage += 1
Dim iPageOriginal As iTextSharp.text.pdf.PdfImportedPage = oPdfStamper.Writer.GetImportedPage(oPdfOriginal, iPage)
PDFDirectContent = oPdfStamper.GetUnderContent(iPage) 'add page under existing pdf in new layer
matrix2 = matrix1.Clone 'Cloning is necessary, otherwise all adaptations to matrix2 are also done in matrix1.

'Compensate for the orientation of the original pdf-file.
Dim iRotation As Single = oPdfOriginal.GetPageRotation(iPage)
Select Case iRotation
Case Is = 90
matrix2.Rotate(-iRotation)
matrix2.Translate(-oPdfOriginal.GetPageSize(iPage).Width, 0)
Case Is = 180 'Not tested yet.
matrix2.Rotate(-iRotation)
matrix2.Translate(-oPdfOriginal.GetPageSize(iPage).Width, -oPdfOriginal.GetPageSize(iPage).Height)
Case Is = 270 'Not tested yet.
matrix2.Rotate(-iRotation)
matrix2.Translate(0, oPdfOriginal.GetPageSize(iPage).Height)
Case Else
End Select

'Add the new layer ot this page.
PDFDirectContent.BeginLayer(PDFNewLayer)
PDFDirectContent.AddTemplate(iPageOriginal, matrix2)
PDFDirectContent.EndLayer()
Loop
oPdfStamper.SetFullCompression()
Return True
Catch ex As Exception
Return False
Finally
oPdfMarkup.Close()
oPdfOriginal.Close()
oPdfStamper.Close()
matrix1.Dispose()
matrix2.Dispose()
End Try
End Function

Code has been posted on Google Code http://code.google.com/p/pdflayermerger/


Many thanks to iText for the excellent library and to Lukasz Swiatkowski for the glass button component (http://www.codeproject.com/Articles/17695/Creating-a-Glass-Button-using-GDI).

Thursday, April 26, 2012

Apple is 10 years behind Microsoft when it comes to security. Time to face the music…

 

http://malware.cbronline.com/news/apple-10-years-behind-microsoft-on-security-kaspersky-250412

Credits goto Steve Evans & CBR Online
http://malware.cbronline.com/archive/4294941974

It seems it’s time to face the music for Apple..

Kaspersky founder and CEO Eugene Kaspersky,
speaking exclusively to CBR at Info Security 2012, Kaspersky told us that Apple is a long way behind Microsoft when it comes to security and will have to change the ways it approaches updates following the recent malware attacks.

"I think they are ten years behind Microsoft in terms of security," Kaspersky told CBR. "For many years I've been saying that from a security point of view there is no big difference between Mac and Windows. It's always been possible to develop Mac malware, but this one was a bit different. For example it was asking questions about being installed on the system and, using vulnerabilities, it was able to get to the user mode without any alarms."

Kaspersky added that his company is seeing more and more malware aimed at Macs, which is unsurprising given the huge number of devices being sold. Its most recent quarter revealed Mac sales of 4 million, a 7% rise on the year ago quarter. These figures are still dwarfed by PC sales of course, and Kaspersky said Windows will remain the primary target for cyber criminals.

However he added an increase in Mac malware was, "just a question of time and market share. Cyber criminals have now recognised that Mac is an interesting area. Now we have more, it's not just Flashback or Flashfake. Welcome to Microsoft's world, Mac. It's full of malware."

"Apple is now entering the same world as Microsoft has been in for more than 10 years: updates, security patches and so on," he added. "We now expect to see more and more because cyber criminals learn from success and this was the first successful one."

Tuesday, April 17, 2012

Springpad : Make your live easier

Springpad helps you share & discover with the people you trust.

Create notebooks for recipes, books, movies or anything else that matters to you, together with friends, family and co-workers. Save ideas and info from anywhere, access them whenever, and start getting more from life.
Get Started



Collaborate with your friends and family.



Start a notebook for any interest, any project, any “I’ve got to do this!” list. Then invite the right people to help with each one – your foodie friends, your book club buddies, your mom – anyone! Comment on each other’s contributions and build something great together.


Save anything to Springpad, from anywhere.

Fill your Springpads with things you find on the web or on the go. Clip an article, snap a photo, scan a product barcode, record a voice memo, or save a place nearby. Then access it anytime, anywhere you need it.


Whatever you save, we’ll make even better.

Add something to your Springpad, and we’ll instantly enhance it with more information. Save a restaurant and we’ll give you a map and reviews. Save a movie, and we’ll give you the showtimes near you. Save a book, and we’ll link you to where you can buy it. Save a product, we’ll tell you when there’s a price drop. Get the idea?




Monday, April 16, 2012

Chronology of Programming Languages

Found a nice article check it out : The Semicolon Wars » American Scientist





A chronology of selected programming languages shows a few of the links between them. The diagram is not a genealogy but merely indicates major patterns of influence. The classification of languages as imperative, functional, object-oriented or declarative is also approximate; only a few "pure" languages belong exclusively to one of these categories. The chronology is based in part on time lines constructed by Éric Lévénez and by Pascal Rigaux and on information from the Association for Computing Machinery History of Programming Languages conferences.
Brian Hayes

Saturday, October 29, 2011

Getting Mimetype .NET


Private Function MimeType(Filename As String) As String
 Dim mime As String = "application/octetstream"
 Dim ext As String = System.IO.Path.GetExtension(Filename).ToLower()
 Dim rk As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext)
 If rk IsNot Nothing AndAlso rk.GetValue("Content Type") IsNot Nothing Then
  mime = rk.GetValue("Content Type").ToString()
 End If
 Return mime
End Function
In short - you just feed it with path top a file - and get back the mime type. Ex MimeType("f:\\theimage.jpg") --->>> "image/jpeg"

Sunday, October 16, 2011

Check For 64bit Operating System VB.NET 2.0

    Public Function Is64BitOperatingSystem() As Boolean?
        Dim amount As Integer
        Try
            amount = Runtime.InteropServices.Marshal.SizeOf(IntPtr.Zero)
            If amount = 8 Then : Return True
            Else : Return False
            End If
        Catch ex As Exception
            Return Nothing
        End Try
    End Function 'End Method Is64BitOperatingSystem

Wednesday, October 12, 2011

Count Lines in File


The fastest solution + holds only 1 line at a time in the memory (best solution)

Private Function TotalLines(filePath As String) As Integer
 Using r As New StreamReader(filePath)
  Dim i As Integer = 0
  While r.ReadLine() IsNot Nothing
   i += 1
  End While
  Return i
 End Using
End Function

Sunday, June 19, 2011

Retrieve Environment Variables

   1: ''' <summary>
   2: ''' Class to retrieve environment variables and custom declared variables with following format %VARIABLE%
   3: ''' </summary>
   4: ''' <remarks>A class used to read a string and transform all known variables with format %VARIABLE%,returning the converted string</remarks>
   5: Public Class VariableRetriever
   6:  
   7:     #Region "Methods"
   8:  
   9:     ''' <summary>
  10:     ''' Converts all known variables with format %VARIBALE% in the provided string
  11:     ''' </summary>
  12:     ''' <param name="str">Provide a string to transform</param>
  13:     ''' <returns>Returns the converted string</returns>
  14:     ''' <remarks>If an error occurs an empty string will be returned</remarks>
  15:     Protected Friend Shared Function GetAllVarFromString(ByVal str As String) As String
  16:         'try to get all the special %xxx% from the string
  17:         'replace and rebuild string
  18:         Try
  19:         
  20:             Dim split() As String = Nothing
  21:             Dim i As Integer = 0
  22:             Dim var As String = Nothing
  23:             Dim firstindex As Integer = Nothing
  24:             Dim secondindex As Integer = Nothing
  25:             If Not String.IsNullOrEmpty(str) Then
  26:                 If str.Contains("%") Then
  27:                     Do Until str.Contains("%") = False
  28:                         firstindex = Nothing
  29:                         secondindex = Nothing
  30:                         var = Nothing
  31:  
  32:                         firstindex = str.IndexOf("%")
  33:                         If Not firstindex = -1 Then
  34:                             secondindex = str.IndexOf("%", firstindex + 1)
  35:                             If Not secondindex = -1 Then
  36:                                 var = str.Substring(firstindex + 1, secondindex - firstindex - 1)
  37:                                 ReDim Preserve split(i)
  38:                                 split(i) = str.Substring(0, firstindex)
  39:                                 i = i + 1
  40:                                 ReDim Preserve split(i)
  41:                                 split(i) = GetVar(var)
  42:                                 str = str.Remove(0, secondindex + 1)
  43:                                 i = i + 1
  44:                             End If
  45:                         End If
  46:                     Loop
  47:                     ReDim Preserve split(i)
  48:                     split(i) = str
  49:                     If Not split.Length > 0 Then
  50:                         Return str
  51:                     Else
  52:                         Return Join(split, "")
  53:                     End If
  54:                 Else
  55:                     Return str
  56:                 End If
  57:             Else
  58:                 Return str
  59:             End If
  60:         Catch ex as Exception
  61:             Return ""
  62:         End Try
  63:     End Function 'End Method GetAllVarFromString
  64:  
  65:     ''' <summary>
  66:     ''' Converts a %VARIABLE% to it's value
  67:     ''' </summary>
  68:     ''' <param name="variable">Provide a variable %VARIABLE% as string</param>
  69:     ''' <returns>Returns converted string</returns>
  70:     ''' <remarks></remarks>
  71:     Protected Friend Shared Function GetVar(ByVal variable As String) As String
  72:         Try
  73:             If Not String.IsNullOrEmpty(variable) Then
  74:                 variable = RemoveProcents(variable)
  75:                 'Here you can add some variables
  76:                 'A few examples %APPPATH% will return the application startup path
  77:                 '%APPNAME% just gets the filename without extension
  78:                 Select Case UCase(variable)
  79:                     Case "APPPATH"
  80:                         Return Application.StartupPath
  81:                     Case "APPNAME"
  82:                         Return IO.Path.GetFileNameWithoutExtension(Application.ExecutablePath)
  83:                     Case Else
  84:                         Return Environment.GetEnvironmentVariable(RemoveProcents(variable))
  85:                 End Select
  86:             Else : Return variable
  87:             End If
  88:  
  89:         Catch ex As Exception
  90:             Return ""
  91:         End Try
  92:     End Function 'End Method GetVar
  93:     
  94:     ''' <summary>
  95:     ''' Removes all % characters in a string
  96:     ''' </summary>
  97:     ''' <param name="str">Provide a string</param>
  98:     ''' <returns>Returns a string with % characters stripped</returns>
  99:     ''' <remarks></remarks>
 100:     Private Shared Function RemoveProcents(ByVal str As String) As String
 101:         If Not String.IsNullOrEmpty(str) Then
 102:             str = Replace(str, "%", "")
 103:         End If
 104:         Return str
 105:     End Function 'End Method RemoveProcents
 106:  
 107: #End Region 'Methods
 108:  
 109: End Class 'End Type VariableRetriever
 110:  

Disclaimer

 
   1: #Region "Header"
   2: 'Copyright (c) 2011 <a href="http://kaoticreality.blogspot.com">Kraeven</a>
   3: '
   4: 'Knowledge needs to shared to enlighten the world ~ Kraeven ®
   5: '
   6: 'Permission is hereby granted, free of charge, to any person obtaining a copy
   7: 'of this software and associated documentation files (the "Software"), to deal
   8: 'in the Software without restriction, including without limitation the rights
   9: 'to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10: 'copies of the Software, and to permit persons to whom the Software is
  11: 'furnished to do so, subject to the following conditions:
  12: '
  13: 'The above copyright notice and this permission notice shall be included in
  14: 'all copies or substantial portions of the Software.
  15: '
  16: 'THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17: 'IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18: 'FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19: 'AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20: 'LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21: 'OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22: 'THE SOFTWARE.
  23:  
  24: #End Region 'Header