Agregar archivos de proyecto.

This commit is contained in:
2026-05-27 17:48:50 +02:00
commit 905514c2a9
34 changed files with 8253 additions and 0 deletions

63
.gitattributes vendored Normal file
View File

@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

363
.gitignore vendored Normal file
View File

@@ -0,0 +1,363 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

31
TSPdfUtils.sln Normal file
View File

@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36301.6
MinimumVisualStudioVersion = 10.0.40219.1
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "TSpdfUtils", "TSPdfUtils\TSpdfUtils.vbproj", "{EBE96C43-7754-94F0-D5A0-52CC0CC95392}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tsPDFUtilsCore", "tsPDFUtilsCore\tsPDFUtilsCore.csproj", "{87114C69-A12B-FADE-2C87-D199628C9366}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EBE96C43-7754-94F0-D5A0-52CC0CC95392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBE96C43-7754-94F0-D5A0-52CC0CC95392}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBE96C43-7754-94F0-D5A0-52CC0CC95392}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBE96C43-7754-94F0-D5A0-52CC0CC95392}.Release|Any CPU.Build.0 = Release|Any CPU
{87114C69-A12B-FADE-2C87-D199628C9366}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{87114C69-A12B-FADE-2C87-D199628C9366}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87114C69-A12B-FADE-2C87-D199628C9366}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87114C69-A12B-FADE-2C87-D199628C9366}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6C498ECD-A179-4303-8D50-CE1FF890325C}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,64 @@

Imports System.IO
Imports TSpdf.Kernel.Font
Imports System.Security.Cryptography.X509Certificates
Imports System.Security.Cryptography
Imports TSpdf.Kernel.Pdf
Imports TSpdf.Kernel.Utils
Imports TSpdf.Forms
Imports TSpdf.Signatures
Imports System.Text
Imports TSpdf.Kernel.Pdf.Canvas
Imports TSpdf.Kernel.Geom
Imports TSpdf.Layout.Element
Imports System.Text.RegularExpressions
Imports Org.BouncyCastle.Pkcs
Imports TSpdf.Commons.Bouncycastle.Cert
Imports TSpdf.Commons.Bouncycastle.Crypto
Imports TSpdf.Bouncycastle.Crypto
Imports TSpdf.Bouncycastle.Cert
Imports TSpdf
Imports Org.BouncyCastle.Crypto.Agreement
Imports TSpdf.Layout
Imports TSpdf.IO.Font.Constants
Imports TSpdf.Layout.Properties
Imports System.Drawing
Imports System.Drawing.Imaging
Imports Rectangle = System.Drawing.Rectangle
Imports TSpdf.Kernel.Pdf.Colorspace.PdfDeviceCs
Imports TSpdf.Layout.Renderer
Imports System.Drawing.Text
Imports System.Runtime.InteropServices
Imports TSpdf.Forms.Fields
Imports System.Runtime.CompilerServices
Imports TSpdf.Signatures.PdfSigner
Imports tsPDFUtilsCore
Public Class ExternalTimestampContainer
Implements IExternalSignatureContainer
Private ReadOnly tsaClient As ITSAClient
Public Sub New(ByVal tsaClient As ITSAClient)
Me.tsaClient = tsaClient
End Sub
Public Function Sign(ByVal data As Stream) As Byte() Implements IExternalSignatureContainer.Sign
' Calcula el hash del contenido usando SHA256
Dim hash As Byte()
Using hasher As HashAlgorithm = SHA256.Create()
hash = hasher.ComputeHash(data)
End Using
' Solicita la marca de tiempo a la TSA
Return tsaClient.GetTimeStampToken(hash)
End Function
Public Sub ModifySigningDictionary(ByVal signDic As PdfDictionary) Implements IExternalSignatureContainer.ModifySigningDictionary
signDic.Put(PdfName.Filter, PdfName.Adobe_PPKLite)
signDic.Put(PdfName.SubFilter, PdfName.ETSI_RFC3161)
End Sub
End Class

52
TSPdfUtils/FirmaTiempo.vb Normal file
View File

@@ -0,0 +1,52 @@
Imports System.IO
Imports Org.BouncyCastle.Pkcs
Imports TSpdf.Bouncycastle.Cert
Imports TSpdf.Bouncycastle.Crypto
Imports TSpdf.Commons.Bouncycastle.Cert
Imports TSpdf.Commons.Bouncycastle.Crypto
Imports TSpdf.Kernel.Pdf
Imports TSpdf.Signatures
Public Class FirmaTiempo
Public Shared Sub SignPdfWithTimestamp(src As String, dest As String, keystorePath As Stream, keystorePassword As String, tsaUrl As String)
Dim reader As New PdfReader(src)
Dim output As New FileStream(dest, FileMode.Create)
Dim signer As New PdfSigner(reader, output, New StampingProperties())
' Se coge los datos del certificado
Dim cpassword = keystorePassword.ToCharArray
Dim [alias] As String = Nothing
Dim pk12 As Pkcs12Store = New Pkcs12Store(keystorePath, cpassword)
For Each a In pk12.Aliases
[alias] = (CType(a, String))
If pk12.IsKeyEntry([alias]) Then
Exit For
End If
Next
Dim pk As IPrivateKey = New PrivateKeyBC(pk12.GetKey([alias]).Key)
Dim pks = New PrivateKeySignature(pk, DigestAlgorithms.SHA256)
Dim ce As X509CertificateEntry() = pk12.GetCertificateChain([alias])
Dim chain = New IX509Certificate(ce.Length - 1) {}
For k As Integer = 0 To ce.Length - 1
chain(k) = New X509CertificateBC(ce(k).Certificate)
Next
Dim externalSignature As IExternalSignature = New PrivateKeySignature(pk, "SHA-256")
' Aqui va la URL del servicio de sellado de tiempo
Dim tsaClient As ITSAClient = New TSAClientBouncyCastle(tsaUrl)
' Se hace la firma con el sellado de tiempo que se le pasa por parámetro
signer.SignDetached(externalSignature, chain, Nothing, Nothing, tsaClient, 0, PdfSigner.CryptoStandard.CADES)
End Sub
End Class

1259
TSPdfUtils/Firmas.vb Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MySubMain>true</MySubMain>
<MainForm>Form1</MainForm>
<SingleInstance>false</SingleInstance>
<ShutdownMode>0</ShutdownMode>
<EnableVisualStyles>true</EnableVisualStyles>
<AuthenticationMode>0</AuthenticationMode>
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>

View File

@@ -0,0 +1,83 @@
'------------------------------------------------------------------------------
' <auto-generated>
' Este código fue generado por una herramienta.
' Versión de runtime:4.0.30319.42000
'
' Los cambios en este archivo podrían causar un comportamiento incorrecto y se perderán si
' se vuelve a generar el código.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict On
Option Explicit On
Imports System
Namespace My.Resources
'StronglyTypedResourceBuilder generó automáticamente esta clase
'a través de una herramienta como ResGen o Visual Studio.
'Para agregar o quitar un miembro, edite el archivo .ResX y, a continuación, vuelva a ejecutar ResGen
'con la opción /str o recompile su proyecto de VS.
'''<summary>
''' Clase de recurso fuertemente tipado, para buscar cadenas traducidas, etc.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
Friend Module Resources
Private resourceMan As Global.System.Resources.ResourceManager
Private resourceCulture As Global.System.Globalization.CultureInfo
'''<summary>
''' Devuelve la instancia de ResourceManager almacenada en caché utilizada por esta clase.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
Get
If Object.ReferenceEquals(resourceMan, Nothing) Then
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("TSpdfUtils.Resources", GetType(Resources).Assembly)
resourceMan = temp
End If
Return resourceMan
End Get
End Property
'''<summary>
''' Reemplaza la propiedad CurrentUICulture del subproceso actual para todas las
''' búsquedas de recursos mediante esta clase de recurso fuertemente tipado.
'''</summary>
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
Friend Property Culture() As Global.System.Globalization.CultureInfo
Get
Return resourceCulture
End Get
Set
resourceCulture = value
End Set
End Property
'''<summary>
''' Busca un recurso adaptado de tipo System.Byte[].
'''</summary>
Friend ReadOnly Property Fogra39L() As Byte()
Get
Dim obj As Object = ResourceManager.GetObject("Fogra39L", resourceCulture)
Return CType(obj,Byte())
End Get
End Property
'''<summary>
''' Busca un recurso adaptado de tipo System.Byte[].
'''</summary>
Friend ReadOnly Property sRGB2014() As Byte()
Get
Dim obj As Object = ResourceManager.GetObject("sRGB2014", resourceCulture)
Return CType(obj,Byte())
End Get
End Property
End Module
End Namespace

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Fogra39L" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Coated_Fogra39L_VIGC_300.icc;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="sRGB2014" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\sRGB2014.icc;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

BIN
TSPdfUtils/Resource.Designer.vb generated Normal file

Binary file not shown.

124
TSPdfUtils/Resource.resx Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="ilits" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\ilits.ttf;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
</root>

Binary file not shown.

Binary file not shown.

Binary file not shown.

75
TSPdfUtils/Sellado.cs Normal file
View File

@@ -0,0 +1,75 @@
using System.Collections.Generic;
using System.IO;
namespace TSpdfUtils
{
public class Sellado
{
public static void SellaPDF(Stream PdfOrigen, Stream PdfDestino, List<TextoEnPdf> TextosAInsertar, List<string> ImagenesAInsertar)
{
}
public class TextoEnPdf
{
public string Texto { get; set; }
public FuenteEnum Fuente { get; set; }
public float TamañoFuente { get; set; }
public System.Drawing.Color Color { get; set; }
public double Transparencia { get; set; }
public EsquinaEnum EsquinaReferencia { get; set; }
public float AnguloRotacion { get; set; }
public AlineamientoEnum Alineamiento { get; set; }
public float CoordenadaX { get; set; }
public float CoordenadaY { get; set; }
public int PaginaInicio { get; set; }
public int PaginaFin { get; set; }
}
public class ImagenEnPdf
{
public byte[] Imagen { get; set; }
public EsquinaEnum EsquinaReferencia { get; set; }
public double Transparencia { get; set; }
public float CoordenadaX { get; set; }
public float CoordenadaY { get; set; }
public float AnguloRotacion { get; set; }
public int PaginaInicio { get; set; }
public int PaginaFin { get; set; }
}
public enum EsquinaEnum : int
{
INFERIOR_IZQUIERDA = 0,
INFERIOR_DERECHA = 1,
SUPERIOR_IZQUIERDA = 2,
SUPERIOR_DERECHA = 3
}
public enum AlineamientoEnum : int
{
IZQUIERDA = 0,
DERECHA = 1,
CENTRO = 2,
JUSTIFICADO = 3
}
public enum FuenteEnum
{
COURIER,
COURIER_BOLD,
COURIER_BOLDOBLIQUE,
COURIER_OBLIQUE,
HELVETICA,
HELVETICA_BOLD,
HELVETICA_BOLDOBLIQUE,
HELVETICA_OBLIQUE,
SYMBOL,
TIMES_ROMAN,
TIMES_BOLD,
TIMES_BOLDITALIC,
TIMES_ITALIC,
ZAPFDINGBATS
}
}
}

View File

@@ -0,0 +1,83 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<SignAssembly>True</SignAssembly>
<DelaySign>False</DelaySign>
<DocumentationFile>$(TargetDir)bin\$(Configuration)\$(TargetFramework)\TSpdfUtils.xml</DocumentationFile>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net48</TargetFrameworks>
<OutputType>library</OutputType>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RootNamespace>TSpdfUtils</RootNamespace>
<AssemblyName>TSpdfUtils</AssemblyName>
<PackageId>TSpdfUtils</PackageId>
<PackageTags>libreria, netstandard2.0</PackageTags>
<AssemblyVersion>1.0.18</AssemblyVersion>
<FileVersion>1.0.18</FileVersion>
<Version>1.0.18</Version>
<Authors>Manuel</Authors>
<Company>Tecnosis S.A</Company>
<Description>Utilidades de tratamiento de pdf, de firmas digitales e imagenes.</Description>
<PackageReleaseNotes>
- 1.0.18 2026-05-20 Correcciones dependencias Microsoft.Extensions.Logging
- 1.0.16 2025-10-23 Actualización de tspdfutilscore
- 1.0.14 2025-10-09 Limpieza de compilados
- 1.0.13 2025-10-09 Se eliminan destinos del framework 461 y 48
- 1.0.12 2025-10-09 Actualización para paquete baget
- 1.0.11 2025-10-06 Corrección en dependencias en tspPDFUtilsCore
- 1.0.10 2025-10-06 Corrección en dependencias
- 1.0.9 2025-10-03 Corrección en dependencias
- 1.0.8 Corrección en dependencias
- 1.0.7 Corrección en TSpdf.io
- 1.0.6 Corrección en TSpdf.io
- 1.0.4 Corrección en TSpdf.io
</PackageReleaseNotes>
</PropertyGroup>
<PropertyGroup>
<NoWarn>1701;1702;1591;1570;1572;1573;1574;1580;1584;1658</NoWarn>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net48' ">
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<None Remove="Sellado.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.9" />
<PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" />
<PackageReference Include="TSpdf.kernel" Version="3.0.0" />
<PackageReference Include="TSpdf.layout" Version="3.0.0" />
<PackageReference Include="TSpdf.pdfa" Version="3.0.0" />
<PackageReference Include="TSpdf.sign" Version="3.0.0" />
<PackageReference Include="TSpdf.X509" Version="3.0.0" />
<!----> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\tsPDFUtilsCore\tsPDFUtilsCore.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="My Project\Resources.Designer.vb">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="My Project\Resources.resx">
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

195
TSPdfUtils/Utilidades.vb Normal file
View File

@@ -0,0 +1,195 @@
Imports System.IO
Imports System.Text
Imports TSpdf.Kernel.Pdf
Imports TSpdf.Kernel.Utils
Imports TSpdf.Pdfa
Public Class Utilidades
'Convierte un pdf normal en el formato pdf_A_3B
Public Shared Function crearPDFA(ByVal pdfOrigen As Stream) As MemoryStream
Dim reader As New PdfReader(pdfOrigen)
Dim ms As New MemoryStream
Dim writerProps As New WriterProperties()
writerProps.SetPdfVersion(PdfVersion.PDF_2_0)
Dim writer As New PdfWriter(ms, writerProps)
writer.SetSmartMode(True)
' Necesario para que el memorystream no se cierre y siga abieto
writer.SetCloseStream(False)
Dim sourcePdf As New PdfDocument(reader)
Dim esRGB As Boolean = recorrerPaginas(sourcePdf)
For page As Integer = 1 To sourcePdf.GetNumberOfPages()
Dim paginaActual = sourcePdf.GetPage(page)
Dim anotaciones = paginaActual.GetAnnotations()
If anotaciones IsNot Nothing Then
For Each anotacionActual In anotaciones
Dim diccionario = anotacionActual.GetPdfObject()
If Not diccionario.ContainsKey(PdfName.F) Then
diccionario.Put(PdfName.F, New PdfNumber(4))
End If
Next
End If
Next
Dim disPDF As PdfADocument
'If esRGB Then
' disPDF = New PdfADocument(writer, PdfAConformanceLevel.PDF_A_3B,
' New PdfOutputIntent("Custom", "", "https://www.color.org", "sRGB",
' New MemoryStream(My.Resources.sRGB2014)))
'Else
' disPDF = New PdfADocument(writer, PdfAConformanceLevel.PDF_A_3B,
' New PdfOutputIntent("Custom", "", "https://www.color.org", "FOGRA39",
' New MemoryStream(My.Resources.Fogra39L)))
'End If
disPDF = New PdfADocument(writer, PdfAConformanceLevel.PDF_A_3B,
New PdfOutputIntent("Custom", "", "https://www.color.org", "sRGB",
New MemoryStream(My.Resources.sRGB2014)))
disPDF.InitializeOutlines()
' Configurar parámetros requeridos
disPDF.SetTagged()
disPDF.GetCatalog().SetLang(New PdfString("es-ES"))
disPDF.GetCatalog().SetViewerPreferences(New PdfViewerPreferences().SetDisplayDocTitle(True))
Dim merger As New PdfMerger(disPDF, True, True)
merger.Merge(sourcePdf, 1, sourcePdf.GetNumberOfPages())
sourcePdf.Close()
disPDF.Close()
reader.Close()
writer.Close()
' Esto hace falta para volver al inicio del memorystream
ms.Position = 0
Return ms
End Function
Public Shared Function controlarInterpolate(ByVal resources As PdfDictionary, ByVal tieneRGB As Boolean) As Boolean
Dim xObjects = resources?.GetAsDictionary(PdfName.XObject)
Dim tieneRGBActual As Boolean = tieneRGB
If xObjects IsNot Nothing Then
For Each key In xObjects.KeySet()
Dim stream = xObjects.GetAsStream(key)
Dim subtype = stream.GetAsName(PdfName.Subtype)
If PdfName.Image.Equals(subtype) Then
If stream.GetAsBoolean(PdfName.Interpolate)?.GetValue = True Then
stream.Put(PdfName.Interpolate, PdfBoolean.FALSE)
End If
Dim colorSpace = stream.Get(PdfName.ColorSpace)
If colorSpace IsNot Nothing AndAlso colorSpace.Equals(PdfName.DeviceRGB) Then
tieneRGBActual = True
tieneRGB = True
End If
ElseIf PdfName.Form.Equals(subtype) Then
Dim formRes = stream.GetAsDictionary(PdfName.Resources)
If formRes IsNot Nothing Then
Dim hijoTieneRGB As Boolean = controlarInterpolate(formRes, tieneRGBActual)
If hijoTieneRGB Then
tieneRGBActual = True
End If
End If
End If
Next
End If
Return tieneRGBActual
End Function
Public Shared Function recorrerPaginas(ByVal pdf As PdfDocument) As Boolean
Dim tieneRGB As Boolean = False
For i As Integer = 1 To pdf.GetNumberOfPages
Dim rgbMinimo As Boolean = False
Dim diccPaginaActual = pdf.GetPage(i).GetResources().GetPdfObject()
rgbMinimo = controlarInterpolate(diccPaginaActual, tieneRGB)
If rgbMinimo Then
tieneRGB = True
End If
Next
Return tieneRGB
End Function
Public Shared Sub RepararAnotacionesSinF(pdfDoc As PdfDocument)
For page As Integer = 1 To pdfDoc.GetNumberOfPages()
Dim paginaActual = pdfDoc.GetPage(page)
Dim anotaciones = paginaActual.GetAnnotations()
If anotaciones IsNot Nothing Then
For Each anotacionActual In anotaciones
Dim diccionario = anotacionActual.GetPdfObject()
If Not diccionario.ContainsKey(PdfName.F) Then
diccionario.Put(PdfName.F, New PdfNumber(4))
End If
Next
End If
Next
End Sub
Public Shared Function TieneMarcaPdfA(pdfStream As Stream) As Boolean
Try
If pdfStream Is Nothing Then Return False
If pdfStream.CanSeek Then
pdfStream.Position = 0
End If
Using reader As New PdfReader(pdfStream)
Using pdf As New PdfDocument(reader)
Dim metadata As Byte() = pdf.GetXmpMetadata()
If metadata Is Nothing OrElse metadata.Length = 0 Then
Return False
End If
Dim xmpString As String = Encoding.UTF8.GetString(metadata)
Return xmpString.Contains("pdfaid:part")
End Using
End Using
Catch
Return False
End Try
End Function
End Class

2375
TSPdfUtils/UtilsCert.vb Normal file

File diff suppressed because it is too large Load Diff

743
TSPdfUtils/pdf.vb Normal file
View File

@@ -0,0 +1,743 @@

Imports System.IO
Imports TSpdf.Kernel.Font
Imports System.Security.Cryptography.X509Certificates
Imports System.Security.Cryptography
Imports TSpdf.Kernel.Pdf
Imports TSpdf.Kernel.Utils
Imports TSpdf.Forms
Imports TSpdf.Signatures
Imports System.Text
Imports TSpdf.Kernel.Pdf.Action
Imports TSpdf.Kernel.Pdf.Navigation
Imports TSpdf.Kernel.Pdf.Canvas
Imports TSpdf.Kernel.Geom
Imports TSpdf.Layout.Element
Imports TSpdf.IO.Font.Constants
Imports System.Diagnostics.Contracts
Imports System.Text.RegularExpressions
Imports Microsoft.VisualBasic.Devices
Imports Org.BouncyCastle.Asn1
Imports Org.BouncyCastle.Pkcs
Imports TSpdf.Commons.Bouncycastle.Cert
Imports TSpdf.Commons.Bouncycastle.Crypto
Imports TSpdf.Bouncycastle.Crypto
Imports TSpdf.Bouncycastle.Cert
Imports Org.BouncyCastle.Asn1.X509
Imports Org.BouncyCastle.X509
Imports Org.BouncyCastle.Crypto.Tls
Imports TSpdf
Imports TSpdf.Kernel.Pdf.Canvas.Parser
Imports TSpdf.Kernel.Pdf.Canvas.Parser.Listener
Public Class pdf
Public Shared Sub Aplanar(Origen As String)
Dim PdfDocument = New PdfDocument(New PdfReader(Origen))
Dim form = PdfAcroForm.GetAcroForm(PdfDocument, False)
If form IsNot Nothing Then form.FlattenFields()
PdfDocument.Close()
End Sub
Public Shared Sub Aplanar(Origen As String, Destino As String)
Dim PdfDocument = New PdfDocument(New PdfReader(Origen), New PdfWriter(Destino))
Dim form = PdfAcroForm.GetAcroForm(PdfDocument, False)
If form IsNot Nothing Then form.FlattenFields()
PdfDocument.Close()
End Sub
Public Shared Function ObtieneFicheroAleatorio(ByVal Extension As String) As String
Dim sFichero As String = System.IO.Path.GetTempPath & System.IO.Path.GetRandomFileName & "." & Extension
Do While System.IO.File.Exists(sFichero)
'Try
' IO.File.Delete(sFichero)
'Catch ex As Exception
sFichero = System.IO.Path.GetTempPath & "\" & System.IO.Path.GetRandomFileName & "." & Extension
' End Try
Loop
Return sFichero
End Function
Public Shared Sub UnePdfs(Pdfs()() As Byte, outputPdf As String, Optional UnirTags As Boolean = True, Optional UnirMarcadores As Boolean = True, Optional MarcadoresInicioFichero() As String = Nothing, Optional Aplanar As Boolean = True)
Dim lista = Pdfs.Select(Function(x) New MemoryStream(x)).ToArray
UnePdfs(lista, outputPdf, UnirTags, UnirMarcadores, MarcadoresInicioFichero, Aplanar)
End Sub
Public Shared Sub UnePdfs(Pdfs() As String, st As Stream, Optional UnirTags As Boolean = True, Optional UnirMarcadores As Boolean = True, Optional MarcadoresInicioFichero() As String = Nothing, Optional Aplanar As Boolean = True)
Try
Dim pdfw As New PdfWriter(st)
Dim pdfDoc As PdfDocument = New PdfDocument(pdfw)
Dim merger As PdfMerger = New PdfMerger(pdfDoc, UnirTags, UnirMarcadores)
Dim i As Integer = 0
Dim NumeroPaginasTotal As Integer = 1
Dim rootoutline As PdfOutline = Nothing
Dim pagini(Pdfs.Count - 1) As Integer
For Each pdf In Pdfs
i += 1
Dim pdfr As New PdfReader(pdf)
pdfr.SetUnethicalReading(True)
Dim ms As New MemoryStream
Dim pdfwtmp As New PdfWriter(ms)
Dim srcDoc As PdfDocument
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores Then
srcDoc = New PdfDocument(pdfr, pdfwtmp)
MueveMarcadorARaiz(srcDoc, MarcadoresInicioFichero(i - 1))
srcDoc.Close()
pdfr = New PdfReader(New MemoryStream(ms.ToArray))
srcDoc = New PdfDocument(pdfr)
Else
srcDoc = New PdfDocument(pdfr)
End If
Dim np = srcDoc.GetNumberOfPages
pagini(i - 1) = np
If Aplanar Then
Dim form = PdfAcroForm.GetAcroForm(srcDoc, False)
If form IsNot Nothing Then form.FlattenFields()
End If
merger.SetCloseSourceDocuments(i = Pdfs.Count).Merge(srcDoc, 1, np)
srcDoc.Close()
Next
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores = False Then
pdfDoc.InitializeOutlines()
rootoutline = pdfDoc.GetOutlines(False)
For i = 0 To pagini.Length - 1
Dim oul As PdfOutline = rootoutline.AddOutline(MarcadoresInicioFichero(i))
oul.AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(NumeroPaginasTotal)))
NumeroPaginasTotal += pagini(i)
Next
End If
pdfDoc.Close()
pdfw.Close()
merger.Close()
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Public Shared Sub UnePdfs(Pdfs() As String, outputPdf As String, Optional UnirTags As Boolean = True, Optional UnirMarcadores As Boolean = True, Optional MarcadoresInicioFichero() As String = Nothing, Optional Aplanar As Boolean = True)
Try
Dim pdfw As New PdfWriter(outputPdf)
Dim pdfDoc As PdfDocument = New PdfDocument(pdfw)
Dim merger As PdfMerger = New PdfMerger(pdfDoc, UnirTags, UnirMarcadores)
Dim i As Integer = 0
Dim NumeroPaginasTotal As Integer = 1
Dim rootoutline As PdfOutline = Nothing
Dim pagini(Pdfs.Count - 1) As Integer
For Each pdf In Pdfs
i += 1
Dim pdfr As New PdfReader(pdf)
pdfr.SetUnethicalReading(True)
Dim ms As New MemoryStream
Dim pdfwtmp As New PdfWriter(ms)
Dim srcDoc As PdfDocument
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores Then
srcDoc = New PdfDocument(pdfr, pdfwtmp)
MueveMarcadorARaiz(srcDoc, MarcadoresInicioFichero(i - 1))
srcDoc.Close()
pdfr = New PdfReader(New MemoryStream(ms.ToArray))
srcDoc = New PdfDocument(pdfr)
Else
srcDoc = New PdfDocument(pdfr)
End If
Dim np = srcDoc.GetNumberOfPages
pagini(i - 1) = np
If Aplanar Then
Dim form = PdfAcroForm.GetAcroForm(srcDoc, False)
If form IsNot Nothing Then form.FlattenFields()
End If
merger.SetCloseSourceDocuments(i = Pdfs.Count).Merge(srcDoc, 1, np)
srcDoc.Close()
Next
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores = False Then
pdfDoc.InitializeOutlines()
rootoutline = pdfDoc.GetOutlines(False)
For i = 0 To pagini.Length - 1
Dim oul As PdfOutline = rootoutline.AddOutline(MarcadoresInicioFichero(i))
oul.AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(NumeroPaginasTotal)))
NumeroPaginasTotal += pagini(i)
Next
End If
pdfDoc.Close()
pdfw.Close()
merger.Close()
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Public Shared Sub UnePdfs(Pdfs() As Stream, outputPdf As String, Optional UnirTags As Boolean = True, Optional UnirMarcadores As Boolean = True, Optional MarcadoresInicioFichero() As String = Nothing, Optional Aplanar As Boolean = True)
Try
Dim pdfw As New PdfWriter(outputPdf)
Dim pdfDoc As PdfDocument = New PdfDocument(pdfw)
Dim merger As PdfMerger = New PdfMerger(pdfDoc, UnirTags, UnirMarcadores)
Dim i As Integer = 0
Dim NumeroPaginasTotal As Integer = 1
Dim rootoutline As PdfOutline = Nothing
Dim pagini(Pdfs.Count - 1) As Integer
For Each pdf In Pdfs
i += 1
Dim pdfr As New PdfReader(pdf)
pdfr.SetUnethicalReading(True)
Dim ms As New MemoryStream
Dim pdfwtmp As New PdfWriter(ms)
Dim srcDoc As PdfDocument
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores Then
srcDoc = New PdfDocument(pdfr, pdfwtmp)
MueveMarcadorARaiz(srcDoc, MarcadoresInicioFichero(i - 1))
srcDoc.Close()
pdfr = New PdfReader(New MemoryStream(ms.ToArray))
srcDoc = New PdfDocument(pdfr)
Else
srcDoc = New PdfDocument(pdfr)
End If
Dim np = srcDoc.GetNumberOfPages
pagini(i - 1) = np
If Aplanar Then
Dim form = PdfAcroForm.GetAcroForm(srcDoc, False)
If form IsNot Nothing Then form.FlattenFields()
End If
merger.SetCloseSourceDocuments(i = Pdfs.Count).Merge(srcDoc, 1, np)
srcDoc.Close()
Next
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores = False Then
pdfDoc.InitializeOutlines()
rootoutline = pdfDoc.GetOutlines(False)
For i = 0 To pagini.Length - 1
Dim oul As PdfOutline = rootoutline.AddOutline(MarcadoresInicioFichero(i))
oul.AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(NumeroPaginasTotal)))
NumeroPaginasTotal += pagini(i)
Next
End If
pdfDoc.Close()
pdfw.Close()
merger.Close()
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Public Shared Function UnePdfs(Pdfs()() As Byte, Optional UnirTags As Boolean = True, Optional UnirMarcadores As Boolean = True, Optional MarcadoresInicioFichero() As String = Nothing, Optional Aplanar As Boolean = True) As Byte()
Dim lista = Pdfs.Select(Function(x) New MemoryStream(x)).ToArray
Return UnePdfs(lista, UnirTags, UnirMarcadores, MarcadoresInicioFichero, Aplanar)
End Function
Public Shared Function UnePdfs(Pdfs() As Stream, Optional UnirTags As Boolean = True, Optional UnirMarcadores As Boolean = True, Optional MarcadoresInicioFichero() As String = Nothing, Optional Aplanar As Boolean = True) As Byte()
Try
Dim msw As New MemoryStream
Dim pdfw As New PdfWriter(msw)
Dim pdfDoc As PdfDocument = New PdfDocument(pdfw)
Dim merger As PdfMerger = New PdfMerger(pdfDoc, UnirTags, UnirMarcadores)
Dim i As Integer = 0
Dim NumeroPaginasTotal As Integer = 1
Dim rootoutline As PdfOutline = Nothing
Dim pagini(Pdfs.Count - 1) As Integer
For Each pdf In Pdfs
i += 1
Dim pdfr As New PdfReader(pdf)
pdfr.SetUnethicalReading(True)
Dim ms As New MemoryStream
Dim pdfwtmp As New PdfWriter(ms)
Dim srcDoc As PdfDocument
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores Then
srcDoc = New PdfDocument(pdfr, pdfwtmp)
MueveMarcadorARaiz(srcDoc, MarcadoresInicioFichero(i - 1))
srcDoc.Close()
pdfr = New PdfReader(New MemoryStream(ms.ToArray))
srcDoc = New PdfDocument(pdfr)
Else
srcDoc = New PdfDocument(pdfr)
End If
Dim np = srcDoc.GetNumberOfPages
pagini(i - 1) = np
If Aplanar Then
Dim form = PdfAcroForm.GetAcroForm(srcDoc, False)
If form IsNot Nothing Then form.FlattenFields()
End If
merger.SetCloseSourceDocuments(i = Pdfs.Count).Merge(srcDoc, 1, np)
srcDoc.Close()
Next
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores = False Then
pdfDoc.InitializeOutlines()
rootoutline = pdfDoc.GetOutlines(False)
For i = 0 To pagini.Length - 1
Dim oul As PdfOutline = rootoutline.AddOutline(MarcadoresInicioFichero(i))
oul.AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(NumeroPaginasTotal)))
NumeroPaginasTotal += pagini(i)
Next
End If
pdfDoc.Close()
pdfw.Close()
merger.Close()
Return msw.ToArray
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Function
Public Shared Sub UnePdfs(Pdfs() As Stream, Destino As Stream, Optional UnirTags As Boolean = True, Optional UnirMarcadores As Boolean = True, Optional MarcadoresInicioFichero() As String = Nothing, Optional Aplanar As Boolean = True)
Try
Dim pdfw As New PdfWriter(Destino)
Dim pdfDoc As PdfDocument = New PdfDocument(pdfw)
Dim merger As PdfMerger = New PdfMerger(pdfDoc, UnirTags, UnirMarcadores)
Dim i As Integer = 0
Dim NumeroPaginasTotal As Integer = 1
Dim rootoutline As PdfOutline = Nothing
Dim pagini(Pdfs.Count - 1) As Integer
For Each pdf In Pdfs
i += 1
Dim pdfr As New PdfReader(pdf)
pdfr.SetUnethicalReading(True)
Dim ms As New MemoryStream
Dim pdfwtmp As New PdfWriter(ms)
Dim srcDoc As PdfDocument
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores Then
srcDoc = New PdfDocument(pdfr, pdfwtmp)
MueveMarcadorARaiz(srcDoc, MarcadoresInicioFichero(i - 1))
srcDoc.Close()
pdfr = New PdfReader(New MemoryStream(ms.ToArray))
srcDoc = New PdfDocument(pdfr)
Else
srcDoc = New PdfDocument(pdfr)
End If
Dim np = srcDoc.GetNumberOfPages
pagini(i - 1) = np
If Aplanar Then
Dim form = PdfAcroForm.GetAcroForm(srcDoc, False)
If form IsNot Nothing Then form.FlattenFields()
End If
merger.SetCloseSourceDocuments(i = Pdfs.Count).Merge(srcDoc, 1, np)
srcDoc.Close()
Next
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores = False Then
pdfDoc.InitializeOutlines()
rootoutline = pdfDoc.GetOutlines(False)
For i = 0 To pagini.Length - 1
Dim oul As PdfOutline = rootoutline.AddOutline(MarcadoresInicioFichero(i))
oul.AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(NumeroPaginasTotal)))
NumeroPaginasTotal += pagini(i)
Next
End If
pdfDoc.Close()
pdfw.Close()
merger.Close()
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Public Shared Function UnePdfs(Pdfs() As String, Optional UnirTags As Boolean = True, Optional UnirMarcadores As Boolean = True, Optional MarcadoresInicioFichero() As String = Nothing, Optional Aplanar As Boolean = True) As Byte()
Try
Dim msw As New MemoryStream
Dim pdfw As New PdfWriter(msw)
Dim pdfDoc As PdfDocument = New PdfDocument(pdfw)
Dim merger As PdfMerger = New PdfMerger(pdfDoc, UnirTags, UnirMarcadores)
Dim i As Integer = 0
Dim NumeroPaginasTotal As Integer = 1
Dim rootoutline As PdfOutline = Nothing
Dim pagini(Pdfs.Count - 1) As Integer
For Each pdf In Pdfs
i += 1
Dim pdfr As New PdfReader(pdf)
pdfr.SetUnethicalReading(True)
Dim ms As New MemoryStream
Dim pdfwtmp As New PdfWriter(ms)
Dim srcDoc As PdfDocument
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores Then
srcDoc = New PdfDocument(pdfr, pdfwtmp)
MueveMarcadorARaiz(srcDoc, MarcadoresInicioFichero(i - 1))
srcDoc.Close()
pdfr = New PdfReader(New MemoryStream(ms.ToArray))
srcDoc = New PdfDocument(pdfr)
Else
srcDoc = New PdfDocument(pdfr)
End If
Dim np = srcDoc.GetNumberOfPages
pagini(i - 1) = np
If Aplanar Then
Dim form = PdfAcroForm.GetAcroForm(srcDoc, False)
If form IsNot Nothing Then form.FlattenFields()
End If
merger.SetCloseSourceDocuments(i = Pdfs.Count).Merge(srcDoc, 1, np)
srcDoc.Close()
Next
If MarcadoresInicioFichero IsNot Nothing AndAlso UnirMarcadores = False Then
pdfDoc.InitializeOutlines()
rootoutline = pdfDoc.GetOutlines(False)
For i = 0 To pagini.Length - 1
Dim oul As PdfOutline = rootoutline.AddOutline(MarcadoresInicioFichero(i))
oul.AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(NumeroPaginasTotal)))
NumeroPaginasTotal += pagini(i)
Next
End If
pdfDoc.Close()
pdfw.Close()
merger.Close()
Return msw.ToArray
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Function
Private Shared Sub MueveMarcadorARaiz(ByVal pdfDocument As PdfDocument, ByVal EtiquetaMarcadorRaiz As String)
pdfDocument.InitializeOutlines()
Try
Dim pp = pdfDocument.GetFirstPage()
Dim rootOutline As PdfOutline = pdfDocument.GetOutlines(False)
Dim subOutline As PdfOutline = rootOutline.AddOutline(EtiquetaMarcadorRaiz)
Dim dest As PdfDestination = PdfExplicitDestination.CreateFit(pp)
subOutline.AddDestination(dest)
Dim pdfOutlineChildren As List(Of PdfOutline) = rootOutline.GetAllChildren().ToList
If pdfOutlineChildren.Count = 1 Then
Return
End If
Dim i As Integer = 0
Dim p As PdfOutline
For Each p In pdfOutlineChildren
If Not p.Equals(subOutline) Then
Dim nd = p.GetDestination
If nd Is Nothing Then nd = dest
dest = nd
Corrigeoutl(p, dest)
subOutline.AddOutline(p)
End If
Next
rootOutline.GetAllChildren().Clear()
rootOutline.AddOutline(subOutline)
subOutline.AddDestination(PdfExplicitDestination.CreateFit(pdfDocument.GetFirstPage()))
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Private Shared Sub CreaMarcadorInicioFichero(ByVal pdfDocument As PdfDocument, ByVal EtiquetaMarcadorRaiz As String)
pdfDocument.InitializeOutlines()
Try
Dim pp = pdfDocument.GetFirstPage()
Dim rootOutline As PdfOutline = pdfDocument.GetOutlines(False)
Dim subOutline As PdfOutline = rootOutline.AddOutline(EtiquetaMarcadorRaiz)
Dim dest As PdfDestination = PdfExplicitDestination.CreateFit(pp)
subOutline.AddDestination(dest)
Dim pdfOutlineChildren As List(Of PdfOutline) = rootOutline.GetAllChildren().ToList
If pdfOutlineChildren.Count = 1 Then
Return
End If
Dim i As Integer = 0
Dim p As PdfOutline
For Each p In pdfOutlineChildren
If Not p.Equals(subOutline) Then
Dim nd = p.GetDestination
If nd Is Nothing Then nd = dest
dest = nd
Corrigeoutl(p, dest)
subOutline.AddOutline(p)
End If
Next
rootOutline.GetAllChildren().Clear()
rootOutline.AddOutline(subOutline)
subOutline.AddDestination(PdfExplicitDestination.CreateFit(pdfDocument.GetFirstPage()))
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Private Shared Sub Corrigeoutl(p As PdfOutline, ByRef ultimoDestino As PdfDestination)
If p.GetDestination Is Nothing Then
p.AddDestination(ultimoDestino)
End If
Dim hijos = p.GetAllChildren
For Each h In hijos
If h.GetDestination Is Nothing OrElse h.GetDestination.GetPdfObject Is Nothing Then
h.AddDestination(ultimoDestino)
End If
ultimoDestino = h.GetDestination
Corrigeoutl(h, ultimoDestino)
Next
End Sub
Public Shared Function ObtieneNumeroPaginasPDF(PDF As String) As Integer
Dim pdfr As New PdfReader(PDF)
Dim NP = New PdfDocument(pdfr).GetNumberOfPages
pdfr.Close()
Return NP
End Function
Public Shared Sub ConvierteAPDFX(PdfOrigen As String, PdfDestino As String)
Dim wp As WriterProperties = New WriterProperties()
wp.SetPdfVersion(PdfVersion.PDF_1_3)
Dim pdfDoc As PdfDocument = New PdfDocument(New PdfReader(PdfOrigen), New PdfWriter(PdfDestino, wp))
pdfDoc.Close()
End Sub
Public Shared Sub RotarPdf(ByVal PdfOrigen As String, ByVal PdfDestino As String, Grados As Integer)
Dim pdfDoc As PdfDocument = New PdfDocument(New PdfReader(PdfOrigen), New PdfWriter(PdfDestino))
For p As Integer = 1 To pdfDoc.GetNumberOfPages()
Dim page As PdfPage = pdfDoc.GetPage(p)
Dim rotate As Integer = page.GetRotation()
If rotate = 0 Then
page.SetRotation(Grados)
Else
page.SetRotation((rotate + Grados) Mod 360)
End If
Next
pdfDoc.Close()
End Sub
Public Shared Sub RecortaPDF(ByVal PdfOrigen As String, PdfRecortado As String, PaginaInicio As Integer, PaginaFin As Integer)
Dim pdfDoc As PdfDocument = New PdfDocument(New PdfWriter(PdfRecortado))
Dim merger As PdfMerger = New PdfMerger(pdfDoc, False, False)
Dim srcDoc As PdfDocument = New PdfDocument(New PdfReader(PdfOrigen))
Dim np = srcDoc.GetNumberOfPages
merger.SetCloseSourceDocuments(True).Merge(srcDoc, PaginaInicio, PaginaFin)
pdfDoc.Close()
End Sub
Public Shared Sub RellenaFormularioPDF(PdfOrigen As String, PdfDestino As String, Valores As Hashtable, Optional Aplanar As Boolean = True)
Try
Dim fs As New FileStream(PdfDestino, FileMode.CreateNew, FileAccess.Write)
RellenaFormularioPDF(PdfOrigen, fs, Valores, Aplanar)
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Public Shared Sub RellenaFormularioPDF(PdfOrigen As String, PdfDestino As String, Valores As String, Optional Aplanar As Boolean = True)
Try
Dim fs As New FileStream(PdfDestino, FileMode.CreateNew, FileAccess.Write)
Dim ht As New Hashtable
Dim pares = Valores.Split("|")
For Each par In pares
ht.Add(par.Split(":")(0), par.Split(":")(1))
Next
RellenaFormularioPDF(PdfOrigen, fs, ht, Aplanar)
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Public Shared Sub RellenaFormularioPDF(PdfOrigen As String, Destino As Stream, Valores As Hashtable, Optional Aplanar As Boolean = True)
Try
Dim pdfReader As New PdfReader(PdfOrigen)
Dim pdfDoc As New PdfDocument(pdfReader, New PdfWriter(Destino))
Dim form = PdfAcroForm.GetAcroForm(pdfDoc, True)
For Each Valor As DictionaryEntry In Valores
Try
form.GetField(Valor.Key).SetValue(Valor.Value)
Catch ex As Exception
End Try
Next
If Aplanar Then
form.FlattenFields()
End If
pdfDoc.Close()
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Public Shared Function RellenaFormularioPDF(PdfOrigen As Byte(), ListaValores As List(Of Hashtable), Optional Aplanar As Boolean = True) As Byte()
Try
Dim i, j As Integer
Dim iosPdf(ListaValores.Count - 1)() As Byte
For i = 0 To ListaValores.Count - 1
Dim pdfReader As New PdfReader(New MemoryStream(PdfOrigen))
Dim Valores = ListaValores(i)
Dim ms As New MemoryStream
Dim pdfDoc As New PdfDocument(pdfReader, New PdfWriter(ms))
Dim form = PdfAcroForm.GetAcroForm(pdfDoc, True)
For Each Valor As DictionaryEntry In Valores
Try
form.GetField(Valor.Key).SetValue(Valor.Value)
Catch ex As Exception
End Try
Next
If Aplanar Then
form.FlattenFields()
End If
pdfDoc.Close()
' ms.Seek(0, 0)
iosPdf(i) = ms.ToArray
Next
If ListaValores.Count = 1 Then
Return iosPdf(0).ToArray
Else
Return UnePdfs(iosPdf)
End If
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Function
Public Shared Function RellenaFormularioPDF(PdfOrigen As Byte(), Valores As Hashtable, Optional Aplanar As Boolean = True) As Byte()
Try
Dim pdfReader As New PdfReader(New MemoryStream(PdfOrigen))
Dim ms As New MemoryStream
Dim pdfDoc As New PdfDocument(pdfReader, New PdfWriter(ms))
Dim form = PdfAcroForm.GetAcroForm(pdfDoc, True)
For Each Valor As DictionaryEntry In Valores
Try
Dim f = form.GetField(Valor.Key)
If f IsNot Nothing Then f.SetValue(Valor.Value)
Catch ex As Exception
End Try
Next
If Aplanar Then
form.FlattenFields()
End If
pdfDoc.Close()
If ms.CanSeek Then ms.Seek(0, 0)
Return ms.ToArray
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Function
Public Shared Sub AñadePropiedadesAPdf(ByVal FicheroPdf As String, ByVal Valores As Hashtable)
Try
Dim ms As New MemoryStream
Dim pdfReader As New PdfReader(FicheroPdf)
Dim pdfDoc As New PdfDocument(pdfReader, New PdfWriter(ms))
Dim info = pdfDoc.GetDocumentInfo()
Dim newInfo As IDictionary(Of String, String) = New Dictionary(Of String, String)()
For Each Valor As DictionaryEntry In Valores
Try
newInfo.Add(CStr(Valor.Key), Valor.Value)
Catch ex As Exception
End Try
Next
info.SetMoreInfo(newInfo)
pdfDoc.Close()
Dim b = ms.ToArray
pdfReader.Close()
System.IO.File.Delete(FicheroPdf)
System.IO.File.WriteAllBytes(FicheroPdf, b)
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Public Shared Sub AñadePropiedadesAPdf(pdfDoc As PdfDocument, ByVal Valores As Hashtable)
Try
Dim ms As New MemoryStream
Dim info = pdfDoc.GetDocumentInfo()
Dim newInfo As IDictionary(Of String, String) = New Dictionary(Of String, String)()
For Each Valor As DictionaryEntry In Valores
Try
newInfo.Add(Valor.Key, Valor.Value)
Catch ex As Exception
End Try
Next
info.SetMoreInfo(newInfo)
pdfDoc.Close()
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Sub
Public Shared Function AñadePropiedadesAPdf(ByVal FicheroPdf As MemoryStream, ByVal Valores As Hashtable) As MemoryStream
Try
Dim ms As New MemoryStream
Dim pdfReader As New PdfReader(FicheroPdf)
Dim pdfDoc As New PdfDocument(pdfReader, New PdfWriter(ms))
Dim info = pdfDoc.GetDocumentInfo()
Dim newInfo As IDictionary(Of String, String) = New Dictionary(Of String, String)()
For Each Valor As DictionaryEntry In Valores
Try
newInfo.Add(Valor.Key, Valor.Value)
Catch ex As Exception
End Try
Next
info.SetMoreInfo(newInfo)
pdfDoc.Close()
If ms.CanSeek Then ms.Seek(0, 0)
Return ms
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
End Function
Public Shared Function ExtractTextFromPDF(ByVal RutaPdf As String) As String
Dim pdfReader As PdfReader = New PdfReader(RutaPdf)
Dim pdfDoc As PdfDocument = New PdfDocument(pdfReader)
Dim contenido As String = ""
Dim Estrategia = New SimpleTextExtractionStrategy
For page As Integer = 1 To pdfDoc.GetNumberOfPages()
Dim pagina = pdfDoc.GetPage(page)
Dim Texto = PdfTextExtractor.GetTextFromPage(pagina, Estrategia)
contenido &= Texto & vbCrLf
Next
pdfDoc.Close()
pdfReader.Close()
Return contenido
End Function
Public Shared Sub PruebaSellado(FicheroASellar As String, FicheroDestino As String)
Dim pdfr As New PdfReader(FicheroASellar)
Dim pdfw = New PdfWriter(FicheroDestino)
Dim wp As New WriterProperties
'Dim cl = pdfr.GetPdfAConformanceLevel()
Dim pdfd As New PdfDocument(pdfr, pdfw)
Dim np = pdfd.GetNumberOfPages
Dim fuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN)
For i = 1 To np
Dim page As PdfPage = pdfd.GetPage(i)
Dim pdfc As New PdfCanvas(page)
Dim fc As New PdfCanvas(page.NewContentStreamAfter, page.GetResources, pdfd)
pdfc.BeginText()
pdfc.SetFontAndSize(fuente, 12)
pdfc.MoveText(0, 0)
pdfc.ShowText("PRUEBA PRUEBA")
pdfc.EndText()
Next
pdfd.Close()
pdfw.Close()
End Sub
End Class

