Captured Avatar

ernschd

Active Member
Licensed User
Cool, thats what i'm looking for all the time (the image printing function, not your Avatar ;)).
Do you plan to release (or sell) the sourcecode or a library? That would be wonderful!
 

ernschd

Active Member
Licensed User
Yes, thats what I'm already doing. But I can't print images so far.
I've got an C#- and Delphi-Application which converts the Bitmap for printing to a thermal printer, but no solution for B4A so far.
Can you post an example?
 

DonManfred

Expert
Licensed User
But I can't print images so far.
Maybe your printer comes with a tool to save an image to the ram. After you set the image it can be printed with a specializd ESC-Command to print the stored image....

Exactly this is done here. Peter took my avatar and upload it to the printer with the provided setup-tool for this printer. In b4a he just calls the right ESC-Command
 

ernschd

Active Member
Licensed User
Ok, now it's clear to me. My printer contains an similar tool. I thought you did print the image directly from your app without using a tool.
 

Peter Simpson

Expert
Licensed User
@ernschd if you have C# and Delphi solutions, why don't you just convert one of your solution over to B4A?

Visual Basic example below:
B4X:
Public Function GetLogo() As String
    Dim logo As String = ""
    If Not File.Exists("C:\bitmap.bmp") Then
        Return Nothing
    End If
    Dim data As BitmapData = GetBitmapData("C:\bitmap.bmp")
    Dim dots As BitArray = data.Dots
    Dim width As Byte() = BitConverter.GetBytes(data.Width)

    Dim offset As Integer = 0
    Dim stream As New MemoryStream()
    Dim bw As New BinaryWriter(stream)

    bw.Write(DirectCast(&H1b, Char))
    bw.Write("@"C)

    bw.Write(DirectCast(&H1b, Char))
    bw.Write("3"C)
    bw.Write(DirectCast(24, Byte))

    While offset < data.Height
        bw.Write(DirectCast(&H1b, Char))
        bw.Write("*"C)
        ' bit-image mode
        bw.Write(DirectCast(33, Byte))
        ' 24-dot double-density
        bw.Write(width(0))
        ' width low byte
        bw.Write(width(1))
        ' width high byte
        Dim x As Integer = 0
        While x < data.Width
            Dim k As Integer = 0
            While k < 3
                Dim slice As Byte = 0
                Dim b As Integer = 0
                While b < 8
                    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 = slice Or DirectCast((If(v, 1, 0)) << (7 - b), Byte)
                    System.Threading.Interlocked.Increment(b)
                End While

                bw.Write(slice)
                System.Threading.Interlocked.Increment(k)
            End While
            System.Threading.Interlocked.Increment(x)
        End While
        offset += 24
        bw.Write(DirectCast(&Ha, Char))
    End While
    ' Restore the line spacing to the default of 30 dots.
    bw.Write(DirectCast(&H1b, Char))
    bw.Write("3"C)
    bw.Write(DirectCast(30, Byte))

    bw.Flush()
    Dim bytes As Byte() = stream.ToArray()
    Return logo + Encoding.[Default].GetString(bytes)
End Function
B4X:
Public Function GetBitmapData(bmpFileName As String) As BitmapData
    Using bitmap__1 = DirectCast(Bitmap.FromFile(bmpFileName), Bitmap)
        Dim threshold = 127
        Dim index = 0
        Dim multiplier As Double = 570
        ' this depends on your printer model. for Beiyang you should use 1000
        Dim scale As Double = DirectCast(multiplier / DirectCast(bitmap__1.Width, Double), Double)
        Dim xheight As Integer = DirectCast(bitmap__1.Height * scale, Integer)
        Dim xwidth As Integer = DirectCast(bitmap__1.Width * scale, Integer)
        Dim dimensions = xwidth * xheight
        Dim dots = New BitArray(dimensions)

        Dim y = 0
        While y < xheight
            Dim x = 0
            While x < xwidth
                Dim _x = DirectCast(x / scale, Integer)
                Dim _y = DirectCast(y / scale, Integer)
                Dim color = bitmap__1.GetPixel(_x, _y)
                Dim luminance = DirectCast(color.R * 0.3 + color.G * 0.59 + color.B * 0.11, Integer)
                dots(index) = (luminance < threshold)
                index += 1
                x += 1
            End While
            y += 1
        End While

        Return New BitmapData() With { _
            .Dots = dots, _
            .Height = DirectCast(bitmap__1.Height * scale, Integer), _
            .Width = DirectCast(bitmap__1.Width * scale, Integer) _
        }
    End Using
End Function
B4X:
Public Class BitmapData
    Public Property Dots() As BitArray
        Get
            Return m_Dots
        End Get
        Set
            m_Dots = Value
        End Set
    End Property
    Private m_Dots As BitArray

    Public Property Height() As Integer
        Get
            Return m_Height
        End Get
        Set
            m_Height = Value
        End Set
    End Property
    Private m_Height As Integer

    Public Property Width() As Integer
        Get
            Return m_Width
        End Get
        Set
            m_Width = Value
        End Set
    End Property
    Private m_Width As Integer
End Class
Sending images directly to an EPOS printer is not recommended by Epson or Star (Star Micronics), that's why they add the on board memory to store the images for printing. Obviously you can send the images directly to EPOS printers for printing, but there is a small delay in printing the receipt as the printer receives the image and processes it, but you already know that as you have 2 solutions already. If the image is on board then the receipt get printed instantly. Not all end users know hoe to optimise images (make them smaller) for printing.

It really is better to store the image on board then print it if necessary, but each to their own hey ;)
 
Top