UWP Print multiple images - vb.net

I have modified Microsoft's printing example for printing multiple pictures, but the images are always aligned portrait, how can I align them landscape? According to Microsoft the pictures should be rotated automatically. The printing example is from https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/Printing.
Here is the code:
''' <summary>
''' Generates a page containing a photo.
''' The image will be rotated if detected that there is a gain from that regarding size (try to maximize photo size).
''' </summary>
''' <param name="photoNumber">The photo number.</param>
''' <param name="pageDescription">The description of the printer page.</param>
''' <returns>A task that will return the page.</returns>
Private Async Function GeneratePageAsync(photoNumber As Integer, pageDescription As PageDescription) As Task(Of UIElement)
Dim page As New Canvas() With {
.Width = pageDescription.PageSize.Width,
.Height = pageDescription.PageSize.Height
}
Dim viewablePage As New Canvas() With {
.Width = pageDescription.ViewablePageSize.Width,
.Height = pageDescription.ViewablePageSize.Height
}
viewablePage.SetValue(Canvas.LeftProperty, pageDescription.Margin.Width)
viewablePage.SetValue(Canvas.TopProperty, pageDescription.Margin.Height)
' The image "frame" which also acts as a viewport
Dim blnLandScape As Boolean
If MainPage._picsperprint = 2 OrElse MainPage._picsperprint = 6 OrElse MainPage._picsperprint = 8 OrElse MainPage._picsperprint = 32 OrElse MainPage._picsperprint = 128 Then
blnLandScape = True
ElseIf MainPage._picsperprint > 0 Then
blnLandScape = False
'PrintPageSqareNumbers(e, PrintPage)
ElseIf MainPage._picsperprint = -1 Then
'PrintPageSized(e, PrintPage)
End If
' Return an async task that will complete when the image is fully loaded.
Dim blnSuccess As Boolean = False
Dim pos As Integer = (photoNumber - 1) * MainPage._picsperprint
For i As Integer = 0 To _Rows - 1
For ii = 0 To _Columns - 1
If pos + i * (_Columns) + ii >= MainPage.checkedItems.Count Then Exit For
Dim height As Integer = pageDescription.PictureViewSize.Height
Dim width As Integer = pageDescription.PictureViewSize.Width
height = height / _Rows
width = width / _Columns
Dim photoView As New Grid() With {
.Width = width,
.Height = height
}
' Center the frame.
Dim Left As Integer = (viewablePage.Width - photoView.Width * _Columns) / 2
Dim Top As Integer = (viewablePage.Height - photoView.Height * _Rows) / 2
Top += height * i
Left += width * ii
photoView.SetValue(Canvas.LeftProperty, Left)
photoView.SetValue(Canvas.TopProperty, Top)
Dim position As Integer = (pos + i * (_Columns) + ii)
Dim Item As ImgListItem = GetItemOfPosition(position)
Dim bitmap As WriteableBitmap = Await Item.LoadBitmapAsync(False)
If bitmap IsNot Nothing Then
Dim image As New Image() With {
.Source = bitmap,
.HorizontalAlignment = Windows.UI.Xaml.HorizontalAlignment.Left,
.VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Top
}
' Use the real image size when croping or if the image is smaller then the target area (prevent a scale-up).
If photoScale = Scaling.Crop OrElse (bitmap.PixelWidth <= width AndAlso bitmap.PixelHeight <= height) Then
image.Stretch = Stretch.None
image.Width = bitmap.PixelWidth
image.Height = bitmap.PixelHeight
End If
' Add the newly created image to the visual root.
blnSuccess = True
photoView.Children.Add(image)
viewablePage.Children.Add(photoView)
End If
Next ii
Next i
If blnSuccess Then
page.Children.Add(viewablePage)
' Return the page with the image centered.
Return page
Else
Return Nothing
End If
End Function

There is not automatic rotation. The image must be rotated (transformed) in Item.LoadBitmapAsync(False).

Related

The cropping area has an x and y offset in the new bitmap, but only if the original has been scaled

a strange phenomenon occurs.
With my edge detection program, I can transfer the inside of the GraphicsPath to a new image.
It always works great – except when I scale the original image with GIMP and Word (aspect ratio remains, only the dimensions are changed). Then the area is shifted. To the left and up. See attachement. In line 68, I looked what is in rectCutout. Everything OK.
Does this have anything to do with GIMP? The dots per inch are the same (72). The compression quality of the JPEG also (100%).
I just realized: if I scale an image larger, the result is completely black.
The strange thing is: I'm not saying: the picture that is drawn on is larger than the picture that is saved. Then it would be logical that the path is not in the same position. It's about the fact that the loaded image is just smaller.
I would be happy if someone could tell me why. 😄
this is the scaled image which is loaded
Here you see the GUI, ready to save
cropped image, area has x and y offset
#Disable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
Imports System.Drawing.Drawing2D
Imports Microsoft.WindowsAPICodePack.Dialogs
Public NotInheritable Class AllesGrafische
Public Shared Sub Paint_the_Rectangle(ByVal g As Graphics, ByVal recta As Rectangle)
If g IsNot Nothing Then
g.SmoothingMode = SmoothingMode.AntiAlias
g.CompositingQuality = CompositingQuality.HighQuality
g.PixelOffsetMode = PixelOffsetMode.HighQuality
g.InterpolationMode = InterpolationMode.HighQualityBilinear
Using Pen_Hellblau As Pen = New Pen(Color.FromArgb(0, 200, 255), 1.0F)
g.DrawRectangle(Pen_Hellblau, recta)
End Using
End If
End Sub
Public Shared Sub Draw_Curve(ByVal g As Graphics, ByVal theList As List(Of Point))
If theList IsNot Nothing AndAlso theList.Count > 0 AndAlso g IsNot Nothing Then
g.SmoothingMode = SmoothingMode.AntiAlias
g.CompositingQuality = CompositingQuality.HighQuality
g.PixelOffsetMode = PixelOffsetMode.HighQuality
g.InterpolationMode = InterpolationMode.HighQualityBilinear
Dim theList_neu As New List(Of Point)
Using gp As New GraphicsPath
For i As Integer = 1 To theList.Count - 1 Step 1
Dim a As Integer = theList(i).X
Dim b As Integer = theList(i).Y
Dim c As Integer = theList(i - 1).X
Dim d As Integer = theList(i - 1).Y
Dim Entfernungsbetrag As Double = Math.Sqrt(Math.Pow(a, 2) + Math.Pow(b, 2) + Math.Pow(c, 2) + Math.Pow(d, 2) - 2 * a * c - 2 * b * d)
If Entfernungsbetrag < Form1.erlaubte_Entfernung Then
theList_neu.Add(theList(i))
End If
Next
If theList_neu.Count = 0 Then Return
gp.AddLines(theList_neu.ToArray())
Using Pen_hellrosa As Pen = New Pen(Color.FromArgb(255, 64, 239), 1.0F)
g.DrawPath(Pen_hellrosa, gp)
End Using
If Form1.ClosePath Then
gp.CloseFigure()
End If
If Form1.CheckBox1.Checked Then
Dim Speicherpfad As String
Using SFD1 As New CommonSaveFileDialog
SFD1.Title = "Wo soll das Bild gespeichert werden?"
SFD1.Filters.Add(New CommonFileDialogFilter("PNG", ".png"))
If System.IO.Directory.Exists("C:\Users\...\source\repos\VB.NET\Get mouse position and draw rectangle on screen") Then
SFD1.InitialDirectory = "C:\Users\...\source\repos\VB.NET\Get mouse position and draw rectangle on screen"
Else
SFD1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
End If
If SFD1.ShowDialog = CommonFileDialogResult.Ok Then
Speicherpfad = SFD1.FileName & ".png"
Else
Return
End If
End Using
Using bmpSource As Bitmap = New Bitmap(Form1.Pfad_Bild)
Dim rectCutout As RectangleF = gp.GetBounds()
Using m As Matrix = New Matrix()
m.Translate(-rectCutout.Left, -rectCutout.Top)
gp.Transform(m)
End Using
Using bmpCutout As Bitmap = New Bitmap(CInt(Math.Round(rectCutout.Width, 0)), CInt(Math.Round(rectCutout.Height, 0)))
Using graphicsCutout As Graphics = Graphics.FromImage(bmpCutout)
graphicsCutout.Clip = New Region(gp)
graphicsCutout.DrawImage(bmpSource, CInt(-rectCutout.Left), CInt(-rectCutout.Top))
bmpCutout.Save(Speicherpfad, Imaging.ImageFormat.Png)
Form1.CheckBox1.Checked = False
End Using
End Using
End Using
End If
End Using
End If
End Sub
End Class
#Enable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
The solution is to use .SetResolution()
Using Original As Bitmap = New Bitmap(Form1.Pfad_Bild)
Dim rectCutout As RectangleF = gp.GetBounds()
Using m As System.Drawing.Drawing2D.Matrix = New System.Drawing.Drawing2D.Matrix()
m.Translate(-rectCutout.Left, -rectCutout.Top)
gp.Transform(m)
End Using
Using bmpCutout As Bitmap = New Bitmap(CInt(Math.Round(rectCutout.Width, 0)), CInt(Math.Round(rectCutout.Height, 0)))
bmpCutout.SetResolution(Original.HorizontalResolution, Original.VerticalResolution)
.
.
.
.
.

Convert SVG or Base30 to image file

I'm trying to convert an SVG file to any format of image file.
I'm creating SVG file from base30 value.
Public Sub SaveSignature()
Dim B30 As New Base30Converter
Dim Img = B30.GetData("aQ4895d6d7j5h94840Z39baa6bfb6430Y4538d6a49c59db8863003240Z4374b7ek7j4a33Y255e8j5d6Z52Y3b2428385e9n1vd1Bfq6a4Z4Y3949456Z1e91wi2B2N1u2Eh1H9bY5j81ye1w1u8e5724983329d8pe1Ai1Nf1V1Uft9d5_7WZ266594c4g7gc36452542000Y2648a67334524112100Z1235766Y64Z9ah593420Y75g7d483401000Z34Y133Z332Y7e29262300Z43a3652Y26252556400Z2ig6h2200473720Y2263542006736424241000Z826010")
Dim svg = SVGConverter.ToSVG(Img)
Dim sw As New System.IO.StreamWriter("D:\Sign.svg", False)
sw.Write(svg)
sw.Close()
Dim bmp As Bitmap = renderFile("D:\Sign.svg")
Dim g As Graphics
g = Graphics.FromImage(bmp)
Using g
g.Clear(Color.White)
g.DrawImageUnscaled(bmp, 0, 0)
End Using
bmp.Save("D:\Sign.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
bmp.Save("D:\Sign.jpg", System.Drawing.Imaging.ImageFormat.Jpeg)
bmp.Save("D:\Sign.emf", System.Drawing.Imaging.ImageFormat.Emf)
End Sub
Public Function renderFile(filename As String) As Bitmap
Dim displaySize As System.Drawing.Size
displaySize.Width = 300
displaySize.Height = 200
Dim svgDoc As SvgDocument = SvgDocument.Open(filename)
Dim svgSize = svgDoc.GetDimensions()
If svgSize.Width = 0 Then
Throw New Exception("SVG does not have size specified. Cannot work with it.")
End If
Dim displayProportion = (displaySize.Height * 1.0F) / displaySize.Width
Dim svgProportion = svgSize.Height / svgSize.Width
Dim scalingFactor As Single = 0.0F
Dim padding As Integer = 10
If displayProportion > svgProportion Then
scalingFactor = ((displaySize.Width - padding * 2) * 1.0F) / svgSize.Width
Else
scalingFactor = ((displaySize.Height - padding * 2) * 1.0F) / svgSize.Height
End If
If scalingFactor < 0 Then
Throw New Exception("Viewing area is too small to render the image")
End If
Dim centeringX As Integer = Convert.ToInt16((displaySize.Width - (padding + CInt(svgDoc.Width) * scalingFactor)) / 2)
Dim centeringY As Integer = Convert.ToInt16((displaySize.Height - (padding + CInt(svgDoc.Height) * scalingFactor)) / 2)
svgDoc.Transforms = New SvgTransformCollection()
svgDoc.Transforms.Add(New SvgTranslate(padding + centeringX, padding + centeringY))
svgDoc.Transforms.Add(New SvgScale(scalingFactor))
svgDoc.Width = New SvgUnit(svgDoc.Width.Type, displaySize.Width)
svgDoc.Height = New SvgUnit(svgDoc.Height.Type, displaySize.Height)
Return svgDoc.Draw()
End Function
After all these process the image file left with empty file.
The base30 value I'm getting from a signature panel in asp application.

Drawing an array of PictureBoxes in vb.net

I'm trying to draw an array of PictureBoxes, for testing I use the same picture for each picturebox.
But instead of showing the picture, it shows the color blue.
I would show you a picture, but I dont have 10 reputation..
Dim teren(120) As PictureBox
Dim x_locatie As Integer = 1, y_locatie As Integer = 0
For i = 0 To 10
x_locatie = 210
For j = 0 To 12
teren(i * j) = New PictureBox()
teren(i * j).Size = New Size(61, 61)
teren(i * j).Name = "x" + i.ToString + "y" + j.ToString
teren(i * j).Location = New Point(x_locatie, y_locatie)
Dim locatie As String = folder + "\harta\test.png"
teren(i * j).ImageLocation = locatie
teren(i * j).Show()
Next
y_locatie += 61
Next
I also tried another method , but same result.
Sub PictureBox1_Paint(sender1 As Object, er As PaintEventArgs)
If myImage IsNot Nothing Then
Dim r As New Rectangle(x, y, xlatime, ylungime)
er.Graphics.DrawImage(myImage, r)
End If
End Sub
Sub deseneaza(ByVal poza As String, ByRef x_perm As Integer, ByRef y_perm As Integer, ByRef lungime As Integer, ByRef latime As Integer)
myImage = Image.FromFile(poza)
x = x_perm
y = y_perm
xlatime = latime
ylungime = lungime
Refresh()
End Sub
'this part of code is in body of another function
Dim x_locatie As Integer = 1, y_locatie As Integer = 0
For i = 0 To 10
x_locatie = 210
For j = 0 To 12
Dim locatie As String = folder + "\harta\test.png"
deseneaza(locatie, x_locatie, y_locatie, 61, 61)
Next
y_locatie += 61
Next
I saw in other threads that their problem solution was something like that Dim teren() As PictureBox {teren1, teren2 , ... , teren n} But the problem in my case is that I need 120 PictureBoxes, and I think that it must be a way to do this without writing 120 pictureboxes.
Please try this...it will generate 16 picture box, size 20x20, in a row. I put it under "FormLoading" event.
Dim Shapes(16) As PictureBox
For i = 1 To 16
Shapes(i) = New PictureBox
With Shapes(i)
.BackColor = SystemColors.Control 'Color.Green
.BackgroundImage = New Bitmap(My.Resources.led_blk)
.BackgroundImageLayout = ImageLayout.Zoom
.Size = New Size(20, 20)
.Visible = True
.Location = New Point( 23 * i, 50)
End With
Me.Controls.Add(Shapes(i))
Next
I think GDI+ will be the way to go. I think you need a custom class that has a rectangle structure as a member with other properties that help you with further logic with the character intersecting with them. Paint should be done in the Paint event of the surface control you are using - PictureBox has the best rendering - IMO.
Public Class Tile
Public Property Bounds As New Rectangle
Public Property IsImpassable As Boolean
'others you think of
End Class
Dim iTop = 325
Dim pBox(48) As PictureBox
Dim pinColor = Color.SkyBlue
Dim leftStart = 50
For j = 0 To 3
For i = 0 To 11
pBox(i) = New PictureBox
'pBox(i).Image = Image.FromFile("\NoTest.bmp")
pBox(i).Visible = True
pBox(i).BackColor = pinColor
pBox(i).Top = iTop + (j * 40)
pBox(i).Width = 20
pBox(i).Height = 20
pBox(i).Left = leftStart + (35 * i)
If i > 9 Then
pBox(i).Left = leftStart + (35 * i) + 15
pBox(i).Width = 25
End If
pBox(i).BringToFront()
pBox(i).SizeMode = PictureBoxSizeMode.StretchImage
Controls.Add(pBox(i))
Next
Next

How to compare between two images using VB.net?

I have a small bitmap image and I will do a screenshot. I need to find whether the small image is the screenshot. How I can compare two bitmap images? and then return the coordinates.
If it is MATLAB, (NOTE: I need VB.net)
What my plan is this
screenshot
for x_screen = 1: screen_width_x
for y_screen = 1: screen_col_y
for x_pic = = 1: pic_width_x
for y_pic = = 1: pic_col_y
if screenshot(x_screen, y_screen) != pic(x_pic , y_pic)
break
end
end
xx = (x_screen)
yy = (y_screen)
end
end
See Image comparison if you want something advanced Also you can look for machine learning techniques for such tasks.
Here is naive solution and not optimized one (plus it is better to do such tasks in native code):
Plus Note that it is better to check this with bmp files. otherwise it will not handle problem
Private Function FindSubImg2(img As Bitmap, subimg As Bitmap) As Point
If (img.Width - subimg.Width < 0) Or (img.Height - subimg.Height < 0) Then Return Nothing
Dim stepxLen As Integer = img.Width - subimg.Width
Dim stepyLen As Integer = img.Height - subimg.Height
Dim coor As Point
Dim match As Boolean = False
For oy As Integer = 0 To stepyLen
For ox As Integer = 0 To stepxLen
match = True
For x As Integer = 0 To subimg.Width - 1
For y As Integer = 0 To subimg.Height - 1
'actually here we do not need ToArgb method. But it will skip unneeded Color comparisions
If img.GetPixel(x + ox, y + oy).ToArgb <> subimg.GetPixel(x, y).ToArgb Then
match = False
Exit For 'we can use goto operator instead of double exit for
End If
Next
If match = False Then Exit For
Next
If match = True Then
coor.X = ox
coor.Y = oy
Return coor
End If
Next
Next
Return New Point(-1, -1)
End Function
Private Function FindSubImg(a As Bitmap, b As Bitmap) As Point
Dim subimg As Bitmap
Dim img As Bitmap
If (a.Height <= b.Height AndAlso a.Width <= b.Width) Then
subimg = a : img = b
Return FindSubImg2(img, subimg)
ElseIf (a.Height > b.Height AndAlso a.Width > b.Width) Then
subimg = b : img = a
Return FindSubImg2(img, subimg)
Else
Return New Point(-1, -1)
End If
End Function
Usage:
Dim p As Point = FindSubImg(New Bitmap("A.bmp"), New Bitmap("B.bmp"))
Try something like this:
Public Function CompareImages(ByVal img1 As Bitmap, ByVal img2 As Bitmap) As Boolean
Dim i As Integer
Dim j As Integer
For i = 0 To img1.Width - 1
For j = 0 To img2.Height - 1
If img1.GetPixel(i, j) <> img2.GetPixel(i, j) Then
Return False
End If
Next
Next
Return True
End Function
sample call:
CompareImages(New Bitmap("f:\img1.bmp"), New Bitmap("f:\img2.bmp"))

Print multiple images in vb.net

In VB.NET, I need to print multiple Images of bar codes by arranging them in tabular format. For now what I am doing is, Creating the bar codes and adding them in new picture box. These Picture boxes are added on a panel which I am creating on form at run time and print that panel (with picture boxes in 4x9 table).
But, when I need to print more that 36 bar codes, this idea doesn't work.
So, Please suggest me some improvements in my code or any other way to do this job.
I am sorry, here is the code for generating images and adding them to the panel..
''' Method for create bar code images with a loop and adding them to the panel by picture box...
Private Function GetBarcodeText(RowId As Guid)
Dim BarcodeValue As StringBuilder = New StringBuilder(96)
Dim temp As New StringBuilder
Dim data As String
Dim param = New SqlParameter()
Dim imageNo As Integer = 0
Dim colorValue As String = ""
Dim scaleValue As String = ""
'' Adding the panel on the form which is dynamically created
Me.Controls.Add(outputPanel)
'' Setting the Initial size for the panel
outputPanel.Size = New Point(794, 112)
outputPanel.Name = "outputPanel"
outputPanel.BackColor = Drawing.Color.White
param.ParameterName = "#RowId"
param.Value = RowId
param.SqlDbType = SqlDbType.UniqueIdentifier
' Get the particular row of data from database
dt = objStockProvider.GetBarcodeDetails(param)
' GET colour code
Dim color As String = dt.Rows(0)("COLOUR").ToString()
Dim countColors As Integer = 0
' Get the color code numbers
param.ParameterName = "#Dscale"
param.Value = dgvViewTickets.CurrentRow.Cells("SCALE").Value.ToString()
countColors = objStockProvider.CountColorCodes(param)
For i = 1 To countColors
For j As Integer = 1 + ((12 / countColors) * (i - 1)) To (12 / countColors) * i
If dt.Rows(0)("S" + j.ToString()) <> 0 Then
Dim totalTicketsForASize As Integer
totalTicketsForASize = dt.Rows(0)("S" + j.ToString())
For k As Integer = 1 To totalTicketsForASize
' Set Bar code value which has to create
BarcodeValue = "123456789012"
' Create Barcode Image for given value
Dim image = GetBarcodeImage(BarcodeValue, colorValue, scaleValue)
If image IsNot Nothing Then
'' Create picture box to contain generated Image.
Dim pcbImage As New PictureBox
pcbImage.Width = W
pcbImage.Height = H
pcbImage.Image = image
pcbImage.Location = New Point(X, Y)
imageNo += 1
If imageNo Mod 4 = 0 Then
X = 15
Y += H
outputPanel.Height += H
Else
X += W
Y = Y
End If
pcbImage.Visible = True
'' Adding picture box to panel
outputPanel.Controls.Add(pcbImage)
End If
Next
End If
Next
color = color.Substring(color.IndexOf(",") + 1, color.Length - color.IndexOf(",") - 1)
Next
PrintGeneratedTickets()
End Function
Now, I am printing the panel by following method:
Private Sub PrintGeneratedTickets()
bmp = New Bitmap(outputPanel.DisplayRectangle.Width, outputPanel.DisplayRectangle.Height)
Dim G As Graphics = Graphics.FromImage(bmp)
G.DrawRectangle(Pens.White, New Rectangle(0, 0, Me.outputPanel.DisplayRectangle.Width, Me.outputPanel.DisplayRectangle.Height))
Dim Hdc As IntPtr = G.GetHdc()
SendMessage(outputPanel.Handle, WM_PRINT, Hdc, DrawingOptions.PRF_OWNED Or DrawingOptions.PRF_CHILDREN Or DrawingOptions.PRF_CLIENT Or DrawingOptions.PRF_NONCLIENT)
G.ReleaseHdc(Hdc)
pndocument.DocumentName = bmp.ToString()
Dim previewmode As New PrintPreviewDialog
previewmode.Document = pndocument
previewmode.WindowState = FormWindowState.Maximized
previewmode.PrintPreviewControl.Zoom = 1
pndocument.DefaultPageSettings.Margins.Top = 10
pndocument.DefaultPageSettings.Margins.Bottom = 30
pndocument.DefaultPageSettings.Margins.Left = 16
pndocument.DefaultPageSettings.Margins.Right = 16
pndocument.DefaultPageSettings.Landscape = False
' Set other properties.
previewmode.PrintPreviewControl.Columns = 4
previewmode.PrintPreviewControl.Rows = 9
previewmode.ShowDialog()
Dim file As String = DateTime.Now.ToString()
file = Path.GetFullPath("D:\Bar Codes\" + file.Replace("/", "-").Replace(":", ".") + ".bmp")
bmp.Save(file)
G.Dispose()
outputPanel.Controls.Clear()
End Sub
This code is working fine but what I need to do, is to fix the number of images (4x9) per page. But when I am trying to create more than it, that all are printing on a single page with compressed size.
Also when trying to re-run the code, It shows nothing in preview..
Some body please suggest the correction in code so that I can reprint the tickets and use paging for more than 36 images.
Well, Printing the Images on a panel was not a good idea.. I replaced the panel and created an array of images and used the print document directly and print after arranging images on it.
Thanks.