Skip to content

Commit

Permalink
Merge pull request #79 from hig-dev/SimpleSoftwareBitmapLuminanceSource
Browse files Browse the repository at this point in the history
Simpler SoftwareBitmapLuminanceSource
  • Loading branch information
Redth committed Oct 23, 2023
2 parents d32ca7a + 9fcfd6b commit bc10aa7
Showing 1 changed file with 11 additions and 61 deletions.
72 changes: 11 additions & 61 deletions ZXing.Net.MAUI/Platforms/Windows/SoftwareBitmapLuminanceSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,11 @@
using System.Text;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;
using WinRT;

namespace ZXing.Net.Maui;

[ComImport]
[Guid("5b0d3235-4dba-4d44-865e-8f1d0e4fd04d")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
void GetBuffer(out byte* buffer, out uint capacity);
}

public class SoftwareBitmapLuminanceSource : BaseLuminanceSource
{
public SoftwareBitmapLuminanceSource(SoftwareBitmap softwareBitmap) : base(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight)
Expand All @@ -33,59 +26,16 @@ protected SoftwareBitmapLuminanceSource(byte[] luminanceArray, int width, int he
protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height)
=> new SoftwareBitmapLuminanceSource(width, height) { luminances = newLuminances };

unsafe void CalculateLuminance(SoftwareBitmap bitmap)
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 bufferRef = buffer.CreateReference())
{
//See https://github.com/microsoft/CsWinRT/issues/646#issuecomment-754161785
var reference = bufferRef.As<IMemoryBufferByteAccess>();
if (reference != null)
{
try
{
// Get a pointer to the pixel buffer
byte* data;
uint capacity;
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);
}
}
}
}
if (bitmap.BitmapPixelFormat != BitmapPixelFormat.Gray8)
{
using SoftwareBitmap convertedSoftwareBitmap = SoftwareBitmap.Convert(bitmap, BitmapPixelFormat.Gray8);
convertedSoftwareBitmap.CopyToBuffer(luminances.AsBuffer());
}
else
{
bitmap.CopyToBuffer(luminances.AsBuffer());
}
}
}

0 comments on commit bc10aa7

Please sign in to comment.