Captured Avatar

Discussion in 'Chit Chat' started by DonManfred, Jun 11, 2015.

  1. DonManfred

    DonManfred Expert Licensed User

    Last edited: Jun 11, 2015
    lemonisdead, Peter Simpson and Erel like this.
  2. Peter Simpson

    Peter Simpson Well-Known Member Licensed User

    Hmm the police, I better go underground then :).

    Or do you mean The Police:
     
  3. ernschd

    ernschd 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!
     
  4. DonManfred

    DonManfred Expert Licensed User

    You just need the Bluetooth lib (to connect the printer with your device) and the serial lib to print over bluetooth then.
     
    lemonisdead likes this.
  5. ernschd

    ernschd 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?
     
  6. DonManfred

    DonManfred Expert Licensed User

    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
     
    lemonisdead likes this.
  7. ernschd

    ernschd 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.
     
  8. Peter Simpson

    Peter Simpson Well-Known Member 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:
    Code:
    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, 10)) << (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
    Code:
    Public Function GetBitmapData(bmpFileName As StringAs 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
    Code:
    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 ;)
     
    lemonisdead likes this.
Loading...