Exemple #1
0
        protected override void Execute()
        {
            int    samplesPerView = GlobalInfo.SamplesInChart;
            double dt = 1.0 / GlobalInfo.SampleRate;
            double fundmentalFrequency = 0, thd = 0;
            int    index;

            _configForm.GetChannelIndex(out index);
            if (index < 0)
            {
                return;
            }
            int harmonicLevel = _configForm.GetHarmonicLevel();

            if (_harmonicLevel?.Length != harmonicLevel)
            {
                _harmonicLevel = new double[harmonicLevel];
            }
            double[] waveform = DataBuf.GetRange(samplesPerView * index, samplesPerView).ToArray();
            HarmonicAnalyzer.ToneAnalysis(waveform, dt, out fundmentalFrequency, out thd, ref _harmonicLevel,
                                          harmonicLevel);

            DetailValues[0] = thd.ToString();
            DetailValues[1] = fundmentalFrequency.ToString();
        }
Exemple #2
0
        private static DataBuf[] ProcessDiff(DiffBuf[] diff, DataBuf prev)
        {
            var memory = new DataBuf[2 * diff.Length]; // 2592

            for (var x = 0; x < diff.Length; x++)      // 2592
            {
                var y1 = (ushort)(prev.Y + diff[x].Y1);
                var y2 = (ushort)(prev.Y + diff[x].Y1 + diff[x].Y2);
                var cb = (short)(prev.Cb + diff[x].Cb);
                var cr = (short)(prev.Cr + diff[x].Cr);

                prev.Y  = y2;
                prev.Cb = cb;
                prev.Cr = cr;

                memory[2 * x].Y  = y1;
                memory[2 * x].Cb = cb;
                memory[2 * x].Cr = cr;

                memory[2 * x + 1].Y  = y2;
                memory[2 * x + 1].Cb = cb;
                memory[2 * x + 1].Cr = cr;
            }

            return(memory);
        }
Exemple #3
0
        private static DataBuf[] ProcessDiff(DiffBuf[] diff, int samplesPerLine)
        {
            Assert.AreEqual(samplesPerLine / 4, diff.Length);

            var prev = new DataBuf {
                Y = 0x4000, Cb = 0, Cr = 0
            };

            var memory = new DataBuf[samplesPerLine];       // 2592

            for (var x = 0; x < samplesPerLine / 4; x++)    // 2592
            {
                var y1 = (ushort)(prev.Y + diff[x].Y1);
                var y2 = (ushort)(prev.Y + diff[x].Y1 + diff[x].Y2);
                var y3 = (ushort)(prev.Y + diff[x].Y1 + diff[x].Y2 + diff[x].Y3);
                var y4 = (ushort)(prev.Y + diff[x].Y1 + diff[x].Y2 + diff[x].Y3 + diff[x].Y4);
                var cb = (short)(prev.Cb + diff[x].Cb);
                var cr = (short)(prev.Cr + diff[x].Cr);

                prev.Y  = y2;
                prev.Cb = cb;
                prev.Cr = cr;

                memory[4 * x].Y  = y1;
                memory[4 * x].Cb = cb;
                memory[4 * x].Cr = cr;

                memory[4 * x + 1].Y  = y2;
                memory[4 * x + 1].Cb = cb;
                memory[4 * x + 1].Cr = cr;
            }

            return(memory);
        }
Exemple #4
0
        private static DataBuf[] ProcessDiff(DiffBuf[] diff, DataBuf prev)
        {
            var samplesPerLine = diff.Length * 4;
            var memory         = new DataBuf[samplesPerLine]; // 2592

            for (var x = 0; x < samplesPerLine / 4; x++)      // 2592
            {
                var y1 = (ushort)(prev.Y + diff[x].Y1);
                var y2 = (ushort)(prev.Y + diff[x].Y1 + diff[x].Y2);
                var y3 = (ushort)(prev.Y + diff[x].Y1 + diff[x].Y2 + diff[x].Y3);
                var y4 = (ushort)(prev.Y + diff[x].Y1 + diff[x].Y2 + diff[x].Y3 + diff[x].Y4);
                var cb = (short)(prev.Cb + diff[x].Cb);
                var cr = (short)(prev.Cr + diff[x].Cr);

                prev.Y  = y2;
                prev.Cb = cb;
                prev.Cr = cr;

                memory[4 * x].Y  = y1;
                memory[4 * x].Cb = cb;
                memory[4 * x].Cr = cr;

                memory[4 * x + 1].Y  = y2;
                memory[4 * x + 1].Cb = cb;
                memory[4 * x + 1].Cr = cr;
            }

            return(memory);
        }
Exemple #5
0
        private static void PixelSet(Bitmap bitmap, int row, int col, DataBuf val)
        {
            var r     = val.Y + 1.40200 * val.Cr;
            var g     = val.Y - 0.34414 * val.Cb - 0.71414 * val.Cr;
            var b     = val.Y + 1.77200 * val.Cb;
            var color = Color.FromArgb((byte)((int)r >> 7), (byte)((int)g >> 7), (byte)((int)b >> 7));

            bitmap.SetPixel(col, row, color);
        }
Exemple #6
0
        private static void ProcessSlice(StartOfImage startOfImage, int slice, int samples, BitmapData data, DataBuf pp)
        {
            var startOfFrame = startOfImage.StartOfFrame;
            var scanLines    = startOfFrame.ScanLines;
            var memory       = new DataBuf[2];           // 0x4000

            for (var line = 0; line < scanLines; line++) // 0..1728
            {
                // 6 bytes * 8 bits == 48 bits per pixel
                // 3 = 6 bytes * samplesPerLine / (slices[0] * slices[1] + slices[2]);
                var scan0 = data.Scan0 + data.Stride * line + slice * samples * 3;

                // read four shorts, for two pixels
                for (var col = 0; col < samples / 4; col++)       // 0..216  ==> 0/6 .. 2592/6  --> 0 .. 432
                {
                    cc += 4;
                    var diff = new DiffBuf
                    {
                        Y1 = startOfImage.ProcessColor(0x00),
                        Y2 = startOfImage.ProcessColor(0x00),
                        Cb = startOfImage.ProcessColor(0x01),
                        Cr = startOfImage.ProcessColor(0x01)
                    };

                    if (line % 6 == 0 && col == 0)
                    {
                        pp.Y         = (ushort)(pp.Y + diff.Y1);
                        pp.Cb       += diff.Cb;
                        pp.Cr       += diff.Cr;
                        memory[0].Y  = pp.Y;
                        memory[0].Cb = pp.Cb;
                        memory[0].Cr = pp.Cr;

                        pp.Y         = (ushort)(pp.Y + diff.Y2);
                        memory[1].Y  = pp.Y;
                        memory[1].Cb = pp.Cb;
                        memory[1].Cr = pp.Cr;
                    }
                    else
                    {
                        memory[0].Y  = (ushort)(memory[0].Y + diff.Y1);
                        memory[0].Cb = (short)(memory[0].Cb + diff.Cb);
                        memory[0].Cr = (short)(memory[0].Cr + diff.Cr);

                        memory[1].Y  = (ushort)(memory[1].Y + diff.Y2);
                        memory[1].Cb = memory[0].Cb;
                        memory[1].Cr = memory[0].Cr;
                    }

                    PokePixels(scan0, col, memory[0], memory[1]);
                }
            }
        }
Exemple #7
0
        // 4:2:2 chrominance subsampling pattern
        // 2x1 chroma subsampling
        private static void ProcessSixLines(int slice, int line, DataBuf[,] memory, DataBuf prev, DiffBuf[] diff)
        {
            var last  = memory.GetLength(1);
            var spred = (ushort)0;

            for (var y = 0; y < 6; y++)
            {
                var row = line + y;
                if (slice == 0)
                {
                    prev.Y            = (ushort)(prev.Y + diff[0].Y1);
                    spred             = prev.Y;
                    memory[row, 0].Y  = prev.Y;
                    memory[row, 0].Cb = prev.Cb += diff[0].Cb;
                    memory[row, 0].Cr = prev.Cr += diff[0].Cr;

                    spred             = (ushort)(spred + diff[0].Y2);
                    memory[row, 1].Y  = spred;
                    memory[row, 1].Cb = 0; //(short)(memory[row, 0].Cb + diff[0].Cb);
                    memory[row, 1].Cr = 0; //(short)(memory[row, 0].Cr + diff[0].Cr);
                }
                else
                {
                    spred             = (ushort)(spred + diff[0].Y1);
                    memory[row, 0].Y  = spred;
                    memory[row, 0].Cb = (short)(memory[row, last - 1].Cb + diff[0].Cb);
                    memory[row, 0].Cr = (short)(memory[row, last - 1].Cr + diff[0].Cr);

                    spred             = (ushort)(spred + diff[0].Y2);
                    memory[row, 1].Y  = spred;
                    memory[row, 1].Cb = 0; //(short)(memory[row, 0].Cb + diff[0].Cb);
                    memory[row, 1].Cr = 0; //(short)(memory[row, 0].Cr + diff[0].Cr);
                }

                for (var x = 1; x < diff.Length / 6; x++) // 216
                {
                    var col = 2 * (slice * diff.Length / 6 + x);

                    spred = (ushort)(spred + diff[x].Y1);
                    memory[row, col].Y  = spred;
                    memory[row, col].Cb = (short)(memory[row, col - 1].Cb + diff[x].Cb);
                    memory[row, col].Cr = (short)(memory[row, col - 1].Cr + diff[x].Cr);

                    spred = (ushort)(spred + diff[x].Y2);
                    memory[row, col + 1].Y  = spred;
                    memory[row, col + 1].Cb = (short)(memory[row, col].Cb + diff[x].Cb);
                    memory[row, col + 1].Cr = (short)(memory[row, col].Cr + diff[x].Cr);
                }
            }
        }
Exemple #8
0
        private static void ProcessSlice(StartOfImage startOfImage, int slice, int width, DataBuf[,] memory)
        {
            var       startOfFrame = startOfImage.StartOfFrame;
            const int step         = 6;

            for (var line = 0; line < startOfFrame.ScanLines; line += step)              // 0..1728
            {
                var vpred = new DataBuf {
                    Y = 0x4000
                };
                var diff = ReadDiffBufs(step * width, startOfImage);
                ProcessSixLines(slice, line, memory, vpred, diff);  // 864
            }
        }
Exemple #9
0
        protected override void Execute()
        {
            _spectrumDatas.Clear();
            int dataStartIndex = 0;
            int samplesPerView = DataBuf.Count / GlobalInfo.EnableChannelCount;

            for (int i = 0; i < GlobalInfo.EnableChannelCount; i++)
            {
                double[] showData = DataBuf.GetRange(dataStartIndex, samplesPerView).ToArray();
                Spectrum.PowerSpectrum(showData, GlobalInfo.SampleRate, ref _spectrum, out _df,
                                       SpectrumUnits.dBV, _configForm.Window, _configForm.WindowPara);
                _spectrumDatas.AddRange(_spectrum);
                dataStartIndex += samplesPerView;
            }
        }
