/** * Creates an image with the perlin noise. If the depth value is to big the biggest working value is used. * For possible scaling flags see (Image::)scale(), (Image::)smooth() and (Image::)createWhiteNoise(). * (default flags = WHITE_NOISE_GREY | SMOOTH_NORMAL | SCALE_NEAREST_NEIGHBOR) * @param width of the image * @param height of the image * @param range for the random values * @param seed for the random number generator * @param number of interation * @param weight of the new noise (towards 0 makes the image smoother) * @param flags * @return the created image * @throw bad_alloc exception if something went wrong while allocating memory */ Image Image::createPerlinNoise(size_t width, size_t height, unsigned int seed, unsigned char range, unsigned int depth, float weight, unsigned char flags) { float currentWidth = width; float currentHeight = height; unsigned int actualDepth = 0; //reduce the resolution to the requested depth for(unsigned int i = 0; i <= depth && currentWidth >= 2 && currentHeight >= 2; ++i) { currentWidth /= 2; currentHeight /= 2; actualDepth = i; } //prevent too high depth depth = actualDepth; //fill the new image with white noise Image img = createWhiteNoise((size_t)ceil(currentWidth), (size_t)ceil(currentHeight), seed, flags, range); img.smooth(flags); //merge with bigger smoothed noise images until the given depth is reached for(unsigned int i = 0; i < depth; ++i) { currentWidth *= 2; currentHeight *= 2; Image newImg = createWhiteNoise((size_t)ceil(currentWidth), (size_t)ceil(currentHeight), seed, flags, range); newImg.smooth(flags); img.scale(2.0f, 2.0f, flags); img.smooth(flags); img.maximizeContrast(); img = mergeImages(img, newImg, weight, flags); } return img; }
void merge (FILE *pbmImage1, FILE *pbmImage2) { int fSize1 = size(pbmImage1); int fSize2 = size(pbmImage2); int fSize; int pbmHeight1, pbmWidth1; int pbmHeight2, pbmWidth2; int pbmHeight, pbmWidth; // Error checking file sizes if (fSize1 != fSize2) { fprintf(stderr, "PBM image sizes do not match. Image1: %i, Image2: %i\n", fSize1, fSize2); exit(-1); } // Assign global file size for both images fSize = fSize1; // Set up image chars unsigned char *inputBuffer1 = malloc(fSize); unsigned char *inputBuffer2 = malloc(fSize); memset(inputBuffer1, 0, fSize); memset(inputBuffer2, 0, fSize); // Process Height and Width of image 1 if (!fgets((char *)inputBuffer1, sizeof(inputBuffer1), pbmImage1)) { fprintf(stderr, "Unable to read image format.\n"); exit(-1); } if (inputBuffer1[0] != 'P' || inputBuffer1[1] != '4') { fprintf(stderr, "Invalid image format. Must be P4.\n"); exit(-1); } if (fscanf(pbmImage1, "%d %d", &pbmWidth1, &pbmHeight1) != 2) { fprintf(stderr, "Invalid image size.\n"); exit(-1); } // Process Height and Width of image 2 if (!fgets((char *)inputBuffer2, sizeof(inputBuffer2), pbmImage2)) { fprintf(stderr, "Unable to read image format.\n"); exit(-1); } if (inputBuffer2[0] != 'P' || inputBuffer2[1] != '4') { fprintf(stderr, "Invalid image format. Must be P4.\n"); exit(-1); } if (fscanf(pbmImage2, "%d %d", &pbmWidth2, &pbmHeight2) != 2) { fprintf(stderr, "Invalid image size.\n"); exit(-1); } // Error checking to make sure image 1 is the same dimensions as image 2 if (pbmWidth1 != pbmWidth2 && pbmHeight1 != pbmHeight2) { fprintf(stderr, "PBM Image dimensions do not match. Image 1\tWidth: %i\tHeight: %i\nImage 2\t Width: %i\tHeight: %i\n", pbmWidth1, pbmHeight1, pbmWidth2, pbmHeight2); exit(-1); } else { pbmWidth = pbmWidth1; pbmHeight = pbmHeight1; } // Read the image into respective buffers fread(inputBuffer1, fSize - 4, 1, pbmImage1); fread(inputBuffer2, fSize - 4, 1, pbmImage2); // Finally merge images to output to stdout mergeImages(inputBuffer1, inputBuffer2, pbmHeight, pbmWidth, fSize); }