How to Display a Bmp in a RTF control in VB.net - vb.net

I Started with this C# Question
I'm trying to Display a bmp image inside a rtf Box for a Bot program I'm making.
This function is supposed to convert a bitmap to rtf code whis is inserted to another rtf formatter srtring with additional text. Kind of like Smilies being used in a chat program.
For some reason the output of this function gets rejected by the RTF Box and Vanishes completly. I'm not sure if it the way I'm converting the bmp to a Binary string or if its tied in with the header tags
lb.SelectedRtf = FormatText(build.ToString, newColor)
'returns the RTF string representation of our picture
Public Shared Function PictureToRTF(ByVal Bmp As Bitmap) As String
'Create a new bitmap
Dim BmpNew As New Bitmap(Bmp.Width, Bmp.Height, Imaging.PixelFormat.Format24bppRgb)
Dim gr = Graphics.FromImage(BmpNew)
gr.DrawimageUnscaled(Bmp, 0, 0)
gr.dispose()
Dim stream As New MemoryStream()
BmpNew.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp)
Dim bytes As Byte() = stream.ToArray()
Dim str As String = BitConverter.ToString(bytes, 0).Replace("-", String.Empty)
'header to string we want to insert
Using g As Graphics = Main.CreateGraphics()
xDpi = g.DpiX
yDpi = g.DpiY
End Using
Dim _rtf As New StringBuilder()
' Calculate the current width of the image in (0.01)mm
Dim picw As Integer = CInt(Math.Round((Bmp.Width / xDpi) * HMM_PER_INCH))
' Calculate the current height of the image in (0.01)mm
Dim pich As Integer = CInt(Math.Round((Bmp.Height / yDpi) * HMM_PER_INCH))
' Calculate the target width of the image in twips
Dim picwgoal As Integer = CInt(Math.Round((Bmp.Width / xDpi) * TWIPS_PER_INCH))
' Calculate the target height of the image in twips
Dim pichgoal As Integer = CInt(Math.Round((Bmp.Height / yDpi) * TWIPS_PER_INCH))
' Append values to RTF string
_rtf.Append("{\pict\wbitmap0")
_rtf.Append("\picw")
_rtf.Append(Bmp.Width.ToString)
' _rtf.Append(picw.ToString)
_rtf.Append("\pich")
_rtf.Append(Bmp.Height.ToString)
' _rtf.Append(pich.ToString)
_rtf.Append("\wbmbitspixel24\wbmplanes1")
_rtf.Append("\wbmwidthbytes40")
_rtf.Append("\picwgoal")
_rtf.Append(picwgoal.ToString)
_rtf.Append("\pichgoal")
_rtf.Append(pichgoal.ToString)
_rtf.Append("\bin ")
_rtf.Append(str.ToLower & "}")
Return _rtf.ToString
End Function
Public Function FormatText(ByVal data As String, ByVal newColor As fColorEnum) As String
data = System.Net.WebUtility.HtmlDecode(data)
data = data.Replace("|", " ")
Dim reg As New Regex("\$(.[0-9]+)\$")
If reg.IsMatch(data) Then
Dim meep As String = Regex.Match(data, "\$(.[0-9]+)\$").Groups(1).ToString
Dim idx As Integer = Convert.ToInt32(meep)
Dim img As String = Fox2RTF(idx)
If img IsNot Nothing Then data = Regex.Replace(data, "\$(.[0-9]+)\$", img)
End If
Dim myColor As System.Drawing.Color = fColor(newColor)
Dim ColorString = "{\colortbl ;"
ColorString += "\red" & myColor.R & "\green" & myColor.G & "\blue" & myColor.B & ";}"
Dim FontSize As Integer = cMain.ApFont.Size
Dim FontFace As String = cMain.ApFont.Name
FontSize *= 2
Dim test As String = "{\rtf1\ansi\ansicpg1252\deff0\deflang1033" & ColorString & "{\fonttbl{\f0\fcharset0 " & FontFace & ";}}\viewkind4\uc1\fs" & FontSize.ToString & data & "\par}"
Return "{\rtf1\ansi\ansicpg1252\deff0\deflang1033" & ColorString & "{\fonttbl{\f0\fcharset0 " & FontFace & ";}}\viewkind4\uc1\fs" & FontSize.ToString & data & "\cf0 \par}"
End Function
Private Function Fox2RTF(ByRef Img As Integer) As String
Dim shape As New FurcadiaShapes(Paths.GetDefaultPatchPath() & "system.fsh")
Dim anims As Bitmap() = Helper.ToBitmapArray(shape)
' pic.Image = anims(Img)
Return PictureToRTF.PictureToRTF(anims(Img))
End Function

Never found the Soultion I was hoping for with this.. But I did find a work around http://www.codeproject.com/Articles/30902/RichText-Builder-StringBuilder-for-RTF

Related

Change font style to Richtextbox vb.net

I need to change font style and add it to Richtextbox, this is my code but i get some errors. please help
Dim sb = New StringBuilder()
sb.AppendFormat(New Font("IDAutomationHC39M", 12,FontStyle.Regular).AppendLine("SCAN BARCODE: " & txtBarcode.Text)
RichTextBoxPrintCtrl1.Text = sb.ToString()
To change the font for only a part of the text in your RichTextBox you need to search for the text required, then calculate its length and select it. At this point you can apply the font you want to the SelectionFont property.
Sub SetBarCodeText(searchText as String)
Dim len As Integer = searchText.Length
Dim pos As Integer = RichTextBoxPrintCtrl1.Find(searchText, 0, RichTextBoxFinds.NoHighlight)
if pos >= 0 Then
Dim start As Integer = pos
Dim endpos As Integer = start + len
RichTextBoxPrintCtrl1.Select(start, endpos - start)
RichTextBoxPrintCtrl1.SelectionFont = new Font("IDAutomationHC39M", 12, FontStyle.Regular)
End If
End Sub
and you call the method above with
RichTextBoxPrintCtrl1.Text = "SCAN BARCODE: " & txtBarcode.Text
SetBarCodeText("SCAN BARCODE: " & txtBarcode.Text)

Why can't my GetManifestResourceStream find my image?

I'm currently attempting to layer several images into a single composite, built from several body face pieces for a player's portrait.
Usually for grabbing images from the resources and putting them into a picturebox/etc I'd simply ".Image = My.Resources.ResourceManager.GetObject(filename)".
However I need to transfer to a Bitmap, which doesn't accept objects. I've found the below code from a couple of google results, but the file is bugging out as "Value of null is not valid for 'stream' ", and the pHead is "Nothing". As such I'm presuming the code can't find the file.
The break is causing on the final line of the below code.
Any help or simpler alternatives would be much welcome.
Dim GenderText As String = ""
Select Case ListCharacter(ActiveChar).Gender
Case eGender.Male : GenderText = "masc"
Case eGender.Female : GenderText = "fem"
End Select
Dim Prefix As String = ""
Dim Suffix As String = ".png"
Dim myAsm As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
' Load Head Image
' e.g. prt_fem_head_1_white.png
Dim headImageName As String = "prt_" & GenderText & "_head_" & CharApp.HeadStyle & "_" & CharApp.SkinColour
Dim pHead As Bitmap = New Bitmap(myAsm.GetManifestResourceStream(Me.GetType, headImageName & Suffix))
ps. Also bugs out with/without the suffix.
Edit #1;
I've found the prefix required, as far as I can tell, to the whereabouts of the resources root. However, that still isn't working to any variation.
Edit #2;
I've double checked the resource location via its properties.
"C:\Users\CLEO\Documents\Visual Studio 2015\Projects\Storytime\Storytime\Resources\prt_fem_head_1_white.png"
Solved. I changed the code out for a simpler one I found in my Resources Designer code. The below is very raw and needs tidying, but this is how I was able to make several images build into one picturebox.
' Load Face
Dim PortraitLocation As New Point(573, 51)
Dim CharApp As New Character.cAppearance : CharApp = ListCharacter(ActiveChar).Appearance
' Dim pHead, pEyes, pNose, pMouth, pBase, pHair As New PictureBox
Dim FaceCanvas As New PictureBox
Dim GenderText As String = ""
Select Case ListCharacter(ActiveChar).Gender
Case eGender.Male : GenderText = "masc"
Case eGender.Female : GenderText = "fem"
End Select
Dim resourceCulture As Global.System.Globalization.CultureInfo
Dim headImageName As String = "prt_" & GenderText & "_head_" & CharApp.HeadStyle & "_" & CharApp.SkinColour
Dim obj As Object = My.Resources.ResourceManager.GetObject(headImageName, resourceCulture)
Dim phead As Bitmap = CType(obj, System.Drawing.Bitmap)
Dim eyesImageName As String = "prt_" & GenderText & "_eyes_" & CharApp.EyeStyle & "_" & CharApp.SkinColour
Dim obj2 As Object = My.Resources.ResourceManager.GetObject(eyesImageName, resourceCulture)
Dim pEyes As Bitmap = CType(obj2, System.Drawing.Bitmap)
Dim noseImageName As String = "prt_" & GenderText & "_nose_" & CharApp.NoseStyle & "_" & CharApp.SkinColour
Dim obj3 As Object = My.Resources.ResourceManager.GetObject(noseImageName, resourceCulture)
Dim pNose As Bitmap = CType(obj3, System.Drawing.Bitmap)
Dim mouthImageName As String = "prt_" & GenderText & "_mouth_" & CharApp.MouthStyle & "_" & CharApp.SkinColour
Dim obj4 As Object = My.Resources.ResourceManager.GetObject(mouthImageName, resourceCulture)
Dim pMouth As Bitmap = CType(obj4, System.Drawing.Bitmap)
Dim hairImageName As String = "prt_" & GenderText & "_hair_" & CharApp.HairStyle & "_" & CharApp.HairColour
Dim obj5 As Object = My.Resources.ResourceManager.GetObject(hairImageName, resourceCulture)
Dim pHair As Bitmap = CType(obj5, System.Drawing.Bitmap)
Dim bodyImageName As String = "prt_" & GenderText & "_body_" & CharApp.SkinColour
Dim obj6 As Object = My.Resources.ResourceManager.GetObject(bodyImageName, resourceCulture)
Dim pBody As Bitmap = CType(obj6, System.Drawing.Bitmap)
Dim g As Graphics = Graphics.FromImage(pBody)
g.DrawImage(phead, 0, 0)
g.DrawImage(pEyes, 0, 0)
g.DrawImage(pNose, 0, 0)
g.DrawImage(pMouth, 0, 0)
g.DrawImage(pHair, 0, 0)
With FaceCanvas
.Location = PortraitLocation
.Size = New Size(50, 50)
.Image = pBody
.BackColor = Color.Transparent
End With
Me.Controls.Add(FaceCanvas)

Load pal files on vb.net

Im having this error on vb.net "unable to read beyond the end of the stream".
It happens when i compile the program and it breaks in there.
Dim red As Byte = br.ReadByte()
Dim green As Byte = br.ReadByte()
Dim blue As Byte = br.ReadByte()
Dim flags As Byte = br.ReadByte()
But i will also give all the code:
Public Shared Function LoadPal(filename As String) As List(Of Color)
Dim colors As New List(Of Color)()
Dim stream As New FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)
Using br As New BinaryReader(stream)
' RIFF header
Dim riff As String = ReadByteString(br, 4)
' "RIFF"
Dim dataSize As Integer = br.ReadInt32()
Dim type As String = ReadByteString(br, 4)
' "PAL "
' Data chunk
Dim chunkType As String = ReadByteString(br, 4)
' "data"
Dim chunkSize As Integer = br.ReadInt32()
Dim palVersion As Short = br.ReadInt16()
' always 0x0300
Dim palEntries As Short = br.ReadInt16()
' Colors
For i As Integer = 0 To palEntries - 1
Dim red As Byte = br.ReadByte()
Dim green As Byte = br.ReadByte()
Dim blue As Byte = br.ReadByte()
Dim flags As Byte = br.ReadByte()
' always 0x00
colors.Add(Color.FromArgb(red, green, blue))
Next
End Using
Return colors
End Function
Private Shared Function ReadByteString(br As BinaryReader, length As Integer) As String
Return Encoding.ASCII.GetString(br.ReadBytes(length))
End Function
Another lucky man. I hope this help u, i dont know why but the pallets must load 2 by 2, if not the colors will get mixed or something like that.
To Call load
'''''''''''''''''''''''''''''''''
Dim colors1
colerss = LoadPal(.FileName)
'''''''''''''''''''''''''''''''''
'LOAD PALL
Public Shared Function LoadPal(filename As String) As List(Of Color)
Dim colors As New List(Of Color)()
Dim stream As New FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)
Using br As New BinaryReader(stream)
' RIFF header
' Colors
For i As Integer = 0 To 7
Try
''''''''''''First''''''''''''''''
Dim red As Byte = br.ReadByte()
Dim green As Byte = br.ReadByte()
Dim blue As Byte = br.ReadByte()
Dim flags As Byte = br.ReadByte()
'MsgBox(blue & " " & green & " " & red)
colors.Add(Color.FromArgb(blue, green, red))
''''''''''''''''''Second''''''''''''''''''''
Dim red1 As Byte = br.ReadByte()
Dim green1 As Byte = br.ReadByte()
Dim blue1 As Byte = br.ReadByte()
Dim flags1 As Byte = br.ReadByte()
'MsgBox(blue1 & " " & green1 & " " & red1)
colors.Add(Color.FromArgb(blue1, green1, red1))
'''''''''''''''''''''''''''''''''''''''''''''''
Catch
MsgBox("Erro")
Finally
End Try
Next
End Using
Return colors
End Function
Private Shared Function ReadByteString(br As BinaryReader, length As Integer) As String
Return Encoding.ASCII.GetString(br.ReadBytes(length))
End Function
And why Load if u can Save?
To Call Save
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SavePal(saveFileDialog1.FileName & "TheNameUWant.pal", colors1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'SAVE PAL
Public Shared Sub SavePal(filename As String, colors As List(Of Color))
' Calculate file length
Dim stream As New FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None)
Using bw As New BinaryWriter(stream)
' Colors
For i = 0 To 15
'i dont know why but for writing the pallete the bytes are written in the reverse order
bw.Write(CByte(colors(i).B))
bw.Write(CByte(colors(i).G))
bw.Write(CByte(colors(i).R))
' Flag in W:A always 0x00
bw.Write(CByte(0))
Next
WriteStringBytes(bw, "PAL ")
End Using
End Sub
Private Shared Sub WriteStringBytes(bw As BinaryWriter, value As String)
bw.Write(Encoding.ASCII.GetBytes(value))
End Sub

