Advertisement
Tatarize

Olsen Noise2D Multiple Colors 3x8bit.

Nov 14th, 2015
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.56 KB | None | 0 0
  1. public class OlsenNoise2DColors {
  2.  
  3. public static final int SCALE_FACTOR = 2;
  4. //The scale factor is kind of arbitrary, but the code is only consistent for 2 currently. Gives noise for other scale but not location proper.
  5. private static final int blurEdge = 2; //extra pixels are needed for the blur (3 - 1).
  6.  
  7. /**
  8. * Function adds all the required ints into the ints array.
  9. * Note that the scanline should not actually equal the width.
  10. * It should be larger as per the getRequiredDim function.
  11. *
  12. * @param iterations Number of iterations to perform.
  13. * @param ints pixel array to be used to insert values. (Pass by reference)
  14. * @param stride distance in the array to the next requestedY value.
  15. * @param x requested X location.
  16. * @param y requested Y location.
  17. * @param width width of the image.
  18. * @param height height of the image.
  19. */
  20. public static void olsennoise(int iterations, int[] ints, int stride, int x, int y, int width, int height) {
  21. olsennoise(ints, stride, x, y, width, height, iterations); //Calls the main routine.
  22. applyMask(ints, stride, width, height, 0xFF000000);
  23. }
  24.  
  25. private static void applyMask(int[] pixels, int stride, int width, int height, int mask) {
  26. int index;
  27. index = 0;
  28. for (int k = 0, n = height - 1; k <= n; k++, index += stride) {
  29. for (int j = 0, m = width - 1; j <= m; j++) {
  30. pixels[index + j] |= mask;
  31. }
  32. }
  33. }
  34.  
  35. /**
  36. * Converts a dimension into the dimension required by the algorithm.
  37. * Due to the blurring, to get valid data the array must be slightly larger.
  38. * Due to the interpixel location at lowest levels it needs to be bigger by
  39. * the max value that can be. (SCALE_FACTOR)
  40. *
  41. * @param dim
  42. * @return
  43. */
  44.  
  45. public static int getRequiredDim(int dim) {
  46. return dim + blurEdge + SCALE_FACTOR;
  47. }
  48.  
  49. //Function inserts the values into the given ints array (pass by reference)
  50. //The results will be within 0-255 assuming the requested iterations are 7.
  51. private static void olsennoise(int[] ints, int stride, int x_within_field, int y_within_field, int width, int height, int iteration) {
  52. if (iteration == 0) {
  53. //Base case. If we are at the bottom. Do not run the rest of the function. Return random values.
  54. clearValues(ints, stride, width, height); //base case needs zero, apply Noise will not eat garbage.
  55. applyNoise(ints, stride, x_within_field, y_within_field, width, height, iteration);
  56. return;
  57. }
  58.  
  59. int x_remainder = x_within_field & 1; //Adjust the x_remainder so we know how much more into the pixel are.
  60. int y_remainder = y_within_field & 1; //Math.abs(y_within_field % SCALE_FACTOR) - Would be assumed for larger scalefactors.
  61. /*
  62. Pass the ints, and the stride for that set of ints.
  63. Recurse the call to the function moving the x_within_field forward if we actaully want half a pixel at the start.
  64. Same for the requestedY.
  65. The width should expanded by the x_remainder, and then half the size, with enough extra to store the extra ints from the blur.
  66. If the width is too long, it'll just run more stuff than it needs to.
  67. */
  68. olsennoise(ints, stride,
  69. ((x_within_field + x_remainder) / SCALE_FACTOR) - x_remainder,
  70. ((y_within_field + y_remainder) / SCALE_FACTOR) - y_remainder,
  71. ((width + x_remainder) / SCALE_FACTOR) + blurEdge,
  72. ((height + y_remainder) / SCALE_FACTOR) + blurEdge, iteration - 1);
  73.  
  74. //This will scale the image from half the width and half the height. bounds.
  75. //The scale function assumes you have at least width/2 and height/2 good ints.
  76. //We requested those from olsennoise above, so we should have that.
  77. applyScaleShift(ints, stride, width + blurEdge, height + blurEdge, SCALE_FACTOR, x_remainder, y_remainder);
  78.  
  79. //This applies the blur and uses the given bounds.
  80. //Since the blur loses two at the edge, this will result
  81. //in us having width requestedX height of good ints and required
  82. // width + blurEdge of good ints. height + blurEdge of good ints.
  83. applyBlur(ints, stride, width + blurEdge, height + blurEdge);
  84.  
  85. //Applies noise to all the given ints. Does not require more or less than ints. Just offsets them all randomly.
  86. applyNoise(ints, stride, x_within_field, y_within_field, width, height, iteration);
  87. }
  88.  
  89.  
  90.  
  91. private static void applyNoise(int[] pixels, int stride, int x_within_field, int y_within_field, int width, int height, int iteration) {
  92. long bitmask = 0b00000001000000010000000100000001 << (7-iteration);
  93. int index = 0;
  94. for (int k = 0, n = height - 1; k <= n; k++, index += stride) { //iterate the requestedY positions. Offsetting the index by stride each time.
  95. for (int j = 0, m = width - 1; j <= m; j++) { //iterate the requestedX positions through width.
  96. int current = index + j; // The current position of the pixel is the index which will have added stride each, requestedY iteration
  97. pixels[current] += hashrandom(j + x_within_field, k + y_within_field, iteration) & bitmask;
  98. //add on to this pixel the hash function with the set reduction.
  99. //It simply must scale down with the larger number of iterations.
  100. }
  101. }
  102. }
  103.  
  104. private static void applyScaleShift(int[] pixels, int stride, int width, int height, int factor, int shiftX, int shiftY) {
  105. int index = (height - 1) * stride; //We must iteration backwards to scale so index starts at last Y position.
  106. for (int k = 0, n = height - 1; k <= n; n--, index -= stride) { // we iterate the requestedY, removing stride from index.
  107. for (int j = 0, m = width - 1; j <= m; m--) { // iterate the requestedX positions from width to 0.
  108. int pos = index + m; //current position is the index (position of that scanline of Y) plus our current iteration in scale.
  109. int lower = (((n+shiftY) / factor) * stride) + ((m+shiftX) / factor); //We find the position that is half that size. From where we scale them out.
  110. pixels[pos] = pixels[lower]; // Set the outer position to the inner position. Applying the scale.
  111. }
  112. }
  113. }
  114.  
  115. private static void clearValues(int[] pixels, int stride, int width, int height) {
  116. int index;
  117. index = 0;
  118. for (int k = 0, n = height - 1; k <= n; k++, index += stride) { //iterate the requestedY values.
  119. for (int j = 0, m = width - 1; j <= m; j++) { //iterate the requestedX values.
  120. pixels[index + j] = 0; //clears those values.
  121. }
  122. }
  123. }
  124.  
  125. //Applies the blur.
  126. //box blur 3x3 in each color. Really boxblur 1x3 and 3x1.
  127. private static void applyBlur(int[] pixels, int stride, int width, int height) {
  128. int index = 0;
  129. int v0;
  130. int v1;
  131. int v2;
  132.  
  133. int r;
  134. int g;
  135. int b;
  136.  
  137. for (int j = 0; j < height; j++, index += stride) {
  138. for (int k = 0; k < width; k++) {
  139. int pos = index + k;
  140.  
  141. v0 = pixels[pos];
  142. v1 = pixels[pos+1];
  143. v2 = pixels[pos+2];
  144.  
  145. r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
  146. g = ((v0 >> 8 ) & 0xFF) + ((v1 >> 8) & 0xFF) + ((v2 >> 8) & 0xFF);
  147. b = ((v0 ) & 0xFF) + ((v1 ) & 0xFF) + ((v2 ) & 0xFF);
  148. r/=3;
  149. g/=3;
  150. b/=3;
  151. pixels[pos] = r << 16 | g << 8 | b;
  152. }
  153. }
  154. index = 0;
  155. for (int j = 0; j < height; j++, index += stride) {
  156. for (int k = 0; k < width; k++) {
  157. int pos = index + k;
  158. v0 = pixels[pos];
  159. v1 = pixels[pos+stride];
  160. v2 = pixels[pos+(stride<<1)];
  161.  
  162. r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
  163. g = ((v0 >> 8 ) & 0xFF) + ((v1 >> 8) & 0xFF) + ((v2 >> 8) & 0xFF);
  164. b = ((v0 ) & 0xFF) + ((v1 ) & 0xFF) + ((v2 ) & 0xFF);
  165. r/=3;
  166. g/=3;
  167. b/=3;
  168. pixels[pos] = r << 16 | g << 8 | b;
  169. }
  170. }
  171. }
  172.  
  173.  
  174. public static long hashrandom(int v0, int v1, int v2) {
  175. long hash = 0;
  176. hash ^= v0;
  177. hash = hash(hash);
  178. hash ^= v1;
  179. hash = hash(hash);
  180. hash ^= v2;
  181. hash = hash(hash);
  182. return hash;
  183. }
  184.  
  185. private static long hash(long v) {
  186. long hash = v;
  187. long h = hash;
  188.  
  189. switch ((int) hash & 3) {
  190. case 3:
  191. hash += h;
  192. hash ^= hash << 32;
  193. hash ^= h << 36;
  194. hash += hash >> 22;
  195. break;
  196. case 2:
  197. hash += h;
  198. hash ^= hash << 22;
  199. hash += hash >> 34;
  200. break;
  201. case 1:
  202. hash += h;
  203. hash ^= hash << 20;
  204. hash += hash >> 2;
  205. }
  206. hash ^= hash << 6;
  207. hash += hash >> 10;
  208. hash ^= hash << 8;
  209. hash += hash >> 34;
  210. hash ^= hash << 50;
  211. hash += hash >> 12;
  212. return hash;
  213. }
  214. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement