private unsafe void CalculateLuminance(SoftwareBitmap bitmap) { // Effect is hard-coded to operate on BGRA8 format only if (bitmap.BitmapPixelFormat == BitmapPixelFormat.Bgra8) { // In BGRA8 format, each pixel is defined by 4 bytes const int BYTES_PER_PIXEL = 4; using (var buffer = bitmap.LockBuffer(BitmapBufferAccessMode.Read)) using (var reference = buffer.CreateReference()) { if (reference is IMemoryBufferByteAccess) { try { // Get a pointer to the pixel buffer byte* data; uint capacity; ((IMemoryBufferByteAccess)reference).GetBuffer(out data, out capacity); // Get information about the BitmapBuffer var desc = buffer.GetPlaneDescription(0); var luminanceIndex = 0; // Iterate over all pixels for (uint row = 0; row < desc.Height; row++) { for (uint col = 0; col < desc.Width; col++) { // Index of the current pixel in the buffer (defined by the next 4 bytes, BGRA8) var currPixel = desc.StartIndex + desc.Stride * row + BYTES_PER_PIXEL * col; // Read the current pixel information into b,g,r channels (leave out alpha channel) var b = data[currPixel + 0]; // Blue var g = data[currPixel + 1]; // Green var r = data[currPixel + 2]; // Red var luminance = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); var alpha = data[currPixel + 3]; luminance = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8)); luminances[luminanceIndex] = luminance; luminanceIndex++; } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Luminance Source Failed: {0}", ex); } } } } }
/// <summary> /// Transform image into Bgra8 image using given transform method. /// </summary> /// <param name="softwareBitmap">Input image to transform.</param> /// <param name="transformScanline">Method to map pixels in a scanline.</param> private static unsafe SoftwareBitmap TransformBitmap(SoftwareBitmap softwareBitmap, TransformScanline transformScanline) { // XAML Image control only supports premultiplied Bgra8 format. var outputBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, softwareBitmap.PixelWidth, softwareBitmap.PixelHeight, BitmapAlphaMode.Premultiplied); using (var input = softwareBitmap.LockBuffer(BitmapBufferAccessMode.Read)) using (var output = outputBitmap.LockBuffer(BitmapBufferAccessMode.Write)) { // Get stride values to calculate buffer position for a given pixel x and y position. int inputStride = input.GetPlaneDescription(0).Stride; int outputStride = output.GetPlaneDescription(0).Stride; int pixelWidth = softwareBitmap.PixelWidth; int pixelHeight = softwareBitmap.PixelHeight; using (var outputReference = output.CreateReference()) using (var inputReference = input.CreateReference()) { // Get input and output byte access buffers. byte* inputBytes; uint inputCapacity; ((IMemoryBufferByteAccess)inputReference).GetBuffer(out inputBytes, out inputCapacity); byte* outputBytes; uint outputCapacity; ((IMemoryBufferByteAccess)outputReference).GetBuffer(out outputBytes, out outputCapacity); // Iterate over all pixels and store converted value. for (int y = 0; y < pixelHeight; y++) { byte* inputRowBytes = inputBytes + y * inputStride; byte* outputRowBytes = outputBytes + y * outputStride; transformScanline(pixelWidth, inputRowBytes, outputRowBytes); } } } return outputBitmap; }
/// <summary> /// Applies a basic effect to a Bgra8 SoftwareBitmap in-place /// </summary> /// <param name="bitmap">SoftwareBitmap that will receive the effect</param> private unsafe void ApplyGreenFilter(SoftwareBitmap bitmap) { // Effect is hard-coded to operate on BGRA8 format only if (bitmap.BitmapPixelFormat == BitmapPixelFormat.Bgra8) { // In BGRA8 format, each pixel is defined by 4 bytes const int BYTES_PER_PIXEL = 4; using (var buffer = bitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite)) using (var reference = buffer.CreateReference()) { if (reference is IMemoryBufferByteAccess) { // Get a pointer to the pixel buffer byte* data; uint capacity; ((IMemoryBufferByteAccess)reference).GetBuffer(out data, out capacity); // Get information about the BitmapBuffer var desc = buffer.GetPlaneDescription(0); // Iterate over all pixels for (uint row = 0; row < desc.Height; row++) { for (uint col = 0; col < desc.Width; col++) { // Index of the current pixel in the buffer (defined by the next 4 bytes, BGRA8) var currPixel = desc.StartIndex + desc.Stride * row + BYTES_PER_PIXEL * col; // Read the current pixel information into b,g,r channels (leave out alpha channel) var b = data[currPixel + 0]; // Blue var g = data[currPixel + 1]; // Green var r = data[currPixel + 2]; // Red // Boost the green channel, leave the other two untouched data[currPixel + 0] = b; data[currPixel + 1] = (byte)Math.Min(g + 80, 255); data[currPixel + 2] = r; } } } } } }
/// <summary> /// /// </summary> /// <param name="bitmap"></param> private unsafe void EncodeStream(SoftwareBitmap bitmap) { using (BitmapBuffer buffer = bitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite)) using (var bufferReference = buffer.CreateReference()) { if (bufferReference is IMemoryBufferByteAccess) { byte* frameByte; uint capacity; ((IMemoryBufferByteAccess)bufferReference).GetBuffer(out frameByte, out capacity); var bufferDescription = buffer.GetPlaneDescription(0); byte[] frameData = new byte[bufferDescription.Height * bufferDescription.Width]; Marshal.Copy((IntPtr)frameByte, frameData, 0, frameData.Length); encoder.Ffmpeg_encodeVideoFrame(frameData); } } }