Advertisement
vivienneanthony

Olsen V2.0 rewrote

Feb 20th, 2015
266
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.34 KB | None | 0 0
  1. /*
  2.  * Original Author @author Tat
  3.  * Mod code Vivienne Anthony
  4.  * c++ rewrite vivienne (WIP)
  5.  * verion 1.0 Functional Rewrite
  6.  *
  7.  * Changes
  8.  *  Java to C++ conversion
  9.  *  Memory pointer usage
  10.  */
  11.  
  12. #include <iostream>
  13. #include <vector>
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <png++/png.hpp>
  18.  
  19. using namespace std;
  20.  
  21. void SaveTerrFile(const int * image, int size, char * filename);
  22.  
  23. class OlsenNoise2D
  24. {
  25.  
  26. public:
  27.     OlsenNoise2D();
  28.     void convolve(int * pixels, int offset, int stride, int x, int y, int width, int height, int matrix[], int matrixwidth, int matrixheight);
  29.     void trim(int * pixels, int width, int height, int * workingpixels, int workingstride);
  30.     int hashrandom(std::vector<long long int> elements);
  31.     void olsennoise(int *  pixels, int stride, int x, int y, int width, int height);
  32.     int getRequiredDim(int dim);
  33. private:
  34.     void olsennoise(int * pixels, int stride, int x_within_field, int y_within_field, int width, int height, int iteration) ;
  35.     void applyNoise(int * pixels, int stride, int x_within_field, int y_within_field, int width, int height, int iteration);
  36.     void applyScale(int * pixels, int stride, int width, int height, int factor);
  37.     void applyShift(int * pixels, int stride, int shiftX, int shiftY, int width, int height);
  38.     void applyColor(int * pixels, int stride, int width, int height);
  39.     void applyBlur(int * pixels, int stride, int width, int height);
  40.     int crimp(int color);
  41.     int convolve(int * pixels, int stride, int index, int matrix[], int matrixwidth, int matrixheight);
  42.  
  43.     long long hash(long long v);
  44.  
  45.     /// constant statics
  46.     static const int maxiterations=3;
  47.     static const int blurEdge=2; //extra pixels are needed for the blur (3 - 1).
  48.     static const int SCALE_FACTOR=2;
  49.  
  50.  
  51. };
  52.  
  53. OlsenNoise2D::OlsenNoise2D()
  54. {
  55.  
  56.  
  57. }
  58.  
  59.  
  60. void OlsenNoise2D::olsennoise(int * pixels, int stride, int x, int y, int width, int height)
  61. {
  62.     olsennoise(pixels, stride, x, y, width, height, maxiterations);
  63.     applyColor(pixels, stride, width, height);
  64. }
  65.  
  66. int OlsenNoise2D::getRequiredDim(int dim)
  67. {
  68.     return dim + blurEdge + SCALE_FACTOR;
  69. }
  70.  
  71. void OlsenNoise2D::olsennoise(int * pixels, int stride, int x_within_field, int y_within_field, int width, int height, int iteration)
  72. {
  73.     if (iteration == 0)
  74.     {
  75.         applyNoise(pixels, stride, x_within_field, y_within_field, width, height, iteration);
  76.         return;
  77.     }
  78.     int x_remainder = x_within_field & 1;
  79.     int y_remainder = y_within_field & 1; //Math.abs(y_within_field % SCALE_FACTOR)
  80.     olsennoise(pixels, stride,
  81.                ((x_within_field + x_remainder) / SCALE_FACTOR) - x_remainder,
  82.                ((y_within_field + y_remainder) / SCALE_FACTOR) - y_remainder,
  83.                ((width  + x_remainder) / SCALE_FACTOR) + blurEdge,
  84.                ((height + y_remainder) / SCALE_FACTOR) + blurEdge, iteration - 1);
  85.     applyScale(pixels, stride, width + 2, height + 2, SCALE_FACTOR);
  86.     applyShift(pixels, stride, x_remainder, y_remainder, width + 2, height + 2);
  87.     applyBlur(pixels, stride, width + 2, height + 2);
  88.     applyNoise(pixels, stride, x_within_field, y_within_field, width, height, iteration);
  89. }
  90.  
  91. void OlsenNoise2D::applyNoise(int * pixels, int stride, int x_within_field, int y_within_field, int width, int height, int iteration)
  92. {
  93.     int index = 0;
  94.     for (int k = 0, n = height - 1; k <= n; k++, index += stride)
  95.     {
  96.         for (int j = 0, m = width - 1; j <= m; j++)
  97.         {
  98.             int current = index + (j*width);
  99.             pixels[current] += (hashrandom( {j + x_within_field, k + y_within_field, iteration}) & (1 << (7 - iteration)));
  100.         }
  101.     }
  102. }
  103.  
  104. void OlsenNoise2D::applyScale(int * pixels, int stride, int width, int height, int factor)
  105. {
  106.     int index = (height - 1) * stride;
  107.     for (int k = 0, n = height - 1; k <= n; n--, index -= stride)
  108.     {
  109.         for (int j = 0, m = width - 1; j <= m; m--)
  110.         {
  111.             int current = index + m;
  112.             int lower = ((n / factor) * stride) + (m / factor);
  113.             pixels[current] = pixels[lower];
  114.         }
  115.     }
  116. }
  117.  
  118. void OlsenNoise2D::applyShift(int * pixels, int stride, int shiftX, int shiftY, int width, int height)
  119. {
  120.     if ((shiftX == 0) && (shiftY == 0))
  121.     {
  122.         return;
  123.     }
  124.  
  125.     int index;
  126.     int indexoffset = shiftX + (shiftY * stride);
  127.     index = 0;
  128.     for (int k = 0, n = height - 1; k <= n; k++, index += stride)
  129.     {
  130.         for (int j = 0, m = width - 1; j <= m; j++)
  131.         {
  132.             int current = index + j;
  133.             pixels[current] = pixels[current + indexoffset];
  134.         }
  135.     }
  136. }
  137.  
  138. void OlsenNoise2D::applyColor(int * pixels, int stride, int width, int height)
  139. {
  140.     int index;
  141.     index = 0;
  142.     for (int k = 0, n = height - 1; k <= n; k++, index += stride)
  143.     {
  144.         for (int j = 0, m = width - 1; j <= m; j++)
  145.         {
  146.             int current = index + j;
  147.             int pixel = pixels[current];
  148.             pixels[current] = 0xFF000000 | pixel << 16 | pixel << 8 | pixel;
  149.         }
  150.     }
  151. }
  152.  
  153.  
  154. void OlsenNoise2D::applyBlur(int * pixels, int stride, int width, int height)
  155. {
  156.     /// array
  157.     int blur3x3[] = {1,1,1,1,1,1,1,1,1,1};
  158.  
  159.     convolve(pixels, 0, stride, 0, 0, width, height, blur3x3, 3, 3);
  160. }
  161.  
  162. /**
  163.     * Memory Free In-Place Convolution.
  164.     * Modified to simply add values. (Greyscale as such).
  165.     *
  166.     * @param pixels pixels to be modified
  167.     * @param offset offset within the pixel array to call zero.
  168.     * @param stride width of the memory block to next Y.
  169.     * @param x the start x value.
  170.     * @param y the start y value.
  171.     * @param width the width of blocks to be used for the convolution.
  172.     * @param height the height of the convolution area.
  173.     * @param matrix matrix of the convolution.
  174.     */
  175.  
  176. void OlsenNoise2D::convolve(int * pixels, int offset, int stride, int x, int y, int width, int height,int matrix[], int matrixwidth, int matrixheight)
  177. {
  178.     int index = offset + x + (y*stride);
  179.     for (int j = 0; j < height; j++, index += stride)
  180.     {
  181.         for (int k = 0; k < width; k++)
  182.         {
  183.             int pos = index + k;
  184.             pixels[pos] = convolve(pixels,stride,pos, matrix, matrixwidth, matrixheight);
  185.         }
  186.     }
  187. }
  188.  
  189. int OlsenNoise2D::crimp(int color)
  190. {
  191.     return (color >= 0xFF) ? 0xFF : (color < 0) ? 0 : color;
  192. }
  193.  
  194. int OlsenNoise2D::convolve(int * pixels, int stride, int index, int matrix[], int matrixwidth, int matrixheight)
  195. {
  196.     int parts = 0;
  197.     int sum = 0;
  198.     int factor;
  199.  
  200.     for (int j = 0, m = matrixwidth; j < m; j++, index+=stride)
  201.     {
  202.         for (int k = 0, n = matrixheight; k < n; k++)
  203.         {
  204.             factor = matrix[j+(k*matrixwidth)];
  205.  
  206.             parts += factor;
  207.             sum += factor * pixels[index + k];
  208.         }
  209.     }
  210.     if (parts == 0) return crimp(sum);
  211.     return crimp(sum/parts);
  212. }
  213.  
  214. /**
  215.     * XOR hash the hashed values of each element, in elements
  216.     * @param elements elements to be hashed and xor'ed together.
  217.     * @return
  218.     */
  219.  
  220. int OlsenNoise2D::hashrandom(std::vector<long long int> elements)
  221. {
  222.     long long hashcalc = 0;
  223.  
  224.  
  225.     for (int i = 0; i < elements.size(); i++)
  226.     {
  227.         hashcalc ^= elements[i];
  228.         hashcalc = hash(hashcalc);
  229.     }
  230.     return (int) hashcalc;
  231. };
  232.  
  233. long long OlsenNoise2D::hash(long long v)
  234. {
  235.     long long hash = v;
  236.     long long h = hash;
  237.  
  238.     switch ((int) hash & 3)
  239.     {
  240.     case 3:
  241.         hash += h;
  242.         hash ^= hash << 32;
  243.         hash ^= h << 36;
  244.         hash += hash >> 22;
  245.         break;
  246.     case 2:
  247.         hash += h;
  248.         hash ^= hash << 22;
  249.         hash += hash >> 34;
  250.         break;
  251.     case 1:
  252.         hash += h;
  253.         hash ^= hash << 20;
  254.         hash += hash >> 2;
  255.     }
  256.     hash ^= hash << 6;
  257.     hash += hash >> 10;
  258.     hash ^= hash << 8;
  259.     hash += hash >> 34;
  260.     hash ^= hash << 50;
  261.     hash += hash >> 12;
  262.     return hash;
  263. };
  264.  
  265. /**
  266.  * Trim off the edge pixels
  267.  *
  268.  * @param pixels destination array
  269.  * @param width Width of the new image
  270.  * @param height height of the new image
  271.  * @param workingpixels source array
  272.  * @param workingstride stride of source array
  273.  */
  274. void OlsenNoise2D::trim(int * pixels, int width, int height, int * workingpixels, int workingstride)
  275. {
  276.     for (int k = 0; k < height; k++)
  277.     {
  278.         for (int j = 0; j < width; j++)
  279.         {
  280.             int index = j + (k * width);
  281.             int workingindex = j + (k * workingstride);
  282.             pixels[index] = workingpixels[workingindex];
  283.         }
  284.     }
  285. }
  286.  
  287.  
  288. int main()
  289. {
  290.  
  291.     /// Test
  292.     int ImageSize=2049;
  293.     int * imageInput = new int[ImageSize*ImageSize];
  294.  
  295.     /// Image
  296.     OlsenNoise2D testingolsen;
  297.     testingolsen.olsennoise(imageInput, 1, 0,0,ImageSize,ImageSize);
  298.  
  299.     SaveTerrFile(imageInput, ImageSize, "output.png");
  300.  
  301.     delete imageInput;
  302.  
  303.  
  304.  
  305.     return 1;
  306. }
  307.  
  308.  
  309. void SaveTerrFile(const int * image, int size, char * filename)
  310. {
  311.     png::image< png::rgb_pixel > newimage(size, size);
  312.  
  313.     for (unsigned int y = 0; y < newimage.get_width(); ++y)
  314.     {
  315.         for (unsigned int x = 0; x < newimage.get_height(); ++x)
  316.         {
  317.             int col = int(image[x+(y*newimage.get_width())]);
  318.             newimage[y][x] = png::rgb_pixel(col,col,col);
  319.             // non-checking equivalent of image.set_pixel(x, y, ...);
  320.         }
  321.     }
  322.  
  323.     newimage.write(filename);
  324. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement