// // SPDX-License-Identifier: BSD-3-Clause // Copyright (c) Contributors to the OpenEXR Project. // //----------------------------------------------------------------------------- // // Functions that algorithmically generate images, so that // the code examples for image file reading and writing have // data they can work with. // Note that it is not necessary to study the code below in // order to understand how the file I/O code examples work. // //----------------------------------------------------------------------------- #include "drawImage.h" #include #include #include #include #include "namespaceAlias.h" using namespace IMF; using namespace std; namespace { float pw (float x, int y) { float p = 1; while (y) { if (y & 1) p *= x; x *= x; y >>= 1; } return p; } void sp (Array2D& px, int w, int h, float xc, float yc, float rc, float rd, float gn, float bl, float lm) { int x1 = int (max ((float) floor (xc - rc), 0.0f)); int x2 = int (min ((float) ceil (xc + rc), w - 1.0f)); int y1 = int (max ((float) floor (yc - rc), 0.0f)); int y2 = int (min ((float) ceil (yc + rc), h - 1.0f)); for (int y = y1; y <= y2; ++y) { for (int x = x1; x <= x2; ++x) { float xl = (x - xc) / rc; float yl = (y - yc) / rc; float r = sqrt (xl * xl + yl * yl); if (r >= 1) continue; float a = 1; if (r * rc > rc - 1) a = rc - r * rc; float zl = sqrt (1 - r * r); float dl = xl * 0.42426 - yl * 0.56568 + zl * 0.70710; if (dl < 0) dl *= -0.1; float hl = pw (dl, 50) * 4; float dr = (dl + hl) * rd; float dg = (dl + hl) * gn; float db = (dl + hl) * bl; Rgba& p = px[y][x]; p.r = p.r * (1 - a) + dr * lm * a; p.g = p.g * (1 - a) + dg * lm * a; p.b = p.b * (1 - a) + db * lm * a; p.a = 1 - (1 - p.a) * (1 - a); } } } void zsp ( Array2D& gpx, Array2D& zpx, int w, int h, float xc, float yc, float zc, float rc, float gn) { int x1 = int (max ((float) floor (xc - rc), 0.0f)); int x2 = int (min ((float) ceil (xc + rc), w - 1.0f)); int y1 = int (max ((float) floor (yc - rc), 0.0f)); int y2 = int (min ((float) ceil (yc + rc), h - 1.0f)); for (int x = x1; x <= x2; ++x) { for (int y = y1; y <= y2; ++y) { float xl = (x - xc) / rc; float yl = (y - yc) / rc; float r = sqrt (xl * xl + yl * yl); if (r >= 1) continue; float zl = sqrt (1 - r * r); float zp = zc - rc * zl; if (zp >= zpx[y][x]) continue; float dl = xl * 0.42426 - yl * 0.56568 + zl * 0.70710; if (dl < 0) dl *= -0.1; float hl = pw (dl, 50) * 4; float dg = (dl + hl) * gn; gpx[y][x] = dg; zpx[y][x] = zp; } } } inline float z (float k) { k = 2 * (k - int (k)); return (k < 1) ? k : 2 - k; } inline void clear (Rgba& color) { color.r = 0; color.g = 0; color.b = 0; } inline void clear (GZ& gz) { gz.g = 0; gz.z = 0; } void add (float k, Rgba& color) { color.a = k; k *= 4; color.r += 0.1f + 4 * z (k); color.g += 0.1f + 4 * z (k + .33333f); color.b += 0.1f + 4 * z (k + .66667f); } void add (float k, GZ& gz) { k *= 5; gz.g += 4 * z (k); gz.z = k; } inline void scale (float f, Rgba& color) { color.r *= f; color.g *= f; color.b *= f; color.a *= f; } inline void scale (float f, GZ& gz) { gz.g *= f; gz.z *= f; } template void mndl ( Array2D

