/* * Copyright 2012 ZXing.Net authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System.Windows; #if NETFX_CORE using Windows.UI.Xaml.Media.Imaging; #else using System.Windows.Media; using System.Windows.Media.Imaging; #endif namespace ZXing { /// /// class which represents the luminance source values for bitmap source objects /// public partial class BitmapSourceLuminanceSource : BaseLuminanceSource { /// /// Initializes a new instance of the class. /// /// The width. /// The height. protected BitmapSourceLuminanceSource(int width, int height) : base(width, height) { } /// /// Initializes a new instance of the class. /// /// The bitmap. public BitmapSourceLuminanceSource(BitmapSource bitmap) : base(bitmap.PixelWidth, bitmap.PixelHeight) { switch (bitmap.Format.ToString()) { case "Bgr24": case "Bgr32": CalculateLuminanceBGR(bitmap); break; case "Bgra32": CalculateLuminanceBGRA(bitmap); break; case "Rgb24": CalculateLuminanceRGB(bitmap); break; case "Bgr565": CalculateLuminanceBGR565(bitmap); break; default: // there is no special conversion routine to luminance values // we have to convert the image to a supported format bitmap = new FormatConvertedBitmap(bitmap, PixelFormats.Bgra32, null, 0); CalculateLuminanceBGR(bitmap); break; } } private void CalculateLuminanceRGB(BitmapSource bitmap) { var width = bitmap.PixelWidth; var height = bitmap.PixelHeight; var stepX = (bitmap.Format.BitsPerPixel + 7) / 8; var bufferSize = width * stepX; var buffer = new byte[bufferSize]; var rect = new Int32Rect(0, 0, width, 1); var luminanceIndex = 0; for (var curY = 0; curY < height; curY++) { bitmap.CopyPixels(rect, buffer, bufferSize, 0); for (var curX = 0; curX < bufferSize; curX += stepX) { var r = buffer[curX]; var g = buffer[curX + 1]; var b = buffer[curX + 2]; luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); luminanceIndex++; } rect.Y++; } } private void CalculateLuminanceBGR(BitmapSource bitmap) { var width = bitmap.PixelWidth; var height = bitmap.PixelHeight; var stepX = (bitmap.Format.BitsPerPixel + 7) / 8; var bufferSize = width * stepX; var buffer = new byte[bufferSize]; var rect = new Int32Rect(0, 0, width, 1); var luminanceIndex = 0; for (var curY = 0; curY < height; curY++) { bitmap.CopyPixels(rect, buffer, bufferSize, 0); for (var curX = 0; curX < bufferSize; curX += stepX) { var b = buffer[curX]; var g = buffer[curX + 1]; var r = buffer[curX + 2]; luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); luminanceIndex++; } rect.Y++; } } private void CalculateLuminanceBGRA(BitmapSource bitmap) { var width = bitmap.PixelWidth; var height = bitmap.PixelHeight; var stepX = (bitmap.Format.BitsPerPixel + 7) / 8; var bufferSize = width * stepX; var buffer = new byte[bufferSize]; var rect = new Int32Rect(0, 0, width, 1); var luminanceIndex = 0; for (var curY = 0; curY < height; curY++) { bitmap.CopyPixels(rect, buffer, bufferSize, 0); for (var curX = 0; curX < bufferSize; curX += stepX) { var b = buffer[curX]; var g = buffer[curX + 1]; var r = buffer[curX + 2]; var luminance = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight); var alpha = buffer[curX + 3]; luminance = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8)); luminances[luminanceIndex] = luminance; luminanceIndex++; } rect.Y++; } } private void CalculateLuminanceBGR565(BitmapSource bitmap) { var width = bitmap.PixelWidth; var height = bitmap.PixelHeight; var stepX = (bitmap.Format.BitsPerPixel + 7) / 8; var bufferSize = width * stepX; var buffer = new byte[bufferSize]; var rect = new Int32Rect(0, 0, width, 1); var luminanceIndex = 0; for (var curY = 0; curY < height; curY++) { bitmap.CopyPixels(rect, buffer, bufferSize, 0); for (var curX = 0; curX < bufferSize; curX += stepX) { var byte1 = buffer[curX]; var byte2 = buffer[curX + 1]; var b5 = byte1 & 0x1F; var g5 = (((byte1 & 0xE0) >> 5) | ((byte2 & 0x03) << 3)) & 0x1F; var r5 = (byte2 >> 2) & 0x1F; var r8 = (r5 * 527 + 23) >> 6; var g8 = (g5 * 527 + 23) >> 6; var b8 = (b5 * 527 + 23) >> 6; // cheap, not fully accurate conversion //var pixel = (byte2 << 8) | byte1; //b8 = (((pixel) & 0x001F) << 3); //g8 = (((pixel) & 0x07E0) >> 2) & 0xFF; //r8 = (((pixel) & 0xF800) >> 8); luminances[luminanceIndex] = (byte)((RChannelWeight * r8 + GChannelWeight * g8 + BChannelWeight * b8) >> ChannelWeight); luminanceIndex++; } rect.Y++; } } /// /// Should create a new luminance source with the right class type. /// The method is used in methods crop and rotate. /// /// The new luminances. /// The width. /// The height. /// protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height) { return new BitmapSourceLuminanceSource(width, height) { luminances = newLuminances }; } } }