Processing TIF images with Marshal.Copy ends in a Fatal Error - vb.net

I have a function that inserts one image into another byte-wise:
Public Function InsertPIP(ByRef BmpSrc As Bitmap, ByRef BmpTgt As Bitmap, InsertPoint As Point, Optional bpp As Int16 = 1) As Bitmap
If BmpSrc.Width + InsertPoint.X <= BmpTgt.Width And BmpSrc.Height + InsertPoint.Y <= BmpTgt.Height Then
Try
Dim DataSrc As Imaging.BitmapData = BmpSrc.LockBits(New Rectangle(0, 0, BmpSrc.Width, BmpSrc.Height), Imaging.ImageLockMode.[WriteOnly], Imaging.PixelFormat.Format1bppIndexed)
Dim BytesSrc As Byte() = New Byte(DataSrc.Height * DataSrc.Stride) {}
If VerboseLevel >= 3 Then LW.WriteLine("InsertPIP: Stride=" & DataSrc.Stride.ToString & " Scan=" & DataSrc.Scan0.ToInt64 & " DataSRC.Size=" & DataSrc.Width & "x" & DataSrc.Height & " BytesSRC.len=" & BytesSrc.Length.ToString & " Height*Stride=" & (DataSrc.Height * DataSrc.Stride).ToString)
Marshal.Copy(DataSrc.Scan0, BytesSrc, 0, BytesSrc.Length)
'^^^^^^^^^^^^ ERROR OCURS HERE ^^^^^^^^^^^^
Dim DataTgt As Imaging.BitmapData = BmpTgt.LockBits(New Rectangle(0, 0, BmpTgt.Width, BmpTgt.Height), Imaging.ImageLockMode.[WriteOnly], Imaging.PixelFormat.Format1bppIndexed)
Dim BytesTgt As Byte() = New Byte(DataTgt.Height * DataTgt.Stride - 1) {}
Marshal.Copy(DataTgt.Scan0, BytesTgt, 0, BytesTgt.Length)
BytesTgt = InsertPictureIntoPicture(BytesSrc, BytesTgt, BmpSrc.Width, 1, New Rectangle(InsertPoint.X, InsertPoint.Y, BmpSrc.Width, BmpSrc.Height), DataSrc.Stride * 8 / bpp, DataTgt.Stride * 8 / bpp)
Marshal.Copy(BytesTgt, 0, DataTgt.Scan0, BytesTgt.Length)
BmpSrc.UnlockBits(DataSrc)
BmpTgt.UnlockBits(DataTgt)
Catch ex As Exception
If VerboseLevel >= 3 Then LW.WriteLine("InsertPIP ERROR: " & ex.Message & vbCrLf)
End Try
Return BmpTgt
Else
LW.WriteLine("WARNING: Inserting bitmap into bitmap: Source doesn't fit the target. BmpSrc=[" & BmpSrc.Width & "," & BmpSrc.Height & "] BmpTgt=[" & BmpTgt.Width & "," & BmpTgt.Height & "] pt=[" & InsertPoint.X & "," & InsertPoint.Y & "]")
Return BmpTgt
End If
End Function
It's been working for more than a year fine in 99+% cases. But some rare images throw cause a fatal error on line Marshal.Copy(...) ("Fatal Error Detected - unable to continue. Unhandled operating system exception: e0434352"). I am trying to find the cause of the problem but:
debugger seems to me useless, it just says System.AccessViolationException and System.Reflection.TargetInvocationException with no other details
try-catch does not catch the fatal error
trying to see the print the inputs didn't help me:
InsertPIP: Stride=512 Scan=2562876506112 DataSRC.Size=4088x712 BytesSRC.len=364545 Height*Stride=364544
EDIT: I tried to isolate it into standalone application and debug there and no I get little bit more detailed exception message (and what I expected):
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
I generate all the TIF images, they're generated with the same methods and they have all `PixelFormat.Format1bppIndexed`.
Affected Image:
I haven't been able to find much on the internet, suggestions apprectiated. If I can improve my question, please let me know how.
Link to the original TIF image: https://drive.google.com/file/d/1xTIQi5M9UxK7A98992W3PUNMOmODP8p2/view?usp=sharing

Related

Bitmap read, write & compare