Exemple #10
0
        private static void DumpImage3SRaw(string folder, string file)
        {
            var fileName2 = folder + file;

            using (var fileStream = File.Open(fileName2, FileMode.Open, FileAccess.Read))
                using (var binaryReader = new BinaryReader(fileStream))
                {
                    var rawImage = new RawImage(binaryReader);

                    // Image #3 is a raw image compressed in ITU-T81 lossless JPEG

                    var image  = rawImage.Directories.Skip(3).First();
                    var offset = image.Entries.Single(e => e.TagId == 0x0111 && e.TagType == 4).ValuePointer;
                    var count  = image.Entries.Single(e => e.TagId == 0x0117 && e.TagType == 4).ValuePointer;

                    var imageFileEntry = image.Entries.Single(e => e.TagId == 0xC640 && e.TagType == 3);
                    var slices         = RawImage.ReadUInts16(binaryReader, imageFileEntry);
                    CollectionAssert.AreEqual(new[] { (ushort)5, (ushort)864, (ushort)864 }, slices);

                    binaryReader.BaseStream.Seek(offset, SeekOrigin.Begin);
                    var startOfImage = new StartOfImage(binaryReader, offset, count);

                    var startOfFrame = startOfImage.StartOfFrame;
                    Assert.AreEqual(15, startOfFrame.Precision);         // sraw/sraw2
                    Assert.AreEqual(1728u, startOfFrame.ScanLines);      // height
                    Assert.AreEqual(2592u, startOfFrame.SamplesPerLine); // width
                    Assert.AreEqual(7776, startOfFrame.Width);
                    Assert.AreEqual(startOfFrame.SamplesPerLine * 3, startOfFrame.Width);
                    Assert.AreEqual(startOfFrame.SamplesPerLine * 2, slices[0] * slices[1] + slices[2]);

                    startOfImage.ImageData.Reset();

                    // read one line of diff 2592 * 3 == samples per line
                    // write it to six lines of one slice

                    var memory = new DataBuf[startOfFrame.ScanLines, startOfFrame.SamplesPerLine]; // 1728 x 2592
                    for (var slice = 0; slice < slices[0]; slice++)                                // 0..5
                    {
                        ProcessSlice(startOfImage, slice, slices[1], memory);
                    }
                    ProcessSlice(startOfImage, slices[0], slices[2], memory);

                    Assert.AreEqual(8957952, cc);
                    Assert.AreEqual(3, startOfImage.ImageData.DistFromEnd);

                    MakeBitmap(memory, folder);
                }
        }
Exemple #11
0
        protected override void Execute()
        {
            _filteredDatas.Clear();
            int samplesPerView = GlobalInfo.SamplesInChart;
//            if (null == _filteredWave || _filteredWave.Length != samplesPerView)
//            {
//                _filteredWave = new double[samplesPerView];
//            }
            OnlineFirFilter filter = _configForm.Filter;

            for (int i = 0; i < GlobalInfo.EnableChannelCount; i++)
            {
                double[] showData = DataBuf.GetRange(i * samplesPerView, samplesPerView).ToArray();
                _filteredDatas.AddRange(filter.ProcessSamples(showData));
            }
        }
        public DataBuf[][] ReadImage()
        {
            var memory = new DataBuf[StartOfFrame.ScanLines][];          // [1728][]
            var prev   = new DataBuf {
                Y = 0x4000, Cb = 0, Cr = 0
            };

            for (var line = 0; line < StartOfFrame.ScanLines; line++) // 0 .. 3950
            {
                var diff    = ReadDiffRow();
                var memory1 = ProcessDiff(diff, prev);
                memory[line] = memory1;
            }

            return(memory);
        }
Exemple #13
0
        private static void CreateBitmap(BinaryReader binaryReader, StartOfImage startOfImage, string outFile, uint offset, ushort[] slices)
        {
            binaryReader.BaseStream.Seek(offset, SeekOrigin.Begin);

            var startOfFrame = startOfImage.StartOfFrame;
            var height       = startOfFrame.ScanLines;

            Assert.AreEqual(1728, height);              // image height

            var samplesPerLine = startOfFrame.SamplesPerLine;

            Assert.AreEqual(2592, samplesPerLine);      // image width

            var width = startOfFrame.Width;

            Assert.AreEqual(7776, startOfFrame.Width);
            Assert.AreEqual(samplesPerLine * 2, slices[0] * slices[1] + slices[2]);
            Assert.AreEqual(width, samplesPerLine * 3);
            Assert.AreEqual(3, 6 * samplesPerLine / (slices[0] * slices[1] + slices[2]));

            using (var bitmap = new Bitmap(samplesPerLine, height, PixelFormat.Format48bppRgb))
            {
                var size = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                var data = bitmap.LockBits(size, ImageLockMode.ReadWrite, bitmap.PixelFormat);
                try
                {
                    Assert.AreEqual(6 * samplesPerLine, data.Stride);  // 6 bytes * 8 bits == 48 bits per pixel
                    var pp = new DataBuf {
                        Y = 0x4000
                    };

                    for (var slice = 0; slice < slices[0]; slice++) // 0..5
                    {
                        ProcessSlice(startOfImage, slice, slices[1], data, pp);
                    }
                    ProcessSlice(startOfImage, slices[0], slices[2], data, pp);
                }
                finally
                {
                    bitmap.UnlockBits(data);
                }

                bitmap.Save(outFile);
            }
        }
        protected override void Execute()
        {
            int signalIndex;

            _configForm.GetChannelIndex(out signalIndex);
            if (signalIndex < 0)
            {
                DetailValues[0] = Constants.NotAvailable;
            }
            else
            {
                int samplesInChart = GlobalInfo.SamplesInChart;
                _squareMeasurement.SetWaveform(DataBuf.GetRange(samplesInChart * signalIndex, samplesInChart).ToArray());
                DetailValues[0] = _squareMeasurement.GetHighStateLevel().ToString();
                DetailValues[1] = _squareMeasurement.GetLowStateLevel().ToString();
                DetailValues[2] = (GlobalInfo.SampleRate / _squareMeasurement.GetPeriod()).ToString();
            }
        }
