private bool EnsureBuffersCompatible(PipeFrame frame) { if (_mappedFile1 != null && _mapView1 != null && _mappedFile2 != null && _mapView2 != null && _buffer1 != null && _buffer2 != null && _buffersSize.Width == frame.Width && _buffersSize.Height == frame.Height) { return(true); } try { ReleaseHandles(); lock (mapViewLock) { _mappedFile1 = MemoryMappedFile.OpenExisting("cnc_buffer_spy1", MemoryMappedFileRights.Read); _mapView1 = _mappedFile1.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); _mappedFile2 = MemoryMappedFile.OpenExisting("cnc_buffer_spy2", MemoryMappedFileRights.Read); _mapView2 = _mappedFile2.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); } lock (canvas.ImageLock) { canvas.Image = null; _buffer1 = new Bitmap((int)frame.Width, (int)frame.Height, PixelFormat.Format24bppRgb); _buffer2 = new Bitmap((int)frame.Width, (int)frame.Height, PixelFormat.Format24bppRgb); } _buffersSize = new Size((int)frame.Width, (int)frame.Height); return(true); } catch { return(false); } }
private unsafe Bitmap ImageFromMappedFileView(PipeFrame frame) { if (!EnsureBuffersCompatible(frame)) { return(null); } var view = frame.DestBuffer == DestinationBuffer.Buffer1 ? _mapView1 : _mapView2; var bm = frame.DestBuffer == DestinationBuffer.Buffer1 ? _buffer1 : _buffer2; // Debug.Assert(bm != canvas.Image); // this assert would only work under a lock {} byte *ptr = null; view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr); var bmd = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); bool jet = ckbJetColormap.Checked; int anchorX = (int)((frame.SourceBufferAnchor / 2) % frame.Width); int anchorY = (int)((frame.SourceBufferAnchor / 2) / frame.Width); if (frame.PixelFormat == BufferPixelFormat.Format16bppGrayscale) { Blit16bppGrayscale(frame, ptr, bmd, anchorY, anchorX, jet); } if (frame.PixelFormat == BufferPixelFormat.Format16bppRGB) { Blit16bppRGB(frame, ptr, bmd, anchorY, anchorX); } else if (frame.PixelFormat == BufferPixelFormat.Format8bpp) { Blit8bpp(frame, ptr, bmd, anchorX, anchorY); } view.SafeMemoryMappedViewHandle.ReleasePointer(); bm.UnlockBits(bmd); lock (mapViewLock) _mapViewOfShownImage = view; _lastFrame = frame; return(bm); }
private unsafe void Blit8bpp(PipeFrame frame, byte *ptr, BitmapData bmd, int anchorX, int anchorY) { for (int row = 0; row < bmd.Height; row++) { byte *w = (byte *)bmd.Scan0.ToPointer() + row * bmd.Stride; byte *r = ptr + ((row + anchorY) % frame.Height) * frame.Width; int endCol = (int)((anchorX + frame.Width - 1) % frame.Width); for (int col = anchorX; col != endCol;) { // low byte *w++ = r[col]; *w++ = r[col]; *w++ = r[col]; col++; if (col == frame.Width) { col = 0; } } } }
private static unsafe void Blit16bppRGB(PipeFrame frame, byte *ptr, BitmapData bmd, int anchorY, int anchorX) { for (int row = 0; row < bmd.Height; row++) { byte * w = (byte *)bmd.Scan0.ToPointer() + row * bmd.Stride; ushort *scan = (ushort *)(ptr + 2 * ((row + anchorY) % frame.Height) * frame.Width); int endCol = (int)((anchorX + frame.Width - 1) % frame.Width); for (int col = anchorX; col != endCol;) { ushort bgr565 = scan[col]; * w++ = (byte)((bgr565 & 0x001F) << 3); // b * w++ = (byte)((bgr565 & 0x07E0) >> 3); // g * w++ = (byte)((bgr565 & 0xF800) >> 8); // r col++; if (col == frame.Width) { col = 0; } } } }
private static unsafe void Blit16bppGrayscale(PipeFrame frame, byte *ptr, BitmapData bmd, int anchorY, int anchorX, bool jet) { // determine range ushort *p = (ushort *)ptr; ushort min = 65535; ushort max = 0; if (jet) { ushort *end = p + frame.Width * frame.Height; while (p != end) { if (min > *p) { min = *p; } if (max < *p) { max = *p; } ++p; } } float range = max - min; for (int row = 0; row < bmd.Height; row++) { byte *w = (byte *)bmd.Scan0.ToPointer() + row * bmd.Stride; byte *scan = ptr + 2 * ((row + anchorY) % frame.Height) * frame.Width; int endCol = (int)((anchorX + frame.Width - 1) % frame.Width); for (int col = anchorX; col != endCol;) { if (jet) { ushort u = (ushort)((scan[col * 2 + 1] << 8) | scan[col * 2]); float v = 2 * (u - min) / range; byte b = (byte)Math.Max(0, 255 * (1 - v)); byte r = (byte)Math.Max(0, 255 * (v - 1)); byte g = (byte)(255 - b - r); * w++ = g; * w++ = b; * w++ = r; } else { // low byte *w++ = scan[col * 2 + 0]; *w++ = scan[col * 2 + 0]; *w++ = scan[col * 2 + 0]; } col++; if (col == frame.Width) { col = 0; } } } }