예제 #1
0
파일: I4cDelta.cs 프로젝트: rstarkov/i4c
        public override void Encode(IntField image, Stream output)
        {
            // Predictive transform
            image.ArgbTo4c();
            image.PredictionEnTransformXor(Seer);

            // Convert to three fields' runlengths
            var fields = CodecUtil.FieldcodeRunlengthsEn2(image, RLE, this);

            SetCounter("rle|longer", (RLE as RunLength01LongShortCodec).Counter_Longers);
            SetCounter("rle|muchlonger", (RLE as RunLength01LongShortCodec).Counter_MuchLongers);

            // Write size
            DeltaTracker pos = new DeltaTracker();

            output.WriteUInt32Optim((uint)image.Width);
            output.WriteUInt32Optim((uint)image.Height);
            SetCounter("bytes|size", pos.Next(output.Position));

            // Write probs
            ulong[] probs = CodecUtil.CountValues(fields, RLE.MaxSymbol);
            CodecUtil.SaveFreqs(output, probs, TimwiCecCompressor.runLProbsProbs, "");
            SetCounter("bytes|probs", pos.Next(output.Position));

            // Write fields
            ArithmeticWriter aw = new ArithmeticWriter(output, probs);

            output.WriteUInt32Optim((uint)fields.Length);
            foreach (var sym in fields)
            {
                aw.WriteSymbol(sym);
            }
            aw.Flush();
            SetCounter("bytes|fields", pos.Next(output.Position));
        }
예제 #2
0
파일: CodecTests.cs 프로젝트: rstarkov/i4c
        public static void TestData(int[] data, int symMax, int symDataMax, int rlStages, params int[] symRle)
        {
            //int[] trip;

            //RunLengthCodec enc = new RunLengthCodec(symMax, symDataMax, rlStages, symRle);
            //RunLengthCodec dec = new RunLengthCodec(symMax, symDataMax, rlStages, symRle);
            //trip = dec.Decode(enc.Encode(data));
            //Assert.IsTrue(data.SequenceEqual(trip));

            //ulong[] probs = CodecUtil.CountValues(data);
            //ArithmeticCodec enca = new ArithmeticCodec(probs);
            //ArithmeticCodec deca = new ArithmeticCodec(probs);
            //trip = deca.Decode(enca.Encode(data));
            //Assert.IsTrue(data.SequenceEqual(trip));

            if (symDataMax == 1)
            {
                //RunLength01Codec encz = new RunLength01Codec();
                //RunLength01Codec decz = new RunLength01Codec();
                //trip = decz.Decode(encz.Encode(data));
                //Assert.IsTrue(data.SequenceEqual(trip));

                //RunLength01MaxCodec enczm = new RunLength01MaxCodec(15);
                //RunLength01MaxCodec deczm = new RunLength01MaxCodec(15);
                //trip = deczm.Decode(enczm.Encode(data));
                //Assert.IsTrue(data.SequenceEqual(trip));

                //RunLength01MaxSmartCodec enczs = new RunLength01MaxSmartCodec(15);
                //RunLength01MaxSmartCodec deczs = new RunLength01MaxSmartCodec(15);
                //trip = deczs.Decode(enczs.Encode(data));
                //Assert.IsTrue(data.SequenceEqual(trip));
            }

            {
                ulong[]      input = data.Select(val => (ulong)val).ToArray();
                MemoryStream ms    = new MemoryStream();
                CodecUtil.SaveFreqs(ms, input, TimwiCecCompressor.runLProbsProbs, "");
                ms.Position = 0;
                ulong[] freqs = CodecUtil.LoadFreqs(ms, TimwiCecCompressor.runLProbsProbs, data.Length);
                Assert.IsTrue(input.SequenceEqual(freqs));
            }
        }