Exemple #15
0
        protected override void Execute()
        {
            int signal1Index, signal2Index;

            _configForm.GetChannelIndex(out signal1Index, out signal2Index);
            int samplesPerView = GlobalInfo.SamplesInChart;

            if (signal2Index >= 0 && signal1Index >= 0 && signal1Index != signal2Index)
            {
                double[] signal1 = DataBuf.GetRange(signal1Index * samplesPerView, samplesPerView).ToArray();
                double[] signal2 = DataBuf.GetRange(signal2Index * samplesPerView, samplesPerView).ToArray();
                DetailValues[0] = Phase.CalPhaseShift(signal1, signal2).ToString();
            }
            else
            {
                DetailValues[0] = Constants.NotAvailable;
            }
        }
Exemple #16
0
        private static void PokePixels(IntPtr scan0, IntPtr scan1, int col, DataBuf pixel0, DataBuf pixel1, DataBuf pixel2, DataBuf pixel3)
        {
            {
                var red   = pixel0.Y + 1.40200 * pixel0.Cr;
                var green = pixel0.Y - 0.34414 * pixel0.Cb - 0.71414 * pixel0.Cr;
                var blue  = pixel0.Y + 1.77200 * pixel0.Cb;

                Marshal.WriteInt16(scan0, 12 * col + 4, (short)red);
                Marshal.WriteInt16(scan0, 12 * col + 2, (short)green);
                Marshal.WriteInt16(scan0, 12 * col + 0, (short)blue);
            }

            {
                var red   = pixel1.Y + 1.40200 * pixel1.Cr;
                var green = pixel1.Y - 0.34414 * pixel1.Cb - 0.71414 * pixel1.Cr;
                var blue  = pixel1.Y + 1.77200 * pixel1.Cb;

                Marshal.WriteInt16(scan0, 12 * col + 10, (short)red);
                Marshal.WriteInt16(scan0, 12 * col + 8, (short)green);
                Marshal.WriteInt16(scan0, 12 * col + 6, (short)blue);
            }

            {
                var red   = pixel2.Y + 1.40200 * pixel2.Cr;
                var green = pixel2.Y - 0.34414 * pixel2.Cb - 0.71414 * pixel2.Cr;
                var blue  = pixel2.Y + 1.77200 * pixel2.Cb;

                Marshal.WriteInt16(scan1, 12 * col + 4, (short)red);
                Marshal.WriteInt16(scan1, 12 * col + 2, (short)green);
                Marshal.WriteInt16(scan1, 12 * col + 0, (short)blue);
            }

            {
                var red   = pixel3.Y + 1.40200 * pixel3.Cr;
                var green = pixel3.Y - 0.34414 * pixel3.Cb - 0.71414 * pixel3.Cr;
                var blue  = pixel3.Y + 1.77200 * pixel3.Cb;

                Marshal.WriteInt16(scan1, 12 * col + 10, (short)red);
                Marshal.WriteInt16(scan1, 12 * col + 8, (short)green);
                Marshal.WriteInt16(scan1, 12 * col + 6, (short)blue);
            }
        }
Exemple #17
0
        protected override void Execute()
        {
            int channelCount = GlobalInfo.Channels.Count(item => item.Enabled);
            int sampleCount  = GlobalInfo.SamplesInChart;

            for (int i = 0; i < DetailValues.Length; i++)
            {
                DetailValues[i] = "";
            }
            for (int i = 0; i < channelCount; i++)
            {
                ToneAnalysisResult result = HarmonicAnalysis.ToneAnalysis(DataBuf.GetRange(i * sampleCount, sampleCount).ToArray(),
                                                                          1.0 / GlobalInfo.SampleRate);
                DetailValues[0] += $"{result.THD:f6} ";
                DetailValues[1] += $"{result.THDplusN:f6} ";
                DetailValues[2] += $"{result.SINAD:f6} ";
                DetailValues[3] += $"{result.SNR:f6} ";
                DetailValues[4] += $"{result.NoiseFloor:f6} ";
                DetailValues[5] += $"{result.ENOB:f6} ";
            }
        }
Exemple #18
0
        private static void PokePixels(IntPtr scan0, int col, DataBuf pixel0, DataBuf pixel1)
        {
            {
                var red   = pixel0.R;
                var green = pixel0.G;
                var blue  = pixel0.B;

                Marshal.WriteInt16(scan0, 12 * col + 4, (short)red);
                Marshal.WriteInt16(scan0, 12 * col + 2, (short)green);
                Marshal.WriteInt16(scan0, 12 * col + 0, (short)blue);
            }

            {
                var red   = pixel1.R;
                var green = pixel1.G;
                var blue  = pixel1.B;

                Marshal.WriteInt16(scan0, 12 * col + 10, (short)red);
                Marshal.WriteInt16(scan0, 12 * col + 8, (short)green);
                Marshal.WriteInt16(scan0, 12 * col + 6, (short)blue);
            }
        }
