Beispiel #1
0
		public Frame Process(Frame[] input)
		{
			Frame result = new Frame(input[0].Size);
			AnnotatedFrame frameWithLogs = (AnnotatedFrame)input[0];
			/* Create Bitmap to draw the vectors on */
			using (Bitmap drawableFrame = new Bitmap(input[0].Size.Width, input[0].Size.Width)) {
				for (int x = 0; x < input[0].Size.Width; x++) {
					for (int y = 0; y < input[0].Size.Height; y++) {
						Rgb pixel = input[0][x, y];
						drawableFrame.SetPixel(x, y, Color.FromArgb(pixel.R, pixel.G, pixel.B));
					}
				}
				/* Draw the movementvector of each macroblock */
				for (int x = 0; x < (input[0].Size.Width / 16); x++) {
					for (int y = 0; y < (input[0].Size.Height / 16); y++) {
						DrawVector(drawableFrame, x * 16, y * 16, GetScaledVector(14.0, frameWithLogs.Decisions[x, y].Movement));
					}
				}
				/* Print the frame with vectors into the resultframe */
				for (int x = 0; x < input[0].Size.Width; x++) {
					for (int y = 0; y < input[0].Size.Height; y++) {
						Rgb pixel = new Rgb(drawableFrame.GetPixel(x, y).R, drawableFrame.GetPixel(x, y).G, drawableFrame.GetPixel(x, y).B);
						result[x, y] = pixel;
					}
				}
			}
			return result;
		}
Beispiel #2
0
		public void GetsData()
		{
			// Get the parent PipelineVM and add DiagramNode
			var vm = MainViewModelTest.GetInstance().PipelineViewModel;
			var node = new NodeViewModel(new HistogramNode(), vm);
			vm.Nodes.Add(node);
			vm.Parent.Model.Graph.AddNode(node.Model);

			var hvm = new HistogramViewModel((HistogramNode)vm.Nodes.Single().Model);

			// Generates an array of 1 Frame with randomly filled Data
			var testSize = new Size(5, 5);
			Frame[] inputs = { new Frame(testSize) };
			for (var x = 0; x < testSize.Width; x++) {
				for (var y = 0; y < testSize.Height; y++) {
					inputs[0][x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y));
				}
			}

			hvm.NodeModel.Type = HistogramType.R;

			// porcess one frame with chosen type
			hvm.NodeModel.Process(inputs, 0);
			hvm.Handle(null);

			Assert.NotEmpty(hvm.Data.Data);
		}
Beispiel #3
0
		public override YuvKA.VideoModel.Frame[] Process(YuvKA.VideoModel.Frame[] inputs, int tick)
		{
			Size maxSize = Frame.MaxBoundaries(inputs);
			Frame outputFrame = new Frame(maxSize);
			byte resultR;
			byte resultG;
			byte resultB;
			for (int x = 0; x < maxSize.Width; x++) {
				for (int y = 0; y < maxSize.Height; y++) {
					resultR = 0;
					resultG = 0;
					resultB = 0;

					resultR += inputs[0].GetPixelOrBlack(x, y).R;
					resultR += inputs[0].GetPixelOrBlack(x, y).G;
					resultR += inputs[0].GetPixelOrBlack(x, y).B;

					resultG += inputs[1].GetPixelOrBlack(x, y).R;
					resultG += inputs[1].GetPixelOrBlack(x, y).G;
					resultG += inputs[1].GetPixelOrBlack(x, y).B;

					resultB += inputs[2].GetPixelOrBlack(x, y).R;
					resultB += inputs[2].GetPixelOrBlack(x, y).G;
					resultB += inputs[2].GetPixelOrBlack(x, y).B;

					outputFrame[x, y] = new Rgb(resultR, resultG, resultB);
				}
			}
			return new[] { outputFrame };
		}
