Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.photoembroidery.tat.olsennoise;
- import java.util.Arrays;
- /**
- * Created by Tat on 2/17/2015.
- */
- public class OlsenNoise2D {
- public static void convolve(int[] pixels, int offset, int stride, int x, int y, int width, int height, int[][] matrix, int parts) {
- int startIndex = x + (y * stride);
- int lastIndex = (x + width - 1) + ((y + height - 1) * stride);
- int x_pos = x;
- int y_pos = y;
- int indexInc = 1;
- int yinc = 0;
- int xinc = 1;
- for (int i = 0, s = width + height; i < s; i++) {
- if (i == width) {
- indexInc = stride;
- yinc = 1;
- xinc = 0;
- }
- int x_counter = x_pos;
- int index = startIndex;
- while (x_counter >= x && index <= lastIndex) {
- pixels[offset + index] = convolve(pixels, stride, offset + index, matrix, parts);
- x_counter--;
- index += stride - 1;
- }
- startIndex += indexInc;
- x_pos += xinc;
- y_pos += yinc;
- }
- }
- private static int crimp(int color) {
- return (color >= 0xFF) ? 0xFF : (color < 0) ? 0 : color;
- }
- private static int convolve(int[] pixels, int stride, int index, int[][] matrix, int parts) {
- int redSum = 0;
- int greenSum = 0;
- int blueSum = 0;
- int pixel, factor;
- for (int j = 0, m = matrix.length; j < m; j++, index++) {
- for (int k = 0, n = matrix[j].length, q = index; k < n; k++, q += stride) {
- pixel = pixels[q];
- factor = matrix[j][k];
- redSum += factor * ((pixel >> 16) & 0xFF);
- greenSum += factor * ((pixel >> 8) & 0xFF);
- blueSum += factor * ((pixel) & 0xFF);
- }
- }
- return 0xFF000000 | ((crimp(redSum / parts) << 16) | (crimp(greenSum / parts) << 8) | (crimp(blueSum / parts)));
- }
- //occupies same footprint
- private void applyNoise(int[] pixels, int stride, int x_within_field, int y_within_field, int width, int height, int iteration) {
- int index = 0;
- for (int k = 0, n = height - 1; k <= n; k++, index += stride) {
- for (int j = 0, m = width - 1; j <= m; j++) {
- int current = index + j;
- pixels[current] += (hashrandom(x_within_field + j, y_within_field + k, iteration) & (1 << (7 - iteration)));
- }
- }
- }
- //requires half the height and width be good.
- private void applyScale(int[] pixels, int stride, int width, int height) {
- int index = (height - 1) * stride;
- for (int k = 0, n = 0 + height - 1; k <= n; n--, index -= stride) {
- for (int j = 0, m = width - 1; j <= m; m--) {
- int current = index + m;
- int lower = ((n / 2) * stride) + (m / 2);
- pixels[current] = pixels[lower];
- }
- }
- }
- //requires width + 1 valid, height + 1
- private static final int[][] blur2x2 = new int[][]{
- {1, 1},
- {1, 1},
- };
- private void applyBlur(int[] pixels, int stride, int width, int height) {
- convolve(pixels, 0, stride,0,0, width, height, blur2x2, 4);
- }
- //You need to give it an array larger than the current one. This math is just a guess at a number big enough, it's not actually the max dim the array would properly need to be.
- public int getRequiredDim(int dim) {
- return (dim + 5) * 2;
- }
- private void trim(int[] pixels, int width, int height, int[] workingpixels, int workingstride) {
- for (int k = 0; k < height; k++) {
- for (int j = 0; j < width; j++) {
- int index = j + (k * width);
- int workingindex = j + (k * workingstride);
- pixels[index] = workingpixels[workingindex];
- }
- }
- }
- static final int maxiterations = 7;
- public void olsennoise(int[] pixels, int stride, int x, int y, int width, int height) {
- Arrays.fill(pixels, 0xFF000000);
- olsennoise(pixels, stride, x, y, width, height, maxiterations);
- }
- public void olsennoise(int[] pixels, int stride, int x_within_field, int y_within_field, int width, int height, int iteration) {
- if (iteration == 0) {
- applyNoise(pixels, stride, x_within_field, y_within_field, width, height, iteration);
- return;
- }
- olsennoise(pixels, stride, (x_within_field/2)-2, (y_within_field/2)-2, (width/2)+2, (height/2) + 2, iteration - 1);
- //scale only requires (width/2+1) and (height/2+1) valid pixels.
- applyScale(pixels, stride, width+1, height+1);
- //blur only requires width+1 and height+1 valid pixels.
- applyBlur(pixels, stride, width, height);
- //noise requires width, and height valid pixels
- applyNoise(pixels, stride, x_within_field, y_within_field, width, height, iteration);
- }
- public static int hashrandom(int... elements) {
- long hash = 0;
- for (int i = 0; i < elements.length; i++) {
- hash ^= elements[i];
- hash = hash(hash);
- }
- return (int) hash;
- }
- public static long hash(long v) {
- long hash = v;
- long h = hash;
- switch ((int) hash & 3) {
- case 3:
- hash += h;
- hash ^= hash << 32;
- hash ^= h << 36;
- hash += hash >> 22;
- break;
- case 2:
- hash += h;
- hash ^= hash << 22;
- hash += hash >> 34;
- break;
- case 1:
- hash += h;
- hash ^= hash << 20;
- hash += hash >> 2;
- }
- hash ^= hash << 6;
- hash += hash >> 10;
- hash ^= hash << 8;
- hash += hash >> 34;
- hash ^= hash << 50;
- hash += hash >> 12;
- return hash;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement