|
- /*
- * 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;
-
- namespace ZXing
- {
- /// <summary>
- /// Luminance source class which support different formats of images.
- /// </summary>
- public partial class RGBLuminanceSource : BaseLuminanceSource
- {
- /// <summary>
- /// enumeration of supported bitmap format which the RGBLuminanceSource can process
- /// </summary>
- public enum BitmapFormat
- {
- /// <summary>
- /// format of the byte[] isn't known. RGBLuminanceSource tries to determine the best possible value
- /// </summary>
- Unknown,
- /// <summary>
- /// grayscale array, the byte array is a luminance array with 1 byte per pixel
- /// </summary>
- Gray8,
- /// <summary>
- /// 3 bytes per pixel with the channels red, green and blue
- /// </summary>
- RGB24,
- /// <summary>
- /// 4 bytes per pixel with the channels red, green and blue
- /// </summary>
- RGB32,
- /// <summary>
- /// 4 bytes per pixel with the channels alpha, red, green and blue
- /// </summary>
- ARGB32,
- /// <summary>
- /// 3 bytes per pixel with the channels blue, green and red
- /// </summary>
- BGR24,
- /// <summary>
- /// 4 bytes per pixel with the channels blue, green and red
- /// </summary>
- BGR32,
- /// <summary>
- /// 4 bytes per pixel with the channels blue, green, red and alpha
- /// </summary>
- BGRA32,
- /// <summary>
- /// 2 bytes per pixel, 5 bit red, 6 bits green and 5 bits blue
- /// </summary>
- RGB565,
- /// <summary>
- /// 4 bytes per pixel with the channels red, green, blue and alpha
- /// </summary>
- RGBA32,
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class.
- /// </summary>
- /// <param name="width">The width.</param>
- /// <param name="height">The height.</param>
- protected RGBLuminanceSource(int width, int height)
- : base(width, height)
- {
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class.
- /// It supports a byte array with 3 bytes per pixel (RGB24).
- /// </summary>
- /// <param name="rgbRawBytes">The RGB raw bytes.</param>
- /// <param name="width">The width.</param>
- /// <param name="height">The height.</param>
- public RGBLuminanceSource(byte[] rgbRawBytes, int width, int height)
- : this(rgbRawBytes, width, height, BitmapFormat.RGB24)
- {
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class.
- /// It supports a byte array with 1 byte per pixel (Gray8).
- /// That means the whole array consists of the luminance values (grayscale).
- /// </summary>
- /// <param name="luminanceArray">The luminance array.</param>
- /// <param name="width">The width.</param>
- /// <param name="height">The height.</param>
- /// <param name="is8Bit">if set to <c>true</c> [is8 bit].</param>
- [Obsolete("Use RGBLuminanceSource(luminanceArray, width, height, BitmapFormat.Gray8)")]
- public RGBLuminanceSource(byte[] luminanceArray, int width, int height, bool is8Bit)
- : this(luminanceArray, width, height, BitmapFormat.Gray8)
- {
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="RGBLuminanceSource"/> class.
- /// It supports a byte array with 3 bytes per pixel (RGB24).
- /// </summary>
- /// <param name="rgbRawBytes">The RGB raw bytes.</param>
- /// <param name="width">The width.</param>
- /// <param name="height">The height.</param>
- /// <param name="bitmapFormat">The bitmap format.</param>
- public RGBLuminanceSource(byte[] rgbRawBytes, int width, int height, BitmapFormat bitmapFormat)
- : base(width, height)
- {
- CalculateLuminance(rgbRawBytes, bitmapFormat);
- }
-
- /// <summary>
- /// Should create a new luminance source with the right class type.
- /// The method is used in methods crop and rotate.
- /// </summary>
- /// <param name="newLuminances">The new luminances.</param>
- /// <param name="width">The width.</param>
- /// <param name="height">The height.</param>
- /// <returns></returns>
- protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height)
- {
- return new RGBLuminanceSource(width, height) { luminances = newLuminances };
- }
-
- private static BitmapFormat DetermineBitmapFormat(byte[] rgbRawBytes, int width, int height)
- {
- var square = width*height;
- var byteperpixel = rgbRawBytes.Length/square;
-
- switch (byteperpixel)
- {
- case 1:
- return BitmapFormat.Gray8;
- case 2:
- return BitmapFormat.RGB565;
- case 3:
- return BitmapFormat.RGB24;
- case 4:
- return BitmapFormat.RGB32;
- default:
- throw new ArgumentException("The bitmap format could not be determined. Please specify the correct value.");
- }
- }
-
- protected void CalculateLuminance(byte[] rgbRawBytes, BitmapFormat bitmapFormat)
- {
- if (bitmapFormat == BitmapFormat.Unknown)
- {
- bitmapFormat = DetermineBitmapFormat(rgbRawBytes, Width, Height);
- }
- switch (bitmapFormat)
- {
- case BitmapFormat.Gray8:
- Buffer.BlockCopy(rgbRawBytes, 0, luminances, 0, rgbRawBytes.Length < luminances.Length ? rgbRawBytes.Length : luminances.Length);
- break;
- case BitmapFormat.RGB24:
- CalculateLuminanceRGB24(rgbRawBytes);
- break;
- case BitmapFormat.BGR24:
- CalculateLuminanceBGR24(rgbRawBytes);
- break;
- case BitmapFormat.RGB32:
- CalculateLuminanceRGB32(rgbRawBytes);
- break;
- case BitmapFormat.BGR32:
- CalculateLuminanceBGR32(rgbRawBytes);
- break;
- case BitmapFormat.RGBA32:
- CalculateLuminanceRGBA32(rgbRawBytes);
- break;
- case BitmapFormat.ARGB32:
- CalculateLuminanceARGB32(rgbRawBytes);
- break;
- case BitmapFormat.BGRA32:
- CalculateLuminanceBGRA32(rgbRawBytes);
- break;
- case BitmapFormat.RGB565:
- CalculateLuminanceRGB565(rgbRawBytes);
- break;
- default:
- throw new ArgumentException("The bitmap format isn't supported.", bitmapFormat.ToString());
- }
- }
-
- private void CalculateLuminanceRGB565(byte[] rgb565RawData)
- {
- var luminanceIndex = 0;
- for (var index = 0; index < rgb565RawData.Length && luminanceIndex < luminances.Length; index += 2, luminanceIndex++)
- {
- var byte1 = rgb565RawData[index];
- var byte2 = rgb565RawData[index + 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);
- }
- }
-
- private void CalculateLuminanceRGB24(byte[] rgbRawBytes)
- {
- for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++)
- {
- // Calculate luminance cheaply, favoring green.
- int r = rgbRawBytes[rgbIndex++];
- int g = rgbRawBytes[rgbIndex++];
- int b = rgbRawBytes[rgbIndex++];
- luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
- }
- }
-
- private void CalculateLuminanceBGR24(byte[] rgbRawBytes)
- {
- for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++)
- {
- // Calculate luminance cheaply, favoring green.
- int b = rgbRawBytes[rgbIndex++];
- int g = rgbRawBytes[rgbIndex++];
- int r = rgbRawBytes[rgbIndex++];
- luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
- }
- }
-
- private void CalculateLuminanceRGB32(byte[] rgbRawBytes)
- {
- for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++)
- {
- // Calculate luminance cheaply, favoring green.
- int r = rgbRawBytes[rgbIndex++];
- int g = rgbRawBytes[rgbIndex++];
- int b = rgbRawBytes[rgbIndex++];
- rgbIndex++;
- luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
- }
- }
-
- private void CalculateLuminanceBGR32(byte[] rgbRawBytes)
- {
- for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++)
- {
- // Calculate luminance cheaply, favoring green.
- int b = rgbRawBytes[rgbIndex++];
- int g = rgbRawBytes[rgbIndex++];
- int r = rgbRawBytes[rgbIndex++];
- rgbIndex++;
- luminances[luminanceIndex] = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
- }
- }
-
- private void CalculateLuminanceBGRA32(byte[] rgbRawBytes)
- {
- for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++)
- {
- // Calculate luminance cheaply, favoring green.
- var b = rgbRawBytes[rgbIndex++];
- var g = rgbRawBytes[rgbIndex++];
- var r = rgbRawBytes[rgbIndex++];
- var alpha = rgbRawBytes[rgbIndex++];
- var luminance = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
- luminances[luminanceIndex] = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8));
- }
- }
-
- private void CalculateLuminanceRGBA32(byte[] rgbRawBytes)
- {
- for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++)
- {
- // Calculate luminance cheaply, favoring green.
- var r = rgbRawBytes[rgbIndex++];
- var g = rgbRawBytes[rgbIndex++];
- var b = rgbRawBytes[rgbIndex++];
- var alpha = rgbRawBytes[rgbIndex++];
- var luminance = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
- luminances[luminanceIndex] = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8));
- }
- }
-
- private void CalculateLuminanceARGB32(byte[] rgbRawBytes)
- {
- for (int rgbIndex = 0, luminanceIndex = 0; rgbIndex < rgbRawBytes.Length && luminanceIndex < luminances.Length; luminanceIndex++)
- {
- // Calculate luminance cheaply, favoring green.
- var alpha = rgbRawBytes[rgbIndex++];
- var r = rgbRawBytes[rgbIndex++];
- var g = rgbRawBytes[rgbIndex++];
- var b = rgbRawBytes[rgbIndex++];
- var luminance = (byte)((RChannelWeight * r + GChannelWeight * g + BChannelWeight * b) >> ChannelWeight);
- luminances[luminanceIndex] = (byte)(((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8));
- }
- }
- }
- }
|