Exemplo n.º 1
0
        /// <summary>
        /// Generated from text on F-23, F.13 - Huffman decoded of AC coefficients
        /// on ISO DIS 10918-1. Requirements and Guidelines.
        /// </summary>
        internal void decode_ac_coefficients(JPEGBinaryReader JPEGStream, float[] zz)
        {
            for (int k = 1; k < 64; k++)
            {
                int s = ACTable.Decode(JPEGStream);
                int r = s >> 4;
                s &= 15;


                if (s != 0)
                {
                    k += r;

                    r     = (int)JPEGStream.ReadBits(s);
                    s     = (int)HuffmanTable.Extend(r, s);
                    zz[k] = s;
                }
                else
                {
                    if (r != 15)
                    {
                        //throw new JPEGMarkerFoundException();
                        return;
                    }
                    k += 15;
                }
            }
        }
Exemplo n.º 2
0
        private void TableTwo(StartOfFrame.Component[] components, HuffmanTable luminanceDc, HuffmanTable luminanceAc)
        {
            var i = 0;

            while (!ImageData.EndOfFile)
            {
                try
                {
                    // Luminance (Y) - DC
                    var dc = ReadDcComponent(luminanceDc.Dictionary);

                    // Luminance (Y) - AC
                    var ac = ReadAcComponent(luminanceAc.Dictionary);

                    i++;
                }
                catch (Exception exception)
                {
                    Console.WriteLine("Crash {0}", exception);
                    break;
                }
            }

            Console.WriteLine("Count = {0}", i);
        }
Exemplo n.º 3
0
        public JpegComponent(JpegScan parentScan, byte id, byte factorHorizontal, byte factorVertical,
                             byte quantizationID, byte colorMode)
        {
            parent = parentScan;

            /* Set default tables in case they're not provided.  J. Powers */
            // TODO: only gen if needed

            if (colorMode == JPEGFrame.JPEG_COLOR_YCbCr)
            {
                if (id == 1) // Luminance
                {
                    ACTable = new HuffmanTable(JpegHuffmanTable.StdACLuminance);
                    DCTable = new HuffmanTable(JpegHuffmanTable.StdDCLuminance);
                }
                else
                {
                    ACTable = new HuffmanTable(JpegHuffmanTable.StdACChrominance);
                    DCTable = new HuffmanTable(JpegHuffmanTable.StdACLuminance);
                }
            }

            component_id = id;

            factorH = factorHorizontal;
            factorV = factorVertical;

            quant_id = quantizationID;
        }
Exemplo n.º 4
0
        internal static void ConvertToCanonicalCode(ref HuffmanTable huffmanTable)
        {
            int  newCode      = -1; // Para compensar con el incremento inicial dentro del for debajo
            uint prevLength   = 1;
            uint newCodeIndex = 0;

            huffmanTable.table = new List <CodeInfo>();

            for (uint i = 0; i < huffmanTable.numSymbols.Length; i++)
            {
                uint codeLength = i + 1;

                for (uint j = 0; j < huffmanTable.numSymbols[i]; j++)
                {
                    var code       = new CodeInfo();
                    int difLengths = (int)(codeLength - prevLength);

                    newCode    = (newCode + 1) << difLengths;
                    prevLength = codeLength;

                    code.code   = (uint)newCode;
                    code.length = (byte)codeLength;
                    code.number = (ushort)huffmanTable.codes[newCodeIndex++];

                    huffmanTable.table.Add(code);
                }
            }

            huffmanTable.maxCodeLength = (byte)prevLength;
        }
Exemplo n.º 5
0
        public JpegFrameContext(byte quality, ushort height, ushort width,
                                JpegQuantizationTable luminance = null, JpegQuantizationTable chrominance = null, byte[] hSampFactor = null, byte[] vSampFactor = null)
        {
            Quality = quality;
            Height  = height;
            Width   = width;

            HSampFactor = hSampFactor ?? FrameDefaults.HSampFactor;
            VSampFactor = vSampFactor ?? FrameDefaults.VSampFactor;
            Luminance   = luminance ?? JpegQuantizationTable.K1Luminance;
            Chrominance = chrominance ?? JpegQuantizationTable.K2Chrominance;

            DCT          = new DCT(Quality, Luminance, Chrominance);
            HuffmanTable = HuffmanTable.GetHuffmanTable(null);

            JpegFrame                = new JpegFrame();
            JpegFrame.ScanLines      = height;
            JpegFrame.SamplesPerLine = width;
            JpegFrame.Precision      = 8;                                // Number of bits per sample
            JpegFrame.ComponentCount = FrameDefaults.NumberOfComponents; // Number of components (Y, Cb, Cr)

            var qTables = new JpegQuantizationTable[2];

            qTables[0] = JpegQuantizationTable.GetJpegQuantizationTable(DCT.quantum[0]);
            qTables[1] = JpegQuantizationTable.GetJpegQuantizationTable(DCT.quantum[1]);

            for (byte i = 0; i < FrameDefaults.NumberOfComponents; i++)
            {
                JpegFrame.AddComponent(FrameDefaults.CompId[i], HSampFactor[i], VSampFactor[i], qTables[FrameDefaults.QtableNumber[i]]);
                JpegFrame.SetHuffmanTables(FrameDefaults.CompId[i], JpegFrame.AcTables[FrameDefaults.ACtableNumber[i]], JpegFrame.DcTables[FrameDefaults.DCtableNumber[i]]);
            }
        }
Exemplo n.º 6
0
        public void JPEGDecoder_Test_YDCHuffman()
        {
            string filePath = @"out.jpg"; // has message byte[] {1, 2, 3, 4, 5} encoded

            JPEGDecoder jd = new JPEGDecoder(filePath);

            HuffmanTable outputHuffmandTable = jd.YDCHuffman;
            
            HuffmanTable expectedHuffmanTable = new HuffmanTable(
                #region HuffmanElements
                new HuffmanElement(0x00, 0x00, 2),
                new HuffmanElement(0x01, 0x02, 3),
                new HuffmanElement(0x02, 0x03, 3),
                new HuffmanElement(0x03, 0x04, 3),
                new HuffmanElement(0x04, 0x05, 3),
                new HuffmanElement(0x05, 0x06, 3),
                new HuffmanElement(0x06, 0x0e, 4),
                new HuffmanElement(0x07, 0x1e, 5),
                new HuffmanElement(0x08, 0x3e, 6),
                new HuffmanElement(0x09, 0x7e, 7),
                new HuffmanElement(0x0a, 0xfe, 8),
                new HuffmanElement(0x0b, 0x1fe, 9)
#endregion
            );

            Assert.AreEqual(expectedHuffmanTable.Elements, outputHuffmandTable.Elements);
        }
Exemplo n.º 7
0
        private static void ParseRow(
            StartOfFrame lossless, int x, ushort y, StartOfImage startOfImage, HuffmanTable table0, short[,] rowBuf, short[] predictor, Bitmap image1)
        {
            var i1 = 4 / lossless.Components.Length;

            for (var j = 0; j < lossless.ScanLines / i1; j++)
            {
                for (var g = 0; g < i1; g++)
                {
                    for (var i = 0; i < y / lossless.Components.Length; i++)
                    {
                        for (var h = 0; h < lossless.Components.Length; h++)
                        {
                            var hufCode = UnitTests.GetValue(startOfImage.ImageData, table0);
                            var difCode = startOfImage.ImageData.GetSetOfBits(hufCode);
                            var dif     = UnitTests.DecodeDifBits(hufCode, difCode);

                            if (i == 0)
                            {
                                rowBuf[g * i1 + h, i] = predictor[h] += dif;
                            }
                            else
                            {
                                rowBuf[g * i1 + h, i] = (short)(rowBuf[g * i1 + h, i - 1] + dif);
                            }
                        }
                    }
                }

                UnitTests.DumpPixel(x * y, j, rowBuf, image1);
            }
        }
Exemplo n.º 8
0
        private static void writeHuffmanTable(HuffmanTable table, byte[] pData, ref int pos)
        {
            writeMarker(0x0C4, pData, ref pos);

            // Number of Codes for Bit Lengths [1..16]
            int nCodeCount = 0;

            for (int i = 0; i < 16; ++i)
            {
                nCodeCount += table.aCodes[i];
            }

            write(pData, (ushort)(17 + nCodeCount + 2), ref pos);

            write(pData, table.nClassAndIdentifier, ref pos);
            for (int i = 0; i < 16; i++)
            {
                pData[pos + i] = table.aCodes[i];
            }
            pos += 16;
            for (int i = 0; i < nCodeCount; i++)
            {
                pData[pos + i] = table.aCodes[i + 16];
            }
            pos += nCodeCount;
        }