예제 #3
0
파일: TimwiCec.cs 프로젝트: rstarkov/i4c
        public override void Encode(IntField image, Stream output)
        {
            int blocksX = (image.Width + _blocksizeX - 1) / _blocksizeX;
            int blocksY = (image.Height + _blocksizeY - 1) / _blocksizeY;
            int blocks  = blocksX * blocksY;

            int[]   kinds     = new int[blocks];
            ulong[] blockHigh = new ulong[blocks];
            ulong[] blockLow  = new ulong[blocks];
            var     pixels    = image.Data.Select(p => (uint)p).ToArray();

            for (int i = 0; i < pixels.Length; i++)
            {
                int  x = i % image.Width;
                uint p = pixels[i];

                if (p != 0)
                {
                    int blockIndex = ((i / image.Width) / _blocksizeY) * blocksX + x / _blocksizeX;
                    kinds[blockIndex] |= 1 << (int)(p - 1);
                    int indexInBlock = ((i / image.Width) % _blocksizeY) * _blocksizeX + x % _blocksizeX;
                    if (indexInBlock < 32)
                    {
                        blockLow[blockIndex] |= (ulong)p << (2 * indexInBlock);
                    }
                    else
                    {
                        blockHigh[blockIndex] |= (ulong)p << (2 * (indexInBlock - 32));
                    }
                }
            }

            // Start writing to the file
            long pos = 0;

            output.WriteUInt32Optim((uint)image.Width);
            output.WriteUInt32Optim((uint)image.Height);

            SetCounter("bytes|size", output.Position - pos);
            pos = output.Position;

            // Some slight optimisations
            for (int i = 0; i < blocks; i++)
            {
                var k = kinds[i];

                // If a kind-5 block is sandwiched between two kind-7s, it is worth setting to 7 to improve the run-length encoding
                if (k == 5 && i > 0 && i < blocks - 1 && kinds[i - 1] == 7 && kinds[i + 1] == 7)
                {
                    k = kinds[i] = 7;
                }

                // Kinds 3 and 6 are the rarest. It is more common for a block to have its top or bottom half all black.
                // Therefore, redefine 3 and 6 to mean top and bottom half all black.
                // A block that has kind 5 should also be changed to 3 or 6 if it has one half all black, because
                // having kind 5 reduces the block's entropy by 1/3, but having one half all black by 1/2.
                if (k == 3 || k > 4)
                {
                    kinds[i] = blockLow[i] == 0 ? 3 : blockHigh[i] == 0 ? 6 : k == 5 ? 5 : 7;
                }
            }

            // Encode the kinds as three planes of optim-encoded run lengths
            long pos2         = 0;
            var  ms           = new MemoryStream();
            bool curRunData   = false;
            uint curRunLength = 0;

            for (int c = 0; c < 3; c++)
            {
                for (int i = 0; i < blocks; i++)
                {
                    if (curRunData ^ ((kinds[i] & (1 << c)) != 0))
                    {
                        ms.WriteUInt32Optim(curRunLength);
                        curRunData   = !curRunData;
                        curRunLength = 1;
                    }
                    else
                    {
                        curRunLength++;
                    }
                }
                SetCounter("kinds-raw|" + c, ms.Position - pos2);
                pos2 = ms.Position;
            }
            ms.WriteUInt32Optim(curRunLength);
            ms.Close();
            var kindsArr = ms.ToArray();

            SetCounter("kinds-raw|error", kindsArr.Length - pos2);

            // Save the frequencies of each byte in the Optim-encoded run lengths
            ulong[] kFreq = new ulong[256];
            for (int i = 0; i < kindsArr.Length; i++)
            {
                kFreq[kindsArr[i]]++;
            }
            CodecUtil.SaveFreqs(output, kFreq, kindProbsProbs, "kindProbsProbs");

            SetCounter("bytes|kinds|probs", output.Position - pos);
            pos = output.Position;

            // Save the run lengths themselves
            MemoryStream kMaster = new MemoryStream();
            var          kAcw    = new ArithmeticCodingWriter(kMaster, kFreq);

            foreach (var symb in kindsArr)
            {
                kAcw.WriteSymbol(symb);
            }
            kAcw.Close(false);
            var kArr = kMaster.ToArray();

            output.WriteUInt32Optim((uint)kindsArr.Length);
            output.WriteUInt32Optim((uint)kArr.Length);
            output.Write(kArr, 0, kArr.Length);
            //Console.WriteLine("krl " + kArr.Length);

            SetCounter("bytes|kinds|data", output.Position - pos);
            pos = output.Position;

            /*
             * Bitmap bXor = PixelsToBitmap(newPixels, bw, bh);
             * bXor.Save(target + "-xor.png");
             * Bitmap bBlocks = KindsToBitmap(kinds, blocksizeX, blocksizeY, bw, bh);
             * Graphics g = Graphics.FromImage(bXor);
             * GraphicsUtil.DrawImageAlpha(g, bBlocks, new Rectangle(0, 0, bw, bh), 0.5f);
             * bXor.Save(target + "-xor-blocks.png");
             * /**/

            // Create the sequence of symbols that represents the run lengths for the actual pixels
            ms = new MemoryStream();

            int   j         = 0;
            ulong curLength = 0;
            var   kind      = kinds[0];

            while (j < 3 * pixels.Length)
            {
                var c = j / pixels.Length;
                var i = j % pixels.Length;
                var x = i % image.Width;
                if (x % _blocksizeX == 0)
                {
                    kind = kinds[((i / image.Width) / _blocksizeY) * blocksX + x / _blocksizeX];
                }
                j++;
                if (kind == 3)
                {
                    if (((i / image.Width) % _blocksizeY) * _blocksizeX + x % _blocksizeX < 32)
                    {
                        continue;
                    }
                    kind = 7;
                }
                else if (kind == 6)
                {
                    if (((i / image.Width) % _blocksizeY) * _blocksizeX + x % _blocksizeX > 31)
                    {
                        continue;
                    }
                    kind = 7;
                }
                else if (((kind % 8) & (1 << c)) == 0)
                {
                    continue;
                }

                if (pixels[i] == c + 1)
                {
                    ms.WriteUInt64Optim(curLength);
                    curLength = 0;
                }
                else if (pixels[i] == 0 || pixels[i] > c + 1)
                {
                    curLength++;
                }
            }
            if (curLength > 0)
            {
                ms.WriteUInt64Optim(curLength);
            }

            ms.Close();
            var runLengthsArr = ms.ToArray();

            // Save the frequencies of each byte in the Optim-encoded run lengths
            ulong[] freq = new ulong[256];
            for (int i = 0; i < runLengthsArr.Length; i++)
            {
                freq[runLengthsArr[i]]++;
            }
            CodecUtil.SaveFreqs(output, freq, runLProbsProbs, "runLProbsProbs");

            SetCounter("bytes|runs|probs", output.Position - pos);
            pos = output.Position;

            // Save the run lengths themselves
            MemoryStream master = new MemoryStream();

            master.WriteUInt32Optim((uint)runLengthsArr.Length);
            var acw = new ArithmeticCodingWriter(master, freq);

            foreach (var symb in runLengthsArr)
            {
                acw.WriteSymbol(symb);
            }
            acw.Close(false);
            var arr = master.ToArray();

            output.Write(arr, 0, arr.Length);
            //Console.WriteLine("rl " + arr.Length);

            SetCounter("bytes|runs|data", output.Position - pos);
            pos = output.Position;

            output.Close();
        }