Reduce latency when Embossing an Image in PictureBox - vb.net

How would I go about reducing the latency of grabbing an image from Picturebox then emboss that image and return you picturebox as this is a camera handle and will need to capture/emboss at least 16 fps but i'm getting like 1 every 2.5 seconds
SwitchImageSave = 1
Button1.Enabled = False
StCam.StopTransfer(m_hCamera)
Dim nReval As Integer
Dim nLastErrorNo As Integer
Dim nBufferSize As Integer
Dim dwWidth As Integer
Dim dwHeight As Integer
Dim dwLinePitch As Integer
nReval = StCam.GetPreviewDataSize(m_hCamera, nBufferSize, dwWidth, dwHeight, dwLinePitch)
Dim dwPreviewPixelFormat As Integer
nReval = StCam.GetPreviewPixelFormat(m_hCamera, dwPreviewPixelFormat)
Dim pixelFormat As Imaging.PixelFormat = Imaging.PixelFormat.Format8bppIndexed
Select Case dwPreviewPixelFormat
Case StCam.STCAM_PIXEL_FORMAT_24_BGR
pixelFormat = Imaging.PixelFormat.Format24bppRgb
Case StCam.STCAM_PIXEL_FORMAT_32_BGR
pixelFormat = Imaging.PixelFormat.Format32bppRgb
End Select
Dim pbyteImageBuffer(nBufferSize) As Byte
Dim dwNumberOfByteTrans As Integer = 0
Dim pdwFrameNo(1) As Integer
Dim dwMilliseconds As Integer = 100
Dim gch As System.Runtime.InteropServices.GCHandle = System.Runtime.InteropServices.GCHandle.Alloc(pbyteImageBuffer, System.Runtime.InteropServices.GCHandleType.Pinned)
Dim ptr As IntPtr = gch.AddrOfPinnedObject()
nReval = StCam.TakePreviewSnapShot(m_hCamera, ptr, nBufferSize, dwNumberOfByteTrans, pdwFrameNo, dwMilliseconds)
gch.Free()
Dim bitmap As Bitmap = New Bitmap(dwWidth, dwHeight, pixelFormat)
Select Case pixelFormat
Case Imaging.PixelFormat.Format8bppIndexed
Dim colorPalette As System.Drawing.Imaging.ColorPalette = bitmap.Palette
For pixelValue As Integer = 0 To 255
colorPalette.Entries(pixelValue) = Color.FromArgb(pixelValue, pixelValue, pixelValue)
Next
bitmap.Palette = colorPalette
End Select
Dim bitmapData As Imaging.BitmapData = bitmap.LockBits(New Rectangle(0, 0, dwWidth, dwHeight), Imaging.ImageLockMode.WriteOnly, pixelFormat)
Runtime.InteropServices.Marshal.Copy(pbyteImageBuffer, 0, bitmapData.Scan0(), nBufferSize)
bitmap.UnlockBits(bitmapData)
Dim bmap As Bitmap
bmap = New Bitmap(bitmap)
PictureBox2.Image = bmap
' PictureBox2.Image = bmap
Dim tempbmp As New Bitmap(bmap)
Dim i, j As Integer
Dim DispX As Integer = 1, DispY As Integer = 1
Dim red, green, blue As Integer
With tempbmp
For i = 0 To .Height - 2
For j = 0 To .Width - 2
Dim pixel1, pixel2 As System.Drawing.Color
pixel1 = .GetPixel(j, i)
pixel2 = .GetPixel(j + DispX, i + DispY)
red = Math.Min(Math.Abs(CInt(pixel1.R) - CInt(pixel2.R)) + 128, 255)
green = Math.Min(Math.Abs(CInt(pixel1.G) - CInt(pixel2.G)) + 128, 255)
blue = Math.Min(Math.Abs(CInt(pixel1.B) - CInt(pixel2.B)) + 128, 255)
bmap.SetPixel(j, i, Color.FromArgb(red, green, blue))
Next
Next
End With
PictureBox2.Image = bmap
PictureBox2.Refresh()
PictureBox2.BringToFront()

