Exemple #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Binarizer"/> class.
 /// </summary>
 /// <param name="source">The source.</param>
 protected internal Binarizer(LuminanceSource source)
 {
    if (source == null)
    {
       throw new ArgumentException("Source must be non-null.");
    }
    this.source = source;
 }
Exemple #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Binarizer"/> class.
 /// </summary>
 /// <param name="source">The source.</param>
 protected internal HybridBinarizer(LuminanceSource source)
 {
     if (source == null)
     {
         throw new ArgumentException("Source must be non-null.");
     }
     this.source = source;
 }
Exemple #3
0
        /// <summary>
        /// Returns a new object with rotated image data by 45 degrees counterclockwise.
        /// Only callable if <see cref="RotateSupported"/> is true.
        /// </summary>
        /// <returns>A rotated version of this object.</returns>
        public BinaryBitmap rotateCounterClockwise45()
        {
            LuminanceSource newSource = binarizer.LuminanceSource.rotateCounterClockwise45();

            return(new BinaryBitmap(binarizer.createBinarizer(newSource)));
        }
        /// <summary>
        /// Tries to decode barcodes within an image which is given by a luminance source.
        /// That method gives a chance to prepare a luminance source completely before calling
        /// the time consuming decoding method. On the other hand there is a chance to create
        /// a luminance source which is independent from external resources (like Bitmap objects)
        /// and the decoding call can be made in a background thread.
        /// </summary>
        /// <param name="luminanceSource">The luminance source.</param>
        /// <returns></returns>
        public virtual Result[] DecodeMultiple(LuminanceSource luminanceSource)
        {
            var results = default(Result[]);
            var binarizer = CreateBinarizer(luminanceSource);
            var binaryBitmap = new BinaryBitmap(binarizer);
            var rotationCount = 0;
            var rotationMaxCount = 1;
            MultipleBarcodeReader multiReader = null;

            if (AutoRotate)
            {
                Options.Hints[DecodeHintType.TRY_HARDER_WITHOUT_ROTATION] = true;
                rotationMaxCount = 4;
            }

            var formats = Options.PossibleFormats;
            if (formats != null &&
                formats.Count == 1 &&
                formats.Contains(BarcodeFormat.QR_CODE))
            {
                multiReader = new QRCodeMultiReader();
            }
            else
            {
                multiReader = new GenericMultipleBarcodeReader(Reader);
            }

            for (; rotationCount < rotationMaxCount; rotationCount++)
            {
                results = multiReader.decodeMultiple(binaryBitmap, Options.Hints);

                if (results == null)
                {
                    if (TryInverted && luminanceSource.InversionSupported)
                    {
                        binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.invert()));
                        results = multiReader.decodeMultiple(binaryBitmap, Options.Hints);
                    }
                }

                if (results != null ||
                    !luminanceSource.RotateSupported ||
                    !AutoRotate)
                    break;

                binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.rotateCounterClockwise()));
            }

            if (results != null)
            {
                foreach (var result in results)
                {
                    if (result.ResultMetadata == null)
                    {
                        result.putMetadata(ResultMetadataType.ORIENTATION, rotationCount * 90);
                    }
                    else if (!result.ResultMetadata.ContainsKey(ResultMetadataType.ORIENTATION))
                    {
                        result.ResultMetadata[ResultMetadataType.ORIENTATION] = rotationCount * 90;
                    }
                    else
                    {
                        // perhaps the core decoder rotates the image already (can happen if TryHarder is specified)
                        result.ResultMetadata[ResultMetadataType.ORIENTATION] =
                           ((int)(result.ResultMetadata[ResultMetadataType.ORIENTATION]) + rotationCount * 90) % 360;
                    }
                }

                OnResultsFound(results);
            }

            return results;
        }
        /// <summary>
        /// Tries to decode a barcode within an image which is given by a luminance source.
        /// That method gives a chance to prepare a luminance source completely before calling
        /// the time consuming decoding method. On the other hand there is a chance to create
        /// a luminance source which is independent from external resources (like Bitmap objects)
        /// and the decoding call can be made in a background thread.
        /// </summary>
        /// <param name="luminanceSource">The luminance source.</param>
        /// <returns></returns>
        public virtual Result Decode(LuminanceSource luminanceSource)
        {
            var result = default(Result);
            var binarizer = CreateBinarizer(luminanceSource);
            var binaryBitmap = new BinaryBitmap(binarizer);
            var multiformatReader = Reader as MultiFormatReader;
            var rotationCount = 0;
            var rotationMaxCount = 1;

            if (AutoRotate)
            {
                Options.Hints[DecodeHintType.TRY_HARDER_WITHOUT_ROTATION] = true;
                rotationMaxCount = 4;
            }
            else
            {
                if (Options.Hints.ContainsKey(DecodeHintType.TRY_HARDER_WITHOUT_ROTATION))
                    Options.Hints.Remove(DecodeHintType.TRY_HARDER_WITHOUT_ROTATION);
            }

            for (; rotationCount < rotationMaxCount; rotationCount++)
            {
                if (usePreviousState && multiformatReader != null)
                {
                    result = multiformatReader.decodeWithState(binaryBitmap);
                }
                else
                {
                    result = Reader.decode(binaryBitmap, Options.Hints);
                    usePreviousState = true;
                }

                if (result == null)
                {
                    if (TryInverted && luminanceSource.InversionSupported)
                    {
                        binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.invert()));
                        if (usePreviousState && multiformatReader != null)
                        {
                            result = multiformatReader.decodeWithState(binaryBitmap);
                        }
                        else
                        {
                            result = Reader.decode(binaryBitmap, Options.Hints);
                            usePreviousState = true;
                        }
                    }
                }

                if (result != null ||
                    !luminanceSource.RotateSupported ||
                    !AutoRotate)
                    break;

                luminanceSource = luminanceSource.rotateCounterClockwise();
                binarizer = CreateBinarizer(luminanceSource);
                binaryBitmap = new BinaryBitmap(binarizer);
            }

            if (result != null)
            {
                if (result.ResultMetadata == null)
                {
                    result.putMetadata(ResultMetadataType.ORIENTATION, rotationCount * 90);
                }
                else if (!result.ResultMetadata.ContainsKey(ResultMetadataType.ORIENTATION))
                {
                    result.ResultMetadata[ResultMetadataType.ORIENTATION] = rotationCount * 90;
                }
                else
                {
                    // perhaps the core decoder rotates the image already (can happen if TryHarder is specified)
                    result.ResultMetadata[ResultMetadataType.ORIENTATION] = ((int)(result.ResultMetadata[ResultMetadataType.ORIENTATION]) + rotationCount * 90) % 360;
                }

                OnResultFound(result);
            }

            return result;
        }
