Creating a PDF with an image (datastream o from file) in iTextSharp - vb.net

i'm trying to follow this example to create PDF with an image
Example PDF with an Image
I'm developing with VS2013 in VB.NET (ASP.NET 3.5).
I'm getting crazy, i don't understand 2 things:
what is the name that i've to pass in the IMG tag.
The src-attribute doesn´t contain a http-Url. Instead use the prefix data:imagestream to identify the source type of the image. After the following slash the name of the resource in the manifest of the .NET library is listed.
when the END ovveride function in CustomImageTagProcessor Class is executed
I've embedded an image in the project and the manifest contains
...
}
.mresource public Test1.phone.jpg
{
// Offset: 0x00000000 Length: 0x00003E0D
}
.mresource public Test1.Resources.resources
{
// Offset: 0x00003E11 Length: 0x0000406B
}
I'm debugging step by step but never the code in the ovverride function is executed.
This is the function that produce PDF
Public Function CreateFromHtml(ByVal html As String) As Stream
Dim stream = New MemoryStream()
Using doc = New Document(PageSize.A4)
Using ms = New MemoryStream()
Using writer = PdfWriter.GetInstance(doc, ms)
writer.CloseStream = False
doc.Open()
Dim tagProcessors = CType(Tags.GetHtmlTagProcessorFactory(), DefaultTagProcessorFactory)
tagProcessors.RemoveProcessor(iTextSharp.tool.xml.html.HTML.Tag.IMG)
tagProcessors.AddProcessor(iTextSharp.tool.xml.html.HTML.Tag.IMG, New CustomImageTagProcessor())
Dim cssFiles = New CssFilesImpl()
cssFiles.Add(XMLWorkerHelper.GetInstance().GetDefaultCSS())
Dim cssResolver = New StyleAttrCSSResolver(cssFiles)
Dim charset = Encoding.UTF8
Dim context = New HtmlPipelineContext(New CssAppliersImpl(New XMLWorkerFontProvider()))
context.SetAcceptUnknown(True).AutoBookmark(True).SetTagFactory(tagProcessors)
Dim htmlPipeline = New HtmlPipeline(context, New PdfWriterPipeline(doc, writer))
Dim cssPipeline = New CssResolverPipeline(cssResolver, htmlPipeline)
Dim worker = New XMLWorker(cssPipeline, True)
Dim xmlParser = New XMLParser(True, worker, charset)
Using sr = New StringReader(html)
xmlParser.Parse(sr)
doc.Close()
ms.Position = 0
ms.CopyTo(stream)
stream.Position = 0
End Using
End Using
End Using
End Using
Return stream
End Function
And this is the Class of CustomImageTagProcessor
Imports iTextSharp.tool.xml
Imports System.Reflection
Imports iTextSharp.text
Public Class CustomImageTagProcessor
Inherits iTextSharp.tool.xml.html.Image
Public Overrides Function [End](ByVal ctx As IWorkerContext, ByVal tag As Tag, ByVal currentContent As IList(Of IElement)) As IList(Of IElement)
Dim src = String.Empty
If Not tag.Attributes.TryGetValue(iTextSharp.tool.xml.html.HTML.Attribute.SRC, src) Then Return New List(Of IElement)(1)
If String.IsNullOrEmpty(src) Then Return New List(Of IElement)(1)
If src.StartsWith("data:imagestream/", StringComparison.InvariantCultureIgnoreCase) Then
Dim name = src.Substring(src.IndexOf("/", StringComparison.InvariantCultureIgnoreCase) + 1)
Using stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name)
Return CreateElementList(ctx, tag, Image.GetInstance(stream))
End Using
End If
Return MyBase.[End](ctx, tag, currentContent)
End Function
Protected Function CreateElementList(ByVal ctx As IWorkerContext, ByVal tag As Tag, ByVal image As Image) As IList(Of IElement)
Dim htmlPipelineContext = GetHtmlPipelineContext(ctx)
Dim result = New List(Of IElement)()
Dim element = GetCssAppliers().Apply(New Chunk(CType(GetCssAppliers().Apply(image, tag, htmlPipelineContext), Image), 0, 0, True), tag, htmlPipelineContext)
result.Add(element)
Return result
End Function
End Class
Thanks so much for any helps.
I hope in you guys.