How to convert memory stream to string array and vice versa

I have a code where i want to get an stream from an image and convert the memory stream to string array and store in a variable. But my problem is i also want to get the image from the string variable and paint on a picture box.
If i use this like
PictureBox1.Image = image.FromStream(memoryStream)
I am able to print the picture on picture box. But this is not my need. I just want to get the image stream from file and convert the stream as text and store it to some string variable and again i want to use the string variable and convert it to stream to print the image on picture box.
Here is my Code.(Vb Express 2008)
Public Function ImageConversion(ByVal image As System.Drawing.Image) As String
If image Is Nothing Then Return ""
Dim memoryStream As System.IO.MemoryStream = New System.IO.MemoryStream
image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Gif)
Dim value As String = ""
For intCnt As Integer = 0 To memoryStream.ToArray.Length - 1
value = value & memoryStream.ToArray(intCnt) & " "
Next
Dim strAsBytes() As Byte = New System.Text.UTF8Encoding().GetBytes(value)
Dim ms As New System.IO.MemoryStream(strAsBytes)
PictureBox1.Image = image.FromStream(ms)
Return value
End Function
This wouldn`t work in the way you have posted it (at least the part of recreating the image).
See this:
Public Function ImageConversion(ByVal image As System.Drawing.Image) As String
If image Is Nothing Then Return ""
Dim memoryStream As System.IO.MemoryStream = New System.IO.MemoryStream
image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Gif)
Dim value As String = ""
Dim content As Byte() = memoryStream.ToArray()
' instead of repeatingly call memoryStream.ToArray by using
' memoryStream.ToArray(intCnt)
For intCnt As Integer = 0 To content.Length - 1
value = value & content(intCnt) & " "
Next
value = value.TrimEnd()
Return value
End Function
To recreate the image using the created string you can`t use Encoding.GetBytes() like you did, because you would get a bytearray which represents your string. E.g "123 32 123" you would not get a byte array with the elements 123, 32 , 123
Public Function ImageConversion(ByVal stringRepOfImage As String) As System.Drawing.Image
Dim stringBytes As String() = stringRepOfImage.Split(New String() {" "}, StringSplitOptions.RemoveEmptyEntries)
Dim bytes As New List(Of Byte)
For intCount = 0 To stringBytes.Length - 1
Dim b As Byte
If Byte.TryParse(stringBytes(intCount), b) Then
bytes.Add(b)
Else
Throw new FormatException("Not a byte value")
End If
Next
Dim ms As New System.IO.MemoryStream(bytes.ToArray)
Return Image.FromStream(ms)
End Function
Reference: Byte.TryParse

