Exemplo n.º 1
0
        //Decodes a byte array containing a compressed APIF image to a C# Bitmap image
        public Bitmap Decode(byte[] bytes)
        {
            //Check if the file version matches the version of the this decoder
            if (bytes[0] != version)
            {
                throw new Exception("Version not matching");
            }

            //Start timer for decoding time
            encodingStart = DateTime.Now.TimeOfDay;

            //Read the header info to the correct variables
            int pixelBytes = bytes[1];                  //The amount of color channels
            int width      = bytes[2] * 256 + bytes[3]; //The image width
            int height     = bytes[4] * 256 + bytes[5]; //The image heigth

            compressionType = bytes[6];                 //The compression type

            //Store the image data apart from the header
            byte[] image = new byte[bytes.Length - 7];
            Array.Copy(bytes, 7, image, 0, image.Length);

            //Initialize
            AccessibleBitmap outputBitmap = null;   //The final AccessibleBitmap object

            //Choose the right decoding type from the header info
            switch (compressionType)
            {
            //Uncompressed bitmap
            case 0:
                outputBitmap = UncompressedBitmapCompressor.Decompress(image, width, height, pixelBytes);
                break;

            //Individual compressed color channels merged together
            case 1:
                outputBitmap = ByteLayerVaryingCompression.Decompress(image, width, height, pixelBytes);
                break;

            //Run length encoding
            case 2:
                outputBitmap = RunLengthEncodingCompressor.Decompress(image, width, height, pixelBytes);
                break;

            //Run length encoding vertical
            case 3:
                outputBitmap = RunLengthEncodingCompressorVertical.Decompress(image, width, height, pixelBytes);
                break;

            //LZW compression
            case 4:
                outputBitmap = LZWCompressor.Decompress(image, width, height, pixelBytes);
                break;

            //To add a decompression type add a new case like the existing ones

            //Unknown compression type: error
            default:
                throw new Exception("Unexisting compression type");
            }

            //Stop timer
            encodingStop = DateTime.Now.TimeOfDay;
            SetStatus("Finished");

            //Calculate compression rate in bytes per pixel
            compressionRate = (double)bytes.Length / (outputBitmap.width * outputBitmap.height);

            //Return the output image as bitmap format
            return(outputBitmap.GetBitmap());
        }
Exemplo n.º 2
0
        //Encodes a C# Bitmap image to a byte array containing this image compressed as APIF image
        public byte[] Encode(Bitmap bitmap)
        {
            //Start timer for compression time
            encodingStart = DateTime.Now.TimeOfDay;

            //Creates a AccessibleBitmap class for the input bitmap: this class makes reading pixels easier and faster
            AccessibleBitmap aBitmap = new AccessibleBitmap(bitmap);

            //Compress image using all different compression techniques, where possible at the same time
            byte[][] compressionTechniques = new byte[4][];
            Parallel.For(0, compressionTechniques.Length, (i, state) =>
            {
                switch (i)
                {
                //Uncompressed (only used if no compression technique is smaller)
                case 0:
                    compressionTechniques[i] = UncompressedBitmapCompressor.Compress(aBitmap);
                    break;

                //Split colors in their channels and apply compression over them
                case 1:
                    compressionTechniques[i] = ByteLayerVaryingCompression.Compress(aBitmap);
                    break;

                //Run length compression: save the length of a sequence of pixels with the same color instead of saving them seperately
                case 2:
                    compressionTechniques[i] = RunLengthEncodingCompressor.Compress(aBitmap);
                    break;

                //Run length compression vertical: run length compression, but scan the pixels horizontally, becouse with some images this yields better results
                case 3:
                    compressionTechniques[i] = RunLengthEncodingCompressorVertical.Compress(aBitmap);
                    break;

                    //LZW compression: save sequences of pixels as a single value, without the need of adding a dictionary\
                    // REMOVED BECAUSE VERY SLOW AND NOT PROPERLY WORKING
                    //case 4:
                    //compressionTechniques[i] = LZWCompressor.Compress(aBitmap);
                    //break;

                    //To add a compression technique, add a new case like the existing ones and increase the length of new byte[??][]
                }
            });


            //Choose the smallest compression type

            //Initialize
            int smallestID   = 0;
            int smallestSize = int.MaxValue;

            //Loop trough all saved compression techniques
            for (int i = 0; i < compressionTechniques.Length; i++)
            {
                //If the current technique is smaller than the smallest technique which has been checked
                if (compressionTechniques[i].Length < smallestSize)
                {
                    //Mark this technique as smallest
                    smallestSize = compressionTechniques[i].Length;
                    smallestID   = i;
                }
            }

            //Set the output byte array to the output of the smallest compression technique
            byte[] image = compressionTechniques[smallestID];
            compressionType = smallestID;

            //Build the file header containing information for the decoder
            byte[] header = new byte[7];
            header[0] = (byte)version;                  //This byte indicates the version of the compressor, to handle possible changes in the future
            header[1] = (byte)aBitmap.pixelBytes;       //This byte indicates the amount of color channels in the image
            header[2] = (byte)(aBitmap.width >> 8);     //These 2 bytes together indicate the width of the image
            header[3] = (byte)aBitmap.width;            //The reason for using 2 bytes instead of 1, is that 1 byte can store a width of 0-255, while 2 bytes can store 0-65535
            header[4] = (byte)(aBitmap.height >> 8);    //These 2 bytes together indicate the heigth of the image
            header[5] = (byte)aBitmap.height;           //The reason for using 2 bytes instead of 1, is that 1 byte can store a width of 0-255, while 2 bytes can store 0-65535
            header[6] = (byte)compressionType;          //This contains the number of the compression technique used

            //Merge the header with the image data to form the fimal file data
            byte[] fileBytes = new byte[header.Length + image.Length];
            Array.Copy(header, fileBytes, header.Length);
            Array.Copy(image, 0, fileBytes, header.Length, image.Length);

            //Stop timer
            encodingStop    = DateTime.Now.TimeOfDay;
            compressionRate = (double)fileBytes.Length / (aBitmap.width * aBitmap.height);

            //Return final file as byte array
            return(fileBytes);
        }