Exemple #19
0
        private static void DumpImage3SRaw(string fileName)
        {
            using (var fileStream = File.Open(fileName, FileMode.Open, FileAccess.Read))
                using (var binaryReader = new BinaryReader(fileStream))
                {
                    var rawImage = new RawImage(binaryReader);

                    // Image #3 is a raw image compressed in ITU-T81 lossless JPEG

                    var image = rawImage.Directories.Skip(3).First();
                    Assert.AreEqual(7, image.Entries.Length);

                    var compression = image.Entries.Single(e => e.TagId == 0x0103 && e.TagType == 3).ValuePointer;
                    Assert.AreEqual(6u, compression);

                    var offset = image.Entries.Single(e => e.TagId == 0x0111 && e.TagType == 4).ValuePointer;
                    // Assert.AreEqual(0x2D42DCu, offset);

                    var count = image.Entries.Single(e => e.TagId == 0x0117 && e.TagType == 4).ValuePointer;
                    // Assert.AreEqual(0x1501476u, count);

                    var item3 = image.Entries.Single(e => e.TagId == 0xC5D8 && e.TagType == 4).ValuePointer;
                    Assert.AreEqual(0x1u, item3);

                    var item4 = image.Entries.Single(e => e.TagId == 0xC5E0 && e.TagType == 4).ValuePointer;
                    Assert.AreEqual(0x3u, item4);

                    // 0xC640 UShort 16-bit: [0x000119BE] (3): 8, 1296, 1296,
                    var imageFileEntry = image.Entries.Single(e => e.TagId == 0xC640 && e.TagType == 3);
                    // Assert.AreEqual(0x000119BEu, imageFileEntry.ValuePointer);
                    // Assert.AreEqual(3u, imageFileEntry.NumberOfValue);
                    var slices = RawImage.ReadUInts16(binaryReader, imageFileEntry);
                    CollectionAssert.AreEqual(new ushort[] { 8, 1296, 1296 }, slices);

                    var item6 = image.Entries.Single(e => e.TagId == 0xC6C5 && e.TagType == 4).ValuePointer;
                    Assert.AreEqual(0x4u, item6);

                    binaryReader.BaseStream.Seek(offset, SeekOrigin.Begin);
                    var startOfImage = new StartOfImage(binaryReader, offset, count);

                    var startOfFrame = startOfImage.StartOfFrame;
                    Assert.AreEqual(2592u, startOfFrame.ScanLines);
                    Assert.AreEqual(3888u, startOfFrame.SamplesPerLine);
                    Assert.AreEqual(11664, startOfFrame.Width);

                    // var rowBuf0 = new short[startOfFrame.SamplesPerLine * startOfFrame.Components.Length];
                    // var rowBuf1 = new short[startOfFrame.SamplesPerLine * startOfFrame.Components.Length];
                    // var predictor = new[] { (short)(1 << (startOfFrame.Precision - 1)), (short)(1 << (startOfFrame.Precision - 1)) };
                    Assert.AreEqual(2, startOfImage.HuffmanTable.Tables.Count);
                    // var table0 = startOfImage.HuffmanTable.Tables[0x00];
                    // var table1 = startOfImage.HuffmanTable.Tables[0x01];

                    Assert.AreEqual(15, startOfFrame.Precision); // mraw/sraw1

                    // chrominance subsampling factors
                    Assert.AreEqual(3, startOfFrame.Components.Length); // mraw/sraw1

                    //
                    Assert.AreEqual(1, startOfFrame.Components[0].ComponentId);
                    Assert.AreEqual(2, startOfFrame.Components[0].HFactor);
                    Assert.AreEqual(2, startOfFrame.Components[0].VFactor); // MRAW
                    Assert.AreEqual(0, startOfFrame.Components[0].TableId);

                    Assert.AreEqual(2, startOfFrame.Components[1].ComponentId);
                    Assert.AreEqual(1, startOfFrame.Components[1].HFactor);
                    Assert.AreEqual(1, startOfFrame.Components[1].VFactor);
                    Assert.AreEqual(0, startOfFrame.Components[1].TableId);

                    Assert.AreEqual(3, startOfFrame.Components[2].ComponentId);
                    Assert.AreEqual(1, startOfFrame.Components[2].HFactor);
                    Assert.AreEqual(1, startOfFrame.Components[2].VFactor);
                    Assert.AreEqual(0, startOfFrame.Components[2].TableId);

                    // mraw/sraw1
                    // Y1 Y2 Y3 Y4 Cb Cr
                    // Y1 Cb Cr Y2  x  x
                    // Y3  x  x Y4  x  x

                    var startOfScan = startOfImage.StartOfScan;
                    // DumpStartOfScan(startOfScan);

                    Assert.AreEqual(1, startOfScan.Bb1);               // Start of spectral or predictor selection
                    Assert.AreEqual(0, startOfScan.Bb2);               // end of spectral selection
                    Assert.AreEqual(0, startOfScan.Bb3);               // successive approximation bit positions
                    Assert.AreEqual(3, startOfScan.Components.Length); // sraw/sraw2

                    Assert.AreEqual(1, startOfScan.Components[0].Id);
                    Assert.AreEqual(0, startOfScan.Components[0].Dc);
                    Assert.AreEqual(0, startOfScan.Components[0].Ac);

                    Assert.AreEqual(2, startOfScan.Components[1].Id);
                    Assert.AreEqual(1, startOfScan.Components[1].Dc);
                    Assert.AreEqual(0, startOfScan.Components[1].Ac);

                    Assert.AreEqual(3, startOfScan.Components[2].Id);
                    Assert.AreEqual(1, startOfScan.Components[2].Dc);
                    Assert.AreEqual(0, startOfScan.Components[2].Ac);

                    // DumpCompressedData(startOfImage);

                    // horizontal sampling == 1
                    startOfImage.ImageData.Reset();

                    var memory = new DataBuf[startOfFrame.ScanLines][];       // [2592][]
                    for (var line = 0; line < startOfFrame.ScanLines; line++) // 0 .. 2592
                    {
                        var diff = ReadDiffRow(startOfImage);
                        // VerifyDiff(diff, line);
                        var memory1 = ProcessDiff(diff, startOfFrame.SamplesPerLine); //
                        memory[line] = memory1;
                    }

                    Assert.AreEqual(10077696, cc);
                    Assert.AreEqual(1, startOfImage.ImageData.DistFromEnd);

                    var outFile = Path.ChangeExtension(fileName, ".bmp");
                    MakeBitmap(memory, outFile, slices);
                }
        }
