public void RenderColoredGray2(ColoredFrame frame) { SetPalette(frame.Palette, frame.PaletteIndex); var joinedFrame = FrameUtil.Join(DmdWidth, DmdHeight, frame.Planes); // send frame buffer to device RenderGray4(FrameUtil.ConvertGrayToGray(joinedFrame, new byte[] { 0x0, 0x1, 0x4, 0xf })); }
public void RenderColoredGray2(byte[][] planes, Color[] palette) { SetPalette(palette); var frame = FrameUtil.Join(DmdWidth, DmdHeight, planes); // send frame buffer to device RenderGray4(FrameUtil.ConvertGrayToGray(frame, new byte[] { 0x0, 0x1, 0x4, 0xf })); }
public void RenderGray2(byte[] frame) { // 2-bit frames are rendered as 4-bit RenderGray4(FrameUtil.ConvertGrayToGray(frame, new byte[] { 0x0, 0x1, 0x4, 0xf })); }
public void RenderGray2(byte[] frame) { RenderGray4(FrameUtil.ConvertGrayToGray(frame, new byte[] { 0x0, 0x1, 0x4, 0xf })); }
/// <summary> /// Connects a source with a destination and defines in which mode data is /// sent and received. /// </summary> /// <remarks> /// Note that render bitlength is enforced, i.e. even if the destination /// supports the "from" bitlength, it will be converted to the given "to" /// bitlength. /// </remarks> /// <param name="source">Source to subscribe to</param> /// <param name="dest">Destination to send the data to</param> /// <param name="from">Data format to read from source (incompatible source will throw exception)</param> /// <param name="to">Data forma to send to destination (incompatible destination will throw exception)</param> private void Connect(ISource source, IDestination dest, FrameFormat from, FrameFormat to) { var destFixedSize = dest as IFixedSizeDestination; var destGray2 = dest as IGray2Destination; var destGray4 = dest as IGray4Destination; var destRgb24 = dest as IRgb24Destination; var destBitmap = dest as IBitmapDestination; var destColoredGray2 = dest as IColoredGray2Destination; var destColoredGray4 = dest as IColoredGray4Destination; var scheduler = Scheduler.Default; Logger.Info("Connecting {0} to {1} ({2} => {3})", source.Name, dest.Name, from.ToString(), to.ToString()); switch (from) { // source is gray2: case FrameFormat.Gray2: var sourceGray2 = source as IGray2Source; switch (to) { // gray2 -> gray2 case FrameFormat.Gray2: AssertCompatibility(source, sourceGray2, dest, destGray2, from, to); _activeSources.Add(sourceGray2.GetGray2Frames() .Select(frame => TransformGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray2.RenderGray2)); break; // gray2 -> gray4 case FrameFormat.Gray4: throw new NotImplementedException("Cannot convert from gray2 to gray4 (every gray4 destination should be able to do gray2 as well)."); // gray2 -> rgb24 case FrameFormat.Rgb24: AssertCompatibility(source, sourceGray2, dest, destRgb24, from, to); _activeSources.Add(sourceGray2.GetGray2Frames() .Select(frame => ColorizeGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame)) .Select(frame => TransformRgb24(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destRgb24.RenderRgb24)); break; // gray2 -> bitmap case FrameFormat.Bitmap: AssertCompatibility(source, sourceGray2, dest, destBitmap, from, to); _activeSources.Add(sourceGray2.GetGray2Frames() .Select(frame => ImageUtil.ConvertFromRgb24( source.Dimensions.Value.Width, source.Dimensions.Value.Height, ColorizeGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame) )) .Select(bmp => Transform(bmp, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destBitmap.RenderBitmap)); break; // gray2 -> colored gray2 case FrameFormat.ColoredGray2: throw new NotImplementedException("Cannot convert from gray2 to colored gray2 (doesn't make any sense, colored gray2 can also do gray2)."); // gray2 -> colored gray4 case FrameFormat.ColoredGray4: throw new NotImplementedException("Cannot convert from gray2 to colored gray2 (a colored gray4 destination should also be able to do gray2 directly)."); default: throw new ArgumentOutOfRangeException(nameof(to), to, null); } break; // source is gray4: case FrameFormat.Gray4: var sourceGray4 = source as IGray4Source; switch (to) { // gray4 -> gray2 case FrameFormat.Gray2: AssertCompatibility(source, sourceGray4, dest, destGray2, from, to); _activeSources.Add(sourceGray4.GetGray4Frames() .Select(frame => FrameUtil.ConvertGrayToGray(frame, new byte[] { 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3 })) .Select(frame => TransformGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray2.RenderGray2)); break; // gray4 -> gray4 case FrameFormat.Gray4: AssertCompatibility(source, sourceGray4, dest, destGray4, from, to); _activeSources.Add(sourceGray4.GetGray4Frames() .Select(frame => TransformGray4(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray4.RenderGray4)); break; // gray4 -> rgb24 case FrameFormat.Rgb24: AssertCompatibility(source, sourceGray4, dest, destRgb24, from, to); _activeSources.Add(sourceGray4.GetGray4Frames() .Select(frame => ColorizeGray4(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame)) .Select(frame => TransformRgb24(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destRgb24.RenderRgb24)); break; // gray4 -> bitmap case FrameFormat.Bitmap: AssertCompatibility(source, sourceGray4, dest, destBitmap, from, to); _activeSources.Add(sourceGray4.GetGray4Frames() .Select(frame => ImageUtil.ConvertFromRgb24( source.Dimensions.Value.Width, source.Dimensions.Value.Height, ColorizeGray4(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame) )) .Select(bmp => Transform(bmp, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destBitmap.RenderBitmap)); break; // gray4 -> colored gray2 case FrameFormat.ColoredGray2: throw new NotImplementedException("Cannot convert from gray4 to colored gray2 (doesn't make any sense, colored gray2 can also do gray4)."); // gray4 -> colored gray4 case FrameFormat.ColoredGray4: throw new NotImplementedException("Cannot convert from gray2 to colored gray2 (doesn't make any sense, colored gray4 can also do gray4)."); default: throw new ArgumentOutOfRangeException(nameof(to), to, null); } break; // source is rgb24: case FrameFormat.Rgb24: var sourceRgb24 = source as IRgb24Source; switch (to) { // rgb24 -> gray2 case FrameFormat.Gray2: AssertCompatibility(source, sourceRgb24, dest, destGray2, from, to); _activeSources.Add(sourceRgb24.GetRgb24Frames() .Select(frame => ImageUtil.ConvertToGray(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, 4)) .Select(frame => TransformGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray2.RenderGray2)); break; // rgb24 -> gray4 case FrameFormat.Gray4: AssertCompatibility(source, sourceRgb24, dest, destGray4, from, to); _activeSources.Add(sourceRgb24.GetRgb24Frames() .Select(frame => ImageUtil.ConvertToGray(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, 16)) .Select(frame => TransformGray4(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray4.RenderGray4)); break; // rgb24 -> rgb24 case FrameFormat.Rgb24: AssertCompatibility(source, sourceRgb24, dest, destRgb24, from, to); _activeSources.Add(sourceRgb24.GetRgb24Frames() .Select(frame => TransformRgb24(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destRgb24.RenderRgb24)); break; // rgb24 -> bitmap case FrameFormat.Bitmap: AssertCompatibility(source, sourceRgb24, dest, destBitmap, from, to); _activeSources.Add(sourceRgb24.GetRgb24Frames() .Select(frame => ImageUtil.ConvertFromRgb24(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame)) .Select(bmp => Transform(bmp, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destBitmap.RenderBitmap)); break; // rgb24 -> colored gray2 case FrameFormat.ColoredGray2: throw new NotImplementedException("Cannot convert from rgb24 to colored gray2 (colored gray2 only has 4 colors per frame)."); // rgb24 -> colored gray4 case FrameFormat.ColoredGray4: throw new NotImplementedException("Cannot convert from rgb24 to colored gray2 (colored gray4 only has 16 colors per frame)."); default: throw new ArgumentOutOfRangeException(nameof(to), to, null); } break; // source is bitmap: case FrameFormat.Bitmap: var sourceBitmap = source as IBitmapSource; switch (to) { // bitmap -> gray2 case FrameFormat.Gray2: AssertCompatibility(source, sourceBitmap, dest, destGray2, from, to); _activeSources.Add(sourceBitmap.GetBitmapFrames() .Select(bmp => ImageUtil.ConvertToGray2(bmp)) .Select(frame => TransformGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray2.RenderGray2)); break; // bitmap -> gray4 case FrameFormat.Gray4: AssertCompatibility(source, sourceBitmap, dest, destGray4, from, to); _activeSources.Add(sourceBitmap.GetBitmapFrames() .Select(bmp => ImageUtil.ConvertToGray4(bmp)) .Select(frame => TransformGray4(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray4.RenderGray4)); break; // bitmap -> rgb24 case FrameFormat.Rgb24: AssertCompatibility(source, sourceBitmap, dest, destRgb24, from, to); _activeSources.Add(sourceBitmap.GetBitmapFrames() .Select(bmp => ImageUtil.ConvertToRgb24(bmp)) .Select(frame => TransformRgb24(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destRgb24.RenderRgb24)); break; // bitmap -> bitmap case FrameFormat.Bitmap: AssertCompatibility(Source, sourceBitmap, dest, destBitmap, from, to); _activeSources.Add(sourceBitmap.GetBitmapFrames() .Select(bmp => Transform(bmp, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destBitmap.RenderBitmap)); break; // bitmap -> colored gray2 case FrameFormat.ColoredGray2: throw new NotImplementedException("Cannot convert from bitmap to colored gray2 (colored gray2 only has 4 colors per frame)."); // bitmap -> colored gray4 case FrameFormat.ColoredGray4: throw new NotImplementedException("Cannot convert from bitmap to colored gray2 (colored gray4 only has 16 colors per frame)."); default: throw new ArgumentOutOfRangeException(nameof(to), to, null); } break; // source is colored gray2: case FrameFormat.ColoredGray2: var sourceColoredGray2 = source as IColoredGray2Source; switch (to) { // colored gray2 -> gray2 case FrameFormat.Gray2: AssertCompatibility(source, sourceColoredGray2, dest, destGray2, from, to); _activeSources.Add(sourceColoredGray2.GetColoredGray2Frames() .Select(x => FrameUtil.Join(source.Dimensions.Value.Width, source.Dimensions.Value.Height, x.Item1)) .Select(frame => TransformGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray2.RenderGray2)); break; // colored gray2 -> gray4 case FrameFormat.Gray4: throw new NotImplementedException("Cannot convert from colored gray2 to gray4 (it's not like we can extract luminosity from the colors...)"); // colored gray2 -> rgb24 case FrameFormat.Rgb24: AssertCompatibility(source, sourceColoredGray2, dest, destRgb24, from, to); _activeSources.Add(sourceColoredGray2.GetColoredGray2Frames() .Select(x => ColorUtil.ColorizeFrame( source.Dimensions.Value.Width, source.Dimensions.Value.Height, FrameUtil.Join(source.Dimensions.Value.Width, source.Dimensions.Value.Height, x.Item1), x.Item2) ) .Select(frame => TransformRgb24(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destRgb24.RenderRgb24)); break; // colored gray2 -> bitmap case FrameFormat.Bitmap: AssertCompatibility(source, sourceColoredGray2, dest, destBitmap, from, to); _activeSources.Add(sourceColoredGray2.GetColoredGray2Frames() .Select(x => ColorUtil.ColorizeFrame( source.Dimensions.Value.Width, source.Dimensions.Value.Height, FrameUtil.Join(source.Dimensions.Value.Width, source.Dimensions.Value.Height, x.Item1), x.Item2) ) .Select(frame => ImageUtil.ConvertFromRgb24(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame)) .Select(bmp => Transform(bmp, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destBitmap.RenderBitmap)); break; // colored gray2 -> colored gray2 case FrameFormat.ColoredGray2: AssertCompatibility(source, sourceColoredGray2, dest, destColoredGray2, from, to); _activeSources.Add(sourceColoredGray2.GetColoredGray2Frames() .Select(x => TransformColoredGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, x.Item1, x.Item2, destFixedSize)) .ObserveOn(scheduler) .Subscribe(x => destColoredGray2.RenderColoredGray2(x.Item1, x.Item2))); break; // colored gray2 -> colored gray4 case FrameFormat.ColoredGray4: throw new NotImplementedException("Cannot convert from colored gray2 to colored gray4 (if a destination can do colored gray4 it should be able to do colored gray2 directly)."); default: throw new ArgumentOutOfRangeException(nameof(to), to, null); } break; // source is colored gray4: case FrameFormat.ColoredGray4: var sourceColoredGray4 = source as IColoredGray4Source; switch (to) { // colored gray4 -> gray2 case FrameFormat.Gray2: AssertCompatibility(source, sourceColoredGray4, dest, destGray2, from, to); _activeSources.Add(sourceColoredGray4.GetColoredGray4Frames() .Select(x => FrameUtil.Join(source.Dimensions.Value.Width, source.Dimensions.Value.Height, x.Item1)) .Select(frame => FrameUtil.ConvertGrayToGray(frame, new byte[] { 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, 0x2, 0x3, 0x3, 0x3, 0x3 })) .Select(frame => TransformGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray2.RenderGray2)); break; // colored gray4 -> gray4 case FrameFormat.Gray4: AssertCompatibility(source, sourceColoredGray4, dest, destGray4, from, to); _activeSources.Add(sourceColoredGray4.GetColoredGray4Frames() .Select(x => FrameUtil.Join(source.Dimensions.Value.Width, source.Dimensions.Value.Height, x.Item1)) .Select(frame => TransformGray2(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destGray4.RenderGray4)); break; // colored gray4 -> rgb24 case FrameFormat.Rgb24: AssertCompatibility(source, sourceColoredGray4, dest, destRgb24, from, to); _activeSources.Add(sourceColoredGray4.GetColoredGray4Frames() .Select(x => ColorUtil.ColorizeFrame( source.Dimensions.Value.Width, source.Dimensions.Value.Height, FrameUtil.Join(source.Dimensions.Value.Width, source.Dimensions.Value.Height, x.Item1), x.Item2) ) .Select(frame => TransformRgb24(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destRgb24.RenderRgb24)); break; // colored gray4 -> bitmap case FrameFormat.Bitmap: AssertCompatibility(source, sourceColoredGray4, dest, destBitmap, from, to); _activeSources.Add(sourceColoredGray4.GetColoredGray4Frames() .Select(x => ColorUtil.ColorizeFrame( source.Dimensions.Value.Width, source.Dimensions.Value.Height, FrameUtil.Join(source.Dimensions.Value.Width, source.Dimensions.Value.Height, x.Item1), x.Item2) ) .Select(frame => ImageUtil.ConvertFromRgb24(source.Dimensions.Value.Width, source.Dimensions.Value.Height, frame)) .Select(bmp => Transform(bmp, destFixedSize)) .ObserveOn(scheduler) .Subscribe(destBitmap.RenderBitmap)); break; // colored gray4 -> colored gray2 case FrameFormat.ColoredGray2: throw new NotImplementedException("Cannot convert from colored gray4 to colored gray2 (use rgb24 instead of down-coloring)."); // colored gray4 -> colored gray4 case FrameFormat.ColoredGray4: AssertCompatibility(source, sourceColoredGray4, dest, destColoredGray4, from, to); _activeSources.Add(sourceColoredGray4.GetColoredGray4Frames() .Select(x => TransformColoredGray4(source.Dimensions.Value.Width, source.Dimensions.Value.Height, x.Item1, x.Item2, destFixedSize)) .ObserveOn(scheduler) .Subscribe(x => destColoredGray4.RenderColoredGray4(x.Item1, x.Item2))); break; default: throw new ArgumentOutOfRangeException(nameof(to), to, null); } break; default: throw new ArgumentOutOfRangeException(); } }