Exemple #6
0
 /// <summary> Creates a new object with the same type as this Binarizer implementation, but with pristine
 /// state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache
 /// of 1 bit data. See Effective Java for why we can't use Java's clone() method.
 /// </summary>
 /// <param name="source">The LuminanceSource this Binarizer will operate on.</param>
 /// <returns> A new concrete Binarizer implementation object.</returns>
 public abstract Binarizer createBinarizer(LuminanceSource source);
Exemple #7
0
 /// <summary> Creates a new object with the same type as this Binarizer implementation, but with pristine
 /// state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache
 /// of 1 bit data. See Effective Java for why we can't use Java's clone() method.
 /// </summary>
 /// <param name="source">The LuminanceSource this Binarizer will operate on.</param>
 /// <returns> A new concrete Binarizer implementation object.</returns>
 public abstract Binarizer createBinarizer(LuminanceSource source);
      /// <summary>
      /// Tries to decode a barcode within an image which is given by a luminance source.
      /// That method gives a chance to prepare a luminance source completely before calling
      /// the time consuming decoding method. On the other hand there is a chance to create
      /// a luminance source which is independent from external resources (like Bitmap objects)
      /// and the decoding call can be made in a background thread.
      /// </summary>
      /// <param name="luminanceSource">The luminance source.</param>
      /// <returns></returns>
      private Result Decode(LuminanceSource luminanceSource)
      {
         var result = default(Result);
         var binarizer = CreateBinarizer(luminanceSource);
         var binaryBitmap = new BinaryBitmap(binarizer);
         var multiformatReader = Reader as MultiFormatReader;
         var rotationCount = 0;
         var rotationMaxCount = 1;

         if (AutoRotate)
         {
            Options.Hints[DecodeHintType.TRY_HARDER_WITHOUT_ROTATION] = true;
            rotationMaxCount = 4;
         }
         else
         {
            if (Options.Hints.ContainsKey(DecodeHintType.TRY_HARDER_WITHOUT_ROTATION))
               Options.Hints.Remove(DecodeHintType.TRY_HARDER_WITHOUT_ROTATION);
         }

         for (; rotationCount < rotationMaxCount; rotationCount++)
         {
            if (usePreviousState && multiformatReader != null)
            {
               result = multiformatReader.decodeWithState(binaryBitmap);
            }
            else
            {
               result = Reader.decode(binaryBitmap, Options.Hints);
               usePreviousState = true;
            }

            if (result == null)
            {
               if (TryInverted && luminanceSource.InversionSupported)
               {
                  binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.invert()));
                  if (usePreviousState && multiformatReader != null)
                  {
                     result = multiformatReader.decodeWithState(binaryBitmap);
                  }
                  else
                  {
                     result = Reader.decode(binaryBitmap, Options.Hints);
                     usePreviousState = true;
                  }
               }
            }

            if (result != null ||
                !luminanceSource.RotateSupported ||
                !AutoRotate)
               break;

            binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.rotateCounterClockwise()));
         }

         if (result != null)
         {
            if (result.ResultMetadata == null)
            {
               result.putMetadata(ResultMetadataType.ORIENTATION, rotationCount * 90);
            }
            else if (!result.ResultMetadata.ContainsKey(ResultMetadataType.ORIENTATION))
            {
               result.ResultMetadata[ResultMetadataType.ORIENTATION] = rotationCount * 90;
            }
            else
            {
               // perhaps the core decoder rotates the image already (can happen if TryHarder is specified)
               result.ResultMetadata[ResultMetadataType.ORIENTATION] = ((int)(result.ResultMetadata[ResultMetadataType.ORIENTATION]) + rotationCount * 90) % 360;
            }

            OnResultFound(result);
         }

         return result;
      }
