将BMP图像转换为GRF格式C#/ VB.NET(在ZPL打印机中使用)

时间:2015-07-21 05:02:38

标签: image bmp zebra-printers zpl neodynamic

我使用以下代码将BMP图像转换为GRF格式。

Public Shared Function CreateGrf(filename As String, imagename As String) As String
    Dim bmp As Bitmap = Nothing
    Dim imgData As BitmapData = Nothing
    Dim pixels As Byte()
    Dim x As Integer, y As Integer, width As Integer
    Dim sb As StringBuilder
    Dim ptr As IntPtr

    Try
        bmp = New Bitmap(filename)
        imgData = bmp.LockBits(New System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat)
        width = (bmp.Width + 7) \ 8
        pixels = New Byte(width - 1) {}
        sb = New StringBuilder(width * bmp.Height * 2)
        sb.Append(Environment.NewLine)
        ptr = imgData.Scan0

        For y = 0 To bmp.Height - 1
            Marshal.Copy(ptr, pixels, 0, width)
            For x = 0 To width - 1
                sb.AppendFormat("{0:X2}", CByte(Not pixels(x)))
            Next
            sb.Append(Environment.NewLine)
            ptr = ptr.ToInt64() + imgData.Stride
        Next
    Finally
        If bmp IsNot Nothing Then
            If imgData IsNot Nothing Then
                bmp.UnlockBits(imgData)
            End If
            bmp.Dispose()
        End If
    End Try
    Return [String].Format("~DG{0},{1},{2},", imagename, width * y, width) + sb.ToString()
End Function

但是,即使BMP文件中没有这样的行,在转换的GRF文件的末尾也会绘制一条额外的垂直线。除此之外,尺寸和一切都很好。似乎GRF文件中每行的最后一个像素(十六进制值)不正确。

Original BMP Image

原始BMP文件。

Converted GRF FIle

转换后的GRF文件

3 个答案:

答案 0 :(得分:2)

Marshal.Copy(ptr,pixels,0,width)

位图不是字节对齐的。因此,在这种情况下,当您复制数据时,将剩余的位填充为黑色。

位图宽154字节,可创建19个完整字节,2个像素。所以剩下的6个像素是黑色的。

最后,您需要使用宽度可被8整除的位图,或确保从位图到像素(x)的数据复制结束占剩余字节数。

答案 1 :(得分:2)

Public Function ConvertBmp2Grf(fileName As String, imageName As String) As Boolean
    Dim TI As String
    Dim i As Short
    Dim WID As Object
    Dim high As Object
    Dim TEM As Short, BMPL As Short, EFG As Short, n2 As String, LON As String
    Dim header_name As String, a As String, j As Short, COUN As Short, BASE1 As Short

    Dim L As String, TOT As String
    Dim N As Object
    Dim TOT1 As Integer
    Dim LL As Byte

    FileOpen(1, fileName, OpenMode.Binary, , , 1)  ' OPEN BMP FILE TO READ
    FileGet(1, LL, 1)
    TI = Convert.ToString(Chr(LL))
    FileGet(1, LL, 2)
    TI += Convert.ToString(Chr(LL))

    If TI <> "BM" Then
        FileClose()
        Return False
    End If

    i = 17
    FileGet(1, LL, i + 1)
    N = LL * 256
    FileGet(1, LL, i)
    N = (N + LL) * 256

    FileGet(1, LL, i + 3)
    N = (N + LL) * 256
    FileGet(1, LL, i + 2)
    N += LL
    WID = N
    i = 21
    FileGet(1, LL, i + 1)
    N = LL * 256
    FileGet(1, LL, i)
    N = (N + LL) * 256
    FileGet(1, LL, i + 3)
    N = (N + LL) * 256
    FileGet(1, LL, i + 2)
    N += LL
    high = N
    FileGet(1, LL, 27)
    N = LL
    FileGet(1, LL, 29)

    If N <> 1 Or LL <> 1 Then
        'BMP has too many colors, only support monochrome images
        FileClose(1)
        Return False
    End If

    TEM = Int(WID / 8)
    If (WID Mod 8) <> 0 Then
        TEM += 1
    End If
    BMPL = TEM

    If (BMPL Mod 4) <> 0 Then
        BMPL += (4 - (BMPL Mod 4))
        EFG = 1
    End If

    n2 = fileName.Substring(0, fileName.LastIndexOf("\", StringComparison.Ordinal) + 1) + imageName + ".GRF"

    FileOpen(2, n2, OpenMode.Output) 'OPEN GRF TO OUTPUT
    TOT1 = TEM * high : TOT = Mid(Str(TOT1), 2)
    If Len(TOT) < 5 Then
        TOT = Strings.Left("00000", 5 - Len(TOT)) + TOT
    End If

    LON = Mid(Str(TEM), 2)

    If Len(LON) < 3 Then
        LON = Strings.Left("000", 3 - Len(LON)) + LON
    End If

    header_name = imageName
    PrintLine(2, "~DG" & header_name & "," & TOT & "," & LON & ",")

    For i = high To 1 Step -1
        a = ""
        For j = 1 To TEM
            COUN = 62 + (i - 1) * BMPL + j
            FileGet(1, LL, COUN)
            L = LL

            If j = TEM And (EFG = 1 Or (WID Mod 8) <> 0) Then
                BASE1 = 2 ^ ((TEM * 8 - WID) Mod 8)
                L = Int(L / BASE1) * BASE1 + BASE1 - 1
            End If
            L = Not L
            a += Right(Hex(L), 2)
        Next j
        PrintLine(2, a)
    Next i
    FileClose()

    Return True

End Function

答案 2 :(得分:0)

1)在此部分中删除“ 7”:width =(bmp.Width + 7)\ 8

2)检测Mod之后的位图剩余值

        if(bmp.Width % 8 > 0)
        {
            var remaining = bmp.Width % 8;
            var newbmp = ResizeImage(bmp, bmp.Width + remaining, bmp.Height);
            bmp.Dispose();
            bmp = newbmp;

        }

ResizeImage的逻辑

 public static Bitmap ResizeImage(Image image, int width, int height)
{
    var destRect = new Rectangle(0, 0, width, height);
    var oldRect = new Rectangle(0, 0, image.Width, image.Height);
    var destImage = new Bitmap(width, height);

    destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

    using (var graphics = Graphics.FromImage(destImage))
    {
        graphics.FillRectangle(Brushes.White, destRect);
        graphics.CompositingMode = CompositingMode.SourceCopy;
        graphics.CompositingQuality = CompositingQuality.HighQuality;
        graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        graphics.SmoothingMode = SmoothingMode.HighQuality;
        graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

        using (var wrapMode = new ImageAttributes())
        {
            wrapMode.SetWrapMode(WrapMode.TileFlipXY);
            graphics.DrawImage(image, oldRect, 0, 0, image.Width, image.Height, 
GraphicsUnit.Pixel, wrapMode);
        }
    }

    return destImage;
}