/projects/WeNeedMoreHumans/trunk/src/com/breaktrycatch/needmorehumans/utils/ImageUtils.java

http://breaktrycatchrepo.googlecode.com/ · Java · 311 lines · 229 code · 45 blank · 37 comment · 36 complexity · a77238d9807c1623793f675ddb00ebc1 MD5 · raw file

  1. package com.breaktrycatch.needmorehumans.utils;
  2. import java.awt.Color;
  3. import java.awt.Rectangle;
  4. import java.util.ArrayList;
  5. import processing.core.PApplet;
  6. import processing.core.PImage;
  7. public class ImageUtils
  8. {
  9. public static PImage cloneImage(PImage target)
  10. {
  11. PImage cloned = null;
  12. try
  13. {
  14. cloned = (PImage) target.clone();
  15. } catch (CloneNotSupportedException e)
  16. {
  17. e.printStackTrace();
  18. }
  19. return cloned;
  20. }
  21. public static Color averageColor(PImage target)
  22. {
  23. return averageColor(target, new Rectangle(0, 0, target.width, target.height));
  24. }
  25. public static Color averageColor(PImage target, Rectangle rect)
  26. {
  27. int sumR = 0;
  28. int sumG = 0;
  29. int sumB = 0;
  30. for (int y = rect.y; y < rect.y + rect.height; y++)
  31. {
  32. for (int x = rect.x; x < rect.x + rect.width; x++)
  33. {
  34. int col = target.pixels[y + target.width + x];
  35. int r = (col >> 16) & 0xFF;
  36. int g = (col >> 8) & 0xFF;
  37. int b = col & 0xFF;
  38. sumR += r;
  39. sumG += g;
  40. sumB += b;
  41. }
  42. }
  43. int area = rect.width * rect.height;
  44. return new Color(sumR / area, sumG / area, sumB / area);
  45. }
  46. public static double luminosityVariance(PImage target, Rectangle rect)
  47. {
  48. float sum = 0;
  49. double low = 1;
  50. double high = 0;
  51. for (int y = rect.y; y < rect.y + rect.height; y++)
  52. {
  53. for (int x = rect.x; x < rect.x + rect.width; x++)
  54. {
  55. int col = target.pixels[y * target.width + x];
  56. float[] HSL = new float[3];
  57. ImageUtils.RGBtoHSL((col >> 16) & 0xFF, (col >> 8) & 0xFF, col & 0xFF, HSL);
  58. sum += Math.pow(HSL[2], 2);
  59. if (HSL[2] > high)
  60. {
  61. high = HSL[2];
  62. }
  63. if (HSL[2] < low)
  64. {
  65. low = HSL[2];
  66. }
  67. }
  68. }
  69. int area = rect.width * rect.height;
  70. double mean = sum / area;
  71. double varSum = 0;
  72. for (int y = rect.y; y < rect.y + rect.height; y++)
  73. {
  74. for (int x = rect.x; x < rect.x + rect.width; x++)
  75. {
  76. int col = target.pixels[y * target.width + x];
  77. float[] HSL = new float[3];
  78. ImageUtils.RGBtoHSL((col >> 16) & 0xFF, (col >> 8) & 0xFF, col & 0xFF, HSL);
  79. varSum += Math.pow(HSL[2] - mean, 2);
  80. }
  81. }
  82. double variance = varSum / area;
  83. // PApplet.println("Variance: " + variance + " : DIFF: " + (high -
  84. // low));
  85. return variance;// high - low;
  86. }
  87. public static void averageImages(PImage target, ArrayList<PImage> images)
  88. {
  89. // float totalStdDevR = 0;
  90. // float totalStdDevG = 0;
  91. // float totalStdDevB = 0;
  92. int numPixels = target.pixels.length;
  93. int numBackgrounds = images.size();
  94. for (int i = 0; i < numPixels; i++)
  95. {
  96. int sumR = 0;
  97. int sumG = 0;
  98. int sumB = 0;
  99. for (PImage background : images)
  100. {
  101. int col = background.pixels[i];
  102. int r = (col >> 16) & 0xFF;
  103. int g = (col >> 8) & 0xFF;
  104. int b = col & 0xFF;
  105. sumR += r;
  106. sumG += g;
  107. sumB += b;
  108. }
  109. sumR /= numBackgrounds;
  110. sumG /= numBackgrounds;
  111. sumB /= numBackgrounds;
  112. // float rDevSum = 0;
  113. // float gDevSum = 0;
  114. // float bDevSum = 0;
  115. //
  116. // for (PImage background : images)
  117. // {
  118. // int col = background.pixels[i];
  119. // int r = (col >> 16) & 0xFF;
  120. // int g = (col >> 8) & 0xFF;
  121. // int b = col & 0xFF;
  122. //
  123. // rDevSum += Math.pow((float)r - (float)sumR, 2);
  124. // gDevSum += Math.pow((float)g - (float)sumG, 2);
  125. // bDevSum += Math.pow((float)b - (float)sumB, 2);
  126. // }
  127. //
  128. //
  129. // totalStdDevR += (sumR > 0) ? (Math.sqrt(rDevSum / sumR)) : (0);
  130. // totalStdDevG += (sumG > 0) ? (Math.sqrt(gDevSum / sumG)) : (0);
  131. // totalStdDevB += (sumB > 0) ? (Math.sqrt(bDevSum / sumB)) : (0);
  132. //
  133. // PApplet.println("R: " +totalStdDevR);
  134. target.pixels[i] = (255 << 24 | sumR << 16 | sumG << 8 | sumB);
  135. }
  136. // float avgStdDevR = totalStdDevR / (float)numPixels;
  137. // float avgStdDevG = totalStdDevG / numPixels;
  138. // float avgStdDevB = totalStdDevB / numPixels;
  139. //
  140. // PApplet.println("R: " + totalStdDevR + " G: " + totalStdDevG + " B: "
  141. // + totalStdDevB);
  142. // PApplet.println("R: " + avgStdDevR * avgStdDevR + " G: " + avgStdDevG
  143. // + " B: " + avgStdDevB);
  144. }
  145. public static void RGBtoHSL(int r, int g, int b, float hsl[])
  146. {
  147. float var_R = (r / 255f);
  148. float var_G = (g / 255f);
  149. float var_B = (b / 255f);
  150. float var_Min; // Min. value of RGB
  151. float var_Max; // Max. value of RGB
  152. float del_Max; // Delta RGB value
  153. if (var_R > var_G)
  154. {
  155. var_Min = var_G;
  156. var_Max = var_R;
  157. } else
  158. {
  159. var_Min = var_R;
  160. var_Max = var_G;
  161. }
  162. if (var_B > var_Max)
  163. var_Max = var_B;
  164. if (var_B < var_Min)
  165. var_Min = var_B;
  166. del_Max = var_Max - var_Min;
  167. float H = 0, S, L;
  168. L = (var_Max + var_Min) / 2f;
  169. if (del_Max == 0)
  170. {
  171. H = 0;
  172. S = 0;
  173. } // gray
  174. else
  175. { // Chroma
  176. if (L < 0.5)
  177. S = del_Max / (var_Max + var_Min);
  178. else
  179. S = del_Max / (2 - var_Max - var_Min);
  180. float del_R = (((var_Max - var_R) / 6f) + (del_Max / 2f)) / del_Max;
  181. float del_G = (((var_Max - var_G) / 6f) + (del_Max / 2f)) / del_Max;
  182. float del_B = (((var_Max - var_B) / 6f) + (del_Max / 2f)) / del_Max;
  183. if (var_R == var_Max)
  184. H = del_B - del_G;
  185. else if (var_G == var_Max)
  186. H = (1 / 3f) + del_R - del_B;
  187. else if (var_B == var_Max)
  188. H = (2 / 3f) + del_G - del_R;
  189. if (H < 0)
  190. H += 1;
  191. if (H > 1)
  192. H -= 1;
  193. }
  194. hsl[0] = H;
  195. hsl[1] = S;
  196. hsl[2] = L;
  197. }
  198. public static void tint(PImage masked, int tint, float amt)
  199. {
  200. int rt = (tint >> 16) & 0xFF;
  201. int gt = (tint >> 8) & 0xFF;
  202. int bt = tint & 0xFF;
  203. int numPixels = masked.pixels.length;
  204. for (int i = 0; i < numPixels; i++)
  205. {
  206. int col = masked.pixels[i];
  207. int a = (col >> 24) & 0xFF;
  208. int r = (col >> 16) & 0xFF;
  209. int g = (col >> 8) & 0xFF;
  210. int b = col & 0xFF;
  211. r = (int) (r * (amt - 1) + rt * (amt));
  212. g = (int) (g * (amt - 1) + gt * (amt));
  213. b = (int) (b * (amt - 1) + bt * (amt));
  214. masked.pixels[i] = (a << 24 | r << 16 | g << 8 | b);
  215. }
  216. }
  217. public static PImage trimTransparency(PImage source)
  218. {
  219. // treat the w and h of the rect as the far right left/right points.
  220. Rectangle clipRect = new Rectangle(source.width, source.height, 0, 0);
  221. int i = 0;
  222. for (int y = 0; y < source.height; y++)
  223. {
  224. for (int x = 0; x < source.width; x++)
  225. {
  226. int alpha = (source.pixels[i] >> 24) & 0xFF;
  227. if (alpha > 0)
  228. {
  229. if (x < clipRect.x)
  230. {
  231. clipRect.x = x;
  232. }
  233. if (y < clipRect.y)
  234. {
  235. clipRect.y = y;
  236. }
  237. if (x > clipRect.width)
  238. {
  239. clipRect.width = x;
  240. }
  241. if (y > clipRect.height)
  242. {
  243. clipRect.height = y;
  244. }
  245. }
  246. i++;
  247. }
  248. }
  249. int padding = 3;
  250. int width = clipRect.width - clipRect.x;
  251. int height = clipRect.height - clipRect.y;
  252. // holds the image with a 3 pixel border of transparent pixels.
  253. PImage borderedImage = new PImage(width + padding * 2, height + padding * 2, PApplet.ARGB);
  254. PImage newImage = new PImage(width, height, PApplet.ARGB);
  255. for (int y = clipRect.y; y < clipRect.y + height; y++)
  256. {
  257. for (int x = clipRect.x; x < clipRect.x + width; x++)
  258. {
  259. int pt = y * source.width + x;
  260. newImage.pixels[(y - clipRect.y) * width + (x - clipRect.x)] = source.pixels[pt];
  261. }
  262. }
  263. borderedImage.copy(newImage, 0, 0, newImage.width, newImage.height, padding, padding, newImage.width, newImage.height);
  264. return borderedImage;
  265. }
  266. }