Exemple #20
0
        private static void DumpImage3SRaw(string fileName)
        {
            using (var fileStream = File.Open(fileName, FileMode.Open, FileAccess.Read))
                using (var binaryReader = new BinaryReader(fileStream))
                {
                    var rawImage = new RawImage(binaryReader);

                    // Image #3 is a raw image compressed in ITU-T81 lossless JPEG
                    {
                        var image = rawImage.Directories.Skip(3).First();

                        var offset = image.Entries.Single(e => e.TagId == 0x0111 && e.TagType == 4).ValuePointer;
                        // Assert.AreEqual(0x2D42DCu, offset);

                        var count = image.Entries.Single(e => e.TagId == 0x0117 && e.TagType == 4).ValuePointer;
                        // Assert.AreEqual(0x1501476u, count);

                        // 0xC640 UShort 16-bit: [0x000119BE] (3): 5, 864, 864,
                        var imageFileEntry = image.Entries.Single(e => e.TagId == 0xC640 && e.TagType == 3);
                        // Assert.AreEqual(0x000119BEu, imageFileEntry.ValuePointer);
                        Assert.AreEqual(3u, imageFileEntry.NumberOfValue);
                        var slices = RawImage.ReadUInts16(binaryReader, imageFileEntry);
                        CollectionAssert.AreEqual(new ushort[] { 5, 864, 864 }, slices);

                        binaryReader.BaseStream.Seek(offset, SeekOrigin.Begin);
                        var startOfImage = new StartOfImage(binaryReader, offset, count); // { ImageData = new ImageData(binaryReader, count) };

                        var startOfFrame = startOfImage.StartOfFrame;
                        Assert.AreEqual(1728u, startOfFrame.ScanLines);
                        Assert.AreEqual(2592u, startOfFrame.SamplesPerLine);
                        Assert.AreEqual(7776, startOfFrame.Width);

                        Assert.AreEqual(2, startOfImage.HuffmanTable.Tables.Count);
                        //var table0 = startOfImage.HuffmanTable.Tables[0x00];
                        //var table1 = startOfImage.HuffmanTable.Tables[0x01];

                        Assert.AreEqual(15, startOfFrame.Precision); // sraw/sraw2

                        // chrominance subsampling factors
                        Assert.AreEqual(3, startOfFrame.Components.Length); // sraw/sraw2

                        // J:a:b = 4:2:2, h/v = 2/1
                        Assert.AreEqual(1, startOfFrame.Components[0].ComponentId);
                        Assert.AreEqual(2, startOfFrame.Components[0].HFactor); // SRAW
                        Assert.AreEqual(1, startOfFrame.Components[0].VFactor);
                        Assert.AreEqual(0, startOfFrame.Components[0].TableId);

                        Assert.AreEqual(2, startOfFrame.Components[1].ComponentId);
                        Assert.AreEqual(1, startOfFrame.Components[1].HFactor);
                        Assert.AreEqual(1, startOfFrame.Components[1].VFactor);
                        Assert.AreEqual(0, startOfFrame.Components[1].TableId);

                        Assert.AreEqual(3, startOfFrame.Components[2].ComponentId);
                        Assert.AreEqual(1, startOfFrame.Components[2].HFactor);
                        Assert.AreEqual(1, startOfFrame.Components[2].VFactor);
                        Assert.AreEqual(0, startOfFrame.Components[2].TableId);

                        // sraw/sraw2
                        // Y1 Y2 Cb Cr ...
                        // Y1 Cb Cr Y2 x x
                        // Y1 Cb Cr Y2 x x

                        var startOfScan = startOfImage.StartOfScan;
                        // DumpStartOfScan(startOfScan);

                        Assert.AreEqual(1, startOfScan.Bb1);               // Start of spectral or predictor selection
                        Assert.AreEqual(0, startOfScan.Bb2);               // end of spectral selection
                        Assert.AreEqual(0, startOfScan.Bb3);               // successive approximation bit positions
                        Assert.AreEqual(3, startOfScan.Components.Length); // sraw/sraw2

                        Assert.AreEqual(1, startOfScan.Components[0].Id);
                        Assert.AreEqual(0, startOfScan.Components[0].Dc);
                        Assert.AreEqual(0, startOfScan.Components[0].Ac);

                        Assert.AreEqual(2, startOfScan.Components[1].Id);
                        Assert.AreEqual(1, startOfScan.Components[1].Dc);
                        Assert.AreEqual(0, startOfScan.Components[1].Ac);

                        Assert.AreEqual(3, startOfScan.Components[2].Id);
                        Assert.AreEqual(1, startOfScan.Components[2].Dc);
                        Assert.AreEqual(0, startOfScan.Components[2].Ac);

                        // DumpCompressedData(startOfImage);

                        // horizontal sampling == 1
                        startOfImage.ImageData.Reset();

                        var prev = new DataBuf {
                            Y = 0x4000, Cb = 0, Cr = 0
                        };
                        var memory = new DataBuf[startOfFrame.ScanLines][];       // [1728][]
                        for (var line = 0; line < startOfFrame.ScanLines; line++) // 0 .. 1728
                        {
                            var diff = ReadDiffRow(startOfImage);
                            // VerifyDiff(diff, line);
                            var memory1 = ProcessDiff(diff, prev); // 2592
                            memory[line] = memory1;
                        }

                        Assert.AreEqual(8957952, cc);
                        Assert.AreEqual(3, startOfImage.ImageData.DistFromEnd);

                        var outFile = Path.ChangeExtension(fileName, ".bmp");
                        MakeBitmap(memory, outFile, slices);
                    }
                }
        }