The problem was a lost
</img>
tag
Self Closed tag is not valid.
When i put tag also code inside overrided function has been executed.
Thanks so much.

Related

Roslyn VB.Net Specify Compiler Version

I am trying to compile a VB program using the code below, the code requires VB 15.5 and even when I specify LanguageVersion.Latest or LanguageVersion.VisualBasic15_5, I still get error ERR_ExpectedNamedArgument - Named argument expected. Please use language version 15.5 or greater to use non-trailing named arguments. Some code was removed to simplify example.
Public Function CompileVisualBasicString(StringToBeCompiler As String, SeverityToReport As DiagnosticSeverity, ByRef ResultOfConversion As ConversionResult) As EmitResult
If StringToBeCompiler.IsEmptyNullOrWhitespace Then
ResultOfConversion.FilteredListOfFailures = New List(Of Diagnostic)
ResultOfConversion.Success = True
Return Nothing
End If
Dim syntaxTree As SyntaxTree = VisualBasicSyntaxTree.ParseText(StringToBeCompiler)
Dim assemblyName As String = Path.GetRandomFileName()
Dim PreprocessorSymbols As New Dictionary(Of String, Object) From {
{"NETSTANDARD2_0", Nothing}
}
Dim ParseOptions As VisualBasicParseOptions = New VisualBasicParseOptions(
languageVersion:=LanguageVersion.Latest,
documentationMode:=DocumentationMode.Diagnose,
kind:=SourceCodeKind.Regular,
preprocessorSymbols:=PreprocessorSymbols)
Dim CompilationOptions As VisualBasicCompilationOptions = New VisualBasicCompilationOptions(
outputKind:=OutputKind.DynamicallyLinkedLibrary,
optionExplicit:=False,
optionInfer:=True,
optionStrict:=OptionStrict.Off,
parseOptions:=ParseOptions
)
Dim compilation As VisualBasicCompilation = VisualBasicCompilation.Create(
assemblyName:=assemblyName,
syntaxTrees:={syntaxTree},
references:=References,
options:=CompilationOptions
)
Dim CompileResult As EmitResult
Using ms As MemoryStream = New MemoryStream()
CompileResult = compilation.Emit(ms)
End Using
Return CompileResult
End Function
Thank you George, you solved the problem I needed to include the VisualBasicParseOption to Parse in addition to compile.

VB.NET writing comments to jpeg file programmatically

I searched stackoverflow and I realized that GetPropertyItem and SetPropertyItem can edit comments in JPEG file
Dim images As Image = System.Drawing.Image.FromFile("C:\\Sample.jpeg")
Dim MSGF As New ArrayList
Dim ID() As String = {"hello ","i am here"}
Dim propItem As PropertyItem = images.GetPropertyItem(40092)
Dim encoderParameters As New EncoderParameters(1)
encoderParameters.Param(0) = New EncoderParameter(Encoder.Quality, 100L)
For i = 0 To ID.Length - 1
Dim TEMP As String = ID(i)
For II = 0 To TEMP.Length - 1
MSGF.Add(Convert.ToInt32(TEMP(II)))
Next
Next
For i = 0 To MSGF.Count - 1
propItem.Value.SetValue(Convert.ToByte(MSGF(i)), i)
Next
images.SetPropertyItem(propItem)
images.Save(TextBox1.Text & "\" & "1" & TextBox2.Text)
What I realized was I can get comments from jpeg file by GetPropertyItem. However, comments is based on the ascii code. Therefore, I was trying to convert comment that I wanted to insert to ascii code.
propItem.Value.SetValue(Convert.ToByte(MSGF(i)), i)
This part was actually changed comments which already existed in the jpeg file.
However, if there is no comments in jpeg file, propItem.value.setValue doesn't work because there is nothing to edit.
Is there anyway to just add comments to jpeg file?
Based on this answer in C#, it could be as simple as this:
Dim jpeg = New JpegMetadataAdapter(pathToJpeg)
jpeg.Metadata.Comment = "Some comments"
jpeg.Metadata.Title = "A title"
jpeg.Save()
' Saves the jpeg in-place
jpeg.SaveAs(someNewPath)
' Saves with a new path
Here is the class:
Public Class JpegMetadataAdapter
Private ReadOnly path As String
Private frame As BitmapFrame
Public ReadOnly Metadata As BitmapMetadata
Public Sub New(path As String)
Me.path = path
frame = getBitmapFrame(path)
Metadata = DirectCast(frame.Metadata.Clone(), BitmapMetadata)
End Sub
Public Sub Save()
SaveAs(path)
End Sub
Public Sub SaveAs(path As String)
Dim encoder As New JpegBitmapEncoder()
encoder.Frames.Add(BitmapFrame.Create(frame, frame.Thumbnail, Metadata, frame.ColorContexts))
Using stream As Stream = File.Open(path, FileMode.Create, FileAccess.ReadWrite)
encoder.Save(stream)
End Using
End Sub
Private Function getBitmapFrame(path As String) As BitmapFrame
Dim decoder As BitmapDecoder = Nothing
Using stream As Stream = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
decoder = New JpegBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad)
End Using
Return decoder.Frames(0)
End Function
End Class