Beispiel #4
0
		/// <summary>
		/// Alternate constructor for saving the trouble of using the indexer for setting up a frame with already well formed data
		/// </summary>
		/// <param name="size">The supposed frame size</param>
		/// <param name="data">The frame data</param>
		public Frame(Size size, Rgb[] data)
		{
			if (data.Length != size.Height * size.Width) {
				throw new System.ArgumentException();
			}
			this.data = data;
			Size = size;
		}
Beispiel #5
0
		/// <summary>
		/// Generates an AnnotatedFrame with randomly filled Data and the given Macroblock decisions.
		/// </summary>
		/// <returns> An annotated Frame with random Data and the given Macroblock decisions.</returns>
		public static AnnotatedFrame GenerateAnnFrame(MacroblockDecision[,] decisions)
		{
			var testSize = new YuvKA.VideoModel.Size(8, 8);
			var output = new AnnotatedFrame(testSize, decisions);
			for (int x = 0; x < testSize.Width; x++) {
				for (int y = 0; y < testSize.Height; y++) {
					output[x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y));
				}
			}
			return output;
		}
Beispiel #6
0
		/// <summary>
		/// Splits the first entry of the input into its RGB components
		/// </summary>
		/// <param name="inputs">An array of Frames, with only the first entry regarded.</param>
		/// <param name="tick">The index of the Frame which is processes now.</param>
		/// <returns>An array of Frames with the red components of the input in the first,
		/// the green component in the second and the blue component in the third entry. </returns>
		public override Frame[] Process(Frame[] inputs, int tick)
		{
			Size size = inputs[0].Size;
			Frame[] outputs = { new Frame(size), new Frame(size), new Frame(size) };
			for (int x = 0; x < size.Width; x++) {
				for (int y = 0; y < size.Height; y++) {
					outputs[0][x, y] = new Rgb(inputs[0][x, y].R, 0, 0);
					outputs[1][x, y] = new Rgb(0, inputs[0][x, y].G, 0);
					outputs[2][x, y] = new Rgb(0, 0, inputs[0][x, y].B);
				}
			}
			return outputs;
		}
Beispiel #7
0
		/// <summary>
		/// A Process method to be used by AnonymousNodes. 
		/// Generates an array of 1 Frame and 2 AnnotatedFrame with randomly filled Data.
		/// </summary>
		/// <param name="inputs">The inputs used for processing. This parameter is not used here.</param>
		/// <param name="tick"> The current index of the frame. This parameter is not used here.</param>
		/// <returns> An array of generated Frames.</returns>
		public static Frame[] SourceNode(Frame[] inputs, int tick)
		{
			var testSize = new YuvKA.VideoModel.Size(8, 8);
			Frame[] outputs = { GenerateAnnFrame(new MacroblockDecision[,] 
				{ { new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter4x4 },
					new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter4x4 },
					new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter8x4 } } }),
					new Frame(testSize), 
				GenerateAnnFrame(new MacroblockDecision[,] { {
					new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Intra4x4 },
					new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Intra4x4 },
					new MacroblockDecision { Movement = new Vector(0.0, 0.0), PartitioningDecision = MacroblockPartitioning.Inter8x4 } } }),
				};
			for (int x = 0; x < testSize.Width; x++) {
				for (int y = 0; y < testSize.Height; y++) {
					outputs[1][x, y] = new Rgb((byte)(x * y), (byte)(x * y), (byte)(x * y));
				}
			}
			return outputs;
		}
		/// <summary>
		/// Adds up the weighted frames and finally averages them according to the following formula:
		/// If there are n frames to be merged and w_1,..., w_n are their weights, the resulting frame will be computed by using this formula:
		/// newPixel_xy = (sum(w_i * oldValue_xy_i))/sum(w_i)
		/// (xy represents the position of the pixel in the frame.)
		/// </summary>
		public override Frame[] Process(Frame[] inputs, int tick)
		{
			Size maxSize = Frame.MaxBoundaries(inputs);
			double sumOfWeights = Weights.Sum();
			Frame[] output = { new Frame(new Size(maxSize.Width, maxSize.Height)) };

			for (int x = 0; x < maxSize.Width; x++) {
				for (int y = 0; y < maxSize.Height; y++) {
					// sums up the weighted values
					double newR = 0, newG = 0, newB = 0;
					for (int i = 0; i < inputs.Length; i++) {
						newR += Weights[i] * inputs[i].GetPixelOrBlack(x, y).R;
						newG += Weights[i] * inputs[i].GetPixelOrBlack(x, y).G;
						newB += Weights[i] * inputs[i].GetPixelOrBlack(x, y).B;
					}
					// averages the values
					newR = newR / sumOfWeights;
					newG = newG / sumOfWeights;
					newB = newB / sumOfWeights;
					output[0][x, y] = new Rgb((byte)newR, (byte)newG, (byte)newB);
				}
			}
			return output;
		}
