Storing and retrieving images in Database - vb.net

Here is the code I used to store an image in my database (SQL Server 2008 R2) using VB 2010.
The images get stored but the problem is the clarity of the image is lost when retrieved and seen in a picture box.
Public Function InsertUpdateImage(ByRef _SqlConnection As System.Data.SqlClient.SqlConnection, ByVal _Image As System.Drawing.Image, ByVal _ImageFormat As System.Drawing.Imaging.ImageFormat) As Integer
Dim _SqlRetVal As Integer = 0
'System.IO.Path.GetFullPath(files(ListView1.SelectedIndices(0))) Give the path for the 'image from listview
Dim str As String = System.IO.Path.GetFullPath(files(ListView1.SelectedIndices(0)))
Dim i As Integer = Len(str)
Dim j As Integer = 0
Dim locstr(i + 10) As Char
i = 0
While i < Len(str)
If str(i) = "\" Then
locstr(j) = "\"
j = j + 1
Else
locstr(j) = str(i)
j = j + 1
End If
i = i + 1
End While
Dim loc As New String(locstr)
MsgBox(loc)
' lets add this record to database
Dim _SqlCommand As New System.Data.SqlClient.SqlCommand("insert into maindb(photo,name,location) values(#image,'" + System.IO.Path.GetFileName(files(ListView1.SelectedIndices(0))) + "','" + loc + "')", _SqlConnection)
' Convert image to memory stream
Dim _MemoryStream As New System.IO.MemoryStream()
_Image.Save(_MemoryStream, _ImageFormat)
' Add image as SQL parameter
Dim _SqlParameter As New System.Data.SqlClient.SqlParameter("#image", SqlDbType.Image)
_SqlParameter.Value = _MemoryStream.ToArray()
_SqlCommand.Parameters.Add(_SqlParameter)
' Executes a Transact-SQL statement against the connection
' and returns the number of rows affected.
_SqlRetVal = _SqlCommand.ExecuteNonQuery()
Console.Write(_SqlRetVal)
' Dispose command
_SqlCommand.Dispose()
_SqlCommand = Nothing
' Error occurred while trying to execute reader
' send error message to console (change below line to customize error handling)
Return _SqlRetVal
End Function

Your image.save() reduces the quality of the image (if saved as Jpeg) to the default compression level of aabout 75%.
Please see this MSDN article on increasing this quality level, when you call Save by passing in myEncoderParameters, containing a quality level at a much higher level (say 90%)
http://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoder.quality.aspx
Or see the (untested) code below, that should do the trick
' Create a a single encoder parameter envelope
Dim EncoderParameters As New EncoderParameters(1)
' Create and add a single quality parameter to this envelope, specifying 95%
Dim QualityParam As New EncoderParameter(Encoder.Quality, CType(95L, Int32))
EncoderParameters.Param(0) = QualityParam
' Save the image with the encoder param specifying 95% quality
_image.Save(_MemoryStream, _ImageFormat, EncoderParameters)

Related

Reading files from smart cards using winscard

I am attempting to read smart card files using VB.NET. I have a HID Omnikey 5422 reader.
Following the docs on http://systemmanager.ru/windowsmobile_6_5.en/html/97b287da-5a97-469d-824c-04a3f3caa2a2.htm https://pcsclite.apdu.fr/api/group__API.html#ga33247d5d1257d59e55647c3bb717db24 and others, I am able to get the context (SCardEstablishContext), get the list of readers (SCardListReaders), connect to a selected reader (SCardConnect) and get its status (SCardStatus).
According to the Omnikey 5422 manual, the memory can be read by sending a vendor command. Here is my attempt:
<StructLayout(LayoutKind.Sequential)>
Structure SCARD_IO_REQUEST
Public dwProtocol As SCardPreferredProtocols
Public cbPCILength As UInt32
End Structure
' Read memory
Dim ioSendPci As New SCARD_IO_REQUEST, ioReceivePci As New SCARD_IO_REQUEST
Dim bSendBuffer As Byte(), bReceiveBuffer As Byte()
Dim iSendBufferLength As Int32, iReceiveBufferLength As Int32
ioSendPci.dwProtocol = SCardPreferredProtocols.SCARD_PROTOCOL_RAW
ioSendPci.cbPCILength = 18
Dim bAPDU As Byte() = {&HA6, &H7, &HA2, &H5, &H2, &H8, &HA1, &H50, &H0, &H0}
ReDim bSendBuffer(15)
' First 4 bytes are fixed for Omnikey 5422
' CLA
bSendBuffer(0) = &HFF ' Generic command
' INS
bSendBuffer(1) = &H70 ' Vendor specific command
' P1
bSendBuffer(2) = &H7 ' Vendor id 0x076B - First byte
' P2
bSendBuffer(3) = &H6B ' Vendor id - Second byte
' LC - Number of command data bytes
bSendBuffer(4) = &H9
' APDU command data
Dim i As Integer
For i = 0 To bAPDU.Length - 1
bSendBuffer(5 + i) = bAPDU(i)
Next
ReDim bReceiveBuffer(255)
iSendBufferLength = bSendBuffer.Length
iReceiveBufferLength = bReceiveBuffer.Length
iCardReturn = SCardTransmit(iCardHandle, ioSendPci, bSendBuffer, iSendBufferLength, ioReceivePci, bReceiveBuffer, iReceiveBufferLength)
The iCardReturn value is always 6. (BTW, 6 is not defined here)
I tried changing the protocol and ioSendPci.cbPCILength, but keep getting the same error.

vb- How to assign a different tag property to different array words?

This is my code for inserting from textfile to array to labels, but I want to be able to assign a tag property onto some of the words or perhaps use the 'Answer' which is located a line below on my text file??
IndexNo = 0
Dim FileTerm As String = "D:\soccer.txt"
Dim FileNum As Integer = FreeFile()
FileOpen(FileNum, FileTerm, OpenMode.Input)
Do
Term(IndexNo) = LineInput(FileNum)
Answer(IndexNo) = LineInput(FileNum)
IndexNo = IndexNo + 1
Loop Until EOF(FileNum)
FileClose(FileNum)
Dim Obj As Object, Count As Integer = 0
For Each Obj In Me.Controls
If TypeOf Obj Is Label Then
MyLabels(Count) = Obj
Count = Count + 1
End If
Next
Dim Random1, Random2 As Integer
Dim TempTerm, TempAnswer As Object
For Count = 0 To 15
Randomize()
Random1 = Val(Int(16 * Rnd()))
Random2 = Val(Int(16 * Rnd()))
TempTerm = Term(Random1)
Term(Random1) = Term(Random2)
Term(Random2) = TempTerm
TempAnswer = Answer(Random1)
Answer(Random1) = Answer(Random2)
Answer(Random2) = TempAnswer
Count = Count + 1
Next
For Count = 0 To 15
MyLabels(Count).Text = Term(Count)
Next
If anyone has any ideas, the help is appreciated. Thanks
Even though your question is not very clear. From what I get, you want to have some way to keep your Labels and the corresponding Term and Answers in sync.
There are many ways to do this, but I would prefer to do it as below... the perfect VB.NET way as opposed to using any legacy VB6 techniques.
First declare a class that would keep our Term and Answers in one object. This is the equivalent of Type in VB6.
Public Class TermAnswer
Public Term As String
Public Answer As String
' you may add more fields/properties here if you wish to...
End Class
Now it is easy to code our solution.
' declare a Dictionary object with Label as key and the corresponding Term and Answers as values.
Dim TermAnswers As New Dictionary(Of Label, TermAnswer)
' this is a temporary List to hold our Term and Answers read from file until we randomize them.
Dim tempTermAnswers As New List(Of TermAnswer)
' Our Labels array... yes it is this easy :)
Dim myLabels() As Label = Me.Controls.OfType(Of Label)().ToArray
' read our file into the tempTermAnswers List
Dim FileTerm As String = "D:\soccer.txt"
Using reader As New IO.StreamReader(FileTerm)
While Not reader.EndOfStream
Dim ta As New TermAnswer
ta.Term = reader.ReadLine
ta.Answer = reader.ReadLine
tempTermAnswers.Add(ta)
End While
reader.Close()
End Using
' pick Term Answers from our tempTermAnswers List randomly and add them to our TermAnswers Dictionary
' we also set our Label text here, though you can loop separately too
Dim randomNumbers As New Random
Dim tempTerm As TermAnswer, randomNumber As Integer
For Each label In myLabels
randomNumber = randomNumbers.Next(0, tempTermAnswers.Count)
tempTerm = tempTermAnswers(randomNumber)
TermAnswers.Add(label, tempTerm)
tempTermAnswers.Remove(tempTerm)
label.Text = tempTerm.Term
Next
' now you have your term answers in a Dictionary, indexed by Label.
' you can get any of them by providing a Label on your form as key and get the corresponding Term and Answer as value.
' e.g. let us list the Label Name, Term and Answer in our debug window...
For Each label In myLabels
Debug.WriteLine(label.Name & " ... " & TermAnswers(label).Term & " ... " & TermAnswers(label).Answer)
Next

ReportViewer.LocalReport.Render("PDF")