Exemple #9
0
      /**
       * Writes out a single PNG which is three times the width of the input image, containing from left
       * to right: the original image, the row sampling monochrome version, and the 2D sampling
       * monochrome version.
       */
      private static void dumpBlackPoint(Uri uri, Bitmap image, BinaryBitmap bitmap, LuminanceSource luminanceSource)
      {
         // TODO: Update to compare different Binarizer implementations.
         String inputName = uri.LocalPath;
         if (inputName.Contains(".mono.png"))
         {
            return;
         }

         // Use the current working directory for URLs
         String resultName = inputName;
         int pos;
         if ("http".Equals(uri.Scheme))
         {
            pos = resultName.LastIndexOf('/');
            if (pos > 0)
            {
               resultName = '.' + resultName.Substring(pos);
            }
         }
         pos = resultName.LastIndexOf('.');
         if (pos > 0)
         {
            resultName = resultName.Substring(0, pos);
         }
         resultName += ".mono.png";

         int width = bitmap.Width;
         int height = bitmap.Height;
         int stride = width * 4;
         var result = new Bitmap(stride, height, PixelFormat.Format32bppArgb);
         var offset = 0;

         // The original image
         for (int indexH = 0; indexH < height; indexH++)
         {
            for (int indexW = 0; indexW < width; indexW++)
            {
               result.SetPixel(indexW, indexH, image.GetPixel(indexW, indexH));
            }
         }

         // Row sampling
         BitArray row = new BitArray(width);
         offset += width;
         for (int y = 0; y < height; y++)
         {
            row = bitmap.getBlackRow(y, row);
            if (row == null)
            {
               // If fetching the row failed, draw a red line and keep going.
               for (int x = 0; x < width; x++)
               {
                  result.SetPixel(offset + x, y, Color.Red);
               }
               continue;
            }

            for (int x = 0; x < width; x++)
            {
               result.SetPixel(offset + x, y, row[x] ? Color.Black : Color.White);
            }
         }

         // 2D sampling
         offset += width;
         BitMatrix matrix = bitmap.BlackMatrix;
         for (int y = 0; y < height; y++)
         {
            for (int x = 0; x < width; x++)
            {
               result.SetPixel(offset + x, y, matrix[x, y] ? Color.Black : Color.White);
            }
         }

         offset += width;
         var luminanceMatrix = luminanceSource.Matrix;
         for (int y = 0; y < height; y++)
         {
            for (int x = 0; x < width; x++)
            {
               result.SetPixel(offset + x, y, Color.FromArgb(luminanceMatrix[y * width + x], luminanceMatrix[y * width + x], luminanceMatrix[y * width + x]));
            }
         }
         result.Save(resultName, ImageFormat.Png);
      }
      /// <summary>
      /// Tries to decode barcodes within an image which is given by a luminance source.
      /// That method gives a chance to prepare a luminance source completely before calling
      /// the time consuming decoding method. On the other hand there is a chance to create
      /// a luminance source which is independent from external resources (like Bitmap objects)
      /// and the decoding call can be made in a background thread.
      /// </summary>
      /// <param name="luminanceSource">The luminance source.</param>
      /// <returns></returns>
      private Result[] DecodeMultiple(LuminanceSource luminanceSource)
      {
         var results = default(Result[]);
         var binarizer = CreateBinarizer(luminanceSource);
         var binaryBitmap = new BinaryBitmap(binarizer);
         var rotationCount = 0;
         var rotationMaxCount = 1;
         MultipleBarcodeReader multiReader = null;

         if (AutoRotate)
         {
            Options.Hints[DecodeHintType.TRY_HARDER_WITHOUT_ROTATION] = true;
            rotationMaxCount = 4;
         }

         var formats = Options.PossibleFormats;
         if (formats != null &&
             formats.Length == 1 &&
             formats[0] == BarcodeFormat.QR_CODE)
         {
            multiReader = new QRCodeMultiReader();
         }
         else
         {
            multiReader = new GenericMultipleBarcodeReader(Reader);
         }

         for (; rotationCount < rotationMaxCount; rotationCount++)
         {
            results = multiReader.decodeMultiple(binaryBitmap, Options.Hints);

            if (results == null)
            {
               if (TryInverted && luminanceSource.InversionSupported)
               {
                  binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.invert()));
                  results = multiReader.decodeMultiple(binaryBitmap, Options.Hints);
               }
            }

            if (results != null ||
                !luminanceSource.RotateSupported ||
                !AutoRotate)
               break;

            binaryBitmap = new BinaryBitmap(CreateBinarizer(luminanceSource.rotateCounterClockwise()));
         }

         if (results != null)
         {
            foreach (var result in results)
            {
               if (result.ResultMetadata == null)
               {
                  result.putMetadata(ResultMetadataType.ORIENTATION, rotationCount * 90);
               }
               else if (!result.ResultMetadata.ContainsKey(ResultMetadataType.ORIENTATION))
               {
                  result.ResultMetadata[ResultMetadataType.ORIENTATION] = rotationCount * 90;
               }
               else
               {
                  // perhaps the core decoder rotates the image already (can happen if TryHarder is specified)
                  result.ResultMetadata[ResultMetadataType.ORIENTATION] =
                     ((int)(result.ResultMetadata[ResultMetadataType.ORIENTATION]) + rotationCount * 90) % 360;
               }
            }

            OnResultsFound(results);
         }

         return results;
      }