Advertisement
TheBat

Battleguard's OCR

Feb 28th, 2012
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.34 KB | None | 0 0
  1. import java.awt.Color;
  2. import java.awt.Point;
  3. import java.awt.Rectangle;
  4. import java.awt.image.BufferedImage;
  5. import java.io.File;
  6. import java.io.IOException;
  7. import java.util.ArrayList;
  8.  
  9. import javax.imageio.ImageIO;
  10.  
  11. import org.runedream.api.methods.Environment;
  12. import org.runedream.api.methods.Game;
  13. import org.runedream.api.util.Log;
  14.  
  15. /**
  16. * Optical Character Recognition (OCR) methods.
  17. *
  18. * @author battlegaurd
  19. */
  20. public class OCR {
  21.  
  22. private static final Font[][] ALL_LETTERS = new Font[FontType.values().length][62];
  23.  
  24. static {
  25. for (int i = 0; i < ALL_LETTERS.length; i++) {
  26. ALL_LETTERS[i] = grabFontSet(ALL_LETTERS[i], FontType.values()[i].getName());
  27. }
  28. }
  29.  
  30. /**
  31. * NOTE THE MORE VARIABLES YOU DEFINE THE FASTER THIS WILL BE AND THE SMALLER THE RECTANGLE THE FASTER IT WILL BE
  32. * SO TRY NOT TO RUN THIS WITH NO FONT SPECIFIED AND NO COLOR OF THE TEXT SPECIFIED BECAUSE IT DRASTICALLY INCREASES THE AMOUNT
  33. * OF OPERATIONS IT MUST PERFORM. I AM WORKING ON A HELPER SCRIPT THAT WILL MAKE THIS A LOT EASIER
  34. */
  35.  
  36. /**
  37. * Finds text within a rectangle of the specified font.
  38. * </br>
  39. * To optimize performance, minimize the bounds of the rectangle, define the color, and define the font.
  40. * @param fontC The color of the text inside of the rectangle; or null to search for any color.
  41. * @param rec The rectangle to search within.
  42. * @param curfont The font to find a string of.
  43. * @return The text found within the rectangle.
  44. */
  45. public static String findString(final Color fontC, final Rectangle rec, final FontType font) {
  46. return findString(rec, fontC, ALL_LETTERS[font.ordinal()], false);
  47. }
  48.  
  49. /**
  50. * Finds text within a rectangle of any supported font.
  51. * </br>
  52. * To optimize performance, minimize the bounds of the rectangle and define the color.
  53. * @param rec The rectangle to search within.
  54. * @param fontC The color of the text inside of the rectangle; or null to search for any color.
  55. * @return The text found within the rectangle.
  56. */
  57. public static String findString(final Rectangle rec, final Color fontC) {
  58. return findString(rec, fontC, null, false);
  59. }
  60.  
  61. /**
  62. * Finds text within a rectangle of the specified font.
  63. * </br>
  64. * To optimize performance, minimize the bounds of the rectangle, define the color, and define the font.
  65. * @param fontC The color of the text inside of the rectangle; or null to search for any color.
  66. * @param rec The rectangle to search within.
  67. * @param curfont The font to find a string of.
  68. * @param multiColorText <tt>true</tt> if the text should be detected in multiple colors; otherwise <tt>false</tt>.
  69. * @return The text found within the rectangle.
  70. */
  71. public static String findString(final Color fontC, final Rectangle rec, final FontType font, final boolean multiColorText) {
  72. return findString(rec, fontC, ALL_LETTERS[font.ordinal()], multiColorText);
  73. }
  74.  
  75. /**
  76. * Finds text within a rectangle of any supported font.
  77. * </br>
  78. * To optimize performance, minimize the bounds of the rectangle and define the color.
  79. * @param rec The rectangle to search within.
  80. * @param fontC The color of the text inside of the rectangle; or null to search for any color.
  81. * @param multiColorText <tt>true</tt> if the text should be detected in multiple colors; otherwise <tt>false</tt>.
  82. * @return The text found within the rectangle.
  83. */
  84. public static String findString(final Rectangle rec, final Color fontC, final boolean multiColorText) {
  85. return findString(rec, fontC, null, multiColorText);
  86. }
  87.  
  88. /**
  89. * Finds text within a rectangle.
  90. * </br>
  91. * To optimize performance, minimize the bounds of the rectangle, define the color, and define the font.
  92. * @param rec The rectangle to search within.
  93. * @param fontC The color of the text inside of the rectangle; or null to search for any color.
  94. * @param font The font type to search for; or null to search for all font types
  95. * @param multiColorText <tt>true</tt> if the text should be detected in multiple colors; otherwise <tt>false</tt>.
  96. * @return The text found within the rectangle.
  97. */
  98. private static String findString(final Rectangle rec, Color fontC, final Font[] font, final boolean multiColorText) {
  99. ArrayList<Letter> nums = new ArrayList<Letter>();
  100. Font[] foundFont = font;
  101. for (int y = rec.y; y < rec.y + rec.height; y++) {
  102. M1: for (int x = rec.x; x < rec.x + rec.width; x++) {
  103. Color c = Game.getColorAt(x, y);
  104. if (fontC != null && !fontC.equals(c)) {
  105. continue;
  106. }
  107. for (int i = 0; i < ALL_LETTERS.length; i++) {
  108. Font[] curFont = ALL_LETTERS[i];
  109. if (foundFont != null) {
  110. curFont = foundFont;
  111. }
  112. M2: for (int j = 0; j < curFont.length; j++) {
  113. final Rectangle loc = new Rectangle(x - curFont[j].goodPts[0].x,
  114. y - curFont[j].goodPts[0].y, curFont[j].letBox.width, curFont[j].letBox.height);
  115. if (!rec.contains(loc)) {
  116. continue;
  117. }
  118. for (int k = 0; k < curFont[j].goodPts.length; k++) {
  119. if (!checkColor(Game.getColorAt(loc.x + curFont[j].goodPts[k].x,
  120. loc.y + curFont[j].goodPts[k].y), c, 40)) {
  121. continue M2;
  122. }
  123. }
  124. for (int k = 0; k < curFont[j].badPts.length; k++) {
  125. if (checkColor(Game.getColorAt(loc.x + curFont[j].badPts[k].x,
  126. loc.y + curFont[j].badPts[k].y), c, 40)) {
  127. continue M2;
  128. }
  129. }
  130. nums.add(new Letter(curFont[j].letter, loc.x, loc.x + curFont[j].letBox.width));
  131. foundFont = curFont;
  132. if (!multiColorText) {
  133. fontC = c;
  134. }
  135. continue M1;
  136. }
  137. if (foundFont != null) {
  138. break;
  139. }
  140. }
  141. }
  142. }
  143. return sortLetters(nums);
  144. }
  145.  
  146. private static class Letter {
  147.  
  148. private int x0;
  149. private int x1;
  150. private char letter;
  151.  
  152. public Letter(final char letter, final int x0, final int x1) {
  153. this.letter = letter;
  154. this.x0 = x0;
  155. this.x1 = x1;
  156. }
  157. }
  158.  
  159. private static class Font {
  160.  
  161. private Point[] goodPts;
  162. private Point[] badPts;
  163. private char letter;
  164. private Rectangle letBox;
  165.  
  166. public Font(final ArrayList<Point> goodpoints, final ArrayList<Point> badpoints,
  167. final char letter, final Rectangle letBox) {
  168. goodPts = new Point[goodpoints.size()];
  169. goodPts = goodpoints.toArray(goodPts);
  170. badPts = new Point[badpoints.size()];
  171. badPts = badpoints.toArray(goodPts);
  172. this.letBox = letBox;
  173. this.letter = letter;
  174. }
  175. }
  176.  
  177. /**
  178. * Enumeration of the fonts available to use.
  179. */
  180. public static enum FontType {
  181. BIG_CHARS("BigChars"),
  182. NPC_CHARS("NPCChars"),
  183. FRIEND_CHARS("FriendChars"),
  184. LOGIN_CHARS("LoginChars"),
  185. SMALL_CHARS("SmallChars"),
  186. STAT_CHARS("StatChars"),
  187. UP_CHARS("UpChars"),
  188. UP_CHARS_EX("UpCharsEx");
  189.  
  190. private String name;
  191.  
  192. private FontType(final String name) {
  193. this.name = name;
  194. }
  195.  
  196. /**
  197. * Gets the name of this FontType.
  198. * @return The FontType's name.
  199. */
  200. public String getName() {
  201. return name;
  202. }
  203. }
  204.  
  205. /**
  206. * Load all images for the current font and store the font information to the Font array
  207. * @param fontset : font array that information will be stored
  208. * @param fontname : name of the current font
  209. * @return : a filled array of font information
  210. */
  211. private static Font[] grabFontSet(final Font[] fontset, final String fontname) {
  212. int cnt = 0;
  213. final String base = Environment.getStorageDirectoryPath() + File.separator
  214. + "Fonts" + File.separator + fontname + File.separator;
  215. for (int i = 48; i < 123; i++) {
  216. try {
  217. if ((i >= 58 && i < 65) || (i >= 91 && i < 97)) {
  218. continue;
  219. }
  220. final BufferedImage img = ImageIO.read(new File(base + i + ".bmp"));
  221. fontset[cnt++] = parseBMP(img, (char) i);
  222. } catch (final IOException e) {
  223. Log.log("Failed to read bitmap " + i + " on font " + fontname);
  224. }
  225. }
  226. /*for (i = 48; i < 58; i++) {
  227. final BufferedImage img = ImageIO.read(new File(base + i + ".bmp"));
  228. fontset[cnt++] = parseBMP(img, (char) i);
  229. }
  230. for (i = 65; i < 91; i++) {
  231. final BufferedImage img = ImageIO.read(new File(base + i + ".bmp"));
  232. fontset[cnt++] = parseBMP(img, (char) i);
  233. }
  234. for (i = 97; i < 123; i++) {
  235. final BufferedImage img = ImageIO.read(new File(base + i + ".bmp"));
  236. fontset[cnt++] = parseBMP(img, (char) i);
  237. }*/
  238. return fontset;
  239. }
  240.  
  241. /**
  242. * Parses a letter font from a bitmap image.
  243. * @param img The image to parse.
  244. * @param letter The character to parse.
  245. * @return The letter font.
  246. */
  247. private static Font parseBMP(final BufferedImage img, final char letter) {
  248. final ArrayList<Point> goodPts = new ArrayList<Point>();
  249. final ArrayList<Point> badPts = new ArrayList<Point>();
  250. for (int y = 0; y < img.getHeight(); y++) {
  251. for (int x = 0; x < img.getWidth(); x++) {
  252. final Color c2 = new Color(img.getRGB(x, y));
  253. if (c2.equals(Color.WHITE)) {
  254. goodPts.add(new Point(x, y));
  255. } else {
  256. badPts.add(new Point(x, y));
  257. }
  258. }
  259. }
  260. return new Font(goodPts, badPts, letter, new Rectangle(img.getWidth(), img.getHeight()));
  261. }
  262.  
  263. private static boolean checkColor(final Color c, final Color c2, final int tol) {
  264. return checkColor(c.getRed(), c2.getRed()) + checkColor(c.getGreen(), c2.getGreen())
  265. + checkColor(c.getBlue(), c2.getBlue()) < tol;
  266. }
  267.  
  268. private static int checkColor(final int rgb, final int val) {
  269. return Math.abs(rgb - val);
  270. }
  271.  
  272. // WE COULD MAYBE REMOVE THIS IF WE ONLY SEARCH ALONG THE MIDDLE OF THE BOX FOR COLORS. THIS WOULD ALSO ALLOW US TO NOT HAVE TO DO ANYWHERE CLOSE
  273. // TO THE AMOUNT OF TRAVERSALS AND WOULD REMOVE A LOT OF EXTRA RUNTIME
  274. // THE ONLY DOWN SIDE WOULD BE THE PERSON MUST MAKE SURE HE HAS HIS BOX CENTERED IN A WAY THAT THE 1 Y LINE THEY SPECIFY HITS ALL THE LETTERS
  275. // THIS COULD ALSO BRING IN THE PROBLEM OF THE PERSON NOT KNOWING WHERE THE TEXT IS ON SCREEN AND WOULD MAKE HIS JOB A LOT MORE TROUBLESOME
  276. private static String sortLetters(final ArrayList<Letter> letters) {
  277. String text = "";
  278. Letter oldLetter = null;
  279. while (!letters.isEmpty()) {
  280. Letter curLetter = new Letter('X', 800, 800);
  281. for (int i = 0; i < letters.size(); i++) {
  282. if (letters.get(i).x0 < curLetter.x0) {
  283. curLetter = letters.get(i);
  284. }
  285. }
  286. if (oldLetter != null && curLetter.x0 - oldLetter.x1 > 1){
  287. text += " ";
  288. }
  289. oldLetter = curLetter;
  290. text += curLetter.letter;
  291. letters.remove(curLetter);
  292. }
  293. return text;
  294. }
  295. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement