Click here to Skip to main content
16,004,529 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I want to print .bmp image using com port and i try so many times. i found some code and i tried it. but print is very slowly. my codes are below here.

What I have tried:

VB.NET
Public Function GetLogo() As String
        Dim logo As String = ""
        If Not File.Exists("C:\Users\Administrator\Desktop\Sensitive\Invlogo.bmp") Then
            Return Nothing
        End If
        Dim data As BitmapData = GetBitmapData("C:\Users\Administrator\Desktop\Sensitive\Invlogo.bmp")
        Dim dots As BitArray = data.Dots
        Dim width As Byte() = BitConverter.GetBytes(data.Width)

        Dim offset As Integer = 0

        Using stream As New MemoryStream()
            Using bw As New BinaryWriter(stream)
                bw.Write(ChrW(&H1B))
                bw.Write("@"c)

                bw.Write(ChrW(&H1B))
                bw.Write("3"c)
                bw.Write(CByte(24))

                While offset < data.Height
                    bw.Write(ChrW(&H1B))
                    bw.Write("*"c)         ' bit-image mode
                    bw.Write(CByte(33))    ' 24-dot double-density
                    bw.Write(width(0))      ' width low byte
                    bw.Write(width(1))      ' width high byte

                    For x As Integer = 0 To data.Width - 1
                        For k As Integer = 0 To 2
                            Dim slice As Byte = 0
                            For b As Integer = 0 To 7
                                Dim y As Integer = (((offset \ 8) + k) * 8) + b
                                ' Calculate the location of the pixel we want in the bit array.
                                ' It'll be at (y * width) + x.
                                Dim i As Integer = (y * data.Width) + x

                                ' If the image is shorter than 24 dots, pad with zero.
                                Dim v As Boolean = False
                                If i < dots.Length Then
                                    v = dots(i)
                                End If
                                slice = CByte(slice Or ((If(v, 1, 0) << (7 - b))))
                            Next

                            bw.Write(slice)
                        Next
                    Next
                    offset += 24
                    bw.Write(ChrW(&HA))
                End While



                ' Restore the line spacing to the default of 30 dots.
                bw.Write(ChrW(&H1B))
                bw.Write("3"c)
                bw.Write(CByte(30))
                Dim ascii As New ASCIIEncoding()

                bw.Flush()
                Dim bytes As Byte() = stream.ToArray()
                SerialPort1.Write(bytes, 0, bytes.Length)
                Return logo & Encoding.Default.GetString(bytes)
            End Using
        End Using
    End Function


    Public Function GetBitmapData(bmpFileName As String) As BitmapData
        Using bitmap As Bitmap = CType(bitmap.FromFile(bmpFileName), Bitmap)
            Dim threshold As Integer = 127
            Dim index As Integer = 0
            Dim multiplier As Double = 570 ' this depends on your printer model. for Beiyang you should use 1000
            Dim scale As Double = multiplier / bitmap.Width
            Dim xheight As Integer = CInt(bitmap.Height * scale)
            Dim xwidth As Integer = CInt(bitmap.Width * scale)
            Dim dimensions As Integer = xwidth * xheight
            Dim dots As New BitArray(dimensions)

            For y As Integer = 0 To xheight - 1
                For x As Integer = 0 To xwidth - 1
                    Dim _x As Integer = CInt(x / scale)
                    Dim _y As Integer = CInt(y / scale)
                    Dim color As Color = bitmap.GetPixel(_x, _y)
                    Dim luminance As Integer = CInt(color.R * 0.3 + color.G * 0.59 + color.B * 0.11)
                    dots(index) = (luminance < threshold)
                    index += 1
                Next
            Next

            Return New BitmapData() With {
                .Dots = dots,
                .Height = CInt(bitmap.Height * scale),
                .Width = CInt(bitmap.Width * scale)
            }
        End Using
    End Function



   Public Class BitmapData
        Public Property Dots As BitArray

        Public Property Height As Integer

        Public Property Width As Integer
    End Class
Posted
Updated 27-Jul-24 4:12am
v2

We can;t help you to fix this - we have no access to your system while your code is running, and no idea how SerialPort1 is configured.

But ... serial ports are slow: if it's configured to 9600 baud, then that works out at around 1000 bytes per second: so even a pretty small bitmap is going to take a fair amount of time to transfer: a 1MB bitmap would take 1000 seconds just to transfer - that's 1/4 hour!

Start by looking at how the port is configured, and the size of the data you are transferring - chances are it's slow because it's a slow connection!
 
Share this answer
 
Comments
Member 15040693 28-Jul-24 0:55am    
my serial port settings is
SerialPort1 = New SerialPort("com5", 9600, Parity.None, 8, StopBits.One)
SerialPort1.Open()
Dave Kreskowiak 28-Jul-24 1:23am    
9600 baud and you're wondering why it's slow? Like Griff said, that's 1,000 bytes per second. What are the dimensions of the bitmap you're sending?
OriginalGriff 28-Jul-24 1:51am    
And we used to browse the internet via dialup at 9600... What a relief 56K was! :D
Member 15040693 28-Jul-24 1:51am    
width =459px
height=96px
OriginalGriff 28-Jul-24 3:17am    
So, thats 459*96*4 = 176,256 bytes,
At 9600 Baud, 1 start bit, 1 stop bit, no parity that'll take 183.6 seconds to transfer, or just over 3 minutes ... That's why it's slow!

You cannot speed that up over a serial link unless you change the speed - which is up to the device you send to, not your wishes! So see what the device can do to help, or find a USB device!
If you're printing to a ticket printer, you can try and upload the logo to nvram and then use the escape codes to print the logo.
This will be much faster because you only upload the bitmap once and print when you want. Great for customer logos on top of a invoice.
If you must print diferent bitmaps then use usb or ethernet ports. Setting the serial port to a higher baudrate can help but will allways be slow.
Each printer brand will have some documentation and utility to do so.
 
Share this answer
 
If you're experiencing slow printing speed when sending a .bmp image to a printer via a serial port, here are some optimization suggestions:

1. Optimize Bitmap Scaling and Thresholding:
- Ensure that the scaling factor (multiplier) in the GetBitmapData function is appropriate for your printer. A larger scaling factor means more data to process and send.
- Adjust the threshold value for better contrast, but keep in mind this won't directly affect speed.

2. Increase Serial Port Baud Rate:
- Set SerialPort1.BaudRate to the highest rate supported by both your printer and serial port. Common baud rates include 9600, 19200, 38400, 57600, and 115200.

Example:
SerialPort1.BaudRate = 115200;

3. Send Data in Larger Chunks:
- Instead of sending small chunks of data, send larger blocks to reduce the number of write operations.

Example:
SerialPort1.Write(bytes, 0, bytes.Length);

4. Use Compression (If Supported by Printer):
- Check your printer’s documentation to see if it supports any form of compression that could reduce the amount of data being sent.

5. Buffered Writes to Serial Port:
- Ensure the serial port is set to use buffering, and is properly configured to handle the data flow.

Example:
SerialPort1.DtrEnable = True;
SerialPort1.RtsEnable = True;
SerialPort1.Handshake = Handshake.None;
 
Share this answer
 
Comments
Dave Kreskowiak 31-Jul-24 10:35am    
Answers from ChatGPT are not allowed.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900