Beispiel #9
0
		public void TestHistogramNodeValue()
		{
			// Generates an array of 1 Frame with randomly filled Data
			YuvKA.VideoModel.Size testSize = new YuvKA.VideoModel.Size(5, 5);
			Frame[] inputs = { new Frame(testSize) };
			for (int x = 0; x < testSize.Width; x++) {
				for (int y = 0; y < testSize.Height; y++) {
					inputs[0][x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y));
				}
			}

			// Generate Value HistogramNode once
			HistogramNode histNodeValue = new HistogramNode();
			histNodeValue.Type = HistogramType.Value;

			histNodeValue.Process(inputs, 0);

			// Calculate expected results independently from Histogram method.
			Color rgbValue;
			int value;
			int[] intData = new int[256];
			for (int x = 0; x < inputs[0].Size.Width; x++) {
				for (int y = 0; y < inputs[0].Size.Height; y++) {
					rgbValue = Color.FromArgb(inputs[0][x, y].R, inputs[0][x, y].G, inputs[0][x, y].B);
					value = (int)(rgbValue.GetBrightness() * 255);
					intData[value]++;
				}
			}
			int numberOfPixels = inputs[0].Size.Height * inputs[0].Size.Width;
			for (int i = 0; i < 256; i++) {
				Assert.Equal(histNodeValue.Data[i], (double)intData[i] / numberOfPixels);
			}
		}
Beispiel #10
0
		/// <summary>
		/// Helper method for converting a bunch of data from YUV to a single RGB frame
		/// The method supports the IYUV / YUV420 format, and assumes that data array
		/// size, width and height make sense.
		/// </summary>
		/// <param name="data">
		/// The raw Yuv data that constitutes the frame
		/// </param>
		private static Frame YuvToRgb(byte[] data, int width, int height)
		{
			int pixelNum = width * height;
			int quartSize = width * height / 4;
			Rgb[] frameData = new Rgb[height * width];
			int ypixel, upixel, vpixel;
			for (int y = 0; y < height; y++) {
				for (int x = 0; x < width; x++) {
					int coordOffset = y * width + x;
					// Our data format it IYUV / YUV420:
					// first all Y values, then all U value, and then all V values
					// the Y 'frame' is twice as big as the U and V 'frames', as
					// the human eye is better at recognizing luminance than it is at
					// distinguishing between different chromacities.

					// Get YUV data from given dataset
					ypixel = data[coordOffset];
					upixel = data[pixelNum + ((width / 2) * (y / 2) + x / 2)];
					vpixel = data[(pixelNum + quartSize) + ((width / 2) * (y / 2) + x / 2)];

					// Convert data to RGB values
					// YCrCb conversion as described by ITU-R 601, with tweaked coefficients
					byte r = ClampToByte(1.167 * (ypixel - 16) + 1.596 * (vpixel - 128));
					byte g = ClampToByte(1.169 * (ypixel - 16) - 0.393 * (upixel - 128) - 0.816 * (vpixel - 128));
					byte b = ClampToByte(1.167 * (ypixel - 16) + 2.018 * (upixel - 128));
					frameData[coordOffset] = new Rgb(r, g, b);
				}
			}
			return new Frame(new Size(width, height), frameData);
		}