& px, int w, int h, int xMin, int xMax, int yMin, int yMax, int xSamples, int ySamples, double rMin, double rMax, double iMin, double aspect, double rSeed, double iSeed) { if (xSamples > 6) xSamples = 6; if (ySamples > 6) ySamples = 6; double iMax = iMin + aspect * (rMax - rMin) * h / w; double sx = double (rMax - rMin) / w; double sy = double (iMax - iMin) / h; double tx = 1.f / xSamples; double ty = 1.f / ySamples; float t = tx * ty; for (int y = yMin; y < yMax; ++y) { for (int x = xMin; x < xMax; ++x) { P& p = px[y - yMin][x - xMin]; clear (p); for (int i = 0; i < xSamples; ++i) { for (int j = 0; j < ySamples; ++j) { const double a = rMin + sx * (x + i * tx); const double b = iMin + sy * (y + j * ty); const double sMax = 100; const int kMax = 256; double r = rSeed; double i = iSeed; double s = 0; int k = 0; while (k < kMax && s < sMax) { s = r * r - i * i; i = 2 * r * i + b; r = s + a; k++; } add (k / float (kMax), p); } } scale (t, p); } } } } // namespace void drawImage1 (Array2D& px, int w, int h) { for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { Rgba& p = px[y][x]; p.r = 0; p.g = 0; p.b = 0; p.a = 0; } } int n = 5600; for (int i = 0; i < n; ++i) { float t = (i * 2.0 * M_PI) / n; float xp = sin (t * 2.0) + 0.2 * sin (t * 15.0); float yp = cos (t * 3.0) + 0.2 * cos (t * 15.0); float r = float (i + 1) / float (n); float xq = xp + 0.3 * r * sin (t * 80.0); float yq = yp + 0.3 * r * cos (t * 80.0); float xr = xp + 0.3 * r * sin (t * 80.0 + M_PI / 2); float yr = yp + 0.3 * r * cos (t * 80.0 + M_PI / 2); if (i % 10 == 0) sp (px, w, h, xp * w / 3 + w / 2, yp * h / 3 + h / 2, w * 0.05 * r, 2.0, 0.8, 0.1, 0.5 * r * r); sp (px, w, h, xq * w / 3 + w / 2, yq * h / 3 + h / 2, w * 0.01 * r, 0.7, 0.2, 2.0, 0.5 * r * r); sp (px, w, h, xr * w / 3 + w / 2, yr * h / 3 + h / 2, w * 0.01 * r, 0.2, 1.5, 0.1, 0.5 * r * r); } } void drawImage2 (Array2D& gpx, Array2D& zpx, int w, int h) { for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { gpx[y][x] = 0; zpx[y][x] = FLT_MAX; } } int n = 2000; for (int i = 0; i < n; ++i) { float t = (i * 2.0 * M_PI) / n; float xp = sin (t * 4.0) + 0.2 * sin (t * 15.0); float yp = cos (t * 3.0) + 0.2 * cos (t * 15.0); float zp = sin (t * 5.0); float rd = 0.7 + 0.3 * sin (t * 15.0); float gn = 0.5 - 0.5 * zp + 0.2; zsp ( gpx, zpx, w, h, xp * w / 3 + w / 2, yp * h / 3 + h / 2, zp * w + 3 * w, w * rd * 0.05, 2.5 * gn * gn); } } void drawImage3 ( Array2D& px, int w, int h, int xMin, int xMax, int yMin, int yMax, int xLevel, int yLevel) { mndl ( px, w, h, xMin, xMax, yMin, yMax, (1 << xLevel), (1 << yLevel), 0.328, 0.369, 0.5, double (1 << yLevel) / double (1 << xLevel), -0.713, 0.9738); } void drawImage4 ( Array2D& px, int w, int h, int xMin, int xMax, int yMin, int yMax, int xLevel, int yLevel) { mndl ( px, w, h, xMin, xMax, yMin, yMax, (1 << xLevel), (1 << yLevel), 0.3247, 0.33348, 0.4346, double (1 << yLevel) / double (1 << xLevel), 0.4, -0.765); } void drawImage5 ( Array2D& px, int w, int h, int xMin, int xMax, int yMin, int yMax, int xLevel, int yLevel) { mndl ( px, w, h, xMin, xMax, yMin, yMax, (1 << xLevel), (1 << yLevel), 0.2839, 0.2852, 0.00961, double (1 << yLevel) / double (1 << xLevel), 0.25, 0.31); } void drawImage6 (Array2D& px, int w, int h) { mndl (px, w, h, 0, w, 0, h, 3, 3, -2.5, 1.0, -1.3333, 1, 0, 0); } void drawImage7 (Array& px, int w, int h, int y) { for (int x = 0; x < w; ++x) { float xc = x - w / 2; float yc = y - h / 2; float a = atan2 (xc, yc); float r = sqrt (xc * xc + yc * yc); Rgba& p = px[x]; p.r = sin (3.0f * a + 0.3f * sin (0.10f * r)) * 0.5f + 0.5f; p.g = sin (3.0f * a + 0.3f * sin (0.11f * r)) * 0.5f + 0.5f; p.b = sin (3.0f * a + 0.3f * sin (0.12f * r)) * 0.5f + 0.5f; p.a = 1; } }