Skip to content

Instantly share code, notes, and snippets.

@JimBobSquarePants
Created September 26, 2018 09:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JimBobSquarePants/4caeca96639dd94f2ce55bab7ea5219d to your computer and use it in GitHub Desktop.
Save JimBobSquarePants/4caeca96639dd94f2ce55bab7ea5219d to your computer and use it in GitHub Desktop.
Packing to and from 8bit array
void Main()
{
const int bytesPer8bitScanline = 300;
const int bytesPerScanline = 38;
const int bits = 1;
Random r = new Random();
byte[] source = new byte[bytesPer8bitScanline];
for (int i = 0; i < source.Length; i++)
{
source[i] = (byte)r.Next(0, 2);
}
TryScaleDownFrom8BitArray(source, bytesPerScanline, bits, out byte[] temp);
TryScaleUpTo8BitArray(temp, bytesPerScanline, bits, out byte[] destination);
// We're getting difference here. What is wrong?
for (int i = 0; i < source.Length; i++)
{
if (source[i] != destination[i])
{
$"{source[i]} != {destination[i]} at {i}".Dump();
}
}
source.Dump();
destination.Dump();
}
// This should be correct. We're using it to correctly decode pngs
private bool TryScaleUpTo8BitArray(byte[] source, int bytesPerScanline, int bits, out byte[] buffer)
{
if (bits >= 8)
{
buffer = null;
return false;
}
buffer = new byte[bytesPerScanline * 8 / bits];
byte[] result = buffer;
int mask = 0xFF >> (8 - bits);
int resultOffset = 0;
for (int i = 0; i < bytesPerScanline; i++)
{
byte b = source[i];
for (int shift = 0; shift < 8; shift += bits)
{
int index = (b >> (8 - bits - shift)) & mask;
result[resultOffset] = (byte)index;
resultOffset++;
}
}
return true;
}
// This appears to be incorrect.
private bool TryScaleDownFrom8BitArray(byte[] source, int bytesPerScanline, int bits, out byte[] result)
{
if (bits >= 8)
{
result = null;
return false;
}
result = new byte[bytesPerScanline];
byte mask = (byte)(0xFF >> (8 - bits));
byte shift0 = (byte)(8 - bits);
int shift = 8 - bits;
int v = 0;
int resultOffset = 0;
for (int i = 0; i < source.Length; i++)
{
int value = source[i] & mask;
v |= (value << shift);
if (shift == 0)
{
shift = shift0;
result[resultOffset] = (byte)v;
resultOffset++;
v = 0;
}
else
{
shift -= bits;
}
}
if (shift != shift0)
{
result[0] = (byte)v;
}
return true;
}
@JimBobSquarePants
Copy link
Author

When I run the above sample in LinqPad i'm getting differences in the source and destination arrays. They should match. I've no idea why.

@dlemstra
Copy link

Should result[0] = (byte)v; not be result[resultOffset] = (byte)v?

@JimBobSquarePants
Copy link
Author

@JimBobSquarePants
Copy link
Author

Ah @dlemstra You're the man!! Can't believe I missed this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment