Advertisement
Guest User

SearchableImage.cs

a guest
Jul 31st, 2010
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.41 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Drawing;
  5. using System.IO;
  6. using System.Security.Cryptography;
  7. using System.Runtime.InteropServices;
  8. using System.Drawing.Imaging;
  9.  
  10. namespace IronAHK.Rusty
  11. {
  12.  
  13.     /// <summary>
  14.     /// Provides easy to use image comparisation and search Algorythms
  15.     /// </summary>
  16.     public class SearchableImage
  17.     {
  18.  
  19.         #region Private Data
  20.  
  21.         private int mVariation = 0; // 0-255
  22.         private Bitmap mSourceImage = null;
  23.         private Bitmap mNeedleImage = null;
  24.         private byte[] mNeedleImageHash;
  25.         private bool mNeedleImageHashOutdated = true;
  26.  
  27.         #endregion
  28.  
  29.         #region Constructors
  30.  
  31.         public SearchableImage(Bitmap uSourceImage) {
  32.             this.mSourceImage = uSourceImage;
  33.         }
  34.  
  35.         #endregion
  36.  
  37.         #region Public Propertys
  38.  
  39.         /// <summary>Variation of matcher (0 = exact match, 255 = every color matches)
  40.         ///
  41.         /// </summary>
  42.         public int Variation {
  43.             get { return mVariation; }
  44.             set {
  45.                 if(value >= 0 && value <= 255) {
  46.                     mVariation = value;
  47.                 } else
  48.                     throw new ArgumentException("Submitted variation is invalid!");
  49.             }
  50.         }
  51.  
  52.         #endregion
  53.  
  54.         #region Pubic Methods
  55.  
  56.         /// <summary>Searches the image.
  57.         /// Searches a image in antoher image
  58.         ///
  59.         /// 1. search the first pixel of the needle in the source
  60.         /// 2. if found --> lookup required size for performance optimisation
  61.         /// 3. if step 2. passed --> begin pixel per pixel comparisation, with (Variation)
  62.         ///
  63.         /// Further optimisations may include hash comparisation
  64.         /// </summary>
  65.         /// <returns>If nothing is found [Point?]=null is returned, otherwise upperleft corner of found position.</returns>
  66.         public Point? SearchImage(Bitmap uNeedleImage) {
  67.             Point SourceLocation;
  68.             if(mSourceImage == null || uNeedleImage == null)
  69.                 throw new InvalidOperationException();
  70.  
  71.             this.NeedleImage = uNeedleImage;
  72.  
  73.             var Unit = GraphicsUnit.Pixel;
  74.             //Is the needle image conatined (physical size) in the source image?
  75.             if(mSourceImage.GetBounds(ref Unit).Contains(NeedleImage.GetBounds(ref Unit))) {
  76.  
  77.                 var MaxMovement = new Size(mSourceImage.Size.Width - NeedleImage.Size.Width, mSourceImage.Size.Height - NeedleImage.Size.Height);
  78.  
  79.                 for(int row = 0; row <= MaxMovement.Height; row++)
  80.                     for(int col = 0; col <= MaxMovement.Width; col++) {
  81.  
  82.                         SourceLocation = new Point(col, row);
  83.                         if(mVariation == 0) {
  84.                             if(CompareImageHash(SourceLocation))
  85.                                 return SourceLocation;
  86.                         } else {
  87.                             if(CompareImage(SourceLocation))
  88.                                 return SourceLocation;
  89.                         }
  90.                     }
  91.             }
  92.             return null;
  93.         }
  94.  
  95.  
  96.         public void DebugMethod(Bitmap uNeedleImage) {
  97.  
  98.             var NeedleBuf = BufferFromImage(uNeedleImage);
  99.  
  100.             var ImgCopy = new Bitmap(uNeedleImage);
  101.             var g = Graphics.FromImage(ImgCopy);
  102.             g.DrawImageUnscaled(uNeedleImage, new Point(0, 0));
  103.  
  104.             var SourceBuf2 = BufferFromImage(ImgCopy);
  105.  
  106.  
  107.         }
  108.  
  109.  
  110.         /// <summary>Searches a Pixel in a Image.
  111.         ///
  112.         /// </summary>
  113.         /// <param name="ColorId"></param>
  114.         /// <returns>If nothing is found [Point?]=null is returned, otherwise upperleft corner of found position.</returns>
  115.         public Point? SearchPixel(int ColorId) {
  116.  
  117.             var c = CreateComparerMask(ColorId);
  118.  
  119.             for(int row = 0; row < mSourceImage.Size.Height; row++)
  120.                 for(int col = 0; col < mSourceImage.Size.Width; col++) {
  121.                     Color pix = mSourceImage.GetPixel(col, row);
  122.  
  123.                     if(CompareWithMask(pix, c))
  124.                         return new Point(col, row);
  125.                 }
  126.             return null;
  127.         }
  128.  
  129.  
  130.         /// <summary>Searches the Needle Image withhin the Source Image at given Point. Variation and other Parameters are taken into account.
  131.         ///
  132.         /// </summary>
  133.         /// <param name="NeedleImageLocation"></param>
  134.         /// <returns></returns>
  135.         private bool CompareImage(Point NeedleImageLocation) {
  136.             Color NeedlePix;
  137.             Color SourcePix;
  138.  
  139.             // Check if the Needleimage at given Position fits into SourceImage
  140.             var SourceBox = new Rectangle(new Point(0, 0), mSourceImage.Size);
  141.             var NeedleBox = new Rectangle(NeedleImageLocation, NeedleImage.Size);
  142.             if(!SourceBox.Contains(NeedleBox))
  143.                 return false;
  144.  
  145.             //If so, perform a comarisation for each pixel from needle:
  146.             for(int row = 0; row < NeedleImage.Size.Height; row++)
  147.                 for(int col = 0; col < NeedleImage.Size.Width; col++) {
  148.                     NeedlePix = NeedleImage.GetPixel(col, row);
  149.                     SourcePix = mSourceImage.GetPixel(col + NeedleImageLocation.X, row + NeedleImageLocation.Y);
  150.                     if(!CompareWithMask(SourcePix, CreateComparerMask(NeedlePix.ToArgb()))) {
  151.                         return false; //they don't match
  152.                     }
  153.                 }
  154.             return true;
  155.         }
  156.  
  157.         /// <summary>
  158.         ///
  159.         /// </summary>
  160.         /// <param name="NeedleImageLocation"></param>
  161.         /// <returns></returns>
  162.         private bool CompareImageHash(Point NeedleImageLocation) {
  163.             var SourceImageRegion = Copy(this.SourceImage, new Rectangle(NeedleImageLocation, NeedleImage.Size));
  164.             var SourceBuffer = BufferFromImage(SourceImageRegion);
  165.             var SourceHash = HashFromBuffer(SourceBuffer);
  166.             //cmp Hashes
  167.             for(int i = 0; i < SourceHash.Length && i < SourceHash.Length; i++) {
  168.                 if(!(SourceHash[i] == NeedleHash[i]))
  169.                     return false;
  170.             }
  171.             return true;
  172.         }
  173.  
  174.         public Bitmap SourceImage {
  175.             get { return mSourceImage; }
  176.             set { mSourceImage = value; }
  177.         }
  178.  
  179.         private byte[] NeedleHash {
  180.             get {
  181.                 if(mNeedleImageHashOutdated) {
  182.                     var buf = BufferFromImage(this.NeedleImage);
  183.                     mNeedleImageHash = HashFromBuffer(buf);
  184.                     mNeedleImageHashOutdated = false;
  185.                 }
  186.                 return mNeedleImageHash;
  187.  
  188.             }
  189.         }
  190.  
  191.         private Bitmap NeedleImage {
  192.             get {
  193.                 return mNeedleImage;
  194.             }
  195.             set {
  196.                 mNeedleImage = value;
  197.                 mNeedleImageHashOutdated = true;
  198.             }
  199.         }
  200.  
  201.  
  202.  
  203.         #endregion
  204.  
  205.         #region Private Methods
  206.  
  207.         /// <summary>Create a Comarer Mask with given Variation
  208.         ///
  209.         /// </summary>
  210.         /// <param name="ColorID">Source Color</param>
  211.         /// <returns></returns>
  212.         private int[,] CreateComparerMask(int ColorID) {
  213.             var c = new int[3, 2];
  214.  
  215.             for(int i = 0; i < 3; i++) {
  216.                 int t = ColorID >> (2 - i) * 8 & 0xff;
  217.                 c[i, 0] = t - this.Variation; c[i, 1] = t + this.Variation;
  218.             }
  219.             return c;
  220.         }
  221.  
  222.         private byte[] HashFromBuffer(byte[] buf) {
  223.             var shaprovider = new SHA256Managed();
  224.             return shaprovider.ComputeHash(buf);
  225.         }
  226.  
  227.  
  228.         /// <summary>Generate byte Buffer from Image
  229.         ///
  230.         /// </summary>
  231.         /// <param name="img"></param>
  232.         /// <returns></returns>
  233.         private byte[] BufferFromImage(Bitmap bmp) {
  234.             /*
  235.             ImageConverter converter = new ImageConverter();
  236.             return (byte[])converter.ConvertTo(img, typeof(byte[]));
  237.              * */
  238.  
  239.             byte[] bytes;
  240.             var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
  241.             try {
  242.                 bytes = new Byte[bmpData.Stride * bmp.Height];
  243.                 Marshal.Copy(bmpData.Scan0, bytes, 0, bytes.Length);
  244.             } finally {
  245.                 bmp.UnlockBits(bmpData);
  246.             }
  247.             return bytes;
  248.         }
  249.  
  250.  
  251.         private Bitmap Copy(Bitmap srcBitmap, Rectangle section) {
  252.  
  253.             Bitmap bmp = new Bitmap(section.Width, section.Height, Graphics.FromImage(NeedleImage));
  254.             Graphics g = Graphics.FromImage(bmp);
  255.             g.DrawImage(srcBitmap, 0, 0, section, GraphicsUnit.Pixel);
  256.             g.Dispose();
  257.             return bmp;
  258.         }
  259.  
  260.         /// <summary>Compares given Color with Comparer Mask
  261.         ///
  262.         /// </summary>
  263.         /// <param name="GivenColor"></param>
  264.         /// <param name="c"></param>
  265.         /// <returns></returns>
  266.         private bool CompareWithMask(Color GivenColor, int[,] c) {
  267.             return (GivenColor.R >= c[0, 0] && GivenColor.R <= c[0, 1] &&
  268.                          GivenColor.G >= c[1, 0] && GivenColor.G <= c[1, 1] &&
  269.                          GivenColor.B >= c[2, 0] && GivenColor.B <= c[2, 1]);
  270.         }
  271.         #endregion
  272.     }
  273. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement