2013-07-01 02:42:19 +04:00
|
|
|
/*
|
2010-07-31 06:52:47 +04:00
|
|
|
* The Python Imaging Library
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* various special effects and image generators
|
|
|
|
*
|
|
|
|
* history:
|
|
|
|
* 1997-05-21 fl Just for fun
|
|
|
|
* 1997-06-05 fl Added mandelbrot generator
|
|
|
|
* 2003-05-24 fl Added perlin_turbulence generator (in progress)
|
|
|
|
*
|
|
|
|
* Copyright (c) 1997-2003 by Fredrik Lundh.
|
|
|
|
* Copyright (c) 1997 by Secret Labs AB.
|
|
|
|
*
|
|
|
|
* See the README file for information on usage and redistribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "Imaging.h"
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
Imaging
|
2021-01-03 06:17:51 +03:00
|
|
|
ImagingEffectMandelbrot(int xsize, int ysize, double extent[4], int quality) {
|
2010-07-31 06:52:47 +04:00
|
|
|
/* Generate a Mandelbrot set covering the given extent */
|
|
|
|
|
|
|
|
Imaging im;
|
|
|
|
int x, y, k;
|
|
|
|
double width, height;
|
|
|
|
double x1, y1, xi2, yi2, cr, ci, radius;
|
|
|
|
double dr, di;
|
|
|
|
|
|
|
|
/* Check arguments */
|
2021-01-03 06:17:51 +03:00
|
|
|
width = extent[2] - extent[0];
|
2010-07-31 06:52:47 +04:00
|
|
|
height = extent[3] - extent[1];
|
2020-05-10 12:56:36 +03:00
|
|
|
if (width < 0.0 || height < 0.0 || quality < 2) {
|
2021-01-03 06:17:51 +03:00
|
|
|
return (Imaging)ImagingError_ValueError(NULL);
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2017-08-17 03:23:13 +03:00
|
|
|
im = ImagingNewDirty("L", xsize, ysize);
|
2020-05-10 12:56:36 +03:00
|
|
|
if (!im) {
|
2010-07-31 06:52:47 +04:00
|
|
|
return NULL;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2021-01-03 06:17:51 +03:00
|
|
|
dr = width / (xsize - 1);
|
|
|
|
di = height / (ysize - 1);
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
radius = 100.0;
|
|
|
|
|
|
|
|
for (y = 0; y < ysize; y++) {
|
2021-01-03 06:17:51 +03:00
|
|
|
UINT8 *buf = im->image8[y];
|
2014-09-02 16:14:00 +04:00
|
|
|
for (x = 0; x < xsize; x++) {
|
|
|
|
x1 = y1 = xi2 = yi2 = 0.0;
|
2021-01-03 06:17:51 +03:00
|
|
|
cr = x * dr + extent[0];
|
|
|
|
ci = y * di + extent[1];
|
2014-09-02 16:14:00 +04:00
|
|
|
for (k = 1;; k++) {
|
2021-01-03 06:17:51 +03:00
|
|
|
y1 = 2 * x1 * y1 + ci;
|
2014-09-02 16:14:00 +04:00
|
|
|
x1 = xi2 - yi2 + cr;
|
2021-01-03 06:17:51 +03:00
|
|
|
xi2 = x1 * x1;
|
|
|
|
yi2 = y1 * y1;
|
2014-09-02 16:14:00 +04:00
|
|
|
if ((xi2 + yi2) > radius) {
|
2021-01-03 06:17:51 +03:00
|
|
|
buf[x] = k * 255 / quality;
|
2014-09-02 16:14:00 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (k > quality) {
|
|
|
|
buf[x] = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
|
|
|
|
Imaging
|
2021-01-03 06:17:51 +03:00
|
|
|
ImagingEffectNoise(int xsize, int ysize, float sigma) {
|
2014-09-02 15:11:08 +04:00
|
|
|
/* Generate Gaussian noise centered around 128 */
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
Imaging imOut;
|
|
|
|
int x, y;
|
|
|
|
int nextok;
|
|
|
|
double this, next;
|
|
|
|
|
2017-08-17 03:23:13 +03:00
|
|
|
imOut = ImagingNewDirty("L", xsize, ysize);
|
2020-05-10 12:56:36 +03:00
|
|
|
if (!imOut) {
|
2014-09-02 15:11:08 +04:00
|
|
|
return NULL;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
next = 0.0;
|
|
|
|
nextok = 0;
|
|
|
|
|
|
|
|
for (y = 0; y < imOut->ysize; y++) {
|
2021-01-03 06:17:51 +03:00
|
|
|
UINT8 *out = imOut->image8[y];
|
2017-08-17 03:23:13 +03:00
|
|
|
for (x = 0; x < imOut->xsize; x++) {
|
2010-07-31 06:52:47 +04:00
|
|
|
if (nextok) {
|
|
|
|
this = next;
|
|
|
|
nextok = 0;
|
|
|
|
} else {
|
2014-09-02 15:11:08 +04:00
|
|
|
/* after numerical recipes */
|
2010-07-31 06:52:47 +04:00
|
|
|
double v1, v2, radius, factor;
|
|
|
|
do {
|
2021-01-03 06:17:51 +03:00
|
|
|
v1 = rand() * (2.0 / RAND_MAX) - 1.0;
|
|
|
|
v2 = rand() * (2.0 / RAND_MAX) - 1.0;
|
|
|
|
radius = v1 * v1 + v2 * v2;
|
2010-07-31 06:52:47 +04:00
|
|
|
} while (radius >= 1.0);
|
2021-01-03 06:17:51 +03:00
|
|
|
factor = sqrt(-2.0 * log(radius) / radius);
|
2010-07-31 06:52:47 +04:00
|
|
|
this = factor * v1;
|
|
|
|
next = factor * v2;
|
|
|
|
}
|
2018-04-21 11:14:05 +03:00
|
|
|
out[x] = CLIP8(128 + sigma * this);
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return imOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
Imaging
|
2021-01-03 06:17:51 +03:00
|
|
|
ImagingEffectSpread(Imaging imIn, int distance) {
|
2010-07-31 06:52:47 +04:00
|
|
|
/* Randomly spread pixels in an image */
|
|
|
|
|
|
|
|
Imaging imOut;
|
|
|
|
int x, y;
|
|
|
|
|
2017-08-17 03:23:13 +03:00
|
|
|
imOut = ImagingNewDirty(imIn->mode, imIn->xsize, imIn->ysize);
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2020-05-10 12:56:36 +03:00
|
|
|
if (!imOut) {
|
2017-08-17 03:23:13 +03:00
|
|
|
return NULL;
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2021-01-03 06:17:51 +03:00
|
|
|
#define SPREAD(type, image) \
|
|
|
|
if (distance == 0) { \
|
|
|
|
for (y = 0; y < imOut->ysize; y++) { \
|
|
|
|
for (x = 0; x < imOut->xsize; x++) { \
|
|
|
|
imOut->image[y][x] = imIn->image[y][x]; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} else { \
|
|
|
|
for (y = 0; y < imOut->ysize; y++) { \
|
|
|
|
for (x = 0; x < imOut->xsize; x++) { \
|
|
|
|
int xx = x + (rand() % distance) - distance / 2; \
|
|
|
|
int yy = y + (rand() % distance) - distance / 2; \
|
|
|
|
if (xx >= 0 && xx < imIn->xsize && yy >= 0 && yy < imIn->ysize) { \
|
|
|
|
imOut->image[yy][xx] = imIn->image[y][x]; \
|
|
|
|
imOut->image[y][x] = imIn->image[yy][xx]; \
|
|
|
|
} else { \
|
|
|
|
imOut->image[y][x] = imIn->image[y][x]; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
2020-05-10 12:56:36 +03:00
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
if (imIn->image8) {
|
2014-09-02 17:39:35 +04:00
|
|
|
SPREAD(UINT8, image8);
|
2010-07-31 06:52:47 +04:00
|
|
|
} else {
|
2014-09-02 17:39:35 +04:00
|
|
|
SPREAD(INT32, image32);
|
2010-07-31 06:52:47 +04:00
|
|
|
}
|
|
|
|
|
2017-09-19 20:42:13 +03:00
|
|
|
ImagingCopyPalette(imOut, imIn);
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
return imOut;
|
|
|
|
}
|