Converting Ink to Base64 and then to Image gets shapes cropped - vb.net

I am using the function below to convert some ink shapes I have drawn on a picturebox control to Base64
Function GetBase64(ByVal InkCollector As InkCollector) As String
Dim utf8 As UTF8Encoding = New UTF8Encoding()
InkCollector.Enabled = False
Return utf8.GetString(InkCollector.Ink.Save(PersistenceFormat.Base64InkSerializedFormat, CompressionMode.Maximum))
InkCollector.Enabled = True
End Function
I can then use the string to reproduce the sketch into a new image by feeding it to this function:
Function Base64toImage(ByVal Base64 As String) As System.Drawing.Image
Dim utf8 As UTF8Encoding = New UTF8Encoding()
Dim imgSig As System.Drawing.Image
Dim tmploadedInk As Ink = New Ink()
Dim strGIF As String
Dim imageBytes() As Byte
Dim MS As MemoryStream
'Load the Base64 String in Format(PersistenceFormat = Base64InkSerializedFormat) as ink
tmploadedInk.Load(utf8.GetBytes(Base64))
'Convert the ink to Base64 String in format (PersistenceFormat.Gif, CompressionMode.Maximum)
strGIF = Convert.ToBase64String(tmploadedInk.Save(PersistenceFormat.Gif, CompressionMode.Maximum))
'Convert Base64 String to Byte Array
imageBytes = Convert.FromBase64String(strGIF)
MS = New MemoryStream(imageBytes, 0, imageBytes.Length)
' Convert byte[] to Image
MS.Write(imageBytes, 0, imageBytes.Length)
imgSig = Image.FromStream(MS, True)
Return imgSig
End Function
This works fine except for the fact the shapes are cropped and therefore they get aligned to the top left corner of the generated image. If I use a line of code like below:
PictureBox1.Image = Signiture.Base64toImage(Signiture.GetBase64(Sketch_InkCollector))
The shapes appear at the top left and ignore the fact that they might have been drawn at the center of the original picture box. I believe that the positioning data is being properly saved into the Base64 string, but are somehow being ignored when the shapes are transferred to the image variable. The reason I believe this is because when I use the function below with the Base64 string, the shapes get placed properly in their original position.
Sub SetBase64PictureBox(ByVal InkCollector As InkCollector, ByVal PictureBox As PictureBox, ByVal Base64 As String)
Dim loadedInk As Ink = New Ink()
Dim utf8 As UTF8Encoding = New UTF8Encoding()
InkCollector.Enabled = False
InkCollector.Ink.DeleteStrokes() ' Clear all strokes
loadedInk.Load(utf8.GetBytes(Base64))
InkCollector.Ink = loadedInk
InkCollector.Enabled = True
PictureBox.Invalidate()
End Sub
Thank you
Update:
Found a temporary solution in this link:
InkPicture control - How to save both ink and image to an image file
It is not exactly what I was after but the end result is the same since I wanted to the combined picture and the ink strokes into an image to show in a PDF file.

Related

Embedded base64String for images is to long for large images?

I am embedding a base64String into Tinymce to display images:
<img src="blob:https://path/871bf236-3bae-472c-9f02-0bd3be19a435" alt="Desert.jpg" width="300" height="75" />
It works for small images but when it comes to large images it doesn't work and I am guessing its because the URL containing the base64String for large images hits the limit for URL browser length which I believe is around 2000 characters. Wanted to see if there was a way to shorten my base64String?
'File path of the attachment
DIM filePath = C:\path\solutions\Attachments\1\1726014c-7a2d-41b8-a79e-2acec1e8c7e0
'Converted base64String path
DIM base64URLPath = ToBase64String( ConvertToUrl(filePath)).toString
'Converts the path to a base64String
Public Function ToBase64String(filePath As String) As String
Dim aImage = New Bitmap(filePath)
Using stream = New IO.MemoryStream
Using img As Image = Image.FromFile(filePath)
If img.RawFormat.Equals(Imaging.ImageFormat.Jpeg) Then
aImage.Save(stream, Imaging.ImageFormat.Jpeg)
ElseIf img.RawFormat.Equals(Imaging.ImageFormat.Png) Then
aImage.Save(stream, Imaging.ImageFormat.Png)
ElseIf img.RawFormat.Equals(Imaging.ImageFormat.Icon) Then
aImage.Save(stream, Imaging.ImageFormat.Icon)
End If
End Using
Return Convert.ToBase64String(stream.ToArray)
End Using
End Function
'Gets the full file path
Public Function ConvertToUrl(filePath As String) As String
Dim uri = New Uri(filePath).LocalPath
Dim converted = uri
Return converted.ToString()
End Function
Based on this post I fixed the issue: Resize and Compress image to byte array without saving the new image. The ToBase64String was the only function changed and now it looks like:
'Converts the path to a base64String
Public Function ToBase64String(filePath As String) As String
Dim aImage = New Bitmap(filePath)
Dim aspectRatio As Double = aImage.Height / aImage.Width
Dim imgThumb = New Bitmap(aImage, 200, CInt(Math.Round(200 * aspectRatio)))
Using stream = New IO.MemoryStream
Using img As Image = Image.FromFile(filePath)
If img.RawFormat.Equals(Imaging.ImageFormat.Jpeg) Then
imgThumb.Save(stream, Imaging.ImageFormat.Jpeg)
ElseIf img.RawFormat.Equals(Imaging.ImageFormat.Png) Then
imgThumb.Save(stream, Imaging.ImageFormat.Png)
ElseIf img.RawFormat.Equals(Imaging.ImageFormat.Icon) Then
imgThumb.Save(stream, Imaging.ImageFormat.Icon)
End If
End Using
Return Convert.ToBase64String(stream.ToArray)
End Using
End Function

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.