Dim bitmapData As Imaging.BitmapData = bitmap.LockBits(New Rectangle(0, 0, dwWidth, dwHeight), Imaging.ImageLockMode.WriteOnly, pixelFormat)
Runtime.InteropServices.Marshal.Copy(pbyteImageBuffer, 0, bitmapData.Scan0(), nBufferSize)
bitmap.UnlockBits(bitmapData)
PictureBox2.Image = bitmap
Dim temp As Bitmap = PictureBox2.Image
Dim raz As Integer = temp.Height / 4
Dim height As Integer = temp.Height
Dim width As Integer = temp.Width
Dim rect As New Rectangle(Point.Empty, temp.Size)
Dim bmpData As BitmapData = temp.LockBits(rect, ImageLockMode.[ReadOnly], temp.PixelFormat)
Dim bpp As Integer = If((temp.PixelFormat = PixelFormat.Format32bppArgb), 4, 3)
Dim size As Integer = bmpData.Stride * bmpData.Height
Dim data As Byte() = New Byte(size - 1) {}
'byte[] newdata = new byte[size];
System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, size)
'System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, newdata, 0, size);
Dim options = New ParallelOptions()
Dim maxCore As Integer = Environment.ProcessorCount - 1
options.MaxDegreeOfParallelism = If(maxCore > 0, maxCore, 1)
For y As Integer = 0 To height - 4
For x As Integer = 0 To width - 4
If True Then
Dim index As Integer = y * bmpData.Stride + x * bpp
'Blue
data(index) = CByte(Math.Min(Math.Abs(CInt(data(index)) - CInt(data(index + bpp + bmpData.Stride))) + 128, 255))
'Green
data(index + 1) = CByte(Math.Min(Math.Abs(CInt(data(index + 1)) - CInt(data(index + bpp + 1 + bmpData.Stride))) + 128, 255))
'Red
data(index + 2) = CByte(Math.Min(Math.Abs(CInt(data(index + 2)) - CInt(data(index + bpp + 2 + bmpData.Stride))) + 128, 255))
End If
Next
Next

Related

Graphics drawline scaling vb.net

