Geeks With Blogs
The Life and Times of a Dev Yes, we're really that weird

If you do a search for PackBits and C#, you don’t find much.  I found an Objective C implementation, a C implementation, the Apple Guidelines from 1996, etc. but no solid examples in C#.  For my implementation, I had to stick to the basic rules (no bigger than 128 byte chunks, in particular) for the print controller that I’m sending data to.

Other compression mechanisms will not work for what I need, since the marker only understands PackBits and Monochrome Bitmaps.

For what I needed, compressed byte arrays work great, and given the nature of the data I’m printing, there are a lot of repeating bits, which yields very good compression (about 90%!).

At anyrate, here’s what I’m using.  Yeah, you could probably clean it up a bit more, but it’s good enough.  Enjoy.

 

// -----------------------------------------------------------------------
//    <copyright file="PackBitsCompressor.cs" company="VendRx, Inc.">
//        Copyright (c) VendRx, Inc. 2015
//    </copyright>
//    <summary>
//      Released under the apache 2.0 license.  http://www.apache.org/licenses/LICENSE-2.0.html
//    </summary>
// ---------------------------------------------------------------------

namespace VendRx.Common.Compression
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Class PackBitsCompressor.
    /// </summary>
    public class PackBitsCompressor : IPackBitsCompressor
    {
        /// <summary>
        /// Packs the specified byte array using the packbits algorithm.
        /// </summary>
        /// <param name="source">The source byte[] to pack.</param>
        /// <returns>A byte[] array that has been compressed.</returns>
        public byte[] Pack(byte[] source)
        {
            IList<byte> result = new List<byte>(source.Length);

            const int MaxLength = 127;
            IList<byte> literals = new List<byte>(MaxLength);

            for (int i = 0; i < source.Length; i++)
            {
                byte current = source[i];

                if (i + 1 != source.Length)
                {
                    byte next = source[i + 1];

                    if (next == current)
                    {
                        this.AddLiterals(result, literals);

                        int max = i + MaxLength >= source.Length ? source.Length - i - 1 : MaxLength;
                        bool hitMax = true;
                        byte runLength = 1;

                        for (int j = 2; j <= max; j++)
                        {
                            byte run = source[i + j];
                            if (run != current)
                            {
                                hitMax = false;
                                byte count = (byte)(0 - runLength);
                                i = i + j - 1;
                                result.Add(count);
                                result.Add(current);
                                break;
                            }

                            runLength++;
                        }

                        if (hitMax)
                        {
                            result.Add((byte)(sbyte)(0 - max));
                            result.Add(current);
                            i = i + max;
                        }
                    }
                    else
                    {
                        literals.Add(current);
                        if (literals.Count == MaxLength)
                        {
                            this.AddLiterals(result, literals);
                        }
                    }
                }
                else
                {
                    literals.Add(current);
                    this.AddLiterals(result, literals);
                }
            }

            return result.ToArray();
        }

        /// <summary>
        /// Unpacks the source byte array
        /// </summary>
        /// <param name="source">The source byte array to unpack.</param>
        /// <returns>Unpacks the source array.</returns>
        public byte[] UnPack(byte[] source)
        {
            IList<byte> result = new List<byte>(source.Length * 2);

            for (int i = 0; i < source.Length; i++)
            {
                sbyte count = (sbyte)source[i];

                if (count == -128)
                {
                    // do nothing--skip it.
                }
                else if (count >= 0)
                {
                    int total = count + 1;
                    for (int j = 0; j < total; j++)
                    {
                        result.Add(source[i + j + 1]);
                    }

                    i = i + total;
                }
                else
                {
                    int total = Math.Abs(count) + 1;
                    for (int j = 0; j < total; j++)
                    {
                        result.Add(source[i + 1]);
                    }

                    i = i + 1;
                }
            }

            return result.ToArray();
        }

        /// <summary>
        /// Adds the literal run to the result
        /// </summary>
        /// <param name="result">The result where the literals should be added.</param>
        /// <param name="literals">The list of literals that will be appeneded to the result.</param>
        private void AddLiterals(IList<byte> result, IList<byte> literals)
        {
            if (literals.Count > 0)
            {
                result.Add((byte)(literals.Count - 1));
                foreach (byte literal in literals)
                {
                    result.Add(literal);
                }
            }

            literals.Clear();
        }
    }
}

Posted on Monday, December 14, 2015 4:23 PM | Back to top


Comments on this post: PackBits in C#

# re: PackBits in C#
Requesting Gravatar...
Valentine's Day Flowers to Mexico, Valentine Flowers Mexico, Mexico, Send Valentine's Day Flowers to Mexico, Cheap Valentine Flowers to Mexico
Left by Gaybriyella on Feb 03, 2016 11:34 PM

# re: PackBits in C#
Requesting Gravatar...
we all wish u new year status 2017
Left by daniels danny on Nov 14, 2016 9:52 AM

# You TV Player Apk
Requesting Gravatar...
I am excited to have had discovered YouTV Player. Seriously man, I used to get so bored before coming across this app. It is easy to use and offers tons of cartoons, TV shows and films to choose from. Once a while I end up discovering great shows too, and keep recommending it to everyone. Try out the new app if you haven't already. Check this site You TV Player now to know more about this app You TV Player Apk
Left by William Kreps on May 30, 2017 1:34 AM

# re: PackBits in C#
Requesting Gravatar...
Amazing in your sCript ...http://www.fordphumy.org/
Left by phu my ford on Jun 13, 2017 2:40 AM

Your comment:
 (will show your gravatar)


Copyright © Robert May | Powered by: GeeksWithBlogs.net