Save multiple images to database. Write exception for empty picture boxes

I have 4 picture boxes on my form that I use to store images and send to my database: I do it through a table adapter. The images are converted to a stream through this Function:
Public Function ConvertImage(ByVal myImage As Image) As Byte()
'store image in memory before converting and
'create memory stream, save image in proper format
Dim mStream As New MemoryStream
myImage.Save(mStream, System.Drawing.Imaging.ImageFormat.Jpeg)
'convert new stream into bytes and indicate size
Dim myBytes(mStream.Length - 1) As Byte
mStream.Position = 0
mStream.Read(myBytes, 0, mStream.Length)
Return myBytes
End Function
The problem I have is when one or more of my picture boxes have no images, how do I indicate on procedure if one or more picture boxes are empty, then set the image to Nothing. Here is a shorten version of my procedure as it is now
Private Sub btnSaveCategory_Click(sender As Object, e As EventArgs) Handles btnSaveCategory.Click
Dim picImage As Image = picBox1.Image
Dim picImage 2 As Image = picBox2.Image
Dim picImage 3 As Image = picBox3.Image
Dim picImage 4 As Image = picBox4.Image
PRODUCT_CATEGORYTableAdapter.InsertNewCategory(txtCategoryName.Text, ConvertImage(picImage),Image(picImage2), Image(picImage3), Image(picImage4))
End Sub
How can I check for an empty picture box and set it to empty so my procedure does not error out because an image does not exist on one or more boxes?
Thank you.
Try this
If pictureBox.Image is Nothing Then
//do stuff here
End If

Invert or Flip Text in RDLC report

Okay, I've learned a bit more and have rephrased my question. I've got a need to flip or invert text 180 degrees (so it appears upside-down) on a RDLC report. I have some custom VB code that takes the text, converts it to a bitmap, then flips the rotates the canvas 180 degrees. The effect of this makes the text look a bit.. dithered... or fuzzy. It's not a sharp font anymore. The problem I'm experiencing is I'm using a special TTF Barcode font that creates something a scanner can read. When I flip the barcode font, the fuzziness isn't good since the barcode lines are so close together and the scanner cannot read it. Here's the code:
Function LoadImage(ByVal sImageText as String, iRotationAngle as Integer, ByVal sFontName as String, iFontSize as Integer)
Dim bmpImage As New Drawing.Bitmap(1, 1)
Dim iWidth As Integer = 0
Dim iHeight As Integer = 0
'// Create the Font object for the image text drawing.
Dim MyFont As New Drawing.Font(sFontName, iFontSize) ', System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point)
'// Create a graphics object to measure the text's width and height.
Dim MyGraphics As Drawing.Graphics = Drawing.Graphics.FromImage(bmpImage)
'// This is where the bitmap size is determined.
iWidth = MyGraphics.MeasureString(sImageText, MyFont).Width
iHeight = MyGraphics.MeasureString(sImageText, MyFont).Height
'// Create the bmpImage again with the correct size for the text and font.
bmpImage = New Drawing.Bitmap(bmpImage, New Drawing.Size(iWidth, iHeight))
'// Add the colors to the new bitmap.
MyGraphics = Drawing.Graphics.FromImage(bmpImage)
MyGraphics.Clear(Drawing.Color.White)
MyGraphics.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
MyGraphics.TranslateTransform(iWidth,iHeight)
MyGraphics.RotateTransform(iRotationAngle)
MyGraphics.DrawString(sImageText, MyFont, New Drawing.SolidBrush(Drawing.Color.Black), 0, 0)
MyGraphics.Flush()
Dim stream As IO.MemoryStream = New IO.MemoryStream
Dim bitmapBytes As Byte()
'Create bitmap
bmpImage.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp)
bitmapBytes = stream.ToArray
stream.Close()
bmpImage.Dispose()
Return bitmapBytes
End Function
I really don't know why there's not a built-in way to just flip text. It'll let me reverse it left-to-right. Ridiculous.
Thanks

Image field on ReportViewer

Anybody tried to display image field (image/byte array) data type on reportviewer.
Regards,
Peter
Yes. ReportViewer requires a Base64 Image encoding in order to display the image properly.
If your image is in a Byte array, it will need to be converted to Base64:
Public Function ConvertImageToBase64String(ByVal img As Image) As String
Dim output As String = ""
Dim outputArray() As Byte
Dim stream As New MemoryStream
img.Save(stream, Drawing.Imaging.ImageFormat.Bmp)
outputArray = stream.ToArray()
stream.Close()
output = Convert.ToBase64String(outputArray)
Return output
End Function
I have with an image data type in SQL Server. Works fine with SSRS 2005 and 2008.