I'm trying to develop a program that has been made by another person.
What I develop is just for showing the measurement point like the picture below.
There are min and max data that appear in the form and it's showing from the smallest to the largest value and every time the mouse moves from left to right, the measuring point value will adjust to the graph value that has been determined as above.
The problem is data accuracy at the measuring point does not match with the value that has been determined, this is because the graphic is out of frame.
Here is the code for showing graphics;
Private Sub UpdateDiaGraph()
Call Me.ClearGraph(Me.gDia, Me.PicDiaGraph)
Call Me.InitializeGraph(Me.gDia, Me.PicDiaGraph, Me.recDia)
If Me.dsData.Tables("Dia").Rows.Count = 0 Then
Exit Sub
End If
Dim drs() As DataRow = Me.dsData.Tables("Dia").Select("", "[PathNo],[EquipmentNo],[Point]")
Dim pathNo As Integer = 0
Dim equipmentNo As Integer = 0
Dim diaCount As Integer = 0
Dim maxPoint As Integer = 0
Dim longestDiaCount As Integer = 0
Dim upper As New List(Of Decimal)
Dim lower As New List(Of Decimal)
For Each dr As DataRow In drs
If pathNo <> dr("PathNo") Or equipmentNo <> dr("EquipmentNo") Then
pathNo = dr("PathNo")
equipmentNo = dr("EquipmentNo")
'Count the graphics
diaCount += 1
' Get standard width
upper.Add(dr("Upper"))
lower.Add(dr("Lower"))
End If
' Get the max number of graph points and the number of graphs at that time
If maxPoint < dr("Point") Then
maxPoint = dr("Point")
longestDiaCount = diaCount
End If
Next
Dim x1, x2 As Decimal
Dim y1, y2 As Decimal
' Get the width to draw the reference line
Dim oneHeight As Decimal = Me.recDia.Height / (diaCount + 1)
'Initialize the graph
For i As Integer = 1 To diaCount
x1 = Me.recDia.Left + 1
x2 = Me.recDia.Left + Me.recDia.Width - 1
y1 = Me.recDia.Top + oneHeight * i
' Tolerance range
'※0.01mm/1 Point
Me.gDia.FillRectangle(New SolidBrush(Me.toleranceRecColor) _
, x1 _
, y1 - upper(diaCount - i) * 100 _
, Me.recDia.Width - 1 _
, (upper(diaCount - i) - lower(diaCount - i)) * 100)
' reference line
Me.gDia.DrawLine(New Pen(Me.centerLineColor), x1, y1, x2, y1)
Next
' Determine the drawing magnification of the X-axis so that the max number of points can be displayed
Dim xMag As Decimal = Me.recDia.Width / maxPoint
'Draw a graph
Dim counter As Integer = 0
Dim centerLineY As Decimal
Dim center As Decimal = 0
Dim p As Integer = -1
pathNo = 0 : equipmentNo = 0
For Each dr As DataRow In drs
' Get reference line and reference value
If pathNo <> dr("PathNo") Or equipmentNo <> dr("EquipmentNo") Then
pathNo = dr("PathNo")
equipmentNo = dr("EquipmentNo")
counter += 1
centerLineY = Me.recDia.Top + oneHeight * (diaCount - (counter - 1))
center = dr("Center")
'Draw chart title and reference value
Dim num As New Common.Numeric
Dim numFormat As String = num.GetNumericFormat(1, 2)
Dim s As String = dr("MeasuringTarget").ToString & ControlChars.CrLf
Dim sSize As Size = TextRenderer.MeasureText(Me.gDia, s, Me.Font)
Me.gDia.DrawString(s, Me.Font, Brushes.White, Me.recDia.Left - sSize.Width - 2, centerLineY - sSize.Height / 2)
s = ControlChars.CrLf & Format(center, numFormat)
sSize = TextRenderer.MeasureText(Me.gDia, s, Me.Font)
Me.gDia.DrawString(s, Me.Font, Brushes.White, Me.recDia.Left - sSize.Width - 2, centerLineY - sSize.Height / 2)
x1 = 0 : x2 = 0 : y1 = 0 : y2 = 0 : p = -1
End If
p += 1
'Change the drawing direction and starting point of the graph depending on the number of direction changes
If Me.extRevCnt.Item(pathNo) Mod 2 = 0 Then
x2 = Me.recDia.Left + p * xMag
Else
x2 = Me.recDia.Left + Me.recDia.Width - p * xMag
End If
y2 = centerLineY - (dr("Data") - center) * 100
If p <> 0 Then
'graph drawing
If Me.recDia.Top < y2 And y2 < Me.recDia.Top + Me.recDia.Height Then
' Change the drawing color of the graph for each outer diameter
If counter < Me.diaGraphColor.Count Then
Me.gDia.DrawLine(New Pen(Me.diaGraphColor(counter)), x1, y1, x2, y2)
Else
Me.gDia.DrawLine(New Pen(Me.graphColor), x1, y1, x2, y2)
End If
End If
' out of tolerance
If dr("DataFlag") = Common.Constant.DataFlag.NG Then
Me.gDia.DrawLine(New Pen(Me.ngColor), x1, centerLineY, x2, centerLineY)
End If
'Draw a scale every 10m * However, only when drawing the longest graph
'Drawn for the first graph (normal mandrel diameter)
If counter = 1 Then
If p Mod 100 = 0 Then
Me.gDia.DrawLine(Pens.White, x2, Me.recDia.Top + Me.recDia.Height, x2, Me.recDia.Top + Me.recDia.Height - 3)
Dim s As String = (p \ 10).ToString & "m"
Dim sSize As Size = TextRenderer.MeasureText(Me.gDia, s, Me.Font)
Me.gDia.DrawString(s, Me.Font, Brushes.White, x2 - sSize.Width / 2, Me.recDia.Top + Me.recDia.Height + 2)
End If
End If
Else
' determine the corners of a polygon
Dim points As Point() = {New Point(x2, centerLineY - 10), New Point(x2 - 10, centerLineY - 40), New Point(x2 + 10, centerLineY - 40)}
Me.gDia.FillPolygon(Brushes.Blue, points, System.Drawing.Drawing2D.FillMode.Alternate)
' Display the division number in the circle above
Dim s As String = dr("DivNo").ToString
Dim sSize As Size = TextRenderer.MeasureText(Me.gDia, s, Me.Font)
Me.gDia.DrawString(s, New Font(Me.Font, FontStyle.Regular), Brushes.White, x2 - sSize.Width / 2 + 2, centerLineY - 35)
End If
x1 = x2
y1 = y2
Next
Type.Variable.divideTargetDia = Me.DGVDataDia.SelectedRows.Item(0).Index
Call Me.DrawingGraphDia(Me.DGVDataDia.SelectedRows.Item(0).Index)
Me.PicDiaGraph.Refresh()
End Sub
Here is the code for showing data pointer
Private Sub PicDiaGraph_Paint(ByVal gDia As Graphics)
If IsNothing(tblDataDia) = True Then Exit Sub
If tblDataDia.Rows.Count = 0 Then Exit Sub
If IsNothing(tblEquipmentNoDia) = True Then Exit Sub
If tblEquipmentNoDia.Rows.Count = 0 Then Exit Sub
' Allocate the drawing range according to the number of device numbers
Dim allHeight As Integer = Me.PicDiaGraph.Size.Height
'Drawing range per device number
Dim heightPerEN As Integer = allHeight / (tblEquipmentNoDia.Rows.Count + 1)
' Device number count
Dim count As Integer = 0
' Draw a graph for each device number
For Each rEN As DataRow In tblEquipmentNoDia.Rows
Dim eNo As Integer = rEN("EquipmentNo")
Dim tblSource As DataTable = tblDataDia.Clone
For Each r As DataRow In tblDataDia.Select("EquipmentNo = '" & eNo & "'", "Point ASC")
tblSource.ImportRow(r)
Next
' Acquisition of standard value
Dim tblStandard As New DataTable
If Me.Today = False Then
Dim SQL As String = ""
SQL &= "SELECT Standard.Center "
SQL &= "FROM Standard "
SQL &= "WHERE Standard.EquipmentNo = " & eNo & " And Standard.MfgID = '" & barcodeNo.Trim & "' "
SQL &= "GROUP BY Standard.Center;"
daDia = New OleDb.OleDbDataAdapter(SQL, cnMdbDia)
daDia.Fill(tblStandard)
Else
'
End If
Dim center As Single = Format(tblStandard.Rows(0)("center"), "0.00")
' Drawing start position (height)
Dim shift As Integer = heightPerEN * count
'get width of data
Dim margin As Integer = 0
_xMaxDia = tblSource.Select("Point = MAX(Point)")(0)("Point")
_xMinDia = tblSource.Select("Point = MIN(Point)")(0)("Point")
Dim yMax As Single = tblSource.Select("Data = MAX(Data)")(0)("Data")
Dim yMin As Single = tblSource.Select("Data = MIN(Data)")(0)("Data")
'Width on X-axis data
Dim xRange As Integer = _xMaxDia - _xMinDia
'Width on Y-axis data
Dim yRange As Single = yMax - yMin
'Get size of control
Dim height As Integer = heightPerEN - (margin * 2)
Dim width As Integer = Me.PicDiaGraph.Size.Width - 21
' Nominal length per unit
_xUnitDia = width / xRange
Dim yUnit As Single = 200
'graph drawing
For i As Integer = 0 To tblSource.Rows.Count - 2
Dim x1 As Decimal = Me.recDia.Left + 1
' starting point data
Dim row1 As DataRow = tblSource.Rows(i)
Dim point1 As Integer = row1("Point")
Dim data1 As Single = row1("Data")
' end point data
Dim row2 As DataRow = tblSource.Rows(i + 1)
Dim point2 As Integer = row2("Point")
Dim data2 As Single = row2("Data")
If point2 < point1 Then MessageBox.Show("X")
Me.gDia.DrawLine(Pens.White, _
CInt((point1 - _xMinDia) * _xUnitDia), _
height - (data1 - center) * yUnit + margin + shift, _
CInt(point2 - _xMinDia) * _xUnitDia, _
height - (data2 - center) * yUnit + margin + shift)
Next
count += 1
Next
End Sub
The problem might appear in this code