Beispiel #11
0
		public void TestNoOverlay()
		{
			Frame testFrame = new Frame(new YuvKA.VideoModel.Size(80, 80));
			for (int x = 0; x < testFrame.Size.Width; x++) {
				for (int y = 0; y < testFrame.Size.Height; y++) {
					testFrame[x, y] = new Rgb(111, 111, 111);
				}
			}
			Frame[] input = { testFrame };
			OverlayNode node = new OverlayNode { Type = new NoOverlay() };
			node.ProcessCore(input, 0);
			List<Frame> output = new List<Frame>();
			for (int x = 0; x < testFrame.Size.Width; x++) {
				for (int y = 0; y < testFrame.Size.Height; y++) {
					Assert.Equal(testFrame[x, y], node.Data[x, y]);
				}
			}
		}
Beispiel #12
0
		public void ArtifactOverlay()
		{
			Frame testFrame = new Frame(new YuvKA.VideoModel.Size(80, 80));
			for (int x = 0; x < testFrame.Size.Width; x++) {
				for (int y = 0; y < testFrame.Size.Height; y++) {
					testFrame[x, y] = new Rgb(111, 111, 111);
				}
			}
			Frame alteredTestFrame = new Frame(testFrame.Size);
			for (int x = 0; x < testFrame.Size.Width; x++) {
				for (int y = 0; y < testFrame.Size.Height; y++) {
					alteredTestFrame[x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y));
				}
			}
			Frame[] input = { alteredTestFrame, testFrame };
			OverlayNode node = new OverlayNode { Type = new ArtifactsOverlay() };
			node.ProcessCore(input, 0);
			List<Frame> output = new List<Frame>();
			output.Add(node.Data);
			YuvEncoder.Encode(@"..\..\..\..\output\ArtifactOverlayTest_80x80.yuv", output);
		}
Beispiel #13
0
		public void TestVecorOverlay()
		{
			Frame testFrame = new Frame(new YuvKA.VideoModel.Size(64, 48));
			for (int x = 0; x < testFrame.Size.Width; x++) {
				for (int y = 0; y < testFrame.Size.Height; y++) {
					testFrame[x, y] = new Rgb(111, 111, 111);
				}
			}
			MacroblockDecision[] decisions = new MacroblockDecision[12];
			decisions[0] = new MacroblockDecision { Movement = new Vector(0.0, 12.0) };
			decisions[1] = new MacroblockDecision { Movement = new Vector(12.0, 12.0) };
			decisions[2] = new MacroblockDecision { Movement = new Vector(12.0, 0.0) };
			decisions[3] = new MacroblockDecision { Movement = new Vector(12.0, -12.0) };
			decisions[4] = new MacroblockDecision { Movement = new Vector(3.0, -12.0) };
			decisions[5] = new MacroblockDecision { Movement = new Vector(-38.0, -15.0) };
			decisions[6] = new MacroblockDecision { Movement = new Vector(-120.0, 0.0) };
			decisions[7] = new MacroblockDecision { Movement = new Vector(-20.0, 20.0) };
			decisions[8] = new MacroblockDecision { Movement = new Vector(4.0, 0.0) };
			decisions[9] = new MacroblockDecision { Movement = new Vector(0.0, 4.0) };
			decisions[10] = new MacroblockDecision { Movement = new Vector(4.0, 4.0) };
			decisions[11] = new MacroblockDecision { Movement = new Vector(-4.0, 0.0) };
			Frame[] input = { new AnnotatedFrame(testFrame, decisions) };
			OverlayNode node = new OverlayNode { Type = new MoveVectorsOverlay() };
			node.ProcessCore(input, 0);
			List<Frame> output = new List<Frame>();
			output.Add(node.Data);
			YuvEncoder.Encode(@"..\..\..\..\output\VectorOverlayTest_64x48.yuv", output);
		}