View File

@@ -0,0 +1,8 @@
Public Class tsPDFUtilException
Inherits Exception
Public ReadOnly Property ErrorCode As String
Public Sub New(ByVal paramName As String, ByVal CodigoError As String)
MyBase.New(paramName)
ErrorCode = ErrorCode
End Sub
End Class

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace tsPDFUtilsCore
{
public class DatosFuente
{
public string NombreFuente;
public byte[] memoryFont;
}
}

View File

@@ -0,0 +1,18 @@

using static tsPDFUtilsCore.Enums;
namespace tsPDFUtilsCore
{
public class DatosImagenFirma
{
public EsquinaEnum PosicionEsquina;
public int Ancho;
public int Alto;
public int PosicionX;
public int PosicionY;
public byte[] Imagen;
public int AnguloRotacion;
}
}

View File

@@ -0,0 +1,23 @@
using System.Drawing;
using static tsPDFUtilsCore.Enums;
namespace tsPDFUtilsCore
{
public class DatosTextos
{
public string NombreFuente;
public EsquinaEnum PosicionEsquina;
public AlineamientoEnum AlineacionTexto;
public float size;
public float anguloRotacion;
public string texto;
public int distanciaX;
public int distanciaY;
public Brush colorTexto;
public FontStyle estiloTexto;
}
}

45
tsPDFUtilsCore/Enums.cs Normal file
View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace tsPDFUtilsCore
{
public class Enums
{
public enum EsquinaEnum : int
{
INFERIOR_IZQUIERDA = 0,
INFERIOR_DERECHA = 1,
SUPERIOR_IZQUIERDA = 2,
SUPERIOR_DERECHA = 3
}
public enum AlineamientoEnum : int
{
IZQUIERDA = 0,
DERECHA = 1,
CENTRO = 2,
JUSTIFICADO = 3
}
public enum FuenteEnum
{
COURIER,
COURIER_BOLD,
COURIER_BOLDOBLIQUE,
COURIER_OBLIQUE,
HELVETICA,
HELVETICA_BOLD,
HELVETICA_BOLDOBLIQUE,
HELVETICA_OBLIQUE,
SYMBOL,
TIMES_ROMAN,
TIMES_BOLD,
TIMES_BOLDITALIC,
TIMES_ITALIC,
ZAPFDINGBATS
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace tsPDFUtilsCore
{
public class ImagenEnPdf
{
public byte[] Imagen { get; set; }
public EsquinaEnum EsquinaReferencia { get; set; }
public double Transparencia { get; set; } = 1;
public float CoordenadaX { get; set; }
public float CoordenadaY { get; set; }
public float EscalaVertical { get; set; }
public float EscalaHorizontal { get; set; }
public float AnguloRotacion { get; set; }
public int PaginaInicio { get; set; }
public int PaginaFin { get; set; }
}
}

580
tsPDFUtilsCore/Imagenes.cs Normal file
View File

@@ -0,0 +1,580 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using TSpdf.Kernel.Font;
using TSpdf.IO.Font.Constants;
using static tsPDFUtilsCore.Imagenes;
using static tsPDFUtilsCore.Enums;
namespace tsPDFUtilsCore
{
public class Imagenes
{
public static Bitmap RedimensionaImagen(Bitmap Original, int NuevoAlto, int NuevoAncho, int CoordenadaX, int CoordenadaY)
{
Bitmap newImage = new Bitmap(NuevoAncho, NuevoAlto);
using (Graphics g = Graphics.FromImage(newImage))
{
g.Clear(Color.Transparent);
g.DrawImage(Original, CoordenadaX, CoordenadaY, Original.Width, Original.Height);
}
return newImage;
}
public static Bitmap crearBitMapFirmas(List<DatosTextos> listadoTextos, List<DatosImagenFirma> listadoImagenes, List<DatosFuente> ListadoFuentes, TSpdf.Kernel.Geom.Rectangle medidas)
{
int dpi = 600;
int anchoPixeles = (int)medidas.GetWidth() * dpi / 72;
int altoPixeles = (int)medidas.GetHeight() * dpi / 72;
Bitmap bmp = new Bitmap(anchoPixeles, altoPixeles, PixelFormat.Format32bppArgb);
bmp.SetResolution(dpi, dpi);
Graphics g = Graphics.FromImage(bmp);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.Clear(Color.Transparent);
// Dibujar textos
foreach (var texto in listadoTextos)
{
Font font = null;
if (FontFamily.Families.Any(x => x.Name == texto.NombreFuente))
font = new Font(FontFamily.Families.Where(x => x.Name == texto.NombreFuente).First(), texto.size, texto.estiloTexto, GraphicsUnit.Point);
else if (ListadoFuentes != null && ListadoFuentes.Any(x => x.NombreFuente == texto.NombreFuente))
{
var fuente = ListadoFuentes.Where(x => x.NombreFuente == texto.NombreFuente).First();
int dataLength = fuente.memoryFont.Length;
IntPtr ptrData = Marshal.AllocCoTaskMem(dataLength);
Marshal.Copy(fuente.memoryFont, 0, ptrData, dataLength);
PrivateFontCollection privateFontCollection = new PrivateFontCollection();
privateFontCollection.AddMemoryFont(ptrData, dataLength);
font = new Font(privateFontCollection.Families.FirstOrDefault(), texto.size, texto.estiloTexto, GraphicsUnit.Point);
}
else
throw new Exception("Fuente " + texto.NombreFuente + " no encontrada");
var sizeTexto = g.MeasureString(texto.texto, font);
var coordenadaX = calcularX(texto.distanciaX, texto.distanciaY, texto.PosicionEsquina, bmp, texto.anguloRotacion, (int)sizeTexto.Width, (int)sizeTexto.Height);
var coordenadaY = calcularY(texto.distanciaY, texto.distanciaX, texto.PosicionEsquina, bmp, texto.anguloRotacion, (int)sizeTexto.Width, (int)sizeTexto.Height);
PointF rotationPoint = new PointF(texto.distanciaX, texto.distanciaY);
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
StringFormat stringFormat = new StringFormat();
g.TranslateTransform(0, 0);
g.RotateTransform(texto.anguloRotacion);
if (texto.AlineacionTexto != AlineamientoEnum.JUSTIFICADO)
g.DrawString(texto.texto, font, texto.colorTexto, new PointF(coordenadaX, coordenadaY));
else
DrawJustifiedString(ref g, texto.texto, font, texto.colorTexto, new RectangleF(coordenadaX, coordenadaY, altoPixeles, sizeTexto.Height), stringFormat);
g.ResetTransform();
}
foreach (var imagen in listadoImagenes)
{
MemoryStream stream = new MemoryStream();
stream.Write(imagen.Imagen, 0, imagen.Imagen.Length);
System.Drawing.Image myImage = System.Drawing.Image.FromStream(stream);
g.TranslateTransform(0, 0);
g.RotateTransform(imagen.AnguloRotacion);
int coordenadaX = calcularX(imagen.PosicionX, imagen.PosicionY, imagen.PosicionEsquina, bmp, imagen.AnguloRotacion, myImage.Width, myImage.Height);
int coordenadaY = calcularY(imagen.PosicionY, imagen.PosicionX, imagen.PosicionEsquina, bmp, imagen.AnguloRotacion, myImage.Width, myImage.Height);
if (altoPixeles > anchoPixeles)
g.DrawImage(myImage, new Rectangle(coordenadaX, coordenadaY, altoPixeles, anchoPixeles));
else
g.DrawImage(myImage, new Rectangle(coordenadaX, coordenadaY, anchoPixeles, altoPixeles));
g.ResetTransform();
}
return bmp;
}
public static byte[] BitMapAByteArray(Bitmap bmp)
{
MemoryStream msSalida = new MemoryStream();
bmp.Save(msSalida, ImageFormat.Png);
byte[] byteArray = msSalida.ToArray();
msSalida.Close();
return byteArray;
}
public static void DrawJustifiedString(ref Graphics g, string txt, Font font, Brush brush, RectangleF destination, StringFormat format)
{
using (StringFormat fmt = (StringFormat)format.Clone())
{
fmt.FormatFlags = fmt.FormatFlags | StringFormatFlags.MeasureTrailingSpaces;
CharacterRange[] cr = { new CharacterRange(0, 1) };
fmt.SetMeasurableCharacterRanges(cr);
fmt.Alignment = StringAlignment.Center;
float txtWidth = g.MeasureString(txt, font, destination.Location, fmt).Width;
float spacing = (destination.Width - txtWidth) / (txt.Length - 1);
RectangleF dest = new RectangleF(destination.X, destination.Y, 0, destination.Height);
foreach (char c in txt.AsEnumerable())
{
// Graphics#MeasureString is too inaccurate for character placement
dest.Width = g.MeasureCharacterRanges(c.ToString(), font, destination, fmt)[0].GetBounds(g).Width;
g.DrawString(c.ToString(), font, brush, dest, fmt);
dest.X += dest.Width + spacing;
}
}
}
private static int calcularX(int coordenadaX, int coordenadaY, EsquinaEnum PosicionEsquina, Bitmap medidasFirma, float rotacionElemento, int anchoElemento, int altoElemento)
{
int anchoFirma = medidasFirma.Width;
int altoFirma = medidasFirma.Height;
int ejeX = 0;
switch (PosicionEsquina)
{
case EsquinaEnum.SUPERIOR_IZQUIERDA:
{
switch (rotacionElemento)
{
case 90:
{
ejeX = coordenadaY;
break;
}
case 180:
{
ejeX = -coordenadaX - anchoElemento;
break;
}
case 270:
{
ejeX = -coordenadaY - anchoElemento;
break;
}
default:
{
ejeX = coordenadaX;
break;
}
}
break;
}
case EsquinaEnum.INFERIOR_IZQUIERDA:
{
switch (rotacionElemento)
{
case 90:
{
ejeX = (altoFirma - (coordenadaY + anchoElemento));
break;
}
case 180:
{
ejeX = -coordenadaX - anchoElemento;
break;
}
case 270:
{
ejeX = coordenadaY - altoFirma;
break;
}
default:
{
ejeX = coordenadaX;
break;
}
}
break;
}
case EsquinaEnum.SUPERIOR_DERECHA:
{
switch (rotacionElemento)
{
case 90:
{
ejeX = coordenadaY;
break;
}
case 180:
{
ejeX = -anchoFirma + coordenadaX;
break;
}
case 270:
{
ejeX = -coordenadaY - anchoElemento;
break;
}
default:
{
ejeX = anchoFirma - (anchoElemento + coordenadaX);
break;
}
}
break;
}
case EsquinaEnum.INFERIOR_DERECHA:
{
switch (rotacionElemento)
{
case 90:
{
ejeX = (altoFirma - (coordenadaY + anchoElemento));
break;
}
case 180:
{
ejeX = -anchoFirma + coordenadaX;
break;
}
case 270:
{
ejeX = coordenadaY - altoFirma;
break;
}
default:
{
ejeX = anchoFirma - (anchoElemento + coordenadaX);
break;
}
}
break;
}
}
return ejeX;
}
private static int calcularY(int coordenadaY, int coordenadaX, EsquinaEnum PosicionEsquina, Bitmap medidasFirma, float rotacionElemento, int anchoElemento, int altoElemento)
{
int anchoFirma = medidasFirma.Width;
int altoFirma = medidasFirma.Height;
int ejeY = 0;
switch (PosicionEsquina)
{
case EsquinaEnum.SUPERIOR_IZQUIERDA:
{
switch (rotacionElemento)
{
case 90:
{
ejeY = -coordenadaX - altoElemento;
break;
}
case 180:
{
ejeY = -coordenadaY - altoElemento;
break;
}
case 270:
{
ejeY = coordenadaX;
break;
}
default:
{
ejeY = coordenadaY;
break;
}
}
break;
}
case EsquinaEnum.INFERIOR_IZQUIERDA:
{
switch (rotacionElemento)
{
case 90:
{
ejeY = -coordenadaX - altoElemento;
break;
}
case 180:
{
ejeY = -altoFirma + coordenadaY;
break;
}
case 270:
{
ejeY = coordenadaX;
break;
}
default:
{
ejeY = altoFirma - (altoElemento + coordenadaY);
break;
}
}
break;
}
case EsquinaEnum.SUPERIOR_DERECHA:
{
switch (rotacionElemento)
{
case 90:
{
ejeY = coordenadaX - (anchoFirma);
break;
}
case 180:
{
ejeY = -coordenadaY - altoElemento;
break;
}
case 270:
{
ejeY = anchoFirma - (altoElemento + coordenadaX);
break;
}
default:
{
ejeY = coordenadaY;
break;
}
}
break;
}
case EsquinaEnum.INFERIOR_DERECHA:
{
switch (rotacionElemento)
{
case 90:
{
ejeY = coordenadaX - (anchoFirma);
break;
}
case 180:
{
ejeY = -altoFirma + coordenadaY;
break;
}
case 270:
{
ejeY = anchoFirma - (altoElemento + coordenadaX);
break;
}
default:
{
ejeY = altoFirma - (altoElemento + coordenadaY);
break;
}
}
break;
}
}
return ejeY;
}
private static TSpdf.Kernel.Font.PdfFont devolverTipoFuente(string nombreFuente)
{
TSpdf.Kernel.Font.PdfFont tipoFuente;
switch (nombreFuente)
{
case "COURIER":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER);
break;
}
case "COURIER_BOLD":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER_BOLD);
break;
}
case "COURIER_BOLDOBLIQUE":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER_BOLDOBLIQUE);
break;
}
case "COURIER_OBLIQUE":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER_OBLIQUE);
break;
}
case "HELVETICA":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA);
break;
}
case "HELVETICA_BOLD":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD);
break;
}
case "HELVETICA_BOLDOBLIQUE":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLDOBLIQUE);
break;
}
case "HELVETICA_OBLIQUE":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_OBLIQUE);
break;
}
case "SYMBOL":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.SYMBOL);
break;
}
case "TIMES_ROMAN":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN);
break;
}
case "TIMES_BOLD":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_BOLD);
break;
}
case "TIMES_BOLDITALIC":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_BOLDITALIC);
break;
}
case "TIMES_ITALIC":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ITALIC);
break;
}
case "ZAPFDINGBATS":
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.ZAPFDINGBATS);
break;
}
default:
{
tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN);
break;
}
}
return tipoFuente;
}
}
}
public enum EsquinaEnum : int
{
INFERIOR_IZQUIERDA = 0,
INFERIOR_DERECHA = 1,
SUPERIOR_IZQUIERDA = 2,
SUPERIOR_DERECHA = 3
}
public enum AlineamientoEnum : int
{
IZQUIERDA = 0,
DERECHA = 1,
CENTRO = 2,
JUSTIFICADO = 3,
JUSTIFICADO_ALL = 4
}
public enum TipoTextoEnum : int
{
NORMAL = 0,
NUMERO_PAGINA = 1,
NUMERO_PAGINA_TOTAL_PAGINAS = 2,
}
public enum FuenteEnum
{
COURIER,
COURIER_BOLD,
COURIER_BOLDOBLIQUE,
COURIER_OBLIQUE,
HELVETICA,
HELVETICA_BOLD,
HELVETICA_BOLDOBLIQUE,
HELVETICA_OBLIQUE,
SYMBOL,
TIMES_ROMAN,
TIMES_BOLD,
TIMES_BOLDITALIC,
TIMES_ITALIC,
ZAPFDINGBATS
}

View File

@@ -0,0 +1,83 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Este código fue generado por una herramienta.
// Versión de runtime:4.0.30319.42000
//
// Los cambios en este archivo podrían causar un comportamiento incorrecto y se perderán si
// se vuelve a generar el código.
// </auto-generated>
//------------------------------------------------------------------------------
namespace tsPDFUtilsCore.Properties {
using System;
/// <summary>
/// Clase de recurso fuertemente tipado, para buscar cadenas traducidas, etc.
/// </summary>
// StronglyTypedResourceBuilder generó automáticamente esta clase
// a través de una herramienta como ResGen o Visual Studio.
// Para agregar o quitar un miembro, edite el archivo .ResX y, a continuación, vuelva a ejecutar ResGen
// con la opción /str o recompile su proyecto de VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Devuelve la instancia de ResourceManager almacenada en caché utilizada por esta clase.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("tsPDFUtilsCore.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Reemplaza la propiedad CurrentUICulture del subproceso actual para todas las
/// búsquedas de recursos mediante esta clase de recurso fuertemente tipado.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Busca un recurso adaptado de tipo System.Byte[].
/// </summary>
public static byte[] fogra39L {
get {
object obj = ResourceManager.GetObject("fogra39L", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Busca un recurso adaptado de tipo System.Byte[].
/// </summary>
public static byte[] sRGB2014 {
get {
object obj = ResourceManager.GetObject("sRGB2014", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="fogra39L" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\fogra39L.icc;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="sRGB2014" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\sRGB2014.icc;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

Binary file not shown.

Binary file not shown.

1446
tsPDFUtilsCore/Sellado.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace tsPDFUtilsCore
{
public class TextoEnPdf
{
public string Texto { get; set; }
public FuenteEnum Fuente { get; set; }
public float TamañoFuente { get; set; }
public System.Drawing.Color Color { get; set; }
public double Transparencia { get; set; }
public EsquinaEnum EsquinaReferencia { get; set; }
public float AnguloRotacion { get; set; }
public AlineamientoEnum Alineamiento { get; set; }
public float CoordenadaX { get; set; }
public float CoordenadaY { get; set; }
public int PaginaInicio { get; set; }
public int PaginaFin { get; set; }
public float anchoTexto { get; set; }
public float altoTexto { get; set; }
public TipoTextoEnum TipoTexto { get; set; }
}
}

View File

@@ -0,0 +1,158 @@
using System.IO;
using TSpdf.Kernel.Pdf;
using TSpdf.Kernel.Utils;
using TSpdf.Pdfa;
namespace tsPDFUtilsCore
{
public class Utilidades
{
public static MemoryStream crearPDFA(Stream pdfOrigen)
{
var reader = new PdfReader(pdfOrigen);
MemoryStream ms = new MemoryStream();
var writerProps = new WriterProperties();
writerProps.SetPdfVersion(PdfVersion.PDF_2_0);
writerProps.UseSmartMode();
var writer = new PdfWriter(ms, writerProps);
writer.SetSmartMode(true);
// Necesario para que el memoryStream no se cierre, y no de una execpción donde se llame a la función
writer.SetCloseStream(false);
var sourcePDF = new PdfDocument(reader);
bool esRGB = recorrerPaginas(sourcePDF);
// Se recorre las páginas para comprobar que no falte la anotación F, en tal caso la mete
for (int page = 1; page <= sourcePDF.GetNumberOfPages(); page++)
{
var paginaActual = sourcePDF.GetPage(page);
var anotaciones = paginaActual.GetAnnotations();
if (anotaciones != null)
{
foreach (var anotacionActual in anotaciones)
{
var diccionario = anotacionActual.GetPdfObject();
if (!diccionario.ContainsKey(PdfName.F))
{
diccionario.Put(PdfName.F, new PdfNumber(4));
}
}
}
}
PdfADocument disPDF;
if (esRGB)
{
disPDF = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_3B, new PdfOutputIntent("Custom"
, "", "https://www.color.org", "sRGB", new MemoryStream(Properties.Resources.sRGB2014)));
}
else
{
disPDF = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_3B, new PdfOutputIntent("Custom"
, "", "https://www.color.org", "FOGRA39", new MemoryStream(Properties.Resources.fogra39L)));
}
disPDF.InitializeOutlines();
// Configurar parámetros requeridos
disPDF.SetTagged();
disPDF.GetCatalog().SetLang(new PdfString("es-ES"));
disPDF.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));
var merger = new PdfMerger(disPDF, true,true);
merger.Merge(sourcePDF, 1, sourcePDF.GetNumberOfPages());
sourcePDF.Close();
disPDF.Close();
reader.Close();
writer.Close();
// Esto hace falta para volver al inicio del memorystream
ms.Position = 0;
return ms;
}
static bool controlarInterpolate(PdfDictionary resources, bool tieneRGB)
{
var xObjects = resources?.GetAsDictionary(PdfName.XObject);
bool tieneRGBActual = tieneRGB;
foreach (var key in xObjects.KeySet())
{
var stream = xObjects.GetAsStream(key);
// se mira que tenga el prefijo subtype qye es la forma como el pdf pone las imagenes y los formularios -> /Subtype /Image ó /Subtype /Form
var subtype = stream.GetAsName(PdfName.Subtype);
// En caso de que sea una imagen, pone el interpolate a false, que es lo que causaba el fallo en alguno de los pdfs
if (PdfName.Image.Equals(subtype))
{
if (stream.GetAsBoolean(PdfName.Interpolate)?.GetValue() == true)
{
stream.Put(PdfName.Interpolate, PdfBoolean.FALSE);
}
// Detectar RGB
var colorSpace = stream.Get(PdfName.ColorSpace);
if (colorSpace != null && colorSpace.Equals(PdfName.DeviceRGB))
{
tieneRGBActual = true;
tieneRGB = true;
}
}
// En caso de que sea un formulario, vuelve a llamar al metodo para buscar imagenes dentro
else if (PdfName.Form.Equals(subtype))
{
var formRes = stream.GetAsDictionary(PdfName.Resources);
if (formRes != null)
{
bool hijoTieneRGB = controlarInterpolate(formRes, tieneRGBActual);
if (hijoTieneRGB)
{
tieneRGBActual = true;
}
}
}
}
return tieneRGBActual;
}
static bool recorrerPaginas(PdfDocument pdf)
{
bool tieneRGB = false;
for (int i = 1; i <= pdf.GetNumberOfPages(); i++)
{
bool rgbMinimo = false;
var diccPaginaActual = pdf.GetPage(i).GetResources().GetPdfObject();
rgbMinimo = controlarInterpolate(diccPaginaActual, tieneRGB);
if (rgbMinimo)
{
tieneRGB = true;
}
}
return tieneRGB;
}
}
}

View File

@@ -0,0 +1,60 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net48</TargetFrameworks>
<AssemblyVersion>1.0.16</AssemblyVersion>
<FileVersion>1.0.16</FileVersion>
<OutputType>Library</OutputType>
<RootNamespace>tsPDFUtilsCore</RootNamespace>
<PackageId>tsPDFUtilsCore</PackageId>
<PackageTags>netstandard2.0, libreria</PackageTags>
<Version>1.0.16</Version>
<Authors>Manuel, Perea</Authors>
<Company>Tecnosis S.A</Company>
<Description>Utilidades de tratamiento de pdf, de firmas digitales e imagenes.</Description>
<PackageReleaseNotes>
- 1.0.16 2026-05-20 Correcciones dependencias Microsoft.Extensions.Logging
- 1.0.12 2025-10-23 se posiciona en 0 la posicion del stream original
- 1.0.10 2025-10-23 Se relanzan exepciones en caso de error
- 1.0.9 2025-10-23 Se añade parámetro para en caso de pdf/a3b poder decidir si es obligatorio o no
- 1.0.8 2025-10-06 Se añade parámetro para crear el standard pdf/a3b
- 1.0.7 2025-10-06 Se deja solo net standard
- 1.0.6 2025-10-06 Actualización de dependencias microsoft.extensions.options
- 1.0.5 Actualización de dependencias microsoft.extensions.options
- 1.0.4 Corrección en TSpdf.io
- Primera versión estable.
- Probando Nuget
</PackageReleaseNotes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.9" />
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="TSpdf.kernel" Version="3.0.0" />
<PackageReference Include="TSpdf.layout" Version="3.0.0" />
<PackageReference Include="TSpdf.pdfa" Version="3.0.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>