Change red pixels to blue in a bitmap

I want to change the red pixels to blue. The image is 24 bits .bmp. I am using lockbits because it is faster but the code doesnt find the red pixels!
Code:
Dim bmp As Bitmap = New Bitmap("path")
Dim pos As Integer
Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits _
(rect, Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat)
Dim ptr As IntPtr = bmpData.Scan0
Dim bytes As Integer = Math.Abs(bmpData.Stride) * bmp.Height
Dim rgbValues(bytes - 1) As Byte
Marshal.Copy(ptr, rgbValues, 0, bytes)
For y = 0 To bmp.Height - 1
For x = 0 To bmp.Width - 1
pos = y * bmp.Width * 3 + x * 3
If rgbValues(pos) = 255 And rgbValues(pos + 1) = 0 And rgbValues(pos + 2) = 0 Then
rgbValues(pos + 2) = 255
rgbValues(pos) = 0
End If
Next
Next
Marshal.Copy(rgbValues, 0, ptr, bytes)
bmp.UnlockBits(bmpData)
bmp.Save("new path")
Thank you!
The values that are stored in rgbValues are not in this order
R G B R G B.....
but
B G R B G R.....
so the correct code in your loop is:
' B G R
If rgbValues(pos) = 0 And rgbValues(pos + 1) = 0 And rgbValues(pos + 2) = 255 Then
rgbValues(pos + 2) = 0 'R
rgbValues(pos) = 255 'B
End If

