Reputation: 179
I am using following code to convert BMP Image to GRF format.
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
However there is an extra vertical line drawn at the end of the converted GRF file even though there is no such line in the BMP file. Other than that the size and everything is Ok. It seems the last pixel (hex value) of each row is not correct in the GRF file.
Original BMP File.
Converted GRF FIle
Upvotes: 3
Views: 5144
Reputation: 1
This is my go at rewriting the code using .NET
version 8.0
. I hope this might be helpful.
As input, a monochrome BMP
file is used, and the output is a GRF
file.
using System.Drawing;
using System.Text;
if (args.Length < 2)
{
Console.WriteLine("Usage: Bmp2Grf <BMP file> <GRF file>");
return;
}
var fileName = args[0];
var outFile = args[1];
int TEM;
int TotBytes;
int nibble;
StringBuilder grf = new();
//open a bitmap file to read
Bitmap bitmap = (Bitmap)Image.FromFile(fileName);
Console.WriteLine("Width: " + bitmap.Width);
Console.WriteLine("Height: " + bitmap.Height);
Console.WriteLine("PixelFormat: " + bitmap.PixelFormat);
if (bitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Format1bppIndexed)
{
Console.WriteLine("BMP has too many colors, only support monochrome images");
return;
}
TEM = bitmap.Width / 8;
//width must be divisible by 8
if ((bitmap.Width % 8) != 0)
TEM += 1;
TotBytes = TEM * bitmap.Height;
grf.Append("~DGR:" + Path.GetFileName(outFile) + "," + TotBytes.ToString("00000") + "," + TEM.ToString("000") + ",");
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x += 4)
{
//every 4 pixels we have a nibble
nibble = 0;
for (int i = 0; i < 4; i++)
{
if (x + i >= bitmap.Width)
continue;
if (bitmap.GetPixel(x + i, y).R == 0)
nibble += 1 << (3-i);
}
grf.Append(nibble.ToString("X1"));
}
grf.AppendLine();
}
//save the GRF file
File.WriteAllText(outFile, grf.ToString());
Upvotes: 0
Reputation: 375
1) remove "7" in this part : width = (bmp.Width + 7) \ 8
2) detect if the bitmap's remaining value after Mod
if(bmp.Width % 8 > 0)
{
var remaining = bmp.Width % 8;
var newbmp = ResizeImage(bmp, bmp.Width + remaining, bmp.Height);
bmp.Dispose();
bmp = newbmp;
}
the logic for 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;
}
Upvotes: 0
Reputation: 293
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
Upvotes: 2
Reputation: 1544
Marshal.Copy(ptr, pixels, 0, width)
The Bitmap is not byte aligned. So in this case when you copy the data in it is filling in the left over bits as black.
the bitmap is 154 bytes wide which creates 19 full bytes and 2 left over pixels. So the remaining 6 pixels are black.
In the end you need to use bitmaps with widths that are divisible by eight or make sure the end of the data copy from the bitmap to pixels(x) accounts for the remaining bytes.
Upvotes: 2