VB.NET - Take a screenshot of all screens on a computer

I'm trying to capture any and all screens on a computer, I tried to fiddle with Screen.AllScreens and also something with VirtualScreens that I can't remember, so I moved to PrimaryScreen to make sure everything else worked properly.
Here is my current class:
Public Class wmCapture
Public Shared Function screenCapture()
Dim userName As String = Environment.UserName
Dim savePath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
Dim dateString As String = Date.Now.ToString("yyyyMMddHHmmss")
Dim captureSavePath As String = String.Format("{0}\WM\{1}\capture_{2}.png", savePath, userName, dateString)
Dim bmp As Bitmap = New Bitmap( _
Screen.PrimaryScreen.Bounds.Width, _
Screen.PrimaryScreen.Bounds.Height)
Dim gfx As Graphics = Graphics.FromImage(bmp)
gfx.CopyFromScreen( _
Screen.PrimaryScreen.Bounds.Location, _
New Point(0, 0), Screen.PrimaryScreen.Bounds.Size)
bmp.Save(captureSavePath)
End Function
End Class
What should I be using in the Screen namespace to include all active screens?
You were close. I made a couple adjustments and can confirm it's working on my end.
Public Shared Sub screenCapture()
Dim userName As String = Environment.UserName
Dim savePath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
Dim dateString As String = Date.Now.ToString("yyyyMMddHHmmss")
Dim captureSavePath As String = String.Format("{0}\WM\{1}\capture_{2}.png", savePath, userName, dateString)
' This line is modified for multiple screens, also takes into account different screen size (if any)
Dim bmp As Bitmap = New Bitmap( _
Screen.AllScreens.Sum(Function(s As Screen) s.Bounds.Width),
Screen.AllScreens.Max(Function(s As Screen) s.Bounds.Height))
Dim gfx As Graphics = Graphics.FromImage(bmp)
' This line is modified to take everything based on the size of the bitmap
gfx.CopyFromScreen(SystemInformation.VirtualScreen.X,
SystemInformation.VirtualScreen.Y,
0, 0, SystemInformation.VirtualScreen.Size)
' Oh, create the directory if it doesn't exist
Directory.CreateDirectory(Path.GetDirectoryName(captureSavePath))
bmp.Save(captureSavePath)
End Sub