Exemple #21
0
        private static void ProcessSlice(StartOfImage startOfImage, int slice, int width, BitmapData data, ushort[] pp)
        {
            var startOfFrame = startOfImage.StartOfFrame;
            var scanLines    = startOfFrame.ScanLines;
            var memory       = new ushort[2];

            for (var line = 0; line < scanLines; line++)
            {
                // 6 bytes * 8 bits == 48 bits per pixel
                // 3 = 6 bytes * samplesPerLine / (slices[0] * slices[1] + slices[2]);
                var scan0 = data.Scan0 + data.Stride * line + slice * width * 6;

                // read two shorts, for two pixels
                for (var col = 0; col < width / 2; col++)
                {
                    var diff = new DiffBuf
                    {
                        Y1 = startOfImage.ProcessColor(0x00),
                        Y2 = startOfImage.ProcessColor(0x01),
                    };
                    cc += 2;

                    if (line % 2 == 0 && col == 0)
                    {
                        pp[0]     = (ushort)(pp[0] + diff.Y1);
                        memory[0] = pp[0];

                        pp[1]     = (ushort)(pp[1] + diff.Y2);
                        memory[1] = pp[1];
                    }
                    else
                    {
                        memory[0] = (ushort)(memory[0] + diff.Y1);

                        memory[1] = (ushort)(memory[1] + diff.Y2);
                    }

                    if (line % 2 == 0)
                    {
                        var pixel0 = new DataBuf
                        {
                            R = memory[0]
                        };

                        var pixel1 = new DataBuf
                        {
                            G = memory[1]
                        };

                        PokePixels(scan0, col, pixel0, pixel1);
                    }
                    else
                    {
                        var pixel0 = new DataBuf
                        {
                            G = memory[0]
                        };

                        var pixel1 = new DataBuf
                        {
                            B = memory[1]
                        };

                        PokePixels(scan0, col, pixel0, pixel1);
                    }
                }
            }
        }
Exemple #22
0
        // 4:2:2 chrominance subsampling pattern
        // 2x1 chroma subsampling
        private static void ProcessLine15321Old(int slice, int line, int samplesPerLine, StartOfImage startOfImage, DataBuf[,] memory, DataBuf prev)
        {
            var diff = ReadDiffBufs(samplesPerLine, startOfImage);

            for (var x = 0; x < diff.Length; x++)        // 216
            {
                var pp = prev;

                var y1 = (ushort)(pp.Y + diff[x].Y1);
                var y2 = (ushort)(pp.Y + diff[x].Y1 + diff[x].Y2);
                var cb = (short)(pp.Cb + diff[x].Cb);
                var cr = (short)(pp.Cr + diff[x].Cr);

                pp.Y  = y2;
                pp.Cb = cb;
                pp.Cr = cr;

                var col = 2 * slice * diff.Length + 2 * x;
                memory[line, col].Y  = y1;
                memory[line, col].Cb = cb;
                memory[line, col].Cr = cr;

                memory[line, col + 1].Y  = y2;
                memory[line, col + 1].Cb = 0;
                memory[line, col + 1].Cr = 0;
            }
        }
Exemple #23
0
        private void button1_Click(object sender, EventArgs e)
        {
            this.button1.Enabled = false;
            DllInvoke dllInvoke = new DllInvoke("Rad.dll");

            colorDataSrc = new ColorDataSrc()
            {
                pd000_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pd000_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pd000_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pd016_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pd016_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pd016_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pd032_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pd032_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pd032_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pd064_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pd064_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pd064_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pd096_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pd096_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pd096_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pd128_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pd128_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pd128_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pd160_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pd160_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pd160_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pd192_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pd192_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pd192_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pd224_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pd224_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pd224_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pucBmpSrc  = new byte[MAX_WIDTH * MAX_HEIGHT * 3],
                pucDllCtrl = new byte[DEMURA_CFG_SIZE],
            };

            dataBuf = new DataBuf()
            {
                pdBuf0_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf1_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf2_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf3_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf4_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf5_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf6_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf7_R = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf8_R = new double[MAX_WIDTH * MAX_HEIGHT],

                pdBuf0_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf1_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf2_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf3_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf4_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf5_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf6_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf7_G = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf8_G = new double[MAX_WIDTH * MAX_HEIGHT],

                pdBuf0_B = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf1_B = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf2_B = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf3_B = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf4_B = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf5_B = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf6_B = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf7_B = new double[MAX_WIDTH * MAX_HEIGHT],
                pdBuf8_B = new double[MAX_WIDTH * MAX_HEIGHT],

                pdBuf9 = new double[MAX_WIDTH * MAX_HEIGHT],
            };

            compDataResult = new CompDataResult()
            {
                pucCompData    = new byte[MAX_WIDTH * MAX_HEIGHT * 3],
                pucFlhCompData = new byte[MAX_FLASH_SIZE_QHD],
            };

            #region path
            string str_exe_directory_path          = Environment.CurrentDirectory + "\\";
            string str_cfg_file_full_path          = str_exe_directory_path + "DMR_CFG_GVO_720_2160.rad";
            string str_capras_032_R_file_full_path = str_exe_directory_path + "Red32.csv";
            string str_capras_032_G_file_full_path = str_exe_directory_path + "Green32.csv";
            string str_capras_032_B_file_full_path = str_exe_directory_path + "Blue32.csv";
            string str_capras_064_R_file_full_path = str_exe_directory_path + "Red64.csv";
            string str_capras_064_G_file_full_path = str_exe_directory_path + "Green64.csv";
            string str_capras_064_B_file_full_path = str_exe_directory_path + "Blue64.csv";
            string str_capras_096_R_file_full_path = str_exe_directory_path + "Red96.csv";
            string str_capras_096_G_file_full_path = str_exe_directory_path + "Green96.csv";
            string str_capras_096_B_file_full_path = str_exe_directory_path + "Blue96.csv";
            string str_capras_160_R_file_full_path = str_exe_directory_path + "Red160.csv";
            string str_capras_160_G_file_full_path = str_exe_directory_path + "Green160.csv";
            string str_capras_160_B_file_full_path = str_exe_directory_path + "Blue160.csv";
            string str_capras_192_R_file_full_path = str_exe_directory_path + "Red192.csv";
            string str_capras_192_G_file_full_path = str_exe_directory_path + "Green192.csv";
            string str_capras_192_B_file_full_path = str_exe_directory_path + "Blue192.csv";
            string str_capras_224_R_file_full_path = str_exe_directory_path + "Red224.csv";
            string str_capras_224_G_file_full_path = str_exe_directory_path + "Green224.csv";
            string str_capras_224_B_file_full_path = str_exe_directory_path + "Blue224.csv";
            string str_flash_file_full_path        = str_exe_directory_path + "DemuraFlash.txt";

            using (var file = new FileStream(str_cfg_file_full_path, FileMode.Open, FileAccess.Read))
            {
                file.Read(colorDataSrc.pucDllCtrl, 0, DEMURA_CFG_SIZE);
            }
            funcFileProc(colorDataSrc.pd032_R, str_capras_032_R_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd032_G, str_capras_032_G_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd032_B, str_capras_032_B_file_full_path, 2160, 720, -1, 0);

            funcFileProc(colorDataSrc.pd064_R, str_capras_064_R_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd064_G, str_capras_064_G_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd064_B, str_capras_064_B_file_full_path, 2160, 720, -1, 0);

            funcFileProc(colorDataSrc.pd096_R, str_capras_096_R_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd096_G, str_capras_096_G_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd096_B, str_capras_096_B_file_full_path, 2160, 720, -1, 0);

            funcFileProc(colorDataSrc.pd160_R, str_capras_160_R_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd160_G, str_capras_160_G_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd160_B, str_capras_160_B_file_full_path, 2160, 720, -1, 0);

            funcFileProc(colorDataSrc.pd192_R, str_capras_192_R_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd192_G, str_capras_192_G_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd192_B, str_capras_192_B_file_full_path, 2160, 720, -1, 0);

            funcFileProc(colorDataSrc.pd224_R, str_capras_224_R_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd224_G, str_capras_224_G_file_full_path, 2160, 720, -1, 0);
            funcFileProc(colorDataSrc.pd224_B, str_capras_224_B_file_full_path, 2160, 720, -1, 0);
            #endregion

            IntPtr dataSrcPtr = Marshal.AllocHGlobal(Marshal.SizeOf(colorDataSrc));
            Marshal.StructureToPtr(colorDataSrc, dataSrcPtr, false);

            IntPtr dataBufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(dataBuf));
            Marshal.StructureToPtr(dataBuf, dataBufPtr, false);


            IntPtr dataResultPtr = Marshal.AllocHGlobal(Marshal.SizeOf(compDataResult));
            Marshal.StructureToPtr(compDataResult, dataResultPtr, false);


            RadFunc radFunc = (RadFunc)dllInvoke.Invoke("RadFunc", typeof(RadFunc));

            var ret = radFunc(dataSrcPtr, dataBufPtr, dataResultPtr);
            if (ret == 0)
            {
                compDataResult = (CompDataResult)Marshal.PtrToStructure(dataResultPtr, typeof(CompDataResult));
                using (var fileStream = File.Open(str_flash_file_full_path, FileMode.OpenOrCreate, FileAccess.Write))
                {
                    int DMRpatter_start   = 256;
                    int compensate_crc    = 2;
                    int flash_full_chksum = 2;
                    int write_size        = 720 * 2160 * 3 * 3 / 8 + DMRpatter_start + compensate_crc + flash_full_chksum;
                    fileStream.Write(compDataResult.pucFlhCompData, 0, write_size);
                }
            }
            this.button1.Enabled = true;
        }