Exemplo n.º 9
0
        internal void decode_ac_coefficients(JPEGBinaryReader JPEGStream, float[] zz)
        {
            int num;

            for (num = 1; num < 64; num++)
            {
                int num2 = ACTable.Decode(JPEGStream);
                int num3 = num2 >> 4;
                num2 &= 0xF;
                if (num2 != 0)
                {
                    num    += num3;
                    num3    = JPEGStream.ReadBits(num2);
                    num2    = HuffmanTable.Extend(num3, num2);
                    zz[num] = num2;
                }
                else
                {
                    if (num3 != 15)
                    {
                        break;
                    }
                    num += 15;
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Get the Huffman tables using reflection for a specific component (AC, DC)
        /// </summary>
        /// <returns></returns>
        public static HuffmanTable[] GetHuffmanTables(string JpegFilePath)
        {
            FileStream             objFileStreamMegaMap = File.Create(JpegFilePath);
            jpeg_decompress_struct jpds = new jpeg_decompress_struct();
            jpeg_compress_struct   jpcs = new jpeg_compress_struct();

            jpcs.jpeg_stdio_dest(objFileStreamMegaMap);
            jpds.jpeg_copy_critical_parameters(jpcs);
            jpds.jpeg_finish_decompress();
            objFileStreamMegaMap.Close();

            // DC Huffman tables
            JHUFF_TBL[] jpeg_dc_huffman_tables = jpcs.Dc_huff_tbl_ptrs;
            var         comp = HuffmanTable.EnumComponent.DC;
            var         htdc = getHTables(jpeg_dc_huffman_tables, comp);

            // AC Huffman tables
            JHUFF_TBL[] jpeg_ac_huffman_tables = jpcs.Ac_huff_tbl_ptrs;
            comp = HuffmanTable.EnumComponent.AC;
            var htac = getHTables(jpeg_ac_huffman_tables, comp);

            HuffmanTable[] hts = new HuffmanTable[htdc.Length + htac.Length];
            Array.Copy(htdc, hts, htdc.Length);
            Array.Copy(htac, 0, hts, htdc.Length, htac.Length);

            return(hts);
        }
Exemplo n.º 11
0
        public JpegComponent(JpegScan parentScan, byte id, byte factorHorizontal, byte factorVertical,
                             byte quantizationID, byte colorMode)
        {
            parent = parentScan;

            /* Set default tables in case they're not provided.  J. Powers */
            // TODO: only gen if needed

            if (colorMode == JPEGFrame.JPEG_COLOR_YCbCr)
            {
                if (id == 1) // Luminance
                {
                    ACTable = new HuffmanTable(JpegHuffmanTable.StdACLuminance);
                    DCTable = new HuffmanTable(JpegHuffmanTable.StdDCLuminance);
                }
                else
                {
                    ACTable = new HuffmanTable( JpegHuffmanTable.StdACChrominance);
                    DCTable = new HuffmanTable( JpegHuffmanTable.StdACLuminance);
                }
            }

            component_id = id;

            factorH = factorHorizontal;
            factorV = factorVertical;

            quant_id = quantizationID;
        }
Exemplo n.º 12
0
 public void DcCodeTestFour()
 {
     for (var i = 8; i < 16; i++)
     {
         var expected = i;
         Assert.AreEqual(expected, HuffmanTable.DcValueEncoding(4, (byte)i));
     }
 }
Exemplo n.º 13
0
        public float decode_dc_coefficient(JPEGBinaryReader JPEGStream)
        {
            int   num  = DCTable.Decode(JPEGStream);
            float num2 = JPEGStream.ReadBits(num);

            num2 = HuffmanTable.Extend((int)num2, num);
            return(previousDC += num2);
        }
Exemplo n.º 14
0
 public void DcCodeTestFourNegative()
 {
     for (var i = 0; i < 8; i++)
     {
         var expected = i - 15;
         Assert.AreEqual(expected, HuffmanTable.DcValueEncoding(4, (byte)i));
     }
 }
Exemplo n.º 15
0
        public void DecodeDCFirst(JPEGBinaryReader stream, float[] dest)
        {
            int num = DCTable.Decode(stream);

            num        = HuffmanTable.Extend(stream.ReadBits(num), num);
            num        = (int)previousDC + num;
            previousDC = num;
            dest[0]    = num << successiveLow;
        }
Exemplo n.º 16
0
 public LJPEGPlain(ImageBinaryReader file, RawImage img, bool DNGCompatible, bool UseBigTable) : base(file, img, DNGCompatible, UseBigTable)
 {
     huff = new HuffmanTable[4] {
         new HuffmanTable(UseBigTable, DNGCompatible),
         new HuffmanTable(UseBigTable, DNGCompatible),
         new HuffmanTable(UseBigTable, DNGCompatible),
         new HuffmanTable(UseBigTable, DNGCompatible)
     };
 }
Exemplo n.º 17
0
        public void DecodeDCFirst(JPEGBinaryReader stream, float[] dest)
        {
            float[] numArray = new float[0x40];
            int     t        = this.DCTable.Decode(stream);

            t = HuffmanTable.Extend(stream.ReadBits(t), t);
            t = ((int)this.previousDC) + t;
            this.previousDC = t;
            dest[0]         = t << this.successiveLow;
        }
Exemplo n.º 18
0
        internal static ushort ReadRunAmplitude(BitReader bReader, HuffmanTable table)
        {
            ushort code = bReader.Peek(table.maxCodeLength);

            CodeInfo currentCode = table.preIndexTable[code];

            bReader.Read(currentCode.length);

            return(currentCode.number);
        }
Exemplo n.º 19
0
        /// <summary>
        /// Generated from text on F-22, F.2.2.1 - Huffman decoding of DC
        /// coefficients on ISO DIS 10918-1. Requirements and Guidelines.
        /// </summary>
        /// <param name="JPEGStream">Stream that contains huffman bits</param>
        /// <returns>DC coefficient</returns>
        public float decode_dc_coefficient(JPEGBinaryReader JPEGStream)
        {
            int   t    = DCTable.Decode(JPEGStream);
            float diff = JPEGStream.ReadBits(t);

            diff       = HuffmanTable.Extend((int)diff, t);
            diff       = (previousDC + diff);
            previousDC = diff;
            return(diff);
        }
Exemplo n.º 20
0
 public JpegEncoder(DecodedJpeg decodedJpeg, int quality, Stream outStream)
 {
     this._input = decodedJpeg;
     this._input.Image.ChangeColorSpace(ColorSpace.YCbCr);
     this._quality   = quality;
     this._height    = this._input.Image.Height;
     this._width     = this._input.Image.Width;
     this._outStream = outStream;
     this._dct       = new DCT(this._quality);
     this._huf       = new HuffmanTable(null);
 }
Exemplo n.º 21
0
 public JpegEncoder(DecodedJpeg decodedJpeg, int quality, Stream outStream)
 {
     _input = decodedJpeg;
     _input.Image.ChangeColorSpace(ColorSpace.YCbCr);
     _quality   = quality;
     _height    = _input.Image.Height;
     _width     = _input.Image.Width;
     _outStream = outStream;
     _dct       = new DCT(_quality);
     _huf       = new HuffmanTable(null);
 }
Exemplo n.º 22
0
        public void BuildTreeCodesTest()
        {
            var data1 = new byte[] { 0, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
            var data2 = new byte[] { 0, 5, 3, 6, 7, 2, 8, 0, 1, 9, 10, 11, 12, 13, 15 };

            var codes = new byte[] { 0, 5, 3, 6, 7, 2, 8, 0, 1, 9, 10, 11, 12, 13, 15 };

            var dictionary = HuffmanTable.BuildTree(data1, data2);

            CollectionAssert.AreEqual(codes, dictionary.Values.Select(key => key.Code).ToArray());
        }
Exemplo n.º 23
0
 public LJPEGPlain(TiffBinaryReader file, RawImage <ushort> img, bool DNGCompatible, bool UseBigTable) : base(file, img, DNGCompatible, UseBigTable)
 {
     CanonFlipDim      = false;
     CanonDoubleHeight = false;
     huff = new HuffmanTable[4] {
         new HuffmanTable(UseBigTable, DNGCompatible),
         new HuffmanTable(UseBigTable, DNGCompatible),
         new HuffmanTable(UseBigTable, DNGCompatible),
         new HuffmanTable(UseBigTable, DNGCompatible)
     };
 }
Exemplo n.º 24
0
        public void BuildTreeKeysTest()
        {
            var data1 = new byte[] { 0, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
            var data2 = new byte[] { 0, 5, 3, 6, 7, 2, 8, 0, 1, 9, 10, 11, 12, 13, 15 };

            var keys = new[] { 0, 1, 4, 5, 12, 13, 28, 29, 30, 62, 126, 254, 510, 1022, 2046 };

            var dictionary = HuffmanTable.BuildTree(data1, data2);

            CollectionAssert.AreEqual(keys, dictionary.Keys);
        }
Exemplo n.º 25
0
        public void BuildTreeLengthTest()
        {
            var data1 = new byte[] { 0, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
            var data2 = new byte[] { 0, 5, 3, 6, 7, 2, 8, 0, 1, 9, 10, 11, 12, 13, 15 };

            var lengths = new byte[] { 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 7, 8, 9, 10, 11 };

            var dictionary = HuffmanTable.BuildTree(data1, data2);

            CollectionAssert.AreEqual(lengths, dictionary.Values.Select(key => key.Length).ToArray());
        }
Exemplo n.º 26
0
        public static HuffmanPacker Load(BinaryReader reader)
        {
            var symbols = HuffmanTable.Load(reader);
            var len     = reader.Read7BitEncodedInt();
            var offsets = new HuffmanTable[len];

            for (int i = 0; i < len; i++)
            {
                offsets[i] = HuffmanTable.Load(reader);
            }
            return(new HuffmanPacker(symbols, offsets));
        }
Exemplo n.º 27
0
        public void DecodeDCFirst(JPEGBinaryReader stream, float[] dest)
        {
            //float[] datablock = new float[64];
            int s = DCTable.Decode(stream);
            int r = stream.ReadBits(s);

            s          = HuffmanTable.Extend(r, s);
            s          = (int)previousDC + s;
            previousDC = s;

            dest[0] = s << successiveLow;
        }
Exemplo n.º 28
0
        //Adds defaultTable.Length amount of textboxes to a given Huffman panel and saves each in an array (to be looped through), sets
        //the size and position of each textbox and writes the default Quantization values in these.
        private void _initializeHuffmanTableComponent(out HuffmanTableComponent huffmanTableComponent, HuffmanTable settingsHuffmanTable, HuffmanTable defaultHuffmanTable) {

            if (settingsHuffmanTable != null) {
                huffmanTableComponent = new HuffmanTableComponent(settingsHuffmanTable);
            } else {
                huffmanTableComponent = new HuffmanTableComponent(defaultHuffmanTable);
            }
            grpCustomHuffman.Controls.Add(huffmanTableComponent);
            huffmanTableComponent.Location = new Point(4, 30);
            huffmanTableComponent.AutoScroll = Enabled;
            huffmanTableComponent.BringToFront();
        }
Exemplo n.º 29
0
        public void HuffmanTableTest()
        {
            var data1 = new byte[] { 0, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
            var data2 = new byte[] { 0, 5, 3, 6, 7, 2, 8, 0, 1, 9, 10, 11, 12, 13, 15 };

            var huffmanTable = new HuffmanTable(0, data1, data2);

            Assert.AreEqual(0, huffmanTable.Index);
            Assert.AreSame(data1, huffmanTable.Data1);
            Assert.AreSame(data2, huffmanTable.Data2);
            Assert.AreEqual(15, huffmanTable.Dictionary.Count);
        }
Exemplo n.º 30
0
        public void ParseDHT()
        {
            uint headerLength = (uint)input.ReadInt16() - 2; // Subtract myself

            while (headerLength != 0)
            {
                uint b  = input.ReadByte();
                uint Tc = (b >> 4);
                if (Tc != 0)
                {
                    throw new RawDecoderException("Unsupported Table class.");
                }

                uint Th = b & 0xf;
                if (Th > 3)
                {
                    throw new RawDecoderException("Invalid huffman table destination id.");
                }

                uint         acc   = 0;
                HuffmanTable table = huff[Th];

                if (table.Initialized)
                {
                    throw new RawDecoderException("Duplicate table definition");
                }

                for (int i = 0; i < 16; i++)
                {
                    table.bits[i + 1] = input.ReadByte();
                    acc += table.bits[i + 1];
                }
                table.bits[0] = 0;
                if (acc > 256)
                {
                    throw new RawDecoderException("Invalid DHT table.");
                }

                if (headerLength < 1 + 16 + acc)
                {
                    throw new RawDecoderException("Invalid DHT table length.");
                }

                for (int i = 0; i < acc; i++)
                {
                    table.huffval[i] = input.ReadByte();
                }
                table.Create(frame.precision);
                headerLength -= 1 + 16 + acc;
            }
        }
Exemplo n.º 31
0
        /// <summary>
        /// <para>
        /// Decode a code from the stream using huffman table h.  Return the symbol or
        /// a negative value if there is an error.  If all of the lengths are zero, i.e.
        /// an empty code, or if the code is incomplete and an invalid code is received,
        /// then -9 is returned after reading MAXBITS bits.
        /// </para>
        ///
        /// <para>Format notes:</para>
        ///
        /// <list type="bullet">
        /// <item>The codes as stored in the compressed data are bit-reversed relative to
        ///   a simple integer ordering of codes of the same lengths.  Hence below the
        ///   bits are pulled from the compressed data one at a time and used to
        ///   build the code value reversed from what is in the stream in order to
        ///   permit simple integer comparisons for decoding.</item>
        ///
        /// <item>The first code for the shortest length is all ones.  Subsequent codes of
        ///   the same length are simply integer decrements of the previous code.  When
        ///   moving up a length, a one bit is appended to the code.  For a complete
        ///   code, the last code of the longest length will be all zeros.  To support
        ///   this ordering, the bits pulled during decoding are inverted to apply the
        ///   more "natural" ordering starting with all zeros and incrementing.</item>
        /// </list>
        /// </summary>
        private int Decode(HuffmanTable h)
        {
            int len   = 1;                       // current number of bits in code
            int code  = 0;                       // len bits being decoded
            int first = 0;                       // first code of length len
            int count;                           // number of codes of length len
            int index = 0;                       // index of first code of length len in symbol table
            int bitbuf;                          // bits from stream
            int left;                            // bits left in next or left to process
            int next = 1;                        // next number of codes

            bitbuf = this._bitBuffer;
            left   = this._bitBufferCount;

            while (true)
            {
                while (left-- > 0)
                {
                    code    |= (bitbuf & 1) ^ 1;
                    bitbuf >>= 1;
                    count    = h.count[next++];
                    if (code < first + count)
                    {
                        this._bitBuffer      = bitbuf;
                        this._bitBufferCount = (this._bitBufferCount - len) & 7;

                        return(h.symbol[index + (code - first)]);
                    }
                    index  += count;
                    first  += count;
                    first <<= 1;
                    code  <<= 1;
                    len++;
                }
                left = (MAX_BITS + 1) - len;

                if (left == 0)
                {
                    break;
                }

                bitbuf = ConsumeByte();
                if (left > 8)
                {
                    left = 8;
                }
            }

            return(-9);
        }
Exemplo n.º 32
0
        public static ushort GetValue(ImageData imageData, HuffmanTable table)
        {
            var hufIndex = (ushort)0;
            var hufBits  = (ushort)0;

            HuffmanTable.HCode hCode;
            do
            {
                hufIndex = imageData.GetNextShort(hufIndex);
                hufBits++;
            }while (!table.Dictionary.TryGetValue(hufIndex, out hCode) || hCode.Length != hufBits);

            return(hCode.Code);
        }
Exemplo n.º 33
0
        /// <summary>
        /// Encodes a JPEG, preserving the colorspace and metadata of the input JPEG.
        /// </summary>
        /// <param name="decodedJpeg">Decoded Jpeg to start with.</param>
        /// <param name="quality">Quality of the image from 0 to 100.  (Compression from max to min.)</param>
        /// <param name="outStream">Stream where the result will be placed.</param>
        public JpegEncoder(DecodedJpeg decodedJpeg, short quality, Stream outStream)
        {
            input = decodedJpeg;

            /* This encoder requires YCbCr */
            input.Image.ChangeColorSpace(ColorSpace.YCbCr);

            this.quality = quality;

            height         = input.Image.Height;
            width          = input.Image.Width;
            this.outStream = outStream;
            dct            = new DCT(quality);
            huf            = HuffmanTable.GetHuffmanTable(null);
        }
Exemplo n.º 34
0
        /// <summary>
        /// Encodes a JPEG, preserving the colorspace and metadata of the input JPEG.
        /// </summary>
        /// <param name="decodedJpeg">Decoded Jpeg to start with.</param>
        /// <param name="quality">Quality of the image from 0 to 100.  (Compression from max to min.)</param>
        /// <param name="outStream">Stream where the result will be placed.</param>
        public JpegEncoder(DecodedJpeg decodedJpeg, int quality, Stream outStream)
        {
            _input = decodedJpeg;
            
            /* This encoder requires YCbCr */
            _input.Image.ChangeColorSpace(ColorSpace.YCbCr);

            _quality = quality;

            _height = _input.Image.Height;
            _width = _input.Image.Width;
            _outStream = outStream;
            _dct = new DCT(_quality);
            _huf = new HuffmanTable(null); 
        }
Exemplo n.º 35
0
        public void HasCode_Test()
        {
            byte runSizeInput1 = 00000000;
            ushort codeWordInput1 = 2; // 10 in base 2
            byte lengthInput1 = 8; // 1000 in base 2

            byte runSizeInput2 = 1;
            ushort codeWordInput2 = 3; // 11 in base 2
            byte lengthInput2 = 8; // 1000 in base 2

            HuffmanElement huffmanTestElement1 = new HuffmanElement(runSizeInput1, codeWordInput1, lengthInput1);
            HuffmanElement huffmanTestElement2 = new HuffmanElement(runSizeInput2, codeWordInput2, lengthInput2);

            HuffmanTable huffTable1 = new HuffmanTable(huffmanTestElement1, huffmanTestElement2);

            Assert.AreEqual(0, huffTable1.HasCode(2, 8).RunSize);
        }
Exemplo n.º 36
0
 /// <summary>
 /// Takes a filepath to a JPEG file.
 /// </summary>
 /// <param name="path">Path to the jpeg file</param>
 public JPEGDecoder(string path) {
     StreamReader sr = new StreamReader(path);
     file = new BinaryReader(sr.BaseStream);
     for (int i = 0; i < 4; i++) {
         byte ClassAndID = 0;
         HuffmanTable temp = getHuffmanTable(out ClassAndID);
         if ((byte)(ClassAndID & 0xf0) == 0) {
             if ((byte)(ClassAndID & 0x0f) == 0) {
                 YDCHuffman = temp;
             } else {
                 ChrDCHuffman = temp;
             }
         } else if ((byte)(ClassAndID & 0x0f) == 0) {
             YACHuffman = temp;
         } else {
             ChrACHuffman = temp;
         }
     }
 }
Exemplo n.º 37
0
        public void HuffmanTable_Access_to_codeword_Test()
        {
            byte runSizeInput1 = 0x00;
            ushort codeWordInput1 = 2; // 10 in base 2
            byte lengthInput1 = 8; // 1000 in base 2

            byte runSizeInput2 = 0x1;
            ushort codeWordInput2 = 3; // 11 in base 2
            byte lengthInput2 = 8; // 1000 in base 2


            HuffmanElement huffmanTestElement1 = new HuffmanElement(runSizeInput1, codeWordInput1, lengthInput1);
            HuffmanElement huffmanTestElement2 = new HuffmanElement(runSizeInput2, codeWordInput2, lengthInput2);

            HuffmanTable huffTable1 = new HuffmanTable(huffmanTestElement1, huffmanTestElement2);
            

            Assert.AreEqual(2, huffTable1.Elements[0x00].CodeWord);
        }
Exemplo n.º 38
0
        public HuffmanTableComponent(HuffmanTable huffmanTable) {
            HuffmanTable table = huffmanTable;
            var elementList = table.Elements.ToList();
            Size = new Size(410, 244);

            _addTopDescription();

            for (int i = 0; i < table.Elements.Count; i++) {
                AddRow();

                string codeWord = Convert.ToString(elementList[i].Value.CodeWord, 2);

                if (codeWord.Length != elementList[i].Value.Length) {
                    codeWord = codeWord.PadLeft(elementList[i].Value.Length, '0');
                }

                codeWordsBoxes[i].Text = codeWord;

                runSizeBoxes[i].Text = Convert.ToString(elementList[i].Value.RunSize, 0x10).PadLeft(2, '0');
            }

            InitializeComponent();
        }
Exemplo n.º 39
0
        public void Combinations_Test() 
        {
            byte runSizeInput1 = 00000000;
            ushort codeWordInput1 = 2; // 10 in base 2
            byte lengthInput1 = 8; // 1000 in base 2

            byte runSizeInput2 = 1;
            ushort codeWordInput2 = 3; // 11 in base 2
            byte lengthInput2 = 8; // 1000 in base 2

            byte runSizeInput3 = 2;
            ushort codeWordInput3 = 4; // 100 in base 2
            byte lengthInput3 = 8; // 1000 in base 2

            HuffmanElement huffmanTestElement1 = new HuffmanElement(runSizeInput1, codeWordInput1, lengthInput1);
            HuffmanElement huffmanTestElement2 = new HuffmanElement(runSizeInput2, codeWordInput2, lengthInput2);
            HuffmanElement huffmanTestElement3 = new HuffmanElement(runSizeInput3, codeWordInput3, lengthInput3);
            HuffmanTable huffTable1 = new HuffmanTable(huffmanTestElement1, huffmanTestElement2, huffmanTestElement3);

            byte[] numberOfCodesOutput = huffTable1.Combinations();

            Assert.AreEqual(3, numberOfCodesOutput[7]);
        }
Exemplo n.º 40
0
 private void _encodeBlocksSubMethod(double[,] blocks, HuffmanTable DC, HuffmanTable AC, int index, QuantizationTable table) {
     blocks = _discreteCosineTransform(blocks);
     int[,] quantiziedBlock = _quantization(blocks, table);
     _quantizedBlocks.Add(new Tuple<int[,], HuffmanTable, HuffmanTable, int>(quantiziedBlock, DC, AC, index));
 }
Exemplo n.º 41
0
        private void _writeHuffmanSegment(HuffmanTable huffman, byte id, bool dc) {
            _jw.WriteBytes(0xff, 0xc4); //DHT marker

            ushort len = (ushort)(huffman.Elements.Count + huffman.Combinations().Length + 3);
            _jw.WriteBytes((byte)(len >> 8), (byte)(len & 0xff));

            byte combined;
            if (!dc) {
                combined = (byte)((1 << 4) + id);
            } else {
                combined = id;
            }

            _jw.WriteBytes(combined);

            _jw.WriteBytes(huffman.Combinations());


            HuffmanElement[] allElements = huffman.Elements.Values.OrderBy(x => x.Length).ThenBy(x => x.RunSize).ToArray();
            foreach (HuffmanElement huffmanElement in allElements) {
                _jw.WriteBytes(huffmanElement.RunSize);
            }
        }
Exemplo n.º 42
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="coverImage"></param>
        /// <param name="quality"></param>
        /// <param name="m"></param>
        /// <param name="yTable"></param>
        /// <param name="chrTable"></param>
        /// <param name="huffmanYDC"></param>
        /// <param name="huffmanYAC"></param>
        /// <param name="huffmanChrDC"></param>
        /// <param name="huffmanChrAC"></param>
        public JpegImage(Bitmap coverImage, int quality, int m, QuantizationTable yTable, QuantizationTable chrTable, HuffmanTable huffmanYDC, HuffmanTable huffmanYAC, HuffmanTable huffmanChrDC, HuffmanTable huffmanChrAC) {
            if (coverImage == null) {
                throw new ArgumentNullException();
            }

            CoverImage = coverImage;
            YQuantizationTable = yTable.Scale(quality);
            ChrQuantizationTable = chrTable.Scale(quality);
            M = m;
            YDCHuffman = huffmanYDC;
            YACHuffman = huffmanYAC;
            ChrDCHuffman = huffmanChrDC;
            ChrACHuffman = huffmanChrAC;

            _calculateCosineCoefficients();
        }
Exemplo n.º 43
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="coverImage"></param>
 /// <param name="quality"></param>
 /// <param name="m"></param>
 /// <param name="huffmanYDC"></param>
 /// <param name="huffmanYAC"></param>
 /// <param name="huffmanChrDC"></param>
 /// <param name="huffmanChrAC"></param>
 public JpegImage(Bitmap coverImage, int quality, int m, HuffmanTable huffmanYDC, HuffmanTable huffmanYAC, HuffmanTable huffmanChrDC, HuffmanTable huffmanChrAC)
     : this(coverImage, quality, m, QuantizationTable.JpegDefaultYTable, QuantizationTable.JpegDefaultChrTable, huffmanYDC, huffmanYAC, huffmanChrDC, huffmanChrAC) { }
Exemplo n.º 44
0
 //Uses the HuffmanTable.Fromstring() method to create a Huffman table from a string optained from a file.
 private static void _loadHuffmanTableFromFile(out HuffmanTable huffmanTable, string filePath) {
     if (File.Exists(filePath)) {
         string input = File.ReadAllText(filePath);
         huffmanTable = HuffmanTable.FromString(input);
     } else {
         huffmanTable = null;
     }
 }
Exemplo n.º 45
0
        private void _writeHuffmanSegment(HuffmanTable huffman, byte id, bool dc) {
            //DHT marker
            _jw.WriteBytes(0xff, 0xc4);

            //Size of Huffman table in bytes. Calculated as the number of elements +
            //the number of combinations + three bytes. Two of them for the length 
            //itself and the last is for whether it is a DC or not and the ID.
            ushort len = (ushort)(huffman.Elements.Count + huffman.Combinations().Length + 3);
            _jw.WriteBytes((byte)(len >> 8), (byte)(len & 0xff));

            byte combined;
            if (!dc) {
                combined = (byte)((1 << 4) + id);
            } else {
                combined = id;
            }

            //DC/AC and ID
            _jw.WriteBytes(combined);

            //The table combinations
            _jw.WriteBytes(huffman.Combinations());

            //Write the elements
            HuffmanElement[] allElements = huffman.Elements.Values.OrderBy(x => x.Length).ThenBy(x => x.RunSize).ToArray();
            foreach (HuffmanElement huffmanElement in allElements) {
                _jw.WriteBytes(huffmanElement.RunSize);
            }
        }
Exemplo n.º 46
0
        //Returns default table if the table made from the tablecomponent is the same as defaultTable, custom table if they are different.
        //Doing this prevents an error from ocuring when changing quality while using a 'default' table manually set.
        private static HuffmanTable _defaultOrCustomHuffmanTable(HuffmanTable customHuffmanTable, HuffmanTable defaultTable) {
            HuffmanTable H;
            if (customHuffmanTable.Equals(defaultTable)) {
                H = defaultTable;
            } else {
                H = customHuffmanTable;
            }

            return H;
        }
Exemplo n.º 47
0
        private static void writeHuffmanTable(HuffmanTable table, byte[] pData, ref int pos)
        {
            writeMarker(0x0C4, pData, ref pos);

            // Number of Codes for Bit Lengths [1..16]
            int nCodeCount = 0;

            for (int i = 0; i < 16; ++i)
            {
                nCodeCount += table.aCodes[i];
            }

            write(pData, (ushort)(17 + nCodeCount + 2), ref pos);

            write(pData, table.nClassAndIdentifier, ref pos);
            for (int i = 0; i < 16; i++)
            {
                pData[pos + i] = table.aCodes[i];
            }
            pos += 16;
            for (int i = 0; i < nCodeCount; i++)
            {
                pData[pos + i] = table.aCodes[i + 16];
            }
            pos += nCodeCount;
        }
Exemplo n.º 48
0
        public HuffmanTable SaveTable() {
            HuffmanTable h = new HuffmanTable();

            for (int i = 0; i < codeWordsBoxes.Count; i++) {
                if (string.IsNullOrWhiteSpace(runSizeBoxes[i].Text) || string.IsNullOrWhiteSpace(codeWordsBoxes[i].Text)) {
                    continue;
                }

                byte runSize = Convert.ToByte(runSizeBoxes[i].Text, 16);
                ushort codeword = Convert.ToUInt16(codeWordsBoxes[i].Text, 2);
                h.Elements.Add(runSize, new HuffmanElement(runSize, codeword, (byte)codeWordsBoxes[i].Text.Length));
            }
            return h;
        }
Exemplo n.º 49
0
        public void HuffmanTableToString_Test()
        {
            byte runSizeInput1 = 00000000;
            ushort codeWordInput1 = 2; // 10 in base 2
            byte lengthInput1 = 8; // 1000 in base 2

            byte runSizeInput2 = 1;
            ushort codeWordInput2 = 3; // 11 in base 2
            byte lengthInput2 = 8; // 1000 in base 2

            HuffmanElement huffmanTestElement1 = new HuffmanElement(runSizeInput1, codeWordInput1, lengthInput1);
            HuffmanElement huffmanTestElement2 = new HuffmanElement(runSizeInput2, codeWordInput2, lengthInput2);

            HuffmanTable huffTable1 = new HuffmanTable(huffmanTestElement1, huffmanTestElement2);

            Assert.AreEqual("0,2,8;1,3,8;", huffTable1.ToString());
        }
Exemplo n.º 50
0
        private static void readHuffmanTables(byte[] pData, ref int p, HuffmanTable[] pTables)
        {
            int pos = p;
            int nLength = readUShort(pData, ref pos) - 2;

            while (nLength > 0)
            {
                byte nClassAndIdentifier = readByte(pData, ref pos);
                int nClass = nClassAndIdentifier >> 4; // AC or DC
                int nIdentifier = nClassAndIdentifier & 0x0f;
                int nIdx = nClass * 2 + nIdentifier;
                pTables[nIdx].nClassAndIdentifier = nClassAndIdentifier;

                // Number of Codes for Bit Lengths [1..16]
                int nCodeCount = 0;

                for (int i = 0; i < 16; ++i)
                {
                    pTables[nIdx].aCodes[i] = readByte(pData, ref pos);
                    nCodeCount += pTables[nIdx].aCodes[i];
                }
                for (int i = 0; i < nCodeCount; i++)
                {
                    pTables[nIdx].aCodes[i + 16] = readByte(pData, ref pos);
                }

                nLength -= 17 + nCodeCount;
            }
        }
Exemplo n.º 51
0
 public void setACTable(JpegHuffmanTable table)
 {
     ACTable = new HuffmanTable(table);
 }
Exemplo n.º 52
0
        private void HuffmanEncode(BitList bits, int[,] block8, HuffmanTable huffmanDC, HuffmanTable huffmanAC, int DCIndex) {
            short diff = (short)(block8[0, 0] - _lastDc[DCIndex]);
            _lastDc[DCIndex] += diff;

            if (diff != 0) {
                byte category = _bitCost(diff);
                HuffmanElement huffmanCode = huffmanDC.GetElementFromRunSize(0, category);
                _ushortToBits(bits, huffmanCode.CodeWord, huffmanCode.Length);

                _ushortToBits(bits, _numberEncoder(diff), category);
            } else {
                HuffmanElement EOB = huffmanDC.GetElementFromRunSize(0x00, 0x00);
                _ushortToBits(bits, EOB.CodeWord, EOB.Length);
            }

            int zeroesCounter = 0;
            for (int i = 1; i < 64; i++) {
                int x = QuantizationTable.RoadPoints[i, 0], y = QuantizationTable.RoadPoints[i, 1];
                if (block8[x, y] == 0) {
                    zeroesCounter++;
                    continue;
                }
                while (zeroesCounter >= 16) {
                    HuffmanElement ZRL = huffmanAC.GetElementFromRunSize(0x0F, 0x00);
                    _ushortToBits(bits, ZRL.CodeWord, ZRL.Length);
                    zeroesCounter -= 16;
                }

                byte cost = _bitCost((short)Math.Abs(block8[x, y]));
                HuffmanElement codeElement = huffmanAC.GetElementFromRunSize((byte)zeroesCounter, cost);
                zeroesCounter = 0;
                _ushortToBits(bits, codeElement.CodeWord, codeElement.Length);

                _ushortToBits(bits, _numberEncoder((short)block8[x, y]), cost);

            }

            if (zeroesCounter != 0) { //EOB
                HuffmanElement EOB = huffmanAC.GetElementFromRunSize(0x00, 0x00);
                _ushortToBits(bits, EOB.CodeWord, EOB.Length);
            }
        }
Exemplo n.º 53
0
        public void HuffmanEncode() //TODO: Delete this
        {
            JpegImage ji = new JpegImage(new Bitmap(200, 100), 100, 4);
            PrivateObject po = new PrivateObject(ji);

            BitList bl = new BitList();
            short[,] inputBlock = new short[8, 8]
            {
                {1, 1, 1, 1, 1, 1, 1, 1},
                {1, 1, 1, 1, 1, 1, 1, 1},
                {1, 1, 1, 1, 1, 1, 1, 1},
                {1, 1, 1, 1, 1, 1, 1, 1},
                {1, 1, 1, 1, 1, 1, 1, 1},
                {1, 1, 1, 1, 1, 1, 1, 1},
                {1, 1, 1, 1, 1, 1, 1, 1},
                {1, 1, 1, 1, 1, 1, 1, 1},
            };
            HuffmanTable inputHuffDC = new HuffmanTable(
            #region HuffmanElements
                new HuffmanElement(0x00, 0x00, 2),
                new HuffmanElement(0x01, 0x02, 3),
                new HuffmanElement(0x02, 0x03, 3),
                new HuffmanElement(0x03, 0x04, 3),
                new HuffmanElement(0x04, 0x05, 3),
                new HuffmanElement(0x05, 0x06, 3),
                new HuffmanElement(0x06, 0x0e, 4),
                new HuffmanElement(0x07, 0x1e, 5),
                new HuffmanElement(0x08, 0x3e, 6),
                new HuffmanElement(0x09, 0x7e, 7),
                new HuffmanElement(0x0a, 0xfe, 8),
                new HuffmanElement(0x0b, 0x1fe, 9)
            #endregion
            );
            
            HuffmanTable inputHuffAC = new HuffmanTable(
            #region HuffmanElements
                new HuffmanElement(0x00, 0xa, 4),
                new HuffmanElement(0x01, 0x0, 2),
                new HuffmanElement(0x02, 0x1, 2),
                new HuffmanElement(0x03, 0x4, 3),
                new HuffmanElement(0x04, 0xb, 4),
                new HuffmanElement(0x05, 0x1a, 5),
                new HuffmanElement(0x06, 0x78, 7),
                new HuffmanElement(0x07, 0xf8, 8),
                new HuffmanElement(0x08, 0x3f6, 10),
                new HuffmanElement(0x09, 0xff82, 16),
                new HuffmanElement(0x0a, 0xff83, 16),
                new HuffmanElement(0x11, 0xc, 4),
                new HuffmanElement(0x12, 0x1b, 5),
                new HuffmanElement(0x13, 0x79, 7),
                new HuffmanElement(0x14, 0x1f6, 9),
                new HuffmanElement(0x15, 0x7f6, 11),
                new HuffmanElement(0x16, 0xff84, 16),
                new HuffmanElement(0x17, 0xff85, 16),
                new HuffmanElement(0x18, 0xff86, 16),
                new HuffmanElement(0x19, 0xff87, 16),
                new HuffmanElement(0x1a, 0xff88, 16),
                new HuffmanElement(0x21, 0x1c, 5),
                new HuffmanElement(0x22, 0xf9, 8),
                new HuffmanElement(0x23, 0x3f7, 10),
                new HuffmanElement(0x24, 0xff4, 12),
                new HuffmanElement(0x25, 0xff89, 16),
                new HuffmanElement(0x26, 0xff8a, 16),
                new HuffmanElement(0x27, 0xff8b, 16),
                new HuffmanElement(0x28, 0xff8c, 16),
                new HuffmanElement(0x29, 0xff8d, 16),
                new HuffmanElement(0x2a, 0xff8e, 16),
                new HuffmanElement(0x31, 0x3a, 6),
                new HuffmanElement(0x32, 0x1f7, 9),
                new HuffmanElement(0x33, 0xff5, 12),
                new HuffmanElement(0x34, 0xff8f, 16),
                new HuffmanElement(0x35, 0xff90, 16),
                new HuffmanElement(0x36, 0xff91, 16),
                new HuffmanElement(0x37, 0xff92, 16),
                new HuffmanElement(0x38, 0xff93, 16),
                new HuffmanElement(0x39, 0xff94, 16),
                new HuffmanElement(0x3a, 0xff95, 16),
                new HuffmanElement(0x41, 0x3b, 6),
                new HuffmanElement(0x42, 0x3f8, 10),
                new HuffmanElement(0x43, 0xff96, 16),
                new HuffmanElement(0x44, 0xff97, 16),
                new HuffmanElement(0x45, 0xff98, 16),
                new HuffmanElement(0x46, 0xff99, 16),
                new HuffmanElement(0x47, 0xff9a, 16),
                new HuffmanElement(0x48, 0xff9b, 16),
                new HuffmanElement(0x49, 0xff9c, 16),
                new HuffmanElement(0x4a, 0xff9d, 16),
                new HuffmanElement(0x51, 0x7a, 7),
                new HuffmanElement(0x52, 0x7f7, 11),
                new HuffmanElement(0x53, 0xff9e, 16),
                new HuffmanElement(0x54, 0xff9f, 16),
                new HuffmanElement(0x55, 0xffa0, 16),
                new HuffmanElement(0x56, 0xffa1, 16),
                new HuffmanElement(0x57, 0xffa2, 16),
                new HuffmanElement(0x58, 0xffa3, 16),
                new HuffmanElement(0x59, 0xffa4, 16),
                new HuffmanElement(0x5a, 0xffa5, 16),
                new HuffmanElement(0x61, 0x7b, 7),
                new HuffmanElement(0x62, 0xff6, 12),
                new HuffmanElement(0x63, 0xffa6, 16),
                new HuffmanElement(0x64, 0xffa7, 16),
                new HuffmanElement(0x65, 0xffa8, 16),
                new HuffmanElement(0x66, 0xffa9, 16),
                new HuffmanElement(0x67, 0xffaa, 16),
                new HuffmanElement(0x68, 0xffab, 16),
                new HuffmanElement(0x69, 0xffac, 16),
                new HuffmanElement(0x6a, 0xffad, 16),
                new HuffmanElement(0x71, 0xfa, 8),
                new HuffmanElement(0x72, 0xff7, 12),
                new HuffmanElement(0x73, 0xffae, 16),
                new HuffmanElement(0x74, 0xffaf, 16),
                new HuffmanElement(0x75, 0xffb0, 16),
                new HuffmanElement(0x76, 0xffb1, 16),
                new HuffmanElement(0x77, 0xffb2, 16),
                new HuffmanElement(0x78, 0xffb3, 16),
                new HuffmanElement(0x79, 0xffb4, 16),
                new HuffmanElement(0x7a, 0xffb5, 16),
                new HuffmanElement(0x81, 0x1f8, 9),
                new HuffmanElement(0x82, 0x7fc0, 15),
                new HuffmanElement(0x83, 0xffb6, 16),
                new HuffmanElement(0x84, 0xffb7, 16),
                new HuffmanElement(0x85, 0xffb8, 16),
                new HuffmanElement(0x86, 0xffb9, 16),
                new HuffmanElement(0x87, 0xffba, 16),
                new HuffmanElement(0x88, 0xffbb, 16),
                new HuffmanElement(0x89, 0xffbc, 16),
                new HuffmanElement(0x8a, 0xffbd, 16),
                new HuffmanElement(0x91, 0x1f9, 9),
                new HuffmanElement(0x92, 0xffbe, 16),
                new HuffmanElement(0x93, 0xffbf, 16),
                new HuffmanElement(0x94, 0xffc0, 16),
                new HuffmanElement(0x95, 0xffc1, 16),
                new HuffmanElement(0x96, 0xffc2, 16),
                new HuffmanElement(0x97, 0xffc3, 16),
                new HuffmanElement(0x98, 0xffc4, 16),
                new HuffmanElement(0x99, 0xffc5, 16),
                new HuffmanElement(0x9a, 0xffc6, 16),
                new HuffmanElement(0xa1, 0x1fa, 9),
                new HuffmanElement(0xa2, 0xffc7, 16),
                new HuffmanElement(0xa3, 0xffc8, 16),
                new HuffmanElement(0xa4, 0xffc9, 16),
                new HuffmanElement(0xa5, 0xffca, 16),
                new HuffmanElement(0xa6, 0xffcb, 16),
                new HuffmanElement(0xa7, 0xffcc, 16),
                new HuffmanElement(0xa8, 0xffcd, 16),
                new HuffmanElement(0xa9, 0xffce, 16),
                new HuffmanElement(0xaa, 0xffcf, 16),
                new HuffmanElement(0xb1, 0x3f9, 10),
                new HuffmanElement(0xb2, 0xffd0, 16),
                new HuffmanElement(0xb3, 0xffd1, 16),
                new HuffmanElement(0xb4, 0xffd2, 16),
                new HuffmanElement(0xb5, 0xffd3, 16),
                new HuffmanElement(0xb6, 0xffd4, 16),
                new HuffmanElement(0xb7, 0xffd5, 16),
                new HuffmanElement(0xb8, 0xffd6, 16),
                new HuffmanElement(0xb9, 0xffd7, 16),
                new HuffmanElement(0xba, 0xffd8, 16),
                new HuffmanElement(0xc1, 0x3fa, 10),
                new HuffmanElement(0xc2, 0xffd9, 16),
                new HuffmanElement(0xc3, 0xffda, 16),
                new HuffmanElement(0xc4, 0xffdb, 16),
                new HuffmanElement(0xc5, 0xffdc, 16),
                new HuffmanElement(0xc6, 0xffdd, 16),
                new HuffmanElement(0xc7, 0xffde, 16),
                new HuffmanElement(0xc8, 0xffdf, 16),
                new HuffmanElement(0xc9, 0xffe0, 16),
                new HuffmanElement(0xca, 0xffe1, 16),
                new HuffmanElement(0xd1, 0x7f8, 11),
                new HuffmanElement(0xd2, 0xffe2, 16),
                new HuffmanElement(0xd3, 0xffe3, 16),
                new HuffmanElement(0xd4, 0xffe4, 16),
                new HuffmanElement(0xd5, 0xffe5, 16),
                new HuffmanElement(0xd6, 0xffe6, 16),
                new HuffmanElement(0xd7, 0xffe7, 16),
                new HuffmanElement(0xd8, 0xffe8, 16),
                new HuffmanElement(0xd9, 0xffe9, 16),
                new HuffmanElement(0xda, 0xffea, 16),
                new HuffmanElement(0xe1, 0xffeb, 16),
                new HuffmanElement(0xe2, 0xffec, 16),
                new HuffmanElement(0xe3, 0xffed, 16),
                new HuffmanElement(0xe4, 0xffee, 16),
                new HuffmanElement(0xe5, 0xffef, 16),
                new HuffmanElement(0xe6, 0xfff0, 16),
                new HuffmanElement(0xe7, 0xfff1, 16),
                new HuffmanElement(0xe8, 0xfff2, 16),
                new HuffmanElement(0xe9, 0xfff3, 16),
                new HuffmanElement(0xea, 0xfff4, 16),
                new HuffmanElement(0xf0, 0x7f9, 11),
                new HuffmanElement(0xf1, 0xfff5, 16),
                new HuffmanElement(0xf2, 0xfff6, 16),
                new HuffmanElement(0xf3, 0xfff7, 16),
                new HuffmanElement(0xf4, 0xfff8, 16),
                new HuffmanElement(0xf5, 0xfff9, 16),
                new HuffmanElement(0xf6, 0xfffa, 16),
                new HuffmanElement(0xf7, 0xfffb, 16),
                new HuffmanElement(0xf8, 0xfffc, 16),
                new HuffmanElement(0xf9, 0xfffd, 16),
                new HuffmanElement(0xfa, 0xfffe, 16)
            #endregion
            );
            int inputDCIndex = 0;

            po.Invoke("HuffmanEncode", new object[] {bl, inputBlock, inputHuffDC, inputHuffAC, inputDCIndex});

            BitList expectedBitList = new BitList();
            expectedBitList.Add(false);

            //Assert.AreEqual(expectedBitList.Count, bl.Count);
            Assert.Pass();
        }
Exemplo n.º 54
0
        const int BUFFER_SIZE = 4 << 23; //32 MegaBytes

        #endregion Fields

        #region Methods

        public static Bitmap LoadJpeg(string aFilename)
        {
            JPEGCompression compression = new JPEGCompression();
            byte[] pJpegData = File.ReadAllBytes(aFilename);
            int nInputLength = pJpegData.Length;

            // Check if this is a valid JPEG file
            int nPos = 0;
            int nMarker = nextMarker(pJpegData, ref nPos, nInputLength);

            if (nMarker != 0x0D8)
            {
                throw new ArgumentException(aFilename + " is not a JPEG file.");
            }

            nMarker = nextMarker(pJpegData, ref nPos, nInputLength);

            // Parsing and Huffman Decoding (on host)
            FrameHeader oFrameHeader = new FrameHeader();

            oFrameHeader.aComponentIdentifier = new byte[3];
            oFrameHeader.aSamplingFactors = new byte[3];
            oFrameHeader.aQuantizationTableSelector = new byte[3];

            QuantizationTable[] aQuantizationTables = new QuantizationTable[4];
            aQuantizationTables[0] = new QuantizationTable();
            aQuantizationTables[1] = new QuantizationTable();
            aQuantizationTables[2] = new QuantizationTable();
            aQuantizationTables[3] = new QuantizationTable();

            CudaDeviceVariable<byte>[] pdQuantizationTables = new CudaDeviceVariable<byte>[4];
            pdQuantizationTables[0] = new CudaDeviceVariable<byte>(64);
            pdQuantizationTables[1] = new CudaDeviceVariable<byte>(64);
            pdQuantizationTables[2] = new CudaDeviceVariable<byte>(64);
            pdQuantizationTables[3] = new CudaDeviceVariable<byte>(64);

            HuffmanTable[] aHuffmanTables = new HuffmanTable[4];
            aHuffmanTables[0] = new HuffmanTable();
            aHuffmanTables[1] = new HuffmanTable();
            aHuffmanTables[2] = new HuffmanTable();
            aHuffmanTables[3] = new HuffmanTable();

            ScanHeader oScanHeader = new ScanHeader();
            oScanHeader.aComponentSelector = new byte[3];
            oScanHeader.aHuffmanTablesSelector = new byte[3];

            int nMCUBlocksH = 0;
            int nMCUBlocksV = 0;

            int nRestartInterval = -1;

            NppiSize[] aSrcSize = new NppiSize[3];

            short[][] aphDCT = new short[3][];
            NPPImage_16sC1[] apdDCT = new NPPImage_16sC1[3];
            int[] aDCTStep = new int[3];

            NPPImage_8uC1[] apSrcImage = new NPPImage_8uC1[3];
            int[] aSrcImageStep = new int[3];

            NPPImage_8uC1[] apDstImage = new NPPImage_8uC1[3];
            int[] aDstImageStep = new int[3];
            NppiSize[] aDstSize = new NppiSize[3];

            //Same read routine as in NPP JPEG sample from Nvidia
            while (nMarker != -1)
            {
                if (nMarker == 0x0D8)
                {
                    // Embeded Thumbnail, skip it
                    int nNextMarker = nextMarker(pJpegData, ref nPos, nInputLength);

                    while (nNextMarker != -1 && nNextMarker != 0x0D9)
                    {
                        nNextMarker = nextMarker(pJpegData, ref nPos, nInputLength);
                    }
                }

                if (nMarker == 0x0DD)
                {
                    readRestartInterval(pJpegData, ref nPos, ref nRestartInterval);
                }

                if ((nMarker == 0x0C0) | (nMarker == 0x0C2))
                {
                    //Assert Baseline for this Sample
                    //Note: NPP does support progressive jpegs for both encode and decode
                    if (nMarker != 0x0C0)
                    {
                        pdQuantizationTables[0].Dispose();
                        pdQuantizationTables[1].Dispose();
                        pdQuantizationTables[2].Dispose();
                        pdQuantizationTables[3].Dispose();

                        throw new ArgumentException(aFilename + " is not a Baseline-JPEG file.");
                    }

                    // Baseline or Progressive Frame Header
                    readFrameHeader(pJpegData, ref nPos, ref oFrameHeader);
                    //Console.WriteLine("Image Size: " + oFrameHeader.nWidth + "x" + oFrameHeader.nHeight + "x" + (int)(oFrameHeader.nComponents));

                    //Assert 3-Channel Image for this Sample
                    if (oFrameHeader.nComponents != 3)
                    {
                        pdQuantizationTables[0].Dispose();
                        pdQuantizationTables[1].Dispose();
                        pdQuantizationTables[2].Dispose();
                        pdQuantizationTables[3].Dispose();

                        throw new ArgumentException(aFilename + " is not a three channel JPEG file.");
                    }

                    // Compute channel sizes as stored in the JPEG (8x8 blocks & MCU block layout)
                    for (int i = 0; i < oFrameHeader.nComponents; ++i)
                    {
                        nMCUBlocksV = Math.Max(nMCUBlocksV, oFrameHeader.aSamplingFactors[i] >> 4);
                        nMCUBlocksH = Math.Max(nMCUBlocksH, oFrameHeader.aSamplingFactors[i] & 0x0f);
                    }

                    for (int i = 0; i < oFrameHeader.nComponents; ++i)
                    {
                        NppiSize oBlocks = new NppiSize();
                        NppiSize oBlocksPerMCU = new NppiSize(oFrameHeader.aSamplingFactors[i] & 0x0f, oFrameHeader.aSamplingFactors[i] >> 4);

                        oBlocks.width = (int)Math.Ceiling((oFrameHeader.nWidth + 7) / 8 *
                                                  (float)(oBlocksPerMCU.width) / nMCUBlocksH);
                        oBlocks.width = DivUp(oBlocks.width, oBlocksPerMCU.width) * oBlocksPerMCU.width;

                        oBlocks.height = (int)Math.Ceiling((oFrameHeader.nHeight + 7) / 8 *
                                                   (float)(oBlocksPerMCU.height) / nMCUBlocksV);
                        oBlocks.height = DivUp(oBlocks.height, oBlocksPerMCU.height) * oBlocksPerMCU.height;

                        aSrcSize[i].width = oBlocks.width * 8;
                        aSrcSize[i].height = oBlocks.height * 8;

                        // Allocate Memory
                        apdDCT[i] = new NPPImage_16sC1(oBlocks.width * 64, oBlocks.height);
                        aDCTStep[i] = apdDCT[i].Pitch;

                        apSrcImage[i] = new NPPImage_8uC1(aSrcSize[i].width, aSrcSize[i].height);
                        aSrcImageStep[i] = apSrcImage[i].Pitch;

                        aphDCT[i] = new short[aDCTStep[i] * oBlocks.height];
                    }
                }

                if (nMarker == 0x0DB)
                {
                    // Quantization Tables
                    readQuantizationTables(pJpegData, ref nPos, aQuantizationTables);
                }

                if (nMarker == 0x0C4)
                {
                    // Huffman Tables
                    readHuffmanTables(pJpegData, ref nPos, aHuffmanTables);
                }

                if (nMarker == 0x0DA)
                {
                    // Scan
                    readScanHeader(pJpegData, ref nPos, ref oScanHeader);
                    nPos += 6 + oScanHeader.nComponents * 2;

                    int nAfterNextMarkerPos = nPos;
                    int nAfterScanMarker = nextMarker(pJpegData, ref nAfterNextMarkerPos, nInputLength);

                    if (nRestartInterval > 0)
                    {
                        while (nAfterScanMarker >= 0x0D0 && nAfterScanMarker <= 0x0D7)
                        {
                            // This is a restart marker, go on
                            nAfterScanMarker = nextMarker(pJpegData, ref nAfterNextMarkerPos, nInputLength);
                        }
                    }

                    NppiDecodeHuffmanSpec[] apHuffmanDCTableDec = new NppiDecodeHuffmanSpec[3];
                    NppiDecodeHuffmanSpec[] apHuffmanACTableDec = new NppiDecodeHuffmanSpec[3];

                    for (int i = 0; i < 3; ++i)
                    {
                        apHuffmanDCTableDec[i] = JPEGCompression.DecodeHuffmanSpecInitAllocHost(aHuffmanTables[(oScanHeader.aHuffmanTablesSelector[i] >> 4)].aCodes, NppiHuffmanTableType.nppiDCTable);
                        apHuffmanACTableDec[i] = JPEGCompression.DecodeHuffmanSpecInitAllocHost(aHuffmanTables[(oScanHeader.aHuffmanTablesSelector[i] & 0x0f) + 2].aCodes, NppiHuffmanTableType.nppiACTable);
                    }

                    byte[] img = new byte[nAfterNextMarkerPos - nPos - 2];
                    Buffer.BlockCopy(pJpegData, nPos, img, 0, nAfterNextMarkerPos - nPos - 2);

                    JPEGCompression.DecodeHuffmanScanHost(img, nRestartInterval, oScanHeader.nSs, oScanHeader.nSe, oScanHeader.nA >> 4, oScanHeader.nA & 0x0f, aphDCT[0], aphDCT[1], aphDCT[2], aDCTStep, apHuffmanDCTableDec, apHuffmanACTableDec, aSrcSize);

                    for (int i = 0; i < 3; ++i)
                    {
                        JPEGCompression.DecodeHuffmanSpecFreeHost(apHuffmanDCTableDec[i]);
                        JPEGCompression.DecodeHuffmanSpecFreeHost(apHuffmanACTableDec[i]);
                    }
                }

                nMarker = nextMarker(pJpegData, ref nPos, nInputLength);
            }

            // Copy DCT coefficients and Quantization Tables from host to device
            for (int i = 0; i < 4; ++i)
            {
                pdQuantizationTables[i].CopyToDevice(aQuantizationTables[i].aTable);
            }

            for (int i = 0; i < 3; ++i)
            {
                apdDCT[i].CopyToDevice(aphDCT[i], aDCTStep[i]);
            }

            // Inverse DCT
            for (int i = 0; i < 3; ++i)
            {
                compression.DCTQuantInv8x8LS(apdDCT[i], apSrcImage[i], aSrcSize[i], pdQuantizationTables[oFrameHeader.aQuantizationTableSelector[i]]);
            }

            //Alloc final image
            NPPImage_8uC3 res = new NPPImage_8uC3(apSrcImage[0].Width, apSrcImage[0].Height);

            //Copy Y color plane to first channel
            apSrcImage[0].Copy(res, 0);

            //Cb anc Cr channel might be smaller
            if ((oFrameHeader.aSamplingFactors[0] & 0x0f) == 1 && oFrameHeader.aSamplingFactors[0] >> 4 == 1)
            {
                //Color planes are of same size as Y channel
                apSrcImage[1].Copy(res, 1);
                apSrcImage[2].Copy(res, 2);
            }
            else
            {
                //rescale color planes to full size
                double scaleX = oFrameHeader.aSamplingFactors[0] & 0x0f;
                double scaleY = oFrameHeader.aSamplingFactors[0] >> 4;

                apSrcImage[1].ResizeSqrPixel(apSrcImage[0], scaleX, scaleY, 0, 0, InterpolationMode.Lanczos);
                apSrcImage[0].Copy(res, 1);
                apSrcImage[2].ResizeSqrPixel(apSrcImage[0], scaleX, scaleY, 0, 0, InterpolationMode.Lanczos);
                apSrcImage[0].Copy(res, 2);
            }

            //System.Drawing.Bitmap is ordered BGR not RGB
            //The NPP routine YCbCR to BGR needs clampled input values, following the YCbCr standard.
            //But JPEG uses unclamped values ranging all from [0..255], thus use our own color matrix:
            float[,] YCbCrToBgr = new float[3, 4]
            {{1.0f, 1.772f,     0.0f,    -226.816f  },
             {1.0f, -0.34414f, -0.71414f, 135.45984f},
             {1.0f, 0.0f,       1.402f,  -179.456f  }};

            //Convert from YCbCr to BGR
            res.ColorTwist(YCbCrToBgr);

            Bitmap bmp = new Bitmap(apSrcImage[0].Width, apSrcImage[0].Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            res.CopyToHost(bmp);

            //Cleanup:
            res.Dispose();
            apSrcImage[2].Dispose();
            apSrcImage[1].Dispose();
            apSrcImage[0].Dispose();

            apdDCT[2].Dispose();
            apdDCT[1].Dispose();
            apdDCT[0].Dispose();

            pdQuantizationTables[0].Dispose();
            pdQuantizationTables[1].Dispose();
            pdQuantizationTables[2].Dispose();
            pdQuantizationTables[3].Dispose();

            compression.Dispose();

            return bmp;
        }
Exemplo n.º 55
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="coverImage"></param>
        /// <param name="quality"></param>
        /// <param name="m"></param>
        /// <param name="yTable"></param>
        /// <param name="chrTable"></param>
        /// <param name="huffmanYDC"></param>
        /// <param name="huffmanYAC"></param>
        /// <param name="huffmanChrDC"></param>
        /// <param name="huffmanChrAC"></param>
        public JpegImage(Bitmap coverImage, int quality, byte m, QuantizationTable yTable, QuantizationTable chrTable, HuffmanTable huffmanYDC, HuffmanTable huffmanYAC, HuffmanTable huffmanChrDC, HuffmanTable huffmanChrAC) {
            if (coverImage == null) {
                throw new ArgumentNullException();
            }

            CoverImage = coverImage;
            YQuantizationTable = yTable.Scale(quality);
            ChrQuantizationTable = chrTable.Scale(quality);
            M = m;
            YDCHuffman = huffmanYDC;
            YACHuffman = huffmanYAC;
            ChrDCHuffman = huffmanChrDC;
            ChrACHuffman = huffmanChrAC;
            _originalCoverWidth = coverImage.Width;
            _originalCoverHeight = coverImage.Height;

            // Calculate coefficients that are used in DCT
            _calculateCosineCoefficients();
        }
Exemplo n.º 56
0
        private void _saveSettingsInternally() {
            Quality = tbarQualitySlider.Value;

            if (_mValue != 0) {
                MValue = _mValue;
            } else {
                MValue = 4;
            }

            if (rdioGTMethod.Checked) {
                LSBMethodSelected = false;
            } else {
                LSBMethodSelected = true;
            }

            HuffmanTableYAC = _defaultOrCustomHuffmanTable(HuffmanTableComponentYAC.SaveTable(), HuffmanTable.JpegHuffmanTableYAC);
            HuffmanTableYDC = _defaultOrCustomHuffmanTable(HuffmanTableComponentYDC.SaveTable(), HuffmanTable.JpegHuffmanTableYDC);
            HuffmanTableChrAC = _defaultOrCustomHuffmanTable(HuffmanTableComponentChrAC.SaveTable(), HuffmanTable.JpegHuffmanTableChrAC);
            HuffmanTableChrDC = _defaultOrCustomHuffmanTable(HuffmanTableComponentChrDC.SaveTable(), HuffmanTable.JpegHuffmanTableChrDC);
            QuantizationTableY = _defaultOrCustomQuantizationTable(QuantizationTableComponentY.SaveTable(), QuantizationTable.JpegDefaultYTable);
            QuantizationTableChr = _defaultOrCustomQuantizationTable(QuantizationTableComponentChr.SaveTable(), QuantizationTable.JpegDefaultChrTable);
        }
Exemplo n.º 57
0
        public void HasCodeTest_for_null_when_no_element_has_code()
        {
            byte runSizeInput1 = 00000000;
            ushort codeWordInput1 = 2; // 10 in base 2
            byte lengthInput1 = 8; // 1000 in base 2

            byte runSizeInput2 = 1;
            ushort codeWordInput2 = 3; // 11 in base 2
            byte lengthInput2 = 8; // 1000 in base 2

            HuffmanElement huffmanTestElement1 = new HuffmanElement(runSizeInput1, codeWordInput1, lengthInput1);
            HuffmanElement huffmanTestElement2 = new HuffmanElement(runSizeInput2, codeWordInput2, lengthInput2);

            HuffmanTable huffTable1 = new HuffmanTable(huffmanTestElement1, huffmanTestElement2);

            Assert.AreEqual(null, huffTable1.HasCode(1, 8));
        }
Exemplo n.º 58
0
        public static void ResetSettingsToDefault() {
            Quality = DefaultQuality;
            MValue = DefaultMValue;
            QualityLocked = false;
            LSBMethodSelected = false;

            HuffmanTableYAC = HuffmanTable.JpegHuffmanTableYAC;
            HuffmanTableYDC = HuffmanTable.JpegHuffmanTableYDC;
            HuffmanTableChrAC = HuffmanTable.JpegHuffmanTableChrAC;
            HuffmanTableChrDC = HuffmanTable.JpegHuffmanTableChrDC;
            QuantizationTableY = QuantizationTable.JpegDefaultYTable;
            QuantizationTableChr = QuantizationTable.JpegDefaultChrTable;
        }
Exemplo n.º 59
0
 private static void _saveHuffmanTableToFile(HuffmanTable huffmanTable, string filePath) {
     if (huffmanTable != null) {
         File.WriteAllText(filePath, huffmanTable.ToString());
     }
 }
Exemplo n.º 60
0
        public static void SaveJpeg(string aFilename, int aQuality, Bitmap aImage)
        {
            if (aImage.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
            {
                throw new ArgumentException("Only three channel color images are supported.");
            }

            if (aImage.Width % 16 != 0 || aImage.Height % 16 != 0)
            {
                throw new ArgumentException("The provided bitmap must have a height and width of a multiple of 16.");
            }

            JPEGCompression compression = new JPEGCompression();

            NPPImage_8uC3 src = new NPPImage_8uC3(aImage.Width, aImage.Height);
            NPPImage_8uC1 srcY = new NPPImage_8uC1(aImage.Width, aImage.Height);
            NPPImage_8uC1 srcCb = new NPPImage_8uC1(aImage.Width / 2, aImage.Height / 2);
            NPPImage_8uC1 srcCr = new NPPImage_8uC1(aImage.Width / 2, aImage.Height / 2);
            src.CopyToDevice(aImage);

            //System.Drawing.Bitmap is ordered BGR not RGB
            //The NPP routine BGR to YCbCR outputs the values in clamped range, following the YCbCr standard.
            //But JPEG uses unclamped values ranging all from [0..255], thus use our own color matrix:
            float[,] BgrToYCbCr = new float[3, 4]
            {{0.114f,     0.587f,    0.299f,   0},
             {0.5f,      -0.33126f, -0.16874f, 128},
             {-0.08131f, -0.41869f,  0.5f,     128}};

            src.ColorTwist(BgrToYCbCr);

            //Reduce size of of Cb and Cr channel
            src.Copy(srcY, 2);
            srcY.Resize(srcCr, 0.5, 0.5, InterpolationMode.SuperSampling);
            src.Copy(srcY, 1);
            srcY.Resize(srcCb, 0.5, 0.5, InterpolationMode.SuperSampling);
            src.Copy(srcY, 0);

            FrameHeader oFrameHeader = new FrameHeader();
            oFrameHeader.nComponents = 3;
            oFrameHeader.nHeight = (ushort)aImage.Height;
            oFrameHeader.nSamplePrecision = 8;
            oFrameHeader.nWidth = (ushort)aImage.Width;
            oFrameHeader.aComponentIdentifier = new byte[] { 1, 2, 3 };
            oFrameHeader.aSamplingFactors = new byte[] { 34, 17, 17 }; //Y channel is twice the sice of Cb/Cr channel
            oFrameHeader.aQuantizationTableSelector = new byte[] { 0, 1, 1 };

            //Get quantization tables from JPEG standard with quality scaling
            QuantizationTable[] aQuantizationTables = new QuantizationTable[2];
            aQuantizationTables[0] = new QuantizationTable(QuantizationTable.QuantizationType.Luminance, aQuality);
            aQuantizationTables[1] = new QuantizationTable(QuantizationTable.QuantizationType.Chroma, aQuality);

            CudaDeviceVariable<byte>[] pdQuantizationTables = new CudaDeviceVariable<byte>[2];
            pdQuantizationTables[0] = aQuantizationTables[0].aTable;
            pdQuantizationTables[1] = aQuantizationTables[1].aTable;

            //Get Huffman tables from JPEG standard
            HuffmanTable[] aHuffmanTables = new HuffmanTable[4];
            aHuffmanTables[0] = new HuffmanTable(HuffmanTable.HuffmanType.LuminanceDC);
            aHuffmanTables[1] = new HuffmanTable(HuffmanTable.HuffmanType.ChromaDC);
            aHuffmanTables[2] = new HuffmanTable(HuffmanTable.HuffmanType.LuminanceAC);
            aHuffmanTables[3] = new HuffmanTable(HuffmanTable.HuffmanType.ChromaAC);

            //Set header
            ScanHeader oScanHeader = new ScanHeader();
            oScanHeader.nA = 0;
            oScanHeader.nComponents = 3;
            oScanHeader.nSe = 63;
            oScanHeader.nSs = 0;
            oScanHeader.aComponentSelector = new byte[] { 1, 2, 3 };
            oScanHeader.aHuffmanTablesSelector = new byte[] { 0, 17, 17 };

            NPPImage_16sC1[] apdDCT = new NPPImage_16sC1[3];

            NPPImage_8uC1[] apDstImage = new NPPImage_8uC1[3];
            NppiSize[] aDstSize = new NppiSize[3];
            aDstSize[0] = new NppiSize(srcY.Width, srcY.Height);
            aDstSize[1] = new NppiSize(srcCb.Width, srcCb.Height);
            aDstSize[2] = new NppiSize(srcCr.Width, srcCr.Height);

            // Compute channel sizes as stored in the output JPEG (8x8 blocks & MCU block layout)
            NppiSize oDstImageSize = new NppiSize();
            float frameWidth = (float)Math.Floor((float)oFrameHeader.nWidth);
            float frameHeight = (float)Math.Floor((float)oFrameHeader.nHeight);

            oDstImageSize.width = (int)Math.Max(1.0f, frameWidth);
            oDstImageSize.height = (int)Math.Max(1.0f, frameHeight);

            //Console.WriteLine("Output Size: " + oDstImageSize.width + "x" + oDstImageSize.height + "x" + (int)(oFrameHeader.nComponents));

            apDstImage[0] = srcY;
            apDstImage[1] = srcCb;
            apDstImage[2] = srcCr;

            int nMCUBlocksH = 0;
            int nMCUBlocksV = 0;

            // Compute channel sizes as stored in the JPEG (8x8 blocks & MCU block layout)
            for (int i = 0; i < oFrameHeader.nComponents; ++i)
            {
                nMCUBlocksV = Math.Max(nMCUBlocksV, oFrameHeader.aSamplingFactors[i] >> 4);
                nMCUBlocksH = Math.Max(nMCUBlocksH, oFrameHeader.aSamplingFactors[i] & 0x0f);
            }

            for (int i = 0; i < oFrameHeader.nComponents; ++i)
            {
                NppiSize oBlocks = new NppiSize();
                NppiSize oBlocksPerMCU = new NppiSize(oFrameHeader.aSamplingFactors[i] & 0x0f, oFrameHeader.aSamplingFactors[i] >> 4);

                oBlocks.width = (int)Math.Ceiling((oFrameHeader.nWidth + 7) / 8 *
                                          (float)(oBlocksPerMCU.width) / nMCUBlocksH);
                oBlocks.width = DivUp(oBlocks.width, oBlocksPerMCU.width) * oBlocksPerMCU.width;

                oBlocks.height = (int)Math.Ceiling((oFrameHeader.nHeight + 7) / 8 *
                                           (float)(oBlocksPerMCU.height) / nMCUBlocksV);
                oBlocks.height = DivUp(oBlocks.height, oBlocksPerMCU.height) * oBlocksPerMCU.height;

                // Allocate Memory
                apdDCT[i] = new NPPImage_16sC1(oBlocks.width * 64, oBlocks.height);

            }

            /***************************
            *
            *   Output
            *
            ***************************/

            // Forward DCT
            for (int i = 0; i < 3; ++i)
            {
                compression.DCTQuantFwd8x8LS(apDstImage[i], apdDCT[i], aDstSize[i], pdQuantizationTables[oFrameHeader.aQuantizationTableSelector[i]]);
            }

            // Huffman Encoding
            CudaDeviceVariable<byte> pdScan = new CudaDeviceVariable<byte>(BUFFER_SIZE);
            int nScanLength = 0;

            int nTempSize = JPEGCompression.EncodeHuffmanGetSize(aDstSize[0], 3);
            CudaDeviceVariable<byte> pJpegEncoderTemp = new CudaDeviceVariable<byte>(nTempSize);

            NppiEncodeHuffmanSpec[] apHuffmanDCTableEnc = new NppiEncodeHuffmanSpec[3];
            NppiEncodeHuffmanSpec[] apHuffmanACTableEnc = new NppiEncodeHuffmanSpec[3];

            for (int i = 0; i < 3; ++i)
            {
                apHuffmanDCTableEnc[i] = JPEGCompression.EncodeHuffmanSpecInitAlloc(aHuffmanTables[(oScanHeader.aHuffmanTablesSelector[i] >> 4)].aCodes, NppiHuffmanTableType.nppiDCTable);
                apHuffmanACTableEnc[i] = JPEGCompression.EncodeHuffmanSpecInitAlloc(aHuffmanTables[(oScanHeader.aHuffmanTablesSelector[i] & 0x0f) + 2].aCodes, NppiHuffmanTableType.nppiACTable);
            }

            JPEGCompression.EncodeHuffmanScan(apdDCT, 0, oScanHeader.nSs, oScanHeader.nSe, oScanHeader.nA >> 4, oScanHeader.nA & 0x0f, pdScan, ref nScanLength, apHuffmanDCTableEnc, apHuffmanACTableEnc, aDstSize, pJpegEncoderTemp);

            for (int i = 0; i < 3; ++i)
            {
                JPEGCompression.EncodeHuffmanSpecFree(apHuffmanDCTableEnc[i]);
                JPEGCompression.EncodeHuffmanSpecFree(apHuffmanACTableEnc[i]);
            }

            // Write JPEG to byte array, as in original sample code
            byte[] pDstOutput = new byte[BUFFER_SIZE];
            int pos = 0;

            oFrameHeader.nWidth = (ushort)oDstImageSize.width;
            oFrameHeader.nHeight = (ushort)oDstImageSize.height;

            writeMarker(0x0D8, pDstOutput, ref pos);
            writeJFIFTag(pDstOutput, ref pos);
            writeQuantizationTable(aQuantizationTables[0], pDstOutput, ref pos);
            writeQuantizationTable(aQuantizationTables[1], pDstOutput, ref pos);
            writeFrameHeader(oFrameHeader, pDstOutput, ref pos);
            writeHuffmanTable(aHuffmanTables[0], pDstOutput, ref pos);
            writeHuffmanTable(aHuffmanTables[1], pDstOutput, ref pos);
            writeHuffmanTable(aHuffmanTables[2], pDstOutput, ref pos);
            writeHuffmanTable(aHuffmanTables[3], pDstOutput, ref pos);
            writeScanHeader(oScanHeader, pDstOutput, ref pos);

            pdScan.CopyToHost(pDstOutput, 0, pos, nScanLength);

            pos += nScanLength;
            writeMarker(0x0D9, pDstOutput, ref pos);

            FileStream fs = new FileStream(aFilename, FileMode.Create, FileAccess.Write);
            fs.Write(pDstOutput, 0, pos);
            fs.Close();

            //cleanup:
            fs.Dispose();
            pJpegEncoderTemp.Dispose();
            pdScan.Dispose();
            apdDCT[2].Dispose();
            apdDCT[1].Dispose();
            apdDCT[0].Dispose();
            pdQuantizationTables[1].Dispose();
            pdQuantizationTables[0].Dispose();

            srcCr.Dispose();
            srcCb.Dispose();
            srcY.Dispose();
            src.Dispose();
            compression.Dispose();
        }