Extract Images with text from PDF and Edit it using iTextSharp

I am trying to do following things in Windows Forms
1) Read a PDF in Windows Forms
2) Get the Images with Text in it
3) Color / fill the Image
4) save everything to a new file
I have tried Problem with PdfTextExtractor in itext!
But It didn't help.
Here is the code I've tried:
Public Shared Sub ExtractImagesFromPDF(sourcePdf As String, outputPath As String)
'NOTE: This will only get the first image it finds per page.'
Dim pdf As New PdfReader(sourcePdf)
Dim raf As RandomAccessFileOrArray = New iTextSharp.text.pdf.RandomAccessFileOrArray(sourcePdf)
Try
For pageNumber As Integer = 1 To pdf.NumberOfPages
Dim pg As PdfDictionary = pdf.GetPageN(pageNumber)
' recursively search pages, forms and groups for images.'
Dim obj As PdfObject = FindImageInPDFDictionary(pg)
If obj IsNot Nothing Then
Dim XrefIndex As Integer = Convert.ToInt32(DirectCast(obj, PRIndirectReference).Number.ToString(System.Globalization.CultureInfo.InvariantCulture))
Dim pdfObj As PdfObject = pdf.GetPdfObject(XrefIndex)
Dim pdfStrem As PdfStream = DirectCast(pdfObj, PdfStream)
Dim bytes As Byte() = PdfReader.GetStreamBytesRaw(DirectCast(pdfStrem, PRStream))
If (bytes IsNot Nothing) Then
Using memStream As New System.IO.MemoryStream(bytes)
memStream.Position = 0
Dim img As System.Drawing.Image = System.Drawing.Image.FromStream(memStream)
' must save the file while stream is open.'
If Not Directory.Exists(outputPath) Then
Directory.CreateDirectory(outputPath)
End If
Dim path__1 As String = Path.Combine(outputPath, [String].Format("{0}.jpg", pageNumber))
Dim parms As New System.Drawing.Imaging.EncoderParameters(1)
parms.Param(0) = New System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Compression, 0)
'Dim jpegEncoder As System.Drawing.Imaging.ImageCodecInfo = iTextSharp.text.Utilities.GetImageEncoder("JPEG")'
img.Save(path__1) 'jpegEncoder, parms'
End Using
End If
End If
Next
Catch
Throw
Finally
pdf.Close()
raf.Close()
End Try
End Sub
Now, the actual purpose of this is to get something like this
If this is the actual PDF, I will have to check if there any any items in that bin(by Text in that box)
If there are items then I have to color it like below
Can someone help me with this
The PDF can be retrieved here.

VB.NET How to parse and add the result into the list(of string) from json file?

I'm creating a launcher for Minecraft. I have a problem, My launcher using json files to load and check files. How can I add the strings from this json (example) into the AssetsList? https://s3.amazonaws.com/Minecraft.Download/indexes/1.8.json
My code, if it helps you to understand me (I'm using Newtonsoft.json to parse json):
The MCAssets class:
Public Class MCAssets
Public hash As String
End Class
The list:
Public AssetsList As New List(Of String)
The funchtion to get the assets:
Public Async Function GetAssets() As Task
If Not Directory.Exists(Root + "\assets\indexes") Then
Directory.CreateDirectory(Root + "\assets\indexes")
End If
Dim client = New WebClient()
Await client.DownloadFileTaskAsync(New Uri(String.Format("http://s3.amazonaws.com/Minecraft.Download/indexes/{0}.json", AssetIndex)), String.Format(Root + "\assets\indexes\{0}.json", AssetIndex))
Dim reader As New StreamReader(Root + "\assets\indexes\" + AssetIndex + ".json")
Dim assets As String = reader.ReadToEnd()
reader.Close()
Dim jsonresult = JsonConvert.DeserializeObject(Of Object)(assets)
For Each i In jsonresult("objects").Children()
AssetsList.Add(i.ToObject(Of MCAssets).hash)
Next
End Function
If you want know more about Minecraft assets, visit this: https://github.com/tomsik68/mclauncher-api/wiki/Minecraft-1.6-resources
You can do something like this:
Dim assetsObject = JsonConvert.DeserializeObject(Of JObject)(assets) 'assets is your json file
Dim allAssets = (From i In assetsObject("objects").Children() _
Select New MCAssets() With {.hash = i.First.Value(Of String)("hash")}).ToList()
By the way, there is not really a need to make a custom class. You can just add all of the hashes to a list of string like so:
Dim assetsObject = JsonConvert.DeserializeObject(Of JObject)(assets)
Dim allAssets = (From i In assetsObject("objects").Children() _
Select i.First.Value(Of String)("hash"))

Use generic type to create new instance of that objects

I am very new to Generics and it looks promising towards my problem although I have some questions around it.
I am in the process to build a generic function that will deserialize xml into an object and then create an ArrayList of that object and return it.
My question is how will I go to implement generics to do so? To be more clear I need to create new instance of object and assign values to its properties.
This is my function:
Private Function DeSerializeArrayList(serializedData As String, ByVal ObjectName As Object, ByVal ObjType As System.Type, ByVal ReturnObjectType As System.Type) As ArrayList
Dim list As New ArrayList()
Dim extraTypes As Type() = New Type(0) {}
extraTypes(0) = ObjectName.GetType()
'Code fails here and says can't include anonymous class
Dim serializer As New System.Xml.Serialization.XmlSerializer(ObjectName.GetType(), extraTypes)
Dim xReader As XmlReader = XmlReader.Create(New StringReader(serializedData))
Try
Dim obj = serializer.Deserialize(xReader)
For i As Integer = 0 To obj.Items.Length - 1
'Need to create NEW object
Dim labPrice As Type() = New Type(0) {}
labPrice(0) = ReturnObjectType
'Need some method to get the properties of that object
'Dim s = labPrice(0).GetEnumNames
'Need to asign values to that object's properties
'With labPrice
' .fLabPricelistID = obj.Items(i).fLabPricelistID
' .ftariffCode = obj.Items(i).fTariffCode
' .fSurfaced = obj.Items(i).fSurfaced
' .fLabCostPrice = obj.Items(i).fLabCostPrice
' .fLabDiscountedPrice = obj.Items(i).fLabDiscountedPrice
' .fEffectiveDate = obj.Items(i).fEffectiveDate
' .fLaboratoryCodeID = obj.Items(i).fLaboratoryCodeID
' .fDescription = obj.Items(i).fDescription
' .flabProduct = obj.Items(i).fLabProduct
' .fActive = obj.Items(i).fActive
'End With
'list.Add(labPrice)
Next
Catch
Throw
Finally
xReader.Close()
End Try
Return list
End Function
I found a solution that works perfectly for my problem that I had:
Dim obj = DeserializeObject(Of TestObject)(xmlString)
'Function will map xml to object/list of objects
Public Function DeserializeObject(Of T)(xml As String) As T
Dim xs As New XmlSerializer(GetType(T))
Dim memoryStream As New MemoryStream(StringToUTF8ByteArray(xml))
Dim xmlTextWriter As New XmlTextWriter(memoryStream, Encoding.UTF8)
Dim obj = DirectCast(xs.Deserialize(memoryStream), T)
Return obj
End Function
Public Shared Function StringToUTF8ByteArray(stringVal As String) As [Byte]()
Dim encoding As New UTF8Encoding()
Dim byteArray As Byte() = encoding.GetBytes(stringVal)
Return byteArray
End Function