A) When I write a BMP file & then read it back into another bitmap object the objects appear different. Looks like Horizontal & Vertical Resolutions are changed.
B) When I make the bitmap object resolutions the same the bitmap objects still appear different despite all attributes appearing the same.
C) If I read the same BMP file twice into two different bitmap objects the objects appear different.
Eventually I want to clone small sections of a larger bitmap & ascertain whether I already have a file for the smaller section by comparing against the contents of each known previously generated file in turn. That is, by reading each file as a bitmap I want to be able to compare against the small section bitmap.
I will eventually be placing a checksum in each file's name or attributes for quicker exclusion but will still need to compare each file contents of those who "survive the exclusion" to prevent different files with the same checksum issue.
When run, the code below shows the issues.
Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
Dim sFileName As String = "c:\Temp\Red.bmp"
' Create red coloured bitmap
Dim oBitMap1 As New Bitmap(200, 100)
Dim oGraphics = Graphics.FromImage(oBitMap1)
oGraphics.FillRectangle(Brushes.Red, 0, 0, 200, 100)
Dim oBitMapA As New Bitmap(200, 100)
oBitMapA = oBitMap1
Debug.Print("oBitMap1 Is oBitMapA = " & CStr(oBitMap1 Is oBitMapA))
' Save the bitmap
oBitMap1.Save(sFileName, Imaging.ImageFormat.Bmp)
' Read the "same" details back into oBitMap2 & BitMap3
Dim oBitMap2 = New Bitmap(sFileName)
Dim oBitMap3 = New Bitmap(sFileName)
'Dim oBitMap2 As Bitmap = Image.FromFile(sFileName)
'Dim oBitMap3 As Bitmap = Image.FromFile(sFileName)
' Show what's what
Debug.Print("Show whether BitMaps are the same (pre changes)")
Debug.Print("oBitMap1 Is oBitMap2 = " & CStr(oBitMap1 Is oBitMap2))
Debug.Print("oBitMap2 Is oBitMap3 = " & CStr(oBitMap2 Is oBitMap3))
Debug.Print("Show resolutions (pre any changes)")
Debug.Print("oBitMap1.Resolution = " & Format(oBitMap1.HorizontalResolution, "##0.###") & "," & Format(oBitMap1.VerticalResolution, "##0.###"))
Debug.Print("oBitMap2.Resolution = " & Format(oBitMap2.HorizontalResolution, "##0.###") & "," & Format(oBitMap2.VerticalResolution, "##0.###"))
Debug.Print("oBitMap3.Resolution = " & Format(oBitMap3.HorizontalResolution, "##0.###") & "," & Format(oBitMap3.VerticalResolution, "##0.###"))
oBitMap2.SetResolution(96, 96)
oBitMap3.SetResolution(96, 96)
Debug.Print("Show resolutions (post changes)")
Debug.Print("oBitMap1.Resolution = " & Format(oBitMap1.HorizontalResolution, "##0.###") & "," & Format(oBitMap1.VerticalResolution, "##0.###"))
Debug.Print("oBitMap2.Resolution = " & Format(oBitMap2.HorizontalResolution, "##0.###") & "," & Format(oBitMap2.VerticalResolution, "##0.###"))
Debug.Print("oBitMap3.Resolution = " & Format(oBitMap3.HorizontalResolution, "##0.###") & "," & Format(oBitMap3.VerticalResolution, "##0.###"))
Debug.Print("Show whether BitMaps are the same (post changes)")
Debug.Print("oBitMap1 Is oBitMap1 = " & CStr(oBitMap1 Is oBitMap1))
Debug.Print("oBitMap1 Is oBitMap2 = " & CStr(oBitMap1 Is oBitMap2))
Debug.Print("oBitMap2 Is oBitMap3 = " & CStr(oBitMap2 Is oBitMap3))
End Sub
Using descriptions above
A) I'm expecting oBitMap2 read from the file created from oBitMap1 to be the same as oBitMap1 but the resolutions are different.
B) When I set the oBitMap2 resolutions to be the same as oBitMap1 I'm expecting oBitMap1 & oBitmap2 to be the same but they're different.
C) When I read the same file twice I'm expecting the two bitmaps created (oBitMap2 & oBitMap3) to be the same but they're different.
I am wondering whether I've misunderstood the "Is" compare operator or the bitmaps have "hidden" attributes that don't show when I "print" them in the debugger as all the shown attributes appear to be the same.

