public static void Draw(this IT8951SPIDevice device, Action <DrawingBuffer> pixelOperateCallback, ImagePixelPackEnum bpp = ImagePixelPackEnum.BPP4, ImageEndianTypeEnum endian = ImageEndianTypeEnum.BigEndian, ImageRotateEnum rotate = ImageRotateEnum.Rotate0, DisplayModeEnum mode = DisplayModeEnum.GC16) { var p = new DrawingBuffer(device, bpp); pixelOperateCallback(p); if (bpp == ImagePixelPackEnum.BPP1) { device.LoadImageArea(ImagePixelPackEnum.BPP8, endian, rotate, p.Buffer.Span, 0, 0, (ushort)(device.DeviceInfo.ScreenSize.Width / 8), (ushort)device.DeviceInfo.ScreenSize.Height); device.Set1BPPMode(true); device.RefreshScreen(DisplayModeEnum.A2); device.Set1BPPMode(false); } else { device.LoadImage(bpp, endian, rotate, p.Buffer.Span); device.RefreshScreen(mode); } }
/// <summary> /// Display a full sreen image from Image Object. /// </summary> /// <param name="device">device to present the image</param> /// <param name="image"> Image object</param> /// <param name="dither">dither the image for better visual</param> /// <param name="autoResize">Resize the image if necessary. An exception will thrown if this parameter is false and image size not equal device screen size</param> /// <param name="bpp">BitsPerPixel mode in pixel transfer. suggest use BPP4 for GC16 and BPP1 for A2 </param> /// <param name="displayMode">Display mode, GC16=16 level greyscale, A2=Balck and White</param> public static void DrawImage(this IT8951SPIDevice device, Image <L8> image, bool dither = true, bool autoResize = true, ImagePixelPackEnum bpp = ImagePixelPackEnum.BPP4, DisplayModeEnum displayMode = DisplayModeEnum.GC16) { if (displayMode == DisplayModeEnum.INIT) { throw new ArgumentOutOfRangeException(nameof(displayMode), "displayMode can't be INIT while drawing image"); } if (device.DeviceInfo.ScreenSize.Width != image.Width || device.DeviceInfo.ScreenSize.Height != image.Height) { if (!autoResize) { throw new ArgumentException("image size should be same as device screen size"); } else { var o = new ResizeOptions(); o.Size = new Size(device.DeviceInfo.ScreenSize.Width, device.DeviceInfo.ScreenSize.Height); o.Mode = ResizeMode.Pad; image.Mutate(opt => { opt.Resize(o); }); } } var p = new DrawingBuffer(device, bpp); if (dither) { switch (bpp) { case ImagePixelPackEnum.BPP2: image.Mutate(opt => { Color[] palette = new Color[4]; for (int i = 0; i < palette.Length; i++) { palette[i] = new Color(new L16((ushort)(i * 16384))); } opt.Dither(KnownDitherings.FloydSteinberg, palette); }); break; case ImagePixelPackEnum.BPP3: throw new NotImplementedException(); case ImagePixelPackEnum.BPP4: //maximum grey scale is 16 levels case ImagePixelPackEnum.BPP8: //BPP8=BPP4, 4 lower bits are ignored image.Mutate(opt => { Color[] palette = new Color[16]; for (int i = 0; i < palette.Length; i++) { palette[i] = new Color(new L16((ushort)(i * 4096))); } opt.Dither(KnownDitherings.FloydSteinberg, palette); }); break; case ImagePixelPackEnum.BPP1: image.Mutate(opt => { opt.BinaryDither(KnownDitherings.FloydSteinberg); }); break; default: break; } } Parallel.For(0, image.Height, i => { var rowBytes = image.DangerousGetPixelRowMemory(i).Span; p.WriteRow(rowBytes, i, getByteFromL8); }); if (bpp == ImagePixelPackEnum.BPP1) { ushort width = (ushort)(image.Width / 8); ushort height = (ushort)(image.Height); //use bpp8 to transfer full bytes data device.LoadImageArea(ImagePixelPackEnum.BPP8, ImageEndianTypeEnum.BigEndian, ImageRotateEnum.Rotate0, p.Buffer.Span, 0, 0, width, height); device.Set1BPPMode(true); device.RefreshArea(displayMode, 0, 0, (ushort)image.Width, (ushort)image.Height); device.Set1BPPMode(false);//restore to default display mode } else { device.LoadImage(bpp, ImageEndianTypeEnum.BigEndian, ImageRotateEnum.Rotate0, p.Buffer.Span); device.RefreshScreen(displayMode); } }