Beispiel #14
0
		public void TestMacroBlockOverlay()
		{
			Frame testFrame = new Frame(new YuvKA.VideoModel.Size(64, 64));
			for (int x = 0; x < testFrame.Size.Width; x++) {
				for (int y = 0; y < testFrame.Size.Height; y++) {
					testFrame[x, y] = new Rgb(111, 111, 111);
				}
			}
			MacroblockDecision[] decisions = new MacroblockDecision[16];
			decisions[0] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.InterSkip };
			decisions[1] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter16x16 };
			decisions[2] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter16x8 };
			decisions[3] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter8x16 };
			decisions[4] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter8x8 };
			decisions[5] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter4x8 };
			decisions[6] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter8x4 };
			decisions[7] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter4x4 };
			decisions[8] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Intra16x16 };
			decisions[9] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Intra8x8 };
			decisions[10] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Intra4x4 };
			decisions[11] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Unknown };
			decisions[12] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Inter8x8OrBelow };
			decisions[13] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.IntraPCM };
			decisions[14] = new MacroblockDecision { PartitioningDecision = null };
			decisions[15] = new MacroblockDecision { PartitioningDecision = MacroblockPartitioning.Unknown };
			Frame[] input = { new AnnotatedFrame(testFrame, decisions) };
			OverlayNode node = new OverlayNode { Type = new BlocksOverlay() };
			node.ProcessCore(input, 0);
			List<Frame> output = new List<Frame>();
			output.Add(node.Data);
			YuvEncoder.Encode(@"..\..\..\..\output\BlockOverlayTest_64x64.yuv", output);
		}
Beispiel #15
0
		public void TestHistogramNodeRGB()
		{
			// Generates an array of 1 Frame with randomly filled Data
			YuvKA.VideoModel.Size testSize = new YuvKA.VideoModel.Size(5, 5);
			Frame[] inputs = { new Frame(testSize) };
			for (int x = 0; x < testSize.Width; x++) {
				for (int y = 0; y < testSize.Height; y++) {
					inputs[0][x, y] = new Rgb((byte)(x + y), (byte)(x + y), (byte)(x + y));
				}
			}

			// Generate all RGB HistogramNode once
			HistogramNode histNodeR = new HistogramNode();
			histNodeR.Type = HistogramType.R;
			HistogramNode histNodeG = new HistogramNode();
			histNodeG.Type = HistogramType.G;
			HistogramNode histNodeB = new HistogramNode();
			histNodeB.Type = HistogramType.B;

			histNodeR.Process(inputs, 0);
			histNodeG.Process(inputs, 0);
			histNodeB.Process(inputs, 0);

			// Calculate expected results independently from Histogram methods.
			int[] value = new int[3];
			int[,] intData = new int[256, 3];
			for (int x = 0; x < inputs[0].Size.Width; x++) {
				for (int y = 0; y < inputs[0].Size.Height; y++) {
					value[0] = inputs[0][x, y].R;
					value[1] = inputs[0][x, y].G;
					value[2] = inputs[0][x, y].B;
					intData[value[0], 0]++;
					intData[value[1], 1]++;
					intData[value[2], 2]++;
				}
			}
			int numberOfPixels = inputs[0].Size.Height * inputs[0].Size.Width;
			for (int i = 0; i < 256; i++) {
				Assert.Equal(histNodeR.Data[i], (double)intData[i, 0] / numberOfPixels);
				Assert.Equal(histNodeG.Data[i], (double)intData[i, 1] / numberOfPixels);
				Assert.Equal(histNodeB.Data[i], (double)intData[i, 2] / numberOfPixels);
			}
		}
Beispiel #16
0
		public Frame Process(Frame[] input)
		{
			AnnotatedFrame frameWithLogs = (AnnotatedFrame)input[0];
			Frame result = new Frame(input[0].Size);
			for (int x = 0; x < input[0].Size.Width; x++) {
				for (int y = 0; y < input[0].Size.Height; y++) {
					/* Make result black and white first to emphasize color highlighting */
					byte average = (byte)((input[0][x, y].R + input[0][x, y].G + input[0][x, y].B) / 3);
					result[x, y] = new Rgb(average, average, average);
					result[x, y] = GetMaskedPixel(result[x, y], x + 1, y + 1, frameWithLogs.Decisions[x / 16, y / 16].PartitioningDecision);
				}
			}
			return result;
		}
Beispiel #17
0
		private Rgb GetMaskedPixel(Rgb pixel, int x, int y, MacroblockPartitioning? decision)
		{
			switch (decision) {
				case MacroblockPartitioning.InterSkip:
					if ((x % 16 == 0) || (y % 16 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, (byte)Math.Min(255, pixel.G + 100), pixel.B);
				case MacroblockPartitioning.Inter16x16:
					if ((x % 16 == 0) || (y % 16 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, (byte)Math.Min(255, pixel.G + 100), pixel.B);
				case MacroblockPartitioning.Inter16x8:
					if ((x % 16 == 0) || (y % 8 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, (byte)Math.Min(255, pixel.G + 100), pixel.B);
				case MacroblockPartitioning.Inter4x4:
					if ((x % 4 == 0) || (y % 4 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, (byte)Math.Min(255, pixel.G + 100), pixel.B);
				case MacroblockPartitioning.Inter4x8:
					if ((x % 4 == 0) || (y % 8 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, (byte)Math.Min(255, pixel.G + 100), pixel.B);
				case MacroblockPartitioning.Inter8x16:
					if ((x % 8 == 0) || (y % 16 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, (byte)Math.Min(255, pixel.G + 100), pixel.B);
				case MacroblockPartitioning.Inter8x4:
					if ((x % 8 == 0) || (y % 4 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, (byte)Math.Min(255, pixel.G + 100), pixel.B);
				case MacroblockPartitioning.Inter8x8:
					if ((x % 8 == 0) || (y % 8 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, (byte)Math.Min(255, pixel.G + 100), pixel.B);
				case MacroblockPartitioning.Inter8x8OrBelow:
					if ((x % 8 == 0) || (y % 8 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, (byte)Math.Min(255, pixel.G + 100), pixel.B);
				case MacroblockPartitioning.Intra16x16:
					if ((x % 16 == 0) || (y % 16 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb((byte)Math.Min(255, pixel.R + 80), pixel.G, (byte)Math.Min(255, pixel.B + 80));
				case MacroblockPartitioning.Intra4x4:
					if ((x % 4 == 0) || (y % 4 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb((byte)Math.Min(255, pixel.R + 80), pixel.G, (byte)Math.Min(255, pixel.B + 80));
				case MacroblockPartitioning.Intra8x8:
					if ((x % 8 == 0) || (y % 8 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb((byte)Math.Min(255, pixel.R + 80), pixel.G, (byte)Math.Min(255, pixel.B + 80));
				case MacroblockPartitioning.IntraPCM:
					if ((x % 16 == 0) || (y % 16 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb((byte)Math.Min(255, pixel.R + 80), pixel.G, (byte)Math.Min(255, pixel.B + 80));
				case MacroblockPartitioning.Unknown:
					if ((x % 16 == 0) || (y % 16 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb((byte)Math.Min(255, pixel.R + 100), pixel.G, pixel.B);
				default:
					if ((x % 16 == 0) || (y % 16 == 0))
						return new Rgb(0, 0, 0);
					else
						return new Rgb(pixel.R, pixel.G, (byte)Math.Max(255, pixel.B + 40));
			}
		}