I did the right portion of the decoding of the command, but when I get to decoding the image data to go the past as a byte array. I can't convert the data string to a byte array, since Zebra doesn't seem to be using base 64.
Here is my code:
The code works from there:
private void ReadGF(string p_command)
{
// ^GFa,b,c,d,data
// data
string data = String.Empty;
string command = String.Empty;
int nbComma = 0;
for (int i = 0; i < p_command.Length; i++)
{
if (p_command.ElementAt(i) == ',')
{
nbComma++;
}
if (nbComma == 4) break;
{
data = p_command.Substring(i + 2);
if (data.Trim().Length == 0)
{
return;
}
command = p_command.Remove(i + 1);
}
}
string[] content = command.Split(',');
// a = compression type
// Values:
// A = ASCII hexa
// B = binary
// C = compressed binary
// Default: A
string compressionType = "A";
// b = binary byte count
// Values: 1 to 99999
// Default: command is ignored if a values is not specified
int binaryByteCount = 0;
// c = graphic field count
// Values: 1 to 99999
// Default: command is ignored if a values is not specified
int graphicFieldCount = 0;
// d = bytes per row
// Values: 1 to 99999
// Default: command is ignored if a values is not specified
int bytesPerRow = 0;
// Compression type
if (content[0].Trim().Length == 3)
{
// A = ASCII hexa
// B = binary
// C = compressed binary
compressionType = content[0].Trim().Substring(2, 1);
if (!(compressionType.Equals("A") || compressionType.Equals("B") || compressionType.Equals("C")))
{
throw new ArgumentOutOfRangeException("The compression type value must be A (ASCII Hexadecimal), B (Binary) or C (Compressed binary).");
}
}
else
{
compressionType = "A";
}
// Binary byte count
if (content[1].Trim().Length != 0)
{
binaryByteCount = TryParseInt(content[1].Trim());
if (binaryByteCount == 0)
{
return;
}
if (binaryByteCount > 99999 || binaryByteCount < 1)
{
return;
}
}
else
{
return;
}
// Graphic Field Count
if (content[2].Trim().Length != 0)
{
graphicFieldCount = TryParseInt(content[2].Trim());
if (binaryByteCount == 0)
{
return;
}
if (binaryByteCount > 99999 || binaryByteCount < 1)
{
return;
}
}
else
{
return;
}
// Bytes Per Row
if (content[3].Trim().Length != 0)
{
bytesPerRow = TryParseInt(content[3].Trim());
if (bytesPerRow == 0)
{
return;
}
if (bytesPerRow > 99999 || bytesPerRow < 1)
{
return;
}
}
else
{
return;
}
ID++;
I'm not sure if I am proceeding correctly from here, I will see on the internet everywhere that Zebra seems to use a compress form of hexadecimal, in Zb64 or B64 form, but it is not super clear. Would there be a better way to proceed, to know if I have the correct encryption, etc.
byte[] imageByte = new byte[data.Length / 2];
try
{
imageByte = Base64StringDecoder(data);
}
catch
{
try
{
imageByte = ConvertZPLImageToByte(data);
}
catch
{
imageByte = Enumerable.Range(0, data.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(data.Substring(x, 2), 16))
.ToArray();
}
}
// A = ASCII hexa
// B = binary
// C = compressed binary
switch (compressionType)
{
case "A":
DesignerForm.MagicToDesignerImage(ID, DateTime.Now.ToString("yyyy-MM-dd:h:mm:ss.tt)") + "_ID_" + ID, this.ActualFieldLocation.X, this.ActualFieldLocation.Y, GetSize(imageByte).Height, GetSize(imageByte).Width, imageByte);
break;
case "B":
throw new NotImplementedException();
case "C":
throw new NotImplementedException();
}
}
In the method called MagicToDesignerImage should draw the image. It is composed of an id, a name, an X and Y position, the width and height of the image and data in the form of a byte [].
Here is what I started with decompression in Zb64 and B64, so how do I try to recover the image size.
B64:
private byte[] Base64StringDecoder(string p_encodedString)
{
return Convert.FromBase64String(p_encodedString);
}
Zb64:
/// <summary>
/// I'm not sure how to do it here.
/// </summary>
private byte[] DecompressZb64(string compressedString)
{
Dictionary<char, int> valuePairs = new Dictionary<char, int>
{
{ 'G', 1 },
{ 'H', 2 },
{ 'I', 3 },
{ 'J', 4 },
{ 'K', 5 },
{ 'L', 6 },
{ 'M', 7 },
{ 'N', 8 },
{ 'O', 9 },
{ 'P', 10 },
{ 'Q', 11 },
{ 'R', 12 },
{ 'S', 13 },
{ 'T', 14 },
{ 'U', 15 },
{ 'V', 16 },
{ 'W', 17 },
{ 'X', 18 },
{ 'Y', 19 },
{ 'g', 20 },
{ 'h', 40 },
{ 'i', 60 },
{ 'j', 80 },
{ 'k', 100 },
{ 'l', 120 },
{ 'm', 140 },
{ 'n', 160 },
{ 'o', 180 },
{ 'p', 200 },
{ 'q', 220 },
{ 'r', 240 },
{ 's', 260 },
{ 't', 280 },
{ 'u', 300 },
{ 'v', 320 },
{ 'w', 340 },
{ 'x', 360 },
{ 'y', 380 },
{ 'z', 400 }
};
throw new NotImplementedException();
}
Image size:
/// <summary>
/// Get the size of an image from a byte array
/// </summary>
/// <param name="bytes">Image</param>
/// <returns></returns>
public Size GetSize(byte[] bytes)
{
using (var stream = new MemoryStream(bytes))
{
var image = System.Drawing.Image.FromStream(stream);
return image.Size;
}
}