mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-03 19:33:07 +03:00
Merge pull request #882 from hugovk/effects
Tests and access functions for Effects.c
This commit is contained in:
commit
86d5d8abed
39
PIL/Image.py
39
PIL/Image.py
|
@ -1910,6 +1910,16 @@ class Image:
|
||||||
im = self.im.transpose(method)
|
im = self.im.transpose(method)
|
||||||
return self._new(im)
|
return self._new(im)
|
||||||
|
|
||||||
|
def effect_spread(self, distance):
|
||||||
|
"""
|
||||||
|
Randomly spread pixels in an image.
|
||||||
|
|
||||||
|
:param distance: Distance to spread pixels.
|
||||||
|
"""
|
||||||
|
self.load()
|
||||||
|
im = self.im.effect_spread(distance)
|
||||||
|
return self._new(im)
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# Lazy operations
|
# Lazy operations
|
||||||
|
@ -2419,3 +2429,32 @@ def _show(image, **options):
|
||||||
def _showxv(image, title=None, **options):
|
def _showxv(image, title=None, **options):
|
||||||
from PIL import ImageShow
|
from PIL import ImageShow
|
||||||
ImageShow.show(image, title, **options)
|
ImageShow.show(image, title, **options)
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------
|
||||||
|
# Effects
|
||||||
|
|
||||||
|
def effect_mandelbrot(size, extent, quality):
|
||||||
|
"""
|
||||||
|
Generate a Mandelbrot set covering the given extent.
|
||||||
|
|
||||||
|
:param size: The requested size in pixels, as a 2-tuple:
|
||||||
|
(width, height).
|
||||||
|
:param extent: The extent to cover, as a 4-tuple:
|
||||||
|
(x0, y0, x1, y2).
|
||||||
|
:param quality: Quality.
|
||||||
|
"""
|
||||||
|
return Image()._new(core.effect_mandelbrot(size, extent, quality))
|
||||||
|
|
||||||
|
|
||||||
|
def effect_noise(size, sigma):
|
||||||
|
"""
|
||||||
|
Generate Gaussian noise centered around 128.
|
||||||
|
|
||||||
|
:param size: The requested size in pixels, as a 2-tuple:
|
||||||
|
(width, height).
|
||||||
|
:param sigma: Standard deviation of noise.
|
||||||
|
"""
|
||||||
|
return Image()._new(core.effect_noise(size, sigma))
|
||||||
|
|
||||||
|
# End of file
|
||||||
|
|
BIN
Tests/images/effect_mandelbrot.png
Normal file
BIN
Tests/images/effect_mandelbrot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
Tests/images/effect_spread.png
Normal file
BIN
Tests/images/effect_spread.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
|
@ -1,6 +1,7 @@
|
||||||
from helper import unittest, PillowTestCase, lena
|
from helper import unittest, PillowTestCase, lena
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
class TestImage(PillowTestCase):
|
class TestImage(PillowTestCase):
|
||||||
|
@ -140,6 +141,60 @@ class TestImage(PillowTestCase):
|
||||||
img_colors = sorted(img.getcolors())
|
img_colors = sorted(img.getcolors())
|
||||||
self.assertEqual(img_colors, expected_colors)
|
self.assertEqual(img_colors, expected_colors)
|
||||||
|
|
||||||
|
def test_effect_mandelbrot(self):
|
||||||
|
# Arrange
|
||||||
|
size = (512, 512)
|
||||||
|
extent = (-3, -2.5, 2, 2.5)
|
||||||
|
quality = 100
|
||||||
|
|
||||||
|
# Act
|
||||||
|
im = Image.effect_mandelbrot(size, extent, quality)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(im.size, (512, 512))
|
||||||
|
im2 = Image.open('Tests/images/effect_mandelbrot.png')
|
||||||
|
self.assert_image_equal(im, im2)
|
||||||
|
|
||||||
|
def test_effect_mandelbrot_bad_arguments(self):
|
||||||
|
# Arrange
|
||||||
|
size = (512, 512)
|
||||||
|
# Get coordinates the wrong way round:
|
||||||
|
extent = (+3, +2.5, -2, -2.5)
|
||||||
|
# Quality < 2:
|
||||||
|
quality = 1
|
||||||
|
|
||||||
|
# Act/Assert
|
||||||
|
self.assertRaises(
|
||||||
|
ValueError,
|
||||||
|
lambda: Image.effect_mandelbrot(size, extent, quality))
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform.startswith('win32'),
|
||||||
|
"Stalls on Travis CI, passes on Windows")
|
||||||
|
def test_effect_noise(self):
|
||||||
|
# Arrange
|
||||||
|
size = (100, 100)
|
||||||
|
sigma = 128
|
||||||
|
|
||||||
|
# Act
|
||||||
|
im = Image.effect_noise(size, sigma)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(im.size, (100, 100))
|
||||||
|
self.assertEqual(im.getpixel((0, 0)), 60)
|
||||||
|
self.assertEqual(im.getpixel((0, 1)), 28)
|
||||||
|
|
||||||
|
def test_effect_spread(self):
|
||||||
|
# Arrange
|
||||||
|
im = lena()
|
||||||
|
distance = 10
|
||||||
|
|
||||||
|
# Act
|
||||||
|
im2 = im.effect_spread(distance)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(im.size, (128, 128))
|
||||||
|
im3 = Image.open('Tests/images/effect_spread.png')
|
||||||
|
self.assert_image_similar(im2, im3, 80)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -48,25 +48,25 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality)
|
||||||
|
|
||||||
for (y = 0; y < ysize; y++) {
|
for (y = 0; y < ysize; y++) {
|
||||||
UINT8* buf = im->image8[y];
|
UINT8* buf = im->image8[y];
|
||||||
for (x = 0; x < xsize; x++) {
|
for (x = 0; x < xsize; x++) {
|
||||||
x1 = y1 = xi2 = yi2 = 0.0;
|
x1 = y1 = xi2 = yi2 = 0.0;
|
||||||
cr = x*dr + extent[0];
|
cr = x*dr + extent[0];
|
||||||
ci = y*di + extent[1];
|
ci = y*di + extent[1];
|
||||||
for (k = 1;; k++) {
|
for (k = 1;; k++) {
|
||||||
y1 = 2*x1*y1 + ci;
|
y1 = 2*x1*y1 + ci;
|
||||||
x1 = xi2 - yi2 + cr;
|
x1 = xi2 - yi2 + cr;
|
||||||
xi2 = x1*x1;
|
xi2 = x1*x1;
|
||||||
yi2 = y1*y1;
|
yi2 = y1*y1;
|
||||||
if ((xi2 + yi2) > radius) {
|
if ((xi2 + yi2) > radius) {
|
||||||
buf[x] = k*255/quality;
|
buf[x] = k*255/quality;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (k > quality) {
|
if (k > quality) {
|
||||||
buf[x] = 0;
|
buf[x] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return im;
|
return im;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality)
|
||||||
Imaging
|
Imaging
|
||||||
ImagingEffectNoise(int xsize, int ysize, float sigma)
|
ImagingEffectNoise(int xsize, int ysize, float sigma)
|
||||||
{
|
{
|
||||||
/* Generate gaussian noise centered around 128 */
|
/* Generate Gaussian noise centered around 128 */
|
||||||
|
|
||||||
Imaging imOut;
|
Imaging imOut;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
@ -83,19 +83,19 @@ ImagingEffectNoise(int xsize, int ysize, float sigma)
|
||||||
|
|
||||||
imOut = ImagingNew("L", xsize, ysize);
|
imOut = ImagingNew("L", xsize, ysize);
|
||||||
if (!imOut)
|
if (!imOut)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
next = 0.0;
|
next = 0.0;
|
||||||
nextok = 0;
|
nextok = 0;
|
||||||
|
|
||||||
for (y = 0; y < imOut->ysize; y++) {
|
for (y = 0; y < imOut->ysize; y++) {
|
||||||
UINT8* out = imOut->image8[y];
|
UINT8* out = imOut->image8[y];
|
||||||
for (x = 0; x < imOut->xsize; x++) {
|
for (x = 0; x < imOut->xsize; x++) {
|
||||||
if (nextok) {
|
if (nextok) {
|
||||||
this = next;
|
this = next;
|
||||||
nextok = 0;
|
nextok = 0;
|
||||||
} else {
|
} else {
|
||||||
/* after numerical recepies */
|
/* after numerical recipes */
|
||||||
double v1, v2, radius, factor;
|
double v1, v2, radius, factor;
|
||||||
do {
|
do {
|
||||||
v1 = rand()*(2.0/32767.0) - 1.0;
|
v1 = rand()*(2.0/32767.0) - 1.0;
|
||||||
|
@ -113,14 +113,6 @@ ImagingEffectNoise(int xsize, int ysize, float sigma)
|
||||||
return imOut;
|
return imOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
Imaging
|
|
||||||
ImagingEffectPerlinTurbulence(int xsize, int ysize)
|
|
||||||
{
|
|
||||||
/* Perlin turbulence (In progress) */
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Imaging
|
Imaging
|
||||||
ImagingEffectSpread(Imaging imIn, int distance)
|
ImagingEffectSpread(Imaging imIn, int distance)
|
||||||
{
|
{
|
||||||
|
@ -132,11 +124,11 @@ ImagingEffectSpread(Imaging imIn, int distance)
|
||||||
imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
|
imOut = ImagingNew(imIn->mode, imIn->xsize, imIn->ysize);
|
||||||
|
|
||||||
if (!imOut)
|
if (!imOut)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#define SPREAD(type, image)\
|
#define SPREAD(type, image)\
|
||||||
for (y = 0; y < imIn->ysize; y++)\
|
for (y = 0; y < imIn->ysize; y++)\
|
||||||
for (x = 0; x < imIn->xsize; x++) {\
|
for (x = 0; x < imIn->xsize; x++) {\
|
||||||
int xx = x + (rand() % distance) - distance/2;\
|
int xx = x + (rand() % distance) - distance/2;\
|
||||||
int yy = y + (rand() % distance) - distance/2;\
|
int yy = y + (rand() % distance) - distance/2;\
|
||||||
if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) {\
|
if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) {\
|
||||||
|
@ -147,9 +139,9 @@ ImagingEffectSpread(Imaging imIn, int distance)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imIn->image8) {
|
if (imIn->image8) {
|
||||||
SPREAD(UINT8, image8);
|
SPREAD(UINT8, image8);
|
||||||
} else {
|
} else {
|
||||||
SPREAD(INT32, image32);
|
SPREAD(INT32, image32);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImagingCopyInfo(imOut, imIn);
|
ImagingCopyInfo(imOut, imIn);
|
||||||
|
@ -157,217 +149,4 @@ ImagingEffectSpread(Imaging imIn, int distance)
|
||||||
return imOut;
|
return imOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
// End of file
|
||||||
/* Taken from the "C" code in the W3C SVG specification. Translated
|
|
||||||
to C89 by Fredrik Lundh */
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
/* Produces results in the range [1, 2**31 - 2].
|
|
||||||
Algorithm is: r = (a * r) mod m
|
|
||||||
where a = 16807 and m = 2**31 - 1 = 2147483647
|
|
||||||
See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
|
|
||||||
To test: the algorithm should produce the result 1043618065
|
|
||||||
as the 10,000th generated number if the original seed is 1.
|
|
||||||
*/
|
|
||||||
#define RAND_m 2147483647 /* 2**31 - 1 */
|
|
||||||
#define RAND_a 16807 /* 7**5; primitive root of m */
|
|
||||||
#define RAND_q 127773 /* m / a */
|
|
||||||
#define RAND_r 2836 /* m % a */
|
|
||||||
|
|
||||||
static long
|
|
||||||
perlin_setup_seed(long lSeed)
|
|
||||||
{
|
|
||||||
if (lSeed <= 0) lSeed = -(lSeed % (RAND_m - 1)) + 1;
|
|
||||||
if (lSeed > RAND_m - 1) lSeed = RAND_m - 1;
|
|
||||||
return lSeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long
|
|
||||||
perlin_random(long lSeed)
|
|
||||||
{
|
|
||||||
long result;
|
|
||||||
result = RAND_a * (lSeed % RAND_q) - RAND_r * (lSeed / RAND_q);
|
|
||||||
if (result <= 0) result += RAND_m;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BSize 0x100
|
|
||||||
#define BM 0xff
|
|
||||||
#define PerlinN 0x1000
|
|
||||||
#define NP 12 /* 2^PerlinN */
|
|
||||||
#define NM 0xfff
|
|
||||||
static int perlin_uLatticeSelector[BSize + BSize + 2];
|
|
||||||
static double perlin_fGradient[4][BSize + BSize + 2][2];
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int nWidth; /* How much to subtract to wrap for stitching. */
|
|
||||||
int nHeight;
|
|
||||||
int nWrapX; /* Minimum value to wrap. */
|
|
||||||
int nWrapY;
|
|
||||||
} StitchInfo;
|
|
||||||
|
|
||||||
static void
|
|
||||||
perlin_init(long lSeed)
|
|
||||||
{
|
|
||||||
double s;
|
|
||||||
int i, j, k;
|
|
||||||
lSeed = perlin_setup_seed(lSeed);
|
|
||||||
for(k = 0; k < 4; k++)
|
|
||||||
{
|
|
||||||
for(i = 0; i < BSize; i++)
|
|
||||||
{
|
|
||||||
perlin_uLatticeSelector[i] = i;
|
|
||||||
for (j = 0; j < 2; j++)
|
|
||||||
perlin_fGradient[k][i][j] = (double)(((lSeed = perlin_random(lSeed)) % (BSize + BSize)) - BSize) / BSize;
|
|
||||||
s = (double) (sqrt(perlin_fGradient[k][i][0] * perlin_fGradient[k][i][0] + perlin_fGradient[k][i][1] * perlin_fGradient[k][i][1]));
|
|
||||||
perlin_fGradient[k][i][0] /= s;
|
|
||||||
perlin_fGradient[k][i][1] /= s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(--i)
|
|
||||||
{
|
|
||||||
k = perlin_uLatticeSelector[i];
|
|
||||||
perlin_uLatticeSelector[i] = perlin_uLatticeSelector[j = (lSeed = perlin_random(lSeed)) % BSize];
|
|
||||||
perlin_uLatticeSelector[j] = k;
|
|
||||||
}
|
|
||||||
for(i = 0; i < BSize + 2; i++)
|
|
||||||
{
|
|
||||||
perlin_uLatticeSelector[BSize + i] = perlin_uLatticeSelector[i];
|
|
||||||
for(k = 0; k < 4; k++)
|
|
||||||
for(j = 0; j < 2; j++)
|
|
||||||
perlin_fGradient[k][BSize + i][j] = perlin_fGradient[k][i][j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define s_curve(t) ( t * t * (3. - 2. * t) )
|
|
||||||
#define lerp(t, a, b) ( a + t * (b - a) )
|
|
||||||
static double
|
|
||||||
perlin_noise2(int nColorChannel, double vec[2], StitchInfo *pStitchInfo)
|
|
||||||
{
|
|
||||||
int bx0, bx1, by0, by1, b00, b10, b01, b11;
|
|
||||||
double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
|
|
||||||
register int i, j;
|
|
||||||
|
|
||||||
t = vec[0] + (double) PerlinN;
|
|
||||||
bx0 = (int)t;
|
|
||||||
bx1 = bx0+1;
|
|
||||||
rx0 = t - (int)t;
|
|
||||||
rx1 = rx0 - 1.0f;
|
|
||||||
t = vec[1] + (double) PerlinN;
|
|
||||||
by0 = (int)t;
|
|
||||||
by1 = by0+1;
|
|
||||||
ry0 = t - (int)t;
|
|
||||||
ry1 = ry0 - 1.0f;
|
|
||||||
|
|
||||||
/* If stitching, adjust lattice points accordingly. */
|
|
||||||
if(pStitchInfo != NULL)
|
|
||||||
{
|
|
||||||
if(bx0 >= pStitchInfo->nWrapX)
|
|
||||||
bx0 -= pStitchInfo->nWidth;
|
|
||||||
if(bx1 >= pStitchInfo->nWrapX)
|
|
||||||
bx1 -= pStitchInfo->nWidth;
|
|
||||||
if(by0 >= pStitchInfo->nWrapY)
|
|
||||||
by0 -= pStitchInfo->nHeight;
|
|
||||||
if(by1 >= pStitchInfo->nWrapY)
|
|
||||||
by1 -= pStitchInfo->nHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
bx0 &= BM;
|
|
||||||
bx1 &= BM;
|
|
||||||
by0 &= BM;
|
|
||||||
by1 &= BM;
|
|
||||||
|
|
||||||
i = perlin_uLatticeSelector[bx0];
|
|
||||||
j = perlin_uLatticeSelector[bx1];
|
|
||||||
b00 = perlin_uLatticeSelector[i + by0];
|
|
||||||
b10 = perlin_uLatticeSelector[j + by0];
|
|
||||||
b01 = perlin_uLatticeSelector[i + by1];
|
|
||||||
b11 = perlin_uLatticeSelector[j + by1];
|
|
||||||
sx = (double) (s_curve(rx0));
|
|
||||||
sy = (double) (s_curve(ry0));
|
|
||||||
q = perlin_fGradient[nColorChannel][b00]; u = rx0 * q[0] + ry0 * q[1];
|
|
||||||
q = perlin_fGradient[nColorChannel][b10]; v = rx1 * q[0] + ry0 * q[1];
|
|
||||||
a = lerp(sx, u, v);
|
|
||||||
q = perlin_fGradient[nColorChannel][b01]; u = rx0 * q[0] + ry1 * q[1];
|
|
||||||
q = perlin_fGradient[nColorChannel][b11]; v = rx1 * q[0] + ry1 * q[1];
|
|
||||||
b = lerp(sx, u, v);
|
|
||||||
return lerp(sy, a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
perlin_turbulence(
|
|
||||||
int nColorChannel, double *point, double fBaseFreqX, double fBaseFreqY,
|
|
||||||
int nNumOctaves, int bFractalSum, int bDoStitching,
|
|
||||||
double fTileX, double fTileY, double fTileWidth, double fTileHeight)
|
|
||||||
{
|
|
||||||
StitchInfo stitch;
|
|
||||||
StitchInfo *pStitchInfo = NULL; /* Not stitching when NULL. */
|
|
||||||
|
|
||||||
double fSum = 0.0f;
|
|
||||||
double vec[2];
|
|
||||||
double ratio = 1;
|
|
||||||
|
|
||||||
int nOctave;
|
|
||||||
|
|
||||||
vec[0] = point[0] * fBaseFreqX;
|
|
||||||
vec[1] = point[1] * fBaseFreqY;
|
|
||||||
|
|
||||||
/* Adjust the base frequencies if necessary for stitching. */
|
|
||||||
if(bDoStitching)
|
|
||||||
{
|
|
||||||
/* When stitching tiled turbulence, the frequencies must be adjusted */
|
|
||||||
/* so that the tile borders will be continuous. */
|
|
||||||
if(fBaseFreqX != 0.0)
|
|
||||||
{
|
|
||||||
double fLoFreq = (double) (floor(fTileWidth * fBaseFreqX)) / fTileWidth;
|
|
||||||
double fHiFreq = (double) (ceil(fTileWidth * fBaseFreqX)) / fTileWidth;
|
|
||||||
if(fBaseFreqX / fLoFreq < fHiFreq / fBaseFreqX)
|
|
||||||
fBaseFreqX = fLoFreq;
|
|
||||||
else
|
|
||||||
fBaseFreqX = fHiFreq;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fBaseFreqY != 0.0)
|
|
||||||
{
|
|
||||||
double fLoFreq = (double) (floor(fTileHeight * fBaseFreqY)) / fTileHeight;
|
|
||||||
double fHiFreq = (double) (ceil(fTileHeight * fBaseFreqY)) / fTileHeight;
|
|
||||||
if(fBaseFreqY / fLoFreq < fHiFreq / fBaseFreqY)
|
|
||||||
fBaseFreqY = fLoFreq;
|
|
||||||
else
|
|
||||||
fBaseFreqY = fHiFreq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up initial stitch values. */
|
|
||||||
pStitchInfo = &stitch;
|
|
||||||
stitch.nWidth = (int) (fTileWidth * fBaseFreqX + 0.5f);
|
|
||||||
stitch.nWrapX = (int) (fTileX * fBaseFreqX + PerlinN + stitch.nWidth);
|
|
||||||
stitch.nHeight = (int) (fTileHeight * fBaseFreqY + 0.5f);
|
|
||||||
stitch.nWrapY = (int) (fTileY * fBaseFreqY + PerlinN + stitch.nHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(nOctave = 0; nOctave < nNumOctaves; nOctave++)
|
|
||||||
{
|
|
||||||
if(bFractalSum)
|
|
||||||
fSum += (double) (perlin_noise2(nColorChannel, vec, pStitchInfo) / ratio);
|
|
||||||
else
|
|
||||||
fSum += (double) (fabs(perlin_noise2(nColorChannel, vec, pStitchInfo)) / ratio);
|
|
||||||
|
|
||||||
vec[0] *= 2;
|
|
||||||
vec[1] *= 2;
|
|
||||||
ratio *= 2;
|
|
||||||
|
|
||||||
if(pStitchInfo != NULL)
|
|
||||||
{
|
|
||||||
/* Update stitch values. Subtracting PerlinN before the multiplication and */
|
|
||||||
/* adding it afterward simplifies to subtracting it once. */
|
|
||||||
stitch.nWidth *= 2;
|
|
||||||
stitch.nWrapX = 2 * stitch.nWrapX - PerlinN;
|
|
||||||
stitch.nHeight *= 2;
|
|
||||||
stitch.nWrapY = 2 * stitch.nWrapY - PerlinN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user