I am using Report Viewer for WinForms. The problem i am having is this: I have a form that contains a form which is used to view a local report which work fine, but when I try to render the same report as a PDF, it is cut-off, but in report viewer the same report renders a report on one page. When I render to PDF it cuts it off and the part of the report that was cut-off renders on a 2nd page. So in other words, part of the same report is on page 1, and 2nd half is on 2nd page in the PDF?
Code:
Private Function GetPDfReport() As String
Dim parameters = Me.GetReportParms()
Dim query = Me.GetReportQuery()
Dim rView As Microsoft.Reporting.WinForms.ReportViewer = New Microsoft.Reporting.WinForms.ReportViewer
rView.Dock = DockStyle.Fill
rView.SetDisplayMode(DisplayMode.PrintLayout)
Dim pnl As New Panel()
pnl.Name = "pnlMain"
pnl.Location = New System.Drawing.Point(0, 25)
pnl.Size = New System.Drawing.Size(734, 478)
pnl.Controls.Add(rView)
Dim dbReader As New dbReader()
Dim ds As DataSet = dbReader.DataSet(query)
Dim rds As Microsoft.Reporting.WinForms.ReportDataSource = New Microsoft.Reporting.WinForms.ReportDataSource("DataSet1", ds.Tables(0))
rView.ProcessingMode = Microsoft.Reporting.WinForms.ProcessingMode.Local
rView.LocalReport.DataSources.Add(rds)
rView.LocalReport.ReportEmbeddedResource = "EasyDose.rptIncident.rdlc"
If Not IsNothing(parameters) Then
Dim Bound0 As Integer = parameters.GetUpperBound(0)
Dim Bound1 As Integer = parameters.GetUpperBound(1)
For index = 0 To Bound0
Dim rParameter As New ReportParameter(parameters(index, 0), parameters(index, 1))
rView.LocalReport.SetParameters(rParameter)
Next
End If
Dim ps As PageSettings = rView.GetPageSettings
ps.Margins.Top = 0 ' 10mm approx
ps.Margins.Right = 0
ps.Margins.Bottom = 0
ps.Margins.Left = 0
ps.Landscape = False
'ps.PaperSize = New PaperSize("LetterExtra", (9.275 * 100), (12 * 100)) ' Letter paper (8.5 in. by 11 in.) ' Letter extra paper (9.275 in. by 12 in.)
ps.PaperSize = New PaperSize("A4", (8.27 * 100), (11.69 * 100))
rView.RefreshReport()
Dim exePath As String = System.IO.Path.GetDirectoryName(Application.ExecutablePath)
Dim dir As New DirectoryInfo(System.IO.Path.Combine(exePath, "tmpDir"))
Dim file As New FileInfo(System.IO.Path.Combine( _
dir.FullName, String.Format("Patient_Details_{0:yyyyMMdd_hhmmss}.pdf", DateTime.Now)))
If Not dir.Exists Then
dir.Create()
End If
Dim bytes As Byte() = rView.LocalReport.Render("PDF")
Using fs As New System.IO.FileStream(file.FullName, System.IO.FileMode.Create)
fs.Write(bytes, 0, bytes.Length)
fs.Close()
End Using
Return file.FullName
End Function
are you seeing the local report in the embedded ReportViewer using the "Print Layout" option activated? That should show exactly the same output as your printed result.
If you have problems in the PDF is probably caused by the design of the report itself. Check the font, the page size and orientation, the margins, the page breaks.
uisng System.IO;
byte[] rep = reportViewer1.LocalReport.Render("pdf", deviceInfo: "");
// if a certificate warning appears just ignore and re-run
File.WriteAllBytes(filepath+filename+".pdf",rep);

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.

Reading a file bug in VB.NET?

The way this file works is there is a null buffer, then a user check sum then a byte that gives you the user name letter count, then a byte for how many bytes to skip to the next user and a byte for which user file the user keeps their settings in.
the loop with the usersm variable in the IF statement sets up the whole file stream for extraction. However with almost the exact same code the else clause specifically the str.Read(xnl, 0, usn - 1) in the else code appears to be reading the very beginning of the file despite the position of the filestream being set earlier, anyone know whats happening here?
this is in vb2005
Private Sub readusersdata(ByVal userdatafile As String)
ListView1.BeginUpdate()
ListView1.Items.Clear()
Using snxl As IO.Stream = IO.File.Open(userdatafile, IO.FileMode.Open)
Using str As New IO.StreamReader(snxl)
str.BaseStream.Position = 4
Dim usersm As Integer = str.BaseStream.ReadByte()
Dim users As Integer = usersm
While users > 0
If usersm = users Then
Dim trailtouser As Integer = 0
str.BaseStream.Position = 6
Dim ust As Integer = str.BaseStream.ReadByte()
str.BaseStream.Position = 8
Dim snb(ust - 1) As Char
str.ReadBlock(snb, 0, ust)
Dim bst = New String(snb)
If usersm = 1 Then
str.BaseStream.Position = 16
Else
str.BaseStream.Position = 15
End If
cLVN(ListView1, bst, str.BaseStream.ReadByte)
str.BaseStream.Position = 8 + snb.Length
str.BaseStream.Position += str.BaseStream.ReadByte + 1
Else
Dim usn As Integer = str.BaseStream.ReadByte
str.BaseStream.Position += 2
Dim chrpos As Integer = str.BaseStream.Position
Dim xnl(usn - 1) As Char
str.Read(xnl, 0, usn - 1)
Dim skpbyte As Integer = str.BaseStream.ReadByte
str.BaseStream.Position += 3
Dim udata As Integer = str.BaseStream.ReadByte
End If
users -= 1
End While
End Using
End Using
ListView1.EndUpdate()
End Sub
When you change the position of the underlying stream, the StreamReader doesn't know you've done that. If it's previously read "too much" data (deliberately, for the sake of efficiency - it tries to avoid doing lots of little reads on the underlying stream) then it will have buffered data that it'll use instead of talking directly to the repositioned stream. You need to call StreamReader.DiscardBufferedData after repositioning the stream to avoid that.