vb Image grid detection

Im looking for a way to detect the center of grid squares when VB.net is feed an image
I want to start with an image of a grid with blue squares like this:
Grid
and i want the program to make an array of points in the center of each square like this (points aren't centered in picture)
Grid with Red points
i dont want to modify the image, i just want to get the points. I've tried getpixel for x and y but that just returns the same point
Dim search_color As Color = Color.FromArgb(255, 64, 128, 192)
Dim background_color As Color = Color.FromArgb(255, 240, 240, 240)
Dim grid_color As Color = Color.FromArgb(255, 144, 144, 144)
Dim pix As Color
Dim liney = 0, linex = 0
Dim loc, sloc, gloc As Point
For ch As Integer = 1 To 64
For y As Integer = liney To Bmp.Height - 1
For x As Integer = linex To Bmp.Width - 1
If Bmp.GetPixel(x, y) = search_color Then
sloc = New Point(x, y)
linex = x
liney = y
x = Bmp.Width - 1
y = Bmp.Height - 1
End If
Next
Next
Dim xloc = 0
For x As Integer = sloc.X To Bmp.Width - 1
If Bmp.GetPixel(x, sloc.Y) = grid_color Then
xloc = x - 1
End If
If Bmp.GetPixel(x, sloc.Y) = background_color Then
xloc = x - 1
End If
Next
For y As Integer = sloc.Y To Bmp.Height - 1
If Bmp.GetPixel(xloc, y) = grid_color Or Bmp.GetPixel(xloc, y) = background_color Then
gloc = New Point(xloc, y - 1)
End If
Next
loc = New Point((gloc.X + sloc.X) / 2, (gloc.Y + sloc.Y) / 2)
liney = gloc.Y
linex = gloc.X + 20
ListBox1.Items.Add(loc.ToString)
Next
Try this:
I added the following controls to a form to test the code:
pbImageToScan (PictureBox) - btnAnalyzeIMG (Button) - lbResult (ListBox)
Public Class Form1
Dim arrCenters() As Point
Dim bmpToAnalyze As Bitmap
Dim search_color As Color = Color.FromArgb(255, 64, 128, 192)
Dim background_color As Color = Color.FromArgb(255, 240, 240, 240)
Dim grid_color As Color = Color.FromArgb(255, 144, 144, 144)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
bmpToAnalyze = New Bitmap(Application.StartupPath & "\Image.bmp")
pbImageToScan.Image = Image.FromFile(Application.StartupPath & "\Image.bmp")
End Sub
Private Sub btnAnalyzeIMG_Click(sender As Object, e As EventArgs) Handles btnAnalyzeIMG.Click
FindCenters()
End Sub
Private Sub FindCenters()
bmpToAnalyze = New Bitmap(Application.StartupPath & "\Image.bmp")
pbImageToScan.Image = Image.FromFile(Application.StartupPath & "\Image.bmp")
'arrCenters is the array who will contains all centers data
ReDim arrCenters(0)
'arrCenters already starts with an element; this boolean is used to handle the first point insertion
Dim bFirstElementAddedToArray As Boolean
lbResult.Items.Clear()
Dim iIMGWidth As Integer = bmpToAnalyze.Width
Dim iIMGHeight As Integer = bmpToAnalyze.Height
'X, Y coordinates used for iterations
Dim iX As Integer = 0
Dim iY As Integer = 0
'Bitmap limits reached
Dim bExit As Boolean
'Used to skip a great part of Ys, if a match has been found along the current examinated line
Dim iDeltaYMax As Integer = 0
'Main cycle
Do While Not bExit
Dim colCurrentColor As Color = bmpToAnalyze.GetPixel(iX, iY)
If colCurrentColor = search_color Then
Dim iXStart As Integer = iX
Dim iYStart As Integer = iY
Dim iXEnd As Integer
Dim iYEnd As Integer
'Width of the Blue square
For iXEnd = iX + 1 To iIMGWidth - 1
Dim colColorSearchX As Color = bmpToAnalyze.GetPixel(iXEnd, iY)
If (colColorSearchX = background_color) Or (colColorSearchX = grid_color) Then
iXEnd -= 1
Exit For
End If
Next
'Height of the Blue square
For iYEnd = iY + 1 To iIMGHeight - 1
Dim colColorSearchY As Color = bmpToAnalyze.GetPixel(iXEnd, iYEnd)
If (colColorSearchY = background_color) Or (colColorSearchY = grid_color) Then
iYEnd -= 1
Exit For
End If
Next
iDeltaYMax = iYEnd - iYStart
'Blue square center coordinates
Dim pCenter As New Point((iXStart + iXEnd) / 2, (iYStart + iYEnd) / 2)
Dim iArrLenght As Integer = 0
If Not bFirstElementAddedToArray Then
bFirstElementAddedToArray = True
Else
iArrLenght = arrCenters.GetLength(0)
ReDim Preserve arrCenters(iArrLenght)
End If
arrCenters(iArrLenght) = pCenter
lbResult.Items.Add(pCenter.ToString)
iX = iXEnd
'Checks if the Width limit of the bitmap has been reached
If iX = (iIMGWidth - 1) Then
iX = 0
iY += iDeltaYMax + 1
iDeltaYMax = 0
Else
iX += 1
End If
Else
'Checks if the Width limit of the bitmap has been reached
If iX = (iIMGWidth - 1) Then
iX = 0
iY += iDeltaYMax + 1
iDeltaYMax = 0
Else
iX += 1
End If
End If
'Width and Height limit of the bitmap have been reached
If (iX = iIMGWidth - 1) And (iY = iIMGHeight - 1) Then
bExit = True
End If
Loop
'Draws a Red point on every center found
For Each P As Point In arrCenters
bmpToAnalyze.SetPixel(P.X, P.Y, Color.Red)
Next
pbImageToScan.Image = bmpToAnalyze
End Sub
End Class

Change subitem backcolor of a listview next item

I have a listview filled with SRT subtitle. I'am trying to change listview color based on subtitle errors. Everything is working fine, but color won't change when subtitles is overlapping. I take end-time of one subtitle and start-time of next subtitle. Based on difference, it decide is there overlapping or not. Calculations are OK but backcolor and forecolor won't change. It does change backcolor for current item but I need to change backcolor for next listview item.
'EXAMPLE #######################################
For i as integer = 0 to listview1.items.count -1
ListView1.Items(i).UseItemStyleForSubItems = False
'this is working #######
ListView1.Items.Item(i).SubItems(1).BackColor = ColorTranslator.FromHtml("#F0A6A7")
'but this is NOT working ( THIS IS WHAT I NEED) ####################
ListView1.Items.Item(i).SubItems(i + 1).BackColor = ColorTranslator.FromHtml("#F0A6A7")
Next i
'########################################################
Public Function Color_Errors(ByVal SubtitleListView As ListView)
For i = 0 To SubtitleListView.Items.Count - 2
SubtitleListView.Items(i).UseItemStyleForSubItems = False
SubtitleListView.Items(i + 1).UseItemStyleForSubItems = False
SubtitleListView.Items.Item(i).SubItems(1).ResetStyle()
SubtitleListView.Items.Item(i).SubItems(2).ResetStyle()
SubtitleListView.Items.Item(i).SubItems(3).ResetStyle()
SubtitleListView.Items.Item(i).SubItems(4).ResetStyle()
SubtitleListView.Items.Item(i).SubItems(5).ResetStyle()
Dim Text As String = SubtitleListView.Items.Item(i + 1).SubItems(5).Text
Dim TextLength As Integer = Get_Longest_Line_Length(Text)
Dim NumberOfLines As Integer = Split(Text, "|").Length
Dim Duration As Double = Convert_Time_to_Milliseconds(SubtitleListView.Items.Item(i).SubItems(4).Text)
Dim Pause As Double = Convert_Time_to_Milliseconds(SubtitleListView.Items.Item(i).SubItems(1).Text)
Dim _Start As Double = Convert_Time_to_Milliseconds(SubtitleListView.Items.Item(i).SubItems(2).Text)
Dim _End As Double = Convert_Time_to_Milliseconds(SubtitleListView.Items.Item(i).SubItems(3).Text)
Dim _NextStart As Double
If i < (SubtitleListView.Items.Count - 1) Then
_NextStart = Convert_TimeSpan_to_Milliseconds(SubtitleListView.Items.Item(i + 1).SubItems(2).Text)
End If
'TOO LONG LINES
If TextLength > MaxLength Then
SubtitleListView.Items.Item(i).SubItems(5).BackColor = ColorTranslator.FromHtml("#F0A6A7")
SubtitleListView.Items.Item(i).SubItems(5).ForeColor = Color.Black
End If
'TOO LONG DURATION
If Duration > 6000 Then
SubtitleListView.Items.Item(i).SubItems(4).BackColor = ColorTranslator.FromHtml("#F5CBD9")
SubtitleListView.Items.Item(i).SubItems(4).ForeColor = ColorTranslator.FromHtml("#6F0021")
SubtitleListView.Items.Item(i).SubItems(3).BackColor = ColorTranslator.FromHtml("#F5CBD9")
SubtitleListView.Items.Item(i).SubItems(3).ForeColor = ColorTranslator.FromHtml("#6F0021")
'SHORTER THAN 2 SECONDS
ElseIf Duration < 2000 AndAlso Duration >= 700 Then
SubtitleListView.Items.Item(i).SubItems(4).BackColor = Color.Red
SubtitleListView.Items.Item(i).SubItems(4).ForeColor = Color.White
'TOO SHORT DURATION
ElseIf Duration < 700 Then
SubtitleListView.Items.Item(i).SubItems(3).BackColor = ColorTranslator.FromHtml("#FFF0E1")
SubtitleListView.Items.Item(i).SubItems(3).ForeColor = ColorTranslator.FromHtml("#A45200")
SubtitleListView.Items.Item(i).SubItems(4).BackColor = ColorTranslator.FromHtml("#FFF0E1")
SubtitleListView.Items.Item(i).SubItems(4).ForeColor = ColorTranslator.FromHtml("#A45200")
End If
''TOO SHORT PAUSE
If Pause < 200 Then
SubtitleListView.Items.Item(i).SubItems(1).BackColor = ColorTranslator.FromHtml("#ACC9E6")
SubtitleListView.Items.Item(i).SubItems(1).ForeColor = Color.Black
SubtitleListView.Items.Item(i).SubItems(2).BackColor = ColorTranslator.FromHtml("#ACC9E6")
SubtitleListView.Items.Item(i).SubItems(2).ForeColor = Color.Black
End If
If NumberOfLines > 2 Then
SubtitleListView.Items.Item(i).SubItems(5).ForeColor = ColorTranslator.FromHtml("#0000FF")
End If
'ERROR PART #################################################
If i < (SubtitleListView.Items.Count - 1) Then
If _End > _NextStart Then
SubtitleListView.Items.Item(i + 1).SubItems(1).BackColor = ColorTranslator.FromHtml("#BB0025")
SubtitleListView.Items.Item(i + 1).SubItems(1).ForeColor = Color.White
SubtitleListView.Items.Item(i).SubItems(2).BackColor = ColorTranslator.FromHtml("#BB0025")
SubtitleListView.Items.Item(i).SubItems(2).ForeColor = Color.White
End If
End If
'############################################################
Next i
Return Nothing
End Function
Public Function Convert_Time_to_Milliseconds(ByVal Time As String)
If Time.Contains(":") = True Then
Dim VremePrviDeo() As String = Split(Time, ":")
If VremePrviDeo.Length = 3 Then
Dim Sati As Integer = VremePrviDeo(0) * 60 * 60 * 1000
Dim Minuti As Integer = VremePrviDeo(1) * 60 * 1000
Dim VremeDrugiDeo() As String = Split(VremePrviDeo(2), ",")
Dim Sekunde As Integer = VremeDrugiDeo(0) * 1000
Dim Milisekunde As Integer = VremeDrugiDeo(1)
Dim Miliseconds As Double = Sati + Minuti + Sekunde + Milisekunde
Return Miliseconds.ToString
ElseIf VremePrviDeo.Length = 2 Then
Dim Minuti As Integer = VremePrviDeo(0) * 60 * 1000
Dim VremeDrugiDeo() As String = Split(VremePrviDeo(2), ",")
Dim Sekunde As Integer = VremeDrugiDeo(0) * 1000
Dim Milisekunde As Integer = VremeDrugiDeo(1)
Dim Miliseconds As Double = Minuti + Sekunde + Milisekunde
Return Miliseconds.ToString
End If
Else
Dim VremePrviDeo() As String = Split(Time, ",")
Dim Sekunde As Integer = VremePrviDeo(0) * 1000
Dim Milisekunde As Integer = VremePrviDeo(1)
Dim Miliseconds As Double = Sekunde + Milisekunde
Return Miliseconds.ToString
End If
Return Nothing
End Function
Public Function Get_Longest_Line_Length(ByVal Text As String)
Dim Duzina As Integer = 0
For Each line As String In Split(Text, "|")
If line.Length > Duzina Then
Duzina = line.Length
End If
Next
Return Duzina
End Function
Public Function Convert_TimeSpan_to_Milliseconds(ByVal Time As String)
'Try
Dim Parsed() As String = Parse_String_to_TimeSpan(Time)
Dim Sat As Double = TimeSpan.FromHours(Parsed(0)).TotalMilliseconds
Dim Minut As Double = TimeSpan.FromMinutes(Parsed(1)).TotalMilliseconds
Dim Sekunda As Double = TimeSpan.FromSeconds(Parsed(2)).TotalMilliseconds
Dim Milisekunda As Double = TimeSpan.FromMilliseconds(Parsed(3)).TotalMilliseconds
Dim TotalTime As Double = Sat + Minut + Sekunda + Milisekunda
Return TotalTime
'Catch ex As Exception
'End Try
'Return Nothing
End Function

listview printing

I have found some code using google for listview printing. I modified the code base on my needs. I have some problem if the list view more than one pages. It will not stop counting "Generating Previews" of my document. If I press the cancel it was display the data in multiple pages but the same content.
Any suggestion would greatly appreciated.
Thanks in advance
Here is the code
Public Sub pd_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs)
Dim pd As New PrintDocument
Dim CurrRow As Integer = 0
Dim Ratio As Single = 0
Dim c As ColumnHeader
Dim g As Graphics = e.Graphics
Dim l As Integer = 0 'stores current left
Dim iCount As Integer
Dim f As Font = lsvToPrint.Font
Dim FontBold As New System.Drawing.Font("Microsoft Sans Serif", 10, FontStyle.Bold)
Dim b As Brush = Brushes.Black
Dim currentY As Integer = 0
Dim maxY As Integer = 0
Dim gap As Integer = 5
Dim lvsi As ListViewItem.ListViewSubItem
Dim colLefts(lsvToPrint.Columns.Count) As Integer
Dim colWidths(lsvToPrint.Columns.Count) As Integer
Dim idx As Integer = 0
Dim ii As Integer
Dim lr As RectangleF
e.HasMorePages = False
'Page Settings
Dim PSize As Integer = lsvToPrint.Items.Count
Dim PHi As Double
With pd.DefaultPageSettings
Dim Ps As PaperSize
PHi = PSize * 20 + 350
Ps = New PaperSize("Cust", 800, PHi)
.Margins.Top = 15
.Margins.Bottom = 20
.PaperSize = Ps
End With
Dim sfc As New StringFormat
sfc.LineAlignment = StringAlignment.Center
sfc.Alignment = StringAlignment.Center
'Title
Dim headfont As Font
Dim X1 As Integer
Dim Y As Integer
headfont = New Font("Courier New", 16, FontStyle.Bold)
X1 = pd.DefaultPageSettings.Margins.Left
Y = pd.DefaultPageSettings.Margins.Top + 5
With pd.DefaultPageSettings
e.Graphics.DrawLine(Pens.Black, 0, Y + 70, e.PageBounds.Width, Y + 70)
End With
'Headings
currentY = 100
For Each c In lsvToPrint.Columns
maxY = Math.Max(maxY, g.MeasureString(c.Text, f, c.Width).Height)
colLefts(idx) = l
colWidths(idx) = c.Width
lr = New RectangleF(colLefts(idx), currentY, colWidths(idx), maxY)
If lr.Width > 0 Then g.DrawString(c.Text, FontBold, b, lr, sfc)
l += c.Width
idx += 1
Next
currentY += maxY + gap
g.DrawLine(Pens.Black, 0, currentY, e.PageBounds.Width, currentY)
currentY += gap
'Rows
iCount = lsvToPrint.Items.Count - 1
For ii = CurrRow To iCount
If (currentY + maxY + maxY) > e.PageBounds.Height Then 'jump down another line to see if this line will fit
CurrRow = ii - 1
e.HasMorePages = True
currentY += maxY + gap
Exit For 'does next page
End If
l = 0
maxY = 0
idx = 0
For Each lvsi In lsvToPrint.Items(ii).SubItems
maxY = Math.Max(maxY, g.MeasureString(lvsi.Text, f, colWidths(idx)).Height)
lr = New RectangleF(colLefts(idx), currentY, colWidths(idx), maxY)
If lsvToPrint.Columns(idx).Text <> "Name" Then
If lr.Width > 0 Then g.DrawString(lvsi.Text , f, b, lr, sfc)
Else
If lr.Width > 0 Then g.DrawString(lvsi.Text, f, b, lr)
End If
idx += 1
Next
currentY += maxY + gap
Next
End Sub
Make sure that you compensate the height of the MaxY for the new page. On the first page it's fine, but then when it gets to the next page, CurrentY + MaxY might already be bigger than the height of the page.