2017 VB.net nullreferenceexception [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
Can you spot my error?
I'm pretty new at VB.net, so I'm sure it's something obvious... I've read all the references to VB.net nullreferenceexception here on StackOverflow and am still confused.
Here's the code:
For Each oSlide In oPres.Slides.Range
strDisplayVerse = oSlide.Shapes.Title.TextFrame.TextRange.Characters.Text
If (IsNumeric(strDisplayVerse.Substring(0, 1)) = True And strDisplayVerse.Substring(2, 1) = "1") Then
arrVersesChorusOther(intVCO) = "Verse " & strDisplayVerse.Substring(0, 1)
strDisplayVerse = "Verse " & strDisplayVerse.Substring(0, 1) &
", slide " & strDisplayVerse.Substring(2, 1)
intVCO = intVCO + 1
End If
Next
'-----------
For Each oSlide In oPres.Slides.Range
strDisplayVerse = oSlide.Shapes.Title.TextFrame.TextRange.Characters.Text
If strDisplayVerse.Substring(0, 1) = "C" Then
strDisplayVerse = "Chorus, slide " & strDisplayVerse.Substring(2, 1)
Else
If IsNumeric(strDisplayVerse.Substring(0, 1)) Then
strDisplayVerse = "Verse " & strDisplayVerse.Substring(0, 1) &
", slide " & strDisplayVerse.Substring(2, 1)
End If
End If
TxtBxVerses.Text = TxtBxVerses.Text & strDisplayVerse & Environment.NewLine
Next
the fifth line is failing:
strDisplayVerse = "Verse " & strDisplayVerse.Substring(0, 1) &
", slide " & strDisplayVerse.Substring(2, 1)
The second loop is code that works. I swapped the line above this code to see if maybe the array setting was causing the problem - I received the error on the same code line. I then swapped the code with:
TxtBxVerses.Text = TxtBxVerses.Text & strDisplayVerse & Environment.NewLine
which also works in the second loop - same error on this line of code.
I can see that strDisplayVerse is equal to "1-1 blah blah blah", so this variable has data and is not null. arrVersesChorusOther is just an undefined size string array defined with PUBLIC just after the Public Class Form1 statement. intVCO is a PUBLIC integer set just below arrVersesChorusOther. TxtBxVerses is a textbox on the form.
I've been playing around with the code to try to figure out what the problem is.
"arrVersesChorusOther is just an undefined size string array defined with PUBLIC" is the culprit.
Being new to VB.Net, I did not know you cannot define a Public array without a dimension. I added a size to the array and it now works.
I do not know if you can have a "Dim arrABC() as String" in a subroutine, but I guess I'll figure that one out when I need it.

PrintDialog ToPage should be less than the page count

I recently upgraded my computer to Windows 10, and now one of the programs is acting weird since the upgrade.
Trying to print a page range out of a PDF, and when I print pages 1 to 100 (out of 477 pages) I get an error saying ToPage should be less than the page count even though 100 is less than 477.
If I skip the page range part and just have it print all of the pages, it works fine.
Sub PrintToPaperSync(ByVal InputfilePath As String, Optional ByVal DeleteAfter As Boolean = False)
On Error GoTo sError
Dim tError As String = ""
Dim toPage As Integer = 0
Console.WriteLine("PrintToPaper " & InputfilePath)
Dim File As String = Split(InputfilePath, "\")(Split(InputfilePath, "\").Length - 1)
Dim viewer As New Syncfusion.Windows.Forms.PdfViewer.PdfDocumentView
viewer.Load(InputfilePath)
Dim print As New System.Windows.Forms.PrintDialog()
print.Document = viewer.PrintDocument
print.Document.DocumentName = File
'print 100 pages at a time
Do While toPage < viewer.PageCount
print.Document.PrinterSettings.PrintRange = Drawing.Printing.PrintRange.SomePages
print.Document.PrinterSettings.FromPage = toPage + 1
toPage += 100
print.Document.PrinterSettings.ToPage = IIf(toPage < viewer.PageCount, toPage, viewer.PageCount)
tError = "From: " & print.Document.PrinterSettings.FromPage & " | To: " & print.Document.PrinterSettings.ToPage & " | PageCount: " & viewer.PageCount & " - "
print.Document.Print()
Application.DoEvents()
Loop
viewer.Unload()
viewer.Dispose()
Console.WriteLine("Printing: " & InputfilePath)
Exit Sub
sError:
Dim ErrorStr As String = ErrorToString()
WriteLine("PrintToPaper " & tError & " " & InputfilePath & " - " & ErrorStr)
End Sub
Full text of the error:
PrintToPaper From: 1 | To: 100 | PageCount: 477 - F:\Process\LogTag-10-30-15-104122.pdf - ToPage should be less than the page count
We want to only print 100 pages at a time, because the printer begins to slow down after 100 pages for some reason.
This printing problem is caused due to the issue with Syncfusion Control. You can contact the Syncfusion Software Support team to get the issue resolved. Please follow the below link to contact Syncfusion Support Team
Click Here

FileInfo returning wrong value?

Okay, so I'm working in VB.NET, manually writing error logs to log files (yes, I know, I didn't make the call). Now, if the files are over an arbitrary size, when the function goes to write out the new error data, it should start a new file with a new file name.
Here's the function:
Dim listener As New Logging.FileLogTraceListener
listener.CustomLocation = System.Configuration.ConfigurationManager.AppSettings("LogDir")
Dim loc As String = DateTime.UtcNow.Year.ToString + DateTime.UtcNow.Month.ToString + DateTime.UtcNow.Day.ToString + DateTime.UtcNow.Hour.ToString + DateTime.UtcNow.Minute.ToString
listener.BaseFileName = loc
Dim logFolder As String
Dim source As String
logFolder = ConfigurationManager.AppSettings("LogDir")
If ex.Data.Item("Source") Is Nothing Then
source = ex.Source
Else
source = ex.Data.Item("Source").ToString
End If
Dim errorFileInfo As New FileInfo(listener.FullLogFileName)
Dim errorLengthInBytes As Long = errorFileInfo.Length
If (errorLengthInBytes > CType(System.Configuration.ConfigurationManager.AppSettings("maxFileSizeInBytes"), Long)) Then
listener.BaseFileName = listener.BaseFileName + "1"
End If
Dim msg As New System.Text.StringBuilder
If String.IsNullOrEmpty(logFolder) Then logFolder = ConfigurationManager.AppSettings("LogDir")
msg.Append(vbCrLf & "Exception" & vbCrLf)
msg.Append(vbTab & String.Concat("App: AppMonitor | Time: ", Date.Now.ToString) & vbCrLf)
msg.Append(vbTab & String.Concat("Source: ", source, " | Message: ", ex.Message) & vbCrLf)
msg.Append(vbTab & "Stack: " & ex.StackTrace & vbCrLf)
listener.Write(msg.ToString())
listener.Flush()
listener.Close()
I have this executing in a loop for testing purposes, so I can see what happens when it gets (say) 10000 errors in all at once. Again, I know there are better ways to handle this systemically, but this was the code I was told to implement.
How can I reliably get the size of the log file before writing to it, as I try to do above?
Well, as with many things, the answer to this turned out to be "did you read your own code closely" with a side order of "eat something, you need to fix your blood sugar."
On review, I saw that I was always checking BaseFileName and, if it was over the arbitrary limit, appending a character and writing to that file. What I didn't do was check to see if that file or, indeed, other more recent files existed. I've solved the issue be grabbing a directory list of all the files matching the "BaseFileName*" argument in Directory.GetFiles and selecting the most recently accessed one. That ensures that the logger will always select the more current file to write to or -if necessary- use as the base-name for another appended character.
Here's that code:
Dim directoryFiles() As String = Directory.GetFiles(listener.Location.ToString(), listener.BaseFileName + "*")
Dim targetFile As String = directoryFiles(0)
For j As Integer = 1 To directoryFiles.Count - 1 Step 1
Dim targetFileInfo As New FileInfo(targetFile)
Dim compareInfo As New FileInfo(directoryFiles(j))
If (targetFileInfo.LastAccessTimeUtc < compareInfo.LastAccessTimeUtc) Then
targetFile = directoryFiles(j)
End If
Next
Dim errorFileInfo As New FileInfo(listener.Location.ToString() + targetFile)
Dim errorLengthInBytes As Long = errorFileInfo.Length

Find height and width of pdf using iTextSharp

In my window application i am using Quick pdf to find height,width of pdf.please refer the below code.But sometimes quickpdf can't able to find correct value.so i want to do the task using iTextSharp. How to find pdf height,width using iTextSharp?
Try
Dim qp1 As New iSED.QuickPDF
Dim sPDFHei, sPDFWid As Double
Dim iPgCnt As Integer
qp1.UnlockKey("6510E9D5C3938A920B3A8D7293C6DF00")
qp1.LoadFromFile(sFilePath & "\" & cmbArticles.Text)
qp1.SetMeasurementUnits(0)
iPgCnt = qp1.PageCount
For i As Integer = 1 To iPgCnt
'MsgBox("pagecount=" & iPgCnt)
qp1.SelectPage(i)
'MsgBox("PageNumber=" & i)
sPDFHei = qp1.PageHeight : sPDFWid = qp1.PageWidth
sPDFHei = Math.Round(sPDFHei, 2) : sPDFWid = Math.Round(sPDFWid, 2)
''If sPDFWid <> 8.26 And sPDFHei <> 11.69 Then
If sPDFWid > 520 Or sPDFHei > 600 Then
MsgBox("Article PDF size should not exit 7.22 x 8.33" & vbCrLf & "Problem in template:" & i)
Exit Function
End If
Next
qp1.clear()
Checkpdfsize = True
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Information, "CheckPdfSize")
End Try
Thanks in Advance
Youll find what you need in chapter 6 of their documentation here. Its under Action by the way.