Exemple #24
0
        private static void ProcessSlice(StartOfImage startOfImage, int slice, int samples, BitmapData data)
        {
            var startOfFrame = startOfImage.StartOfFrame;
            var table0       = startOfImage.HuffmanTable.Tables[0x00];
            var table1       = startOfImage.HuffmanTable.Tables[0x01];

            var lastRow = new DataBuf {
                Y = 0x0000
            };                                                           // 0x4000

            for (var line = 0; line < startOfFrame.ScanLines; line += 2) // 0..2592
            {
                // 6 bytes * 8 bits == 48 bits per pixel
                // 2 = 6 bytes * samplesPerLine / (slices[0] * slices[1] + slices[2]);
                var scan0 = data.Scan0 + data.Stride * line + slice * samples * 2;
                var scan1 = data.Scan0 + data.Stride * (line + 1) + slice * samples * 2;

                // read six shorts, for four pixels
                for (var col = 0; col < samples / 6; col++)       // 0..1296
                {
                    cc += 6;
                    var diff = new DiffBuf
                    {
                        Y1 = startOfImage.ProcessColor(0x00),
                        Y2 = startOfImage.ProcessColor(0x00),
                        Y3 = startOfImage.ProcessColor(0x00),
                        Y4 = startOfImage.ProcessColor(0x00),
                        Cb = startOfImage.ProcessColor(0x01),
                        Cr = startOfImage.ProcessColor(0x01),
                    };

                    var pixel0 = new DataBuf
                    {
                        Y  = (ushort)(lastRow.Y + diff.Y1),
                        Cb = (short)(lastRow.Cb + diff.Cb),
                        Cr = (short)(lastRow.Cr + diff.Cr)
                    };

                    var pixel1 = new DataBuf
                    {
                        Y  = (ushort)(lastRow.Y + diff.Y1 + diff.Y2),
                        Cb = (short)(lastRow.Cb + diff.Cb),
                        Cr = (short)(lastRow.Cr + diff.Cr)
                    };

                    var pixel2 = new DataBuf
                    {
                        Y  = (ushort)(lastRow.Y + diff.Y1 + diff.Y2 + diff.Y3),
                        Cb = (short)(lastRow.Cb + diff.Cb),
                        Cr = (short)(lastRow.Cr + diff.Cr)
                    };

                    var pixel3 = new DataBuf
                    {
                        Y  = (ushort)(lastRow.Y + diff.Y1 + diff.Y2 + diff.Y3 + diff.Y4),
                        Cb = (short)(lastRow.Cb + diff.Cb),
                        Cr = (short)(lastRow.Cr + diff.Cr)
                    };

                    PokePixels(scan0, scan1, col, pixel0, pixel1, pixel